diff --git a/.gitignore b/.gitignore index e4b39ed6e..3fc51de44 100644 --- a/.gitignore +++ b/.gitignore @@ -355,6 +355,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 82bd11d9e..bd7994c01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1052,7 +1052,19 @@ 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)") @@ -1345,6 +1357,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/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 78087f11b..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. * diff --git a/IDE/ECLIPSE/DEOS/deos_malloc.c b/IDE/ECLIPSE/DEOS/deos_malloc.c index e8b213001..3a9c140a2 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. * 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..dbfe4f03a 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. * 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..371aaa6cc 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. * 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..58f9751d4 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. * 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..471ab3de5 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. * 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/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..d5636b493 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. * 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..ae5802316 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. * 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/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/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..604aba93e --- /dev/null +++ b/IDE/WINCE/user_settings.h @@ -0,0 +1,333 @@ +#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 1 + + #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 +#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..695370deb 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. * 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/configure.ac b/configure.ac index 08414bb7d..23deefd52 100644 --- a/configure.ac +++ b/configure.ac @@ -1,12 +1,12 @@ # 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_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]) @@ -22,16 +22,17 @@ 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.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) +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.2]) +LT_PREREQ([2.4.2]) LT_INIT([disable-static win32-dll]) #shared library versioning @@ -168,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 @@ -203,7 +207,7 @@ AS_CASE([$ENABLED_FIPS], FIPS_VERSION="v1" ], [ - AC_MSG_ERROR([Invalid value for --enable-fips \"$ENABLED_FIPS\" (allowed: ready, rand, v1, v2)]) + AC_MSG_ERROR([Invalid value for --enable-fips "$ENABLED_FIPS" (allowed: ready, rand, v1, v2)]) ]) AS_CASE([$FIPS_VERSION], @@ -320,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], @@ -449,6 +458,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) @@ -540,12 +555,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 @@ -933,16 +954,12 @@ 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 @@ -1279,6 +1296,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" && @@ -1419,6 +1441,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)])], @@ -2207,6 +2246,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], @@ -2749,6 +2818,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" @@ -4200,6 +4275,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" @@ -4628,6 +4704,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 @@ -4921,6 +5002,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 @@ -4975,6 +5057,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 @@ -5050,6 +5141,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;; @@ -5093,6 +5188,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" @@ -5106,11 +5205,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 @@ -5225,11 +5319,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]) @@ -5564,7 +5653,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 @@ -5887,6 +5976,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"], @@ -6134,6 +6233,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"]) @@ -6209,6 +6310,7 @@ 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"]) @@ -6459,6 +6561,8 @@ 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" @@ -6556,6 +6660,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/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/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index f130f28d1..aa593058f 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. * 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 729aacdee..2d71522e8 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. * @@ -949,7 +949,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 */ @@ -1120,8 +1120,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, }, @@ -1294,8 +1301,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, }, @@ -1465,9 +1483,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) @@ -1601,6 +1625,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]; @@ -1686,7 +1715,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) while ((ch = mygetopt(argc, argv, "?:" "ab:c:defgh:i;jk:l:mnop:q:rstuv:wxyz" "A:B:CDE:F:GH:IJKL:M:NO:PQRS:TUVW:XYZ:" - "01:23:4568" + "01:23:45689" "@#")) != -1) { switch (ch) { case '?' : @@ -2162,7 +2191,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 @@ -2584,7 +2619,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) { @@ -2608,7 +2643,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) { @@ -2622,6 +2657,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) { @@ -2669,6 +2727,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) { @@ -2692,7 +2755,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #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"); 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 d00458d00..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. * 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..88866b18e 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. * 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..d50f84847 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. * 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/server.c b/examples/server/server.c index 00e17e80e..ae5fe4eab 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. * @@ -582,7 +582,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 +705,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 +848,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,9 +986,15 @@ 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) @@ -1126,6 +1152,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 */ @@ -1191,8 +1222,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) while ((ch = mygetopt(argc, argv, "?:" "abc:defgijk:l:mnop:q:rstuv: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) { @@ -1620,7 +1651,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 @@ -2011,7 +2048,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 +2085,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 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/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..6ca547087 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. * 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..46d511a1c 100755 --- a/scripts/crl-revoked.test +++ b/scripts/crl-revoked.test @@ -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/tls13.test b/scripts/tls13.test index 70f007265..2c9c6c4ce 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 diff --git a/src/bio.c b/src/bio.c index 17541ea2d..6509efcd2 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. * @@ -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; } @@ -250,6 +251,10 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } #endif + if (bio->type == WOLFSSL_BIO_SOCKET) { + ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); + } + /* case where front of list is done */ if (bio == front) { break; /* at front of list so be done */ @@ -606,6 +611,8 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) else { ret = wolfSSL_BIO_SSL_write(bio, data, len, front); } + /* Rest of chain is taken care of inside call */ + break; } if (bio->type == WOLFSSL_BIO_MD) { @@ -615,6 +622,10 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) } #endif /* WOLFCRYPT_ONLY */ + if (bio->type == WOLFSSL_BIO_SOCKET) { + ret = wolfIO_Send(bio->num, (char*)data, len, 0); + } + /* advance to the next bio in list */ bio = bio->next; } @@ -944,6 +955,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) { diff --git a/src/crl.c b/src/crl.c index 1663b347a..148ea5796 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; @@ -911,7 +930,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 +942,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 +952,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 +970,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 +999,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 +1064,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 +1074,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 +1086,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 +1107,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 +1162,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 274a14cf5..6ba2370c6 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) @@ -1781,7 +1785,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,7 +1809,9 @@ 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), @@ -1809,6 +1820,21 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) 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 @@ -1960,6 +1986,17 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) 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 @@ -3577,6 +3614,8 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif + default: + break; } (void)hashAlgo; (void)output; @@ -3611,6 +3650,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 */ @@ -3657,6 +3698,8 @@ static int TypeHash(int hashAlgo) case sha_mac: return SHAh; #endif + default: + break; } return 0; @@ -6352,7 +6395,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); } @@ -6438,9 +6483,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 @@ -8580,6 +8630,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: @@ -8836,62 +8891,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 */ @@ -10534,6 +10588,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) @@ -10955,7 +11201,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); } @@ -11060,6 +11307,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; @@ -11253,6 +11525,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; @@ -13764,14 +14061,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 */ @@ -13810,7 +14127,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]; @@ -13918,6 +14235,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; @@ -13935,6 +14253,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); @@ -13964,7 +14293,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]; @@ -14009,7 +14338,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; } @@ -14342,6 +14671,9 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 #endif /* BUILD_AESGCM || HAVE_AESCCM */ break; } + + default: + break; } /* Reset state */ @@ -14631,6 +14963,9 @@ static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* BUILD_AESGCM || HAVE_AESCCM */ break; } + + default: + break; } /* Reset state */ @@ -15361,7 +15696,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 */ } @@ -15389,6 +15724,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"); @@ -15557,7 +15893,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 - @@ -15876,6 +16212,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"); @@ -15902,7 +16244,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 } @@ -16840,8 +17182,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 @@ -16905,6 +17248,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: @@ -19949,7 +20295,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)); @@ -21684,6 +22030,7 @@ exit_dpk: case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID; #endif /* !NO_ECC_SECP */ #endif + default: break; } return ret; @@ -21736,7 +22083,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) { @@ -26524,6 +26871,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; } @@ -26543,7 +26892,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; @@ -26566,7 +26915,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); } @@ -26740,10 +27090,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 */ @@ -26864,6 +27218,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; } @@ -26898,11 +27254,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 */ @@ -27049,6 +27409,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 */ @@ -28225,8 +28587,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, @@ -28728,6 +29090,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: { @@ -29754,10 +30117,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 @@ -31280,6 +31649,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 07eefb731..5c263371f 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. * @@ -624,28 +624,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; - 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; + + 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); diff --git a/src/sniffer.c b/src/sniffer.c index 3411bc7c5..372e07c59 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. * @@ -5517,7 +5517,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 aaa7d113b..0b89b0d60 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[] = { @@ -4520,13 +4528,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"); @@ -4536,6 +4547,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)); @@ -4572,6 +4584,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); @@ -4619,6 +4632,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; } } @@ -4927,9 +4941,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 @@ -4944,8 +4974,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; @@ -4953,6 +4982,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; @@ -5537,8 +5571,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 */ @@ -5704,21 +5741,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) @@ -6238,7 +6263,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) @@ -6920,8 +6945,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); } @@ -7463,7 +7490,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"); @@ -7496,36 +7523,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); @@ -8118,35 +8160,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; + if (ret == 0 && ret != CRYPTOCB_UNAVAILABLE) + 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; + if (ret == 0 && ret != CRYPTOCB_UNAVAILABLE) + 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); @@ -11294,8 +11349,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) @@ -12205,10 +12262,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); @@ -13321,7 +13389,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; @@ -13345,6 +13413,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); @@ -13446,7 +13516,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 */ @@ -13469,6 +13539,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); @@ -15140,37 +15212,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; } @@ -15798,6 +15860,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*/ } @@ -16053,6 +16117,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) { @@ -16063,6 +16142,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; } @@ -16284,6 +16365,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 */ @@ -17772,24 +17857,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 */ @@ -22384,6 +22507,8 @@ static const char* wolfssl_ffdhe_name(word16 group) case WOLFSSL_FFDHE_8192: str = "FFDHE_8192"; break; + default: + break; } return str; } @@ -23086,6 +23211,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 @@ -24666,15 +24806,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); @@ -24744,12 +24884,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 } @@ -24767,35 +24907,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; } @@ -24803,13 +25093,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; } @@ -25664,7 +25954,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; @@ -25690,6 +25990,17 @@ 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); } @@ -26103,6 +26414,99 @@ 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 */ @@ -29855,6 +30259,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 @@ -30065,8 +30508,9 @@ 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; } @@ -31414,33 +31858,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(); } @@ -31744,48 +32196,75 @@ 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; +#ifdef HAVE_GLOBAL_RNG + int used_global = 0; +#endif 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; + /* 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"); @@ -31795,41 +32274,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; @@ -41226,6 +41715,193 @@ static int ConvertNIDToWolfSSL(int nid) } } +#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 @@ -42036,7 +42712,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; @@ -42331,6 +43008,8 @@ err: } XFREE(pem, 0, DYNAMIC_TYPE_PEM); + if (der) + FreeDer(&der); return WOLFSSL_SUCCESS; err: if (pem) @@ -45682,19 +46361,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; @@ -45805,7 +46471,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"); @@ -46338,7 +47003,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) @@ -50328,7 +50993,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; } @@ -50360,7 +51032,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"); @@ -51787,9 +52485,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){ @@ -51803,15 +52498,13 @@ 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) + 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; @@ -51821,7 +52514,8 @@ 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) + return NULL; } return s; @@ -53746,61 +54440,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; 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; } diff --git a/src/tls.c b/src/tls.c index 33e0fbaf6..8859a94b4 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 */ @@ -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; @@ -5247,7 +5274,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 +5425,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 +5591,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 +5605,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 +5876,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 +6098,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 +6242,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 +6324,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 +6373,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 +6454,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 +6504,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 +6551,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 +6599,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 +6637,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 @@ -6715,9 +6744,8 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) } /* Set key */ - ret = wc_DhSetKey(dhKey, - (byte*)params->p, params->p_len, - (byte*)params->g, params->g_len); + ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, + params->g_len); if (ret != 0) goto end; @@ -7150,7 +7178,7 @@ static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) if (!isRequest && current->key == NULL) continue; - len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen; + len += (word16)(KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen); } return len; @@ -7268,7 +7296,7 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) } /* Set key */ - ret = wc_DhSetKey(dhKey, (byte*)params->p, params->p_len, (byte*)params->g, + ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, params->g_len); if (ret != 0) { wc_FreeDhKey(dhKey); @@ -7309,7 +7337,7 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ssl->arrays->preMasterSz = params->p_len; } - ssl->options.dhKeySz = params->p_len; + ssl->options.dhKeySz = (word16)params->p_len; wc_FreeDhKey(dhKey); #ifdef WOLFSSL_SMALL_STACK @@ -7643,8 +7671,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 +7781,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 +7812,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; @@ -8349,7 +8378,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 +8411,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 +8443,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 +8537,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 +8562,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 +8617,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 +8683,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 +8750,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 +8861,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 +8869,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 +8887,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 +9020,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,7 +9129,7 @@ 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) { @@ -9333,6 +9362,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); @@ -9459,7 +9491,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 @@ -9485,6 +9517,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 */ @@ -9642,7 +9676,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 @@ -9675,6 +9709,8 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, output + offset, msgType); break; #endif + default: + break; } /* writes extension data length. */ @@ -10019,6 +10055,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 && @@ -10065,6 +10102,7 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) return ret; } #endif +#endif (void)ssl; (void)extensions; @@ -10884,6 +10922,9 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset break; #endif #endif + + default: + break; } offset += OPAQUE16_LEN; /* extensions length */ @@ -10928,8 +10969,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; @@ -10972,7 +11013,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; diff --git a/src/tls13.c b/src/tls13.c index 16b449f91..2fd6e18ba 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. * @@ -84,6 +84,11 @@ #include #endif +#if defined(__MACH__) || defined(__FreeBSD__) +#include +#endif /* __MACH__ || __FreeBSD__ */ + + #include #include #include @@ -174,6 +179,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 +393,35 @@ 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: break; - #endif } if (ret != 0) return ret; @@ -1071,6 +1082,8 @@ 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; @@ -1195,6 +1208,9 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) goto end; } break; + + default: + break; } if (!store) @@ -1470,6 +1486,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 @@ -1719,8 +1742,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 +1967,9 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, break; } + + default: + break; } /* Reset state */ @@ -1996,8 +2022,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; } @@ -2227,6 +2253,9 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, break; } + + default: + break; } #ifndef WOLFSSL_EARLY_DATA @@ -2396,6 +2425,9 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } break; } + + default: + break; } exit_buildmsg: @@ -3068,8 +3100,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, 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 + i, totalExtSz, *extMsgType, + &foundVersion))) { return ret; } if (!foundVersion) { @@ -3085,8 +3117,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Parse and handle extensions. */ - ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType, - NULL); + ret = TLSX_Parse(ssl, input + i, totalExtSz, *extMsgType, NULL); if (ret != 0) return ret; @@ -3246,9 +3277,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; @@ -3352,8 +3384,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 +3432,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); @@ -3679,7 +3711,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); if (ext == NULL) return MISSING_HANDSHAKE_DATA; - modes = ext->val; + modes = (word16)ext->val; #ifdef HAVE_SUPPORTED_CURVES ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); @@ -3946,8 +3978,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; } } @@ -4120,7 +4152,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return ret; /* Parse extensions */ - if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, + if ((ret = TLSX_Parse(ssl, input + i, totalExtSz, client_hello, &clSuites))) { return ret; } @@ -4180,6 +4212,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (!usingPSK) { + /* Not using PSK so don't require no KE. */ + ssl->options.noPskDheKe = 0; + #ifndef NO_CERTS if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { WOLFSSL_MSG("Client did not send a KeyShare extension"); @@ -4584,6 +4619,8 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[1] = hashAlgo; break; #endif + default: + break; } } @@ -4665,6 +4702,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 +4884,8 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) hashSz = WC_SHA512_DIGEST_SIZE; break; #endif + default: + break; } if (ret != 0) @@ -5989,11 +6030,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) */ @@ -8137,7 +8180,7 @@ int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) 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; @@ -8172,7 +8215,7 @@ int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) 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; diff --git a/src/wolfio.c b/src/wolfio.c index 27b335c66..cff63d3e2 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. * @@ -133,31 +133,46 @@ 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; + if (wolfSSL_BIO_supports_pending(ssl->biord) && + 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 (ssl->biord->type == WOLFSSL_BIO_SOCKET) { + int err; - 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; + 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"); + + err = wolfSSL_LastError(recvd); + 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; } - break; + } - 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 +201,32 @@ 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; - } - 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) { + sent = wolfSSL_BIO_write(ssl->biowr, buf, sz); + if (sent < 0) { + if (ssl->biowr->type == WOLFSSL_BIO_SOCKET) { + int err = wolfSSL_LastError(sent); + 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; } - break; - - default: - WOLFSSL_MSG("This BIO type is unknown / unsupported"); - return WOLFSSL_CBIO_ERR_GENERAL; + } + return WOLFSSL_CBIO_ERR_GENERAL; } (void)ctx; @@ -235,7 +255,12 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) int err = wolfSSL_LastError(recvd); WOLFSSL_MSG("Embed Receive error"); - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { +#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; } @@ -286,7 +311,12 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) int err = wolfSSL_LastError(sent); WOLFSSL_MSG("Embed Send error"); - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { +#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_WRITE; } @@ -2253,7 +2283,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 05f2214f1..75a6a2c6e 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. * @@ -307,6 +307,7 @@ #include #include #include + #include #ifdef OPENSSL_ALL #include #include @@ -422,7 +423,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 +477,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 +959,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); @@ -2495,7 +2504,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(); @@ -11606,6 +11615,208 @@ 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); + +#endif + return ret; + +} /* END test_wc_AesGcmStream */ /* @@ -14769,7 +14980,7 @@ static int test_wc_CheckProbablePrime (void) ret = 0; } } - + /* Good case */ if (ret == 0) { ret = wc_CheckProbablePrime(p, pSz, q, qSz, e, eSz, @@ -14912,7 +15123,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); @@ -14949,8 +15160,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, @@ -14982,8 +15193,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()"); @@ -15006,7 +15217,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); @@ -22285,7 +22496,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; } } @@ -27757,7 +27968,272 @@ 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); + } + + X509_STORE_free(str); + +#endif + + + printf(resultFmt, passed); +#endif +} static void test_wolfSSL_X509_STORE_CTX_get0_current_issuer(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) @@ -28054,7 +28530,7 @@ static void test_wolfSSL_CTX_get0_set1_param(void) 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 @@ -28077,15 +28553,15 @@ static void test_wolfSSL_CTX_get0_set1_param(void) ret = SSL_CTX_set1_param(ctx, pvpm); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(pParam->hostName, testhostName, + AssertIntEQ(0, XSTRNCMP(pParam->hostName, testhostName, (int)XSTRLEN(testhostName))); AssertIntEQ(0x01, pParam->hostFlags); AssertIntEQ(0, XSTRNCMP(pParam->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); - + SSL_CTX_free(ctx); XFREE(pvpm, NULL, DYNAMIC_TYPE_OPENSSL); - + printf(resultFmt, passed); #endif /* OPENSSL_EXTRA && !defined(NO_RSA)*/ } @@ -28450,7 +28926,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; @@ -28690,7 +29167,7 @@ static int msgCb(SSL_CTX *ctx, SSL *ssl) { (void) ctx; (void) ssl; - #ifdef OPENSSL_ALL + #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) STACK_OF(X509)* sk; X509* x509; int i, num; @@ -28702,7 +29179,7 @@ static int msgCb(SSL_CTX *ctx, SSL *ssl) AssertIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 2); #endif - #ifdef OPENSSL_ALL + #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); @@ -29724,6 +30201,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) && \ @@ -29961,7 +30634,7 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) 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()"); paramTo = wolfSSL_X509_VERIFY_PARAM_new(); @@ -29975,9 +30648,9 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) ret = wolfSSL_X509_VERIFY_PARAM_set1_host(paramFrom, testhostName1, (int)XSTRLEN(testhostName1)); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(paramFrom->hostName, testhostName1, + AssertIntEQ(0, XSTRNCMP(paramFrom->hostName, testhostName1, (int)XSTRLEN(testhostName1))); - + wolfSSL_X509_VERIFY_PARAM_set_hostflags(NULL, 0x00); wolfSSL_X509_VERIFY_PARAM_set_hostflags(paramFrom, 0x01); @@ -30010,7 +30683,7 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) /* inherit flags test : VPARAM_DEFAULT */ ret = wolfSSL_X509_VERIFY_PARAM_set1(paramTo, paramFrom); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, (int)XSTRLEN(testhostName1))); AssertIntEQ(0x01, paramTo->hostFlags); AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); @@ -30020,12 +30693,12 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) (int)XSTRLEN(testhostName2)); wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4); wolfSSL_X509_VERIFY_PARAM_set_hostflags(paramTo, 0x00); - + paramTo->inherit_flags = WOLFSSL_VPARAM_OVERWRITE; ret = wolfSSL_X509_VERIFY_PARAM_set1(paramTo, paramFrom); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, (int)XSTRLEN(testhostName1))); AssertIntEQ(0x01, paramTo->hostFlags); AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); @@ -30035,12 +30708,12 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) (int)XSTRLEN(testhostName2)); wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4); wolfSSL_X509_VERIFY_PARAM_set_hostflags(paramTo, 0x10); - + paramTo->inherit_flags = WOLFSSL_VPARAM_RESET_FLAGS; ret = wolfSSL_X509_VERIFY_PARAM_set1(paramTo, paramFrom); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, (int)XSTRLEN(testhostName1))); AssertIntEQ(0x01, paramTo->hostFlags); AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); @@ -30050,12 +30723,12 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) (int)XSTRLEN(testhostName2)); wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4); wolfSSL_X509_VERIFY_PARAM_set_hostflags(paramTo, 0x00); - + paramTo->inherit_flags = WOLFSSL_VPARAM_LOCKED; ret = wolfSSL_X509_VERIFY_PARAM_set1(paramTo, paramFrom); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName2, + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName2, (int)XSTRLEN(testhostName2))); AssertIntEQ(0x00, paramTo->hostFlags); AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); @@ -30176,20 +30849,139 @@ 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) + WOLFSSL_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()"); + + AssertIntNE(wolfSSL_RAND_status(), 5432); + AssertIntEQ(*was_cleanup_called, 0); + wolfSSL_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(wolfSSL_RAND_set_rand_method(&rand_methods), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_RAND_seed(buf, num), 123); + AssertIntEQ(wolfSSL_RAND_bytes(buf, num), 456); + AssertIntEQ(wolfSSL_RAND_pseudo_bytes(buf, num), 9876); + AssertIntEQ(wolfSSL_RAND_status(), 5432); + + AssertIntEQ(*was_add_called, 0); + /* The function pointer for RAND_add returns int, but RAND_add itself returns void. */ + wolfSSL_RAND_add(buf, num, entropy); + AssertIntEQ(*was_add_called, 1); + was_add_called = 0; + AssertIntEQ(*was_cleanup_called, 0); + wolfSSL_RAND_Cleanup(); + AssertIntEQ(*was_cleanup_called, 1); + *was_cleanup_called = 0; + + + AssertIntEQ(wolfSSL_RAND_set_rand_method(NULL), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_RAND_status(), 5432); + AssertIntEQ(*was_cleanup_called, 0); + wolfSSL_RAND_Cleanup(); + AssertIntEQ(*was_cleanup_called, 0); + + 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; - + my_buf = (byte*)XMALLOC(max_bufsize * sizeof(byte), NULL, DYNAMIC_TYPE_TMP_BUFFER); AssertNotNull(my_buf); @@ -30198,7 +30990,7 @@ static void test_wolfSSL_RAND_bytes(void) AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size2), 1); AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size3), 1); AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size4), 1); - + XFREE(my_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf(resultFmt, passed); @@ -30579,15 +31371,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'); @@ -31588,6 +32380,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) + 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) @@ -32801,7 +33662,7 @@ 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); AssertNotNull(SHA(in, XSTRLEN((char*)in), out)); @@ -33021,26 +33882,26 @@ static void test_wolfSSL_MD5(void) byte input1[] = ""; byte input2[] = "message digest"; byte hash[WC_MD5_DIGEST_SIZE]; - unsigned char output1[] = + 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)); - + /* Init MD5 CTX */ AssertIntEQ(wolfSSL_MD5_Init(&md5), 1); - AssertIntEQ(wolfSSL_MD5_Update(&md5, input1, + 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, + 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); @@ -33064,18 +33925,18 @@ static void test_wolfSSL_MD5_Transform(void) byte input2[] = "abc"; byte local[WC_MD5_BLOCK_SIZE]; word32 sLen = 0; - unsigned char output1[] = + 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"; WOLFSSL_MD5_CTX md5; - + printf(testingFmt, "wolfSSL_MD5_Transform()"); - + XMEMSET(&md5, 0, sizeof(md5)); XMEMSET(&local, 0, sizeof(local)); - + /* sanity check */ AssertIntEQ(wolfSSL_MD5_Transform(NULL, NULL), 0); AssertIntEQ(wolfSSL_MD5_Transform(NULL, (const byte*)&input1), 0); @@ -33083,24 +33944,24 @@ static void test_wolfSSL_MD5_Transform(void) 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(wolfSSL_MD5_Transform(&md5, (const byte*)&local[0]), 1); - - AssertIntEQ(XMEMCMP(&((wc_Md5*)&md5)->digest[0], output1, + + AssertIntEQ(XMEMCMP(&((wc_Md5*)&md5)->digest[0], output1, WC_MD5_DIGEST_SIZE), 0); - + /* Init MD5 CTX */ AssertIntEQ(wolfSSL_MD5_Init(&md5), 1); sLen = (word32)XSTRLEN((char*)input2); XMEMSET(local, 0, WC_MD5_BLOCK_SIZE); XMEMCPY(local, input2, sLen); AssertIntEQ(wolfSSL_MD5_Transform(&md5, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Md5*)&md5)->digest[0], output2, + AssertIntEQ(XMEMCMP(&((wc_Md5*)&md5)->digest[0], output2, WC_MD5_DIGEST_SIZE), 0); printf(resultFmt, passed); @@ -33139,7 +34000,7 @@ static void test_wolfSSL_SHA_Transform(void) byte input2[] = "abc"; byte local[WC_SHA_BLOCK_SIZE]; word32 sLen = 0; - unsigned char output1[] = + 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[] = @@ -33147,12 +34008,12 @@ static void test_wolfSSL_SHA_Transform(void) "\xb8\x08\x6e\x7c"; WOLFSSL_SHA_CTX sha; - + printf(testingFmt, "wolfSSL_SHA_Transform()"); - + XMEMSET(&sha, 0, sizeof(sha)); XMEMSET(&local, 0, sizeof(local)); - + /* sanity check */ AssertIntEQ(wolfSSL_SHA_Transform(NULL, NULL), 0); AssertIntEQ(wolfSSL_SHA_Transform(NULL, (const byte*)&input1), 0); @@ -33160,25 +34021,25 @@ static void test_wolfSSL_SHA_Transform(void) 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(wolfSSL_SHA_Init(&sha), 1); /* Do Transform*/ sLen = (word32)XSTRLEN((char*)input1); XMEMCPY(local, input1, sLen); AssertIntEQ(wolfSSL_SHA_Transform(&sha, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha)->digest[0], output1, + AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha)->digest[0], output1, WC_SHA_DIGEST_SIZE), 0); - + /* Init SHA256 CTX */ AssertIntEQ(wolfSSL_SHA_Init(&sha), 1); sLen = (word32)XSTRLEN((char*)input2); XMEMSET(local, 0, WC_SHA_BLOCK_SIZE); XMEMCPY(local, input2, sLen); AssertIntEQ(wolfSSL_SHA_Transform(&sha, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha)->digest[0], output2, + AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha)->digest[0], output2, WC_SHA_DIGEST_SIZE), 0); - + printf(resultFmt, passed); #endif #endif @@ -33193,20 +34054,20 @@ static void test_wolfSSL_SHA256_Transform(void) byte input2[] = "abc"; byte local[WC_SHA256_BLOCK_SIZE]; word32 sLen = 0; - unsigned char output1[] = + 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"; - + WOLFSSL_SHA256_CTX sha256; - + printf(testingFmt, "wolfSSL_SHA256_Transform()"); - + XMEMSET(&sha256, 0, sizeof(sha256)); XMEMSET(&local, 0, sizeof(local)); - + /* sanity check */ AssertIntEQ(wolfSSL_SHA256_Transform(NULL, NULL), 0); AssertIntEQ(wolfSSL_SHA256_Transform(NULL, (const byte*)&input1), 0); @@ -33214,25 +34075,25 @@ static void test_wolfSSL_SHA256_Transform(void) 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(wolfSSL_SHA256_Init(&sha256), 1); /* Do Transform*/ sLen = (word32)XSTRLEN((char*)input1); XMEMCPY(local, input1, sLen); AssertIntEQ(wolfSSL_SHA256_Transform(&sha256, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Sha256*)&sha256)->digest[0], output1, + AssertIntEQ(XMEMCMP(&((wc_Sha256*)&sha256)->digest[0], output1, WC_SHA256_DIGEST_SIZE), 0); - + /* Init SHA256 CTX */ AssertIntEQ(wolfSSL_SHA256_Init(&sha256), 1); sLen = (word32)XSTRLEN((char*)input2); XMEMSET(local, 0, WC_SHA256_BLOCK_SIZE); XMEMCPY(local, input2, sLen); AssertIntEQ(wolfSSL_SHA256_Transform(&sha256, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Sha256*)&sha256)->digest[0], output2, + AssertIntEQ(XMEMCMP(&((wc_Sha256*)&sha256)->digest[0], output2, WC_SHA256_DIGEST_SIZE), 0); - + printf(resultFmt, passed); #endif #endif @@ -33271,7 +34132,7 @@ static void test_wolfSSL_SHA512_Transform(void) byte input2[] = "abc"; byte local[WC_SHA512_BLOCK_SIZE]; word32 sLen = 0; - unsigned char output1[] = + 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" @@ -33281,14 +34142,14 @@ static void test_wolfSSL_SHA512_Transform(void) "\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"; - + WOLFSSL_SHA512_CTX sha512; - + printf(testingFmt, "wolfSSL_SHA512_Transform()"); - + XMEMSET(&sha512, 0, sizeof(sha512)); XMEMSET(&local, 0, sizeof(local)); - + /* sanity check */ AssertIntEQ(wolfSSL_SHA512_Transform(NULL, NULL), 0); AssertIntEQ(wolfSSL_SHA512_Transform(NULL, (const byte*)&input1), 0); @@ -33296,7 +34157,7 @@ static void test_wolfSSL_SHA512_Transform(void) 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); @@ -33304,16 +34165,16 @@ static void test_wolfSSL_SHA512_Transform(void) sLen = (word32)XSTRLEN((char*)input1); XMEMCPY(local, input1, sLen); AssertIntEQ(wolfSSL_SHA512_Transform(&sha512, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Sha512*)&sha512)->digest[0], output1, + AssertIntEQ(XMEMCMP(&((wc_Sha512*)&sha512)->digest[0], output1, WC_SHA512_DIGEST_SIZE), 0); - + /* Init SHA512 CTX */ AssertIntEQ(wolfSSL_SHA512_Init(&sha512), 1); sLen = (word32)XSTRLEN((char*)input2); XMEMSET(local, 0, WC_SHA512_BLOCK_SIZE); XMEMCPY(local, input2, sLen); AssertIntEQ(wolfSSL_SHA512_Transform(&sha512, (const byte*)&local[0]), 1); - AssertIntEQ(XMEMCMP(&((wc_Sha512*)&sha512)->digest[0], output2, + AssertIntEQ(XMEMCMP(&((wc_Sha512*)&sha512)->digest[0], output2, WC_SHA512_DIGEST_SIZE), 0); (void)input1; printf(resultFmt, passed); @@ -33836,7 +34697,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; @@ -34023,6 +34884,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 } @@ -34237,7 +35128,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)) @@ -34299,7 +35190,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)) @@ -35412,7 +36303,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 @@ -35490,7 +36381,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[] = { @@ -35702,7 +36593,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); @@ -36322,7 +37213,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; @@ -36340,7 +37231,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) @@ -36387,7 +37278,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; @@ -36435,7 +37326,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; @@ -36454,7 +37345,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); @@ -36490,7 +37381,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; @@ -36498,7 +37389,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); @@ -36507,9 +37398,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; @@ -36539,7 +37430,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; @@ -36568,7 +37459,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; @@ -36677,7 +37568,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) { @@ -39103,11 +39994,11 @@ static void test_wolfSSL_X509_load_crl_file(void) WOLFSSL_X509_STORE* store; WOLFSSL_X509_LOOKUP* lookup; - printf(testingFmt, "wolfSSL_X509_laod_crl_file"); + printf(testingFmt, "wolfSSL_X509_load_crl_file"); AssertNotNull(store = wolfSSL_X509_STORE_new()); AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); - + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", X509_FILETYPE_PEM), 1); AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/server-revoked-cert.pem", @@ -39119,12 +40010,12 @@ static void test_wolfSSL_X509_load_crl_file(void) AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), 1); } - + for (i = 0; pem[i][0] != '\0'; i++) { AssertIntEQ(wolfSSL_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", @@ -39133,10 +40024,10 @@ static void test_wolfSSL_X509_load_crl_file(void) /* once feeing store */ wolfSSL_X509_STORE_free(store); store = NULL; - + AssertNotNull(store = wolfSSL_X509_STORE_new()); AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); - + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", X509_FILETYPE_PEM), 1); AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/server-revoked-cert.pem", @@ -39148,21 +40039,21 @@ static void test_wolfSSL_X509_load_crl_file(void) AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), 1); } - + for (i = 0; der[i][0] != '\0'; i++) { AssertIntEQ(wolfSSL_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); } - + wolfSSL_X509_STORE_free(store); store = NULL; - + printf(resultFmt, passed); #endif } @@ -39445,15 +40336,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"); @@ -39461,25 +40356,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); @@ -39487,16 +40394,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); @@ -39505,16 +40419,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); @@ -39527,23 +40448,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 */ + 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]; 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}; @@ -39558,7 +40480,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)); @@ -39566,7 +40489,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)); @@ -39576,7 +40499,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); } @@ -39688,7 +40611,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); @@ -39741,7 +40664,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; @@ -39767,7 +40690,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; @@ -39865,7 +40788,7 @@ ASN1_SEQUENCE(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) @@ -39923,7 +40846,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; @@ -40059,13 +40982,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 @@ -40086,14 +41009,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); @@ -40103,7 +41028,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) && \ @@ -40122,7 +41047,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; @@ -40255,7 +41180,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) @@ -40440,7 +41365,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; @@ -40545,7 +41470,7 @@ static void test_ENGINE_cleanup(void) #endif /* OPENSSL_EXTRA */ } -static void test_wolfSSL_CTX_LoadCRL() +static void test_wolfSSL_CTX_LoadCRL(void) { #ifdef HAVE_CRL WOLFSSL_CTX* ctx = NULL; @@ -41227,6 +42152,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(); @@ -41246,6 +42174,7 @@ void ApiTest(void) 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(); @@ -41262,6 +42191,7 @@ void ApiTest(void) 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_pseudo_rand(); test_wolfSSL_PKCS8_Compat(); @@ -41288,6 +42218,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 @@ -41347,9 +42278,9 @@ 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(); @@ -41599,6 +42530,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); 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/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 7828b273b..2e1a09f65 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. * 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..c86124b6d 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. * diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index d390b5483..1091d3f48 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. * diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index b9e919dee..71f451007 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. * @@ -108,6 +108,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 +184,12 @@ #ifdef HAVE_ED448 #include #endif +#ifdef WOLFCRYPT_HAVE_ECCSI + #include +#endif +#ifdef WOLFCRYPT_HAVE_SAKKE + #include +#endif #include #ifdef HAVE_NTRU @@ -289,6 +309,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 +346,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 +401,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 +456,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 +489,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 +537,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 +640,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 +792,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 +1954,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 +2394,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 +2446,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 +4677,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 +5462,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 +5493,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 +5526,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 +5550,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 +5566,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 +5578,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], @@ -6029,6 +6150,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; + + 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; + + 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; + + 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; + wc_GenerateSakkeRskTable(&genKey, rsk, NULL, &len); + if (len > 0) { + table = (byte*)XMALLOC(len, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + 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) @@ -6378,7 +6915,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 b08a5c69f..4cb300b1b 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) @@ -3645,7 +3648,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) @@ -4048,7 +4052,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 +4171,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 +4368,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. */ @@ -5257,7 +5278,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 +5862,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 +6158,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 +6487,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 +6802,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, @@ -6663,6 +7018,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 +7236,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 +7323,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); @@ -7145,6 +7500,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 +7735,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), sizeof(AES_LASTBLOCK(aes))); +} + +#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 +8933,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 +8973,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 +9165,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 +9262,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 +9738,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 +9828,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 +9875,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 +10451,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 +10470,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 +10481,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 +10502,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 +10564,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 +10572,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 +10605,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 9f847e133..a19529107 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) @@ -908,7 +912,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; } @@ -1761,6 +1765,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(hashSha512hOid); break; #endif + default: + break; } break; @@ -1998,6 +2004,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(blkDes3CbcOid); break; #endif /* !NO_DES3 */ + default: + break; } break; @@ -2012,6 +2020,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = ocspNonceOid; *oidSz = sizeof(ocspNonceOid); break; + default: + break; } break; #endif /* HAVE_OCSP */ @@ -2070,6 +2080,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(ocspNoCheckOid); break; #endif + default: + break; } break; @@ -2080,6 +2092,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAuthKeyOid; *oidSz = sizeof(extAuthKeyOid); break; + default: + break; } #endif break; @@ -2096,6 +2110,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAuthInfoCaIssuerOid; *oidSz = sizeof(extAuthInfoCaIssuerOid); break; + default: + break; } break; @@ -2105,6 +2121,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extCertPolicyAnyOid; *oidSz = sizeof(extCertPolicyAnyOid); break; + default: + break; } break; @@ -2114,6 +2132,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAltNamesHwNameOid; *oidSz = sizeof(extAltNamesHwNameOid); break; + default: + break; } break; @@ -2147,6 +2167,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extExtKeyUsageOcspSignOid; *oidSz = sizeof(extExtKeyUsageOcspSignOid); break; + default: + break; } break; @@ -2156,6 +2178,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = pbkdf2Oid; *oidSz = sizeof(pbkdf2Oid); break; + default: + break; } break; @@ -2184,6 +2208,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = pbes2; *oidSz = sizeof(pbes2); break; + default: + break; } break; @@ -2213,6 +2239,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(wrapPwriKekOid); break; #endif + default: + break; } break; @@ -2248,6 +2276,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid); break; #endif + default: + break; } break; @@ -2278,6 +2308,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(hmacSha512Oid); break; #endif + default: + break; } break; #endif /* !NO_HMAC */ @@ -2289,6 +2321,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = zlibCompress; *oidSz = sizeof(zlibCompress); break; + default: + break; } break; #endif /* HAVE_LIBZ */ @@ -2299,6 +2333,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = dnsSRVOid; *oidSz = sizeof(dnsSRVOid); break; + default: + break; } break; case oidTlsExtType: @@ -2307,6 +2343,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = tlsFeatureOid; *oidSz = sizeof(tlsFeatureOid); break; + default: + break; } break; #endif /* WOLFSSL_APACHE_HTTPD */ @@ -2321,6 +2359,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = attrSerialNumberOid; *oidSz = sizeof(attrSerialNumberOid); break; + default: + break; } break; #endif @@ -3497,8 +3537,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; } @@ -4983,8 +5022,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; @@ -6834,7 +6875,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; @@ -7670,6 +7711,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } /* SIG_STATE_CHECK */ + + default: + break; } /* switch (sigCtx->state) */ exit_cs: @@ -7823,6 +7867,8 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) #endif /* !WOLFSSL_NO_ASN_STRICT */ break; } + default: + break; }; /* switch */ base = base->next; } @@ -7902,6 +7948,8 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) } break; } + default: + break; } /* switch */ base = base->next; } @@ -8090,9 +8138,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; } } @@ -8620,6 +8667,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) @@ -10350,7 +10399,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 && @@ -10530,18 +10580,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; @@ -10810,10 +10861,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; @@ -10886,7 +10937,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); @@ -11001,7 +11052,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); @@ -12117,7 +12168,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; } @@ -12997,11 +13048,11 @@ 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 */ -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 */ @@ -13076,11 +13127,12 @@ int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, case ASN_EMAIL_NAME: { const byte EMAIL_OID[] = { - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16 + 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; } @@ -13121,6 +13173,36 @@ int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, return idx; } +/* 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 + */ +int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr, char nameType, + byte type) +{ + return wc_EncodeName_ex(name, nameStr, nameType, type, 0x0c/* CTC_UTF8 */); +} + +/* 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 + * + * returns length on success + */ +int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, + byte type) +{ + return wc_EncodeName_ex(name, nameStr, nameType, type, ASN_IA5_STRING); +} /* encode CertName into output, return total bytes written */ int SetName(byte* output, word32 outputSz, CertName* name) { @@ -16310,7 +16392,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, #if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) /* build DER formatted ECC key, include optional public key if requested, * return length on success, negative on error */ -static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, +static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, int pubIn) { byte curve[MAX_ALGO_SZ+2]; @@ -16330,7 +16412,7 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0; word32 seqSz, privSz, pubSz = ECC_BUFSIZE; - if (key == NULL || output == NULL || inLen == 0) + if (key == NULL || (output == NULL && inLen == NULL)) return BAD_FUNC_ARG; /* curve */ @@ -16345,6 +16427,14 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, /* private */ privSz = key->dp->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); @@ -16356,7 +16446,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 @@ -16413,7 +16508,15 @@ 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; + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pubIn) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + return LENGTH_ONLY_E; + } + if (inLen != NULL && totalSz > (int)*inLen) { #ifndef WOLFSSL_NO_MALLOC XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); if (pubIn) { @@ -16459,17 +16562,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. @@ -16491,6 +16610,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; @@ -16509,7 +16629,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); diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 1d89fbe78..24f54cfd7 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. * diff --git a/wolfcrypt/src/blake2s.c b/wolfcrypt/src/blake2s.c index 7c74cac15..30ae6c038 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. * 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 8959397b6..822c5e48f 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. * 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..a7d67b2cd 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. * 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..97ead9717 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. * diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 245765c02..c7803c33b 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. * 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 56acf3e15..696da3eb1 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. * @@ -56,9 +56,9 @@ Possible ECC enable options: * 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. + * 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 + * 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 @@ -159,6 +159,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) @@ -1134,6 +1138,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 */ { @@ -1328,7 +1352,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; @@ -2487,8 +2511,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; @@ -2708,8 +2732,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; @@ -2719,6 +2743,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; @@ -2755,12 +2780,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; } @@ -2964,10 +2992,11 @@ 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) @@ -3095,7 +3124,7 @@ 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) @@ -3173,7 +3202,7 @@ 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) { err = mp_sub(modulus, tG->y, &t); @@ -3252,7 +3281,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); @@ -3326,11 +3355,21 @@ void wc_ecc_del_point(ecc_point* p) } +void wc_ecc_forcezero_point(ecc_point* p) +{ + if (p != NULL) { + mp_forcezero(p->x); + mp_forcezero(p->y); + mp_forcezero(p->z); + } +} + + /** Copy the value of a point to an other one 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; @@ -3978,7 +4017,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 @@ -4219,7 +4258,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) { @@ -4730,11 +4769,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; } @@ -4837,7 +4880,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 @@ -5127,8 +5174,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; } @@ -5141,6 +5187,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); @@ -5210,6 +5261,152 @@ 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) + 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 + + /* 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 @@ -5254,15 +5451,14 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #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_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 @@ -5282,19 +5478,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 } @@ -5303,19 +5499,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 } @@ -5395,7 +5591,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) @@ -5404,7 +5600,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 @@ -5492,149 +5687,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 } } @@ -5743,6 +5804,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; @@ -6053,12 +6121,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) { @@ -6081,7 +6148,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; @@ -6520,25 +6587,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 @@ -6554,21 +6620,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 } @@ -6577,21 +6643,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 } @@ -6847,8 +6913,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 @@ -6913,7 +6980,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 */ @@ -7016,7 +7083,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); @@ -7031,7 +7098,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); @@ -7210,6 +7277,22 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) if (key->type == ECC_PRIVATEKEY_ONLY) return ECC_PRIVATEONLY_E; +#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; } @@ -7639,13 +7722,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 @@ -7675,6 +7764,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)) { @@ -7844,7 +7945,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 */ @@ -7942,7 +8043,7 @@ 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); } } @@ -8018,9 +8119,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 } @@ -8056,6 +8179,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); } @@ -8152,6 +8283,35 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, { 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; + } + if (caamWriteToPartition(vaddr, priv, privSz) != 0) + return WC_HW_E; + + key->blackKey = (word32)vaddr; + + 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 @@ -8576,7 +8736,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 +9584,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 +9621,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 +9641,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 +10170,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 +10279,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) diff --git a/wolfcrypt/src/eccsi.c b/wolfcrypt/src/eccsi.c new file mode 100644 index 000000000..555020c35 --- /dev/null +++ b/wolfcrypt/src/eccsi.c @@ -0,0 +1,2225 @@ +/* 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 ((err == 0) && (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. + */ +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) { + mp_copy(ssk, &key->ssk); + 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..a01e0bffd 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. * 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..3680eac86 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,15 @@ 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"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 8f4471e80..ff0569854 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. * @@ -553,6 +553,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 +571,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 +609,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 +663,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 +807,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 +837,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; @@ -4073,10 +4129,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; @@ -4373,14 +4437,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 +4473,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 +4509,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 +4579,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 +4607,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 +4633,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 +5359,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 +5373,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; 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..921210bce 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. * diff --git a/wolfcrypt/src/hc128.c b/wolfcrypt/src/hc128.c index 96f02d16d..000501da9 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. * 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 b2eafb4cc..fbdff4c6f 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; @@ -1449,10 +1449,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; + int i = (int)(b / DIGIT_BIT); /* word index */ + int s = b % DIGIT_BIT; /* bit index */ - return (int)((a->dp[b/DIGIT_BIT] >> b%DIGIT_BIT) & (mp_digit)1); + if (a->used <= i) { + /* no words avaialable 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 */ diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index 5a9908831..447dbcb30 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. * @@ -227,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 e4ffc2f09..22774d54d 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. * @@ -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]; 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..13bcc3aca 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. * diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 10bb8b3cc..824f91aa0 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. * @@ -536,6 +536,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 +544,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; } diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 2e93f4b58..0073e895e 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. * @@ -5077,6 +5077,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 */ @@ -5136,7 +5141,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; } @@ -5155,6 +5160,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 */ @@ -8423,6 +8433,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) { diff --git a/wolfcrypt/src/poly1305.c b/wolfcrypt/src/poly1305.c index 4fde6be95..2c4aa12af 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. * @@ -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..b6ad0e79c 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. * 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..f52fc07ac 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. * diff --git a/wolfcrypt/src/port/arm/armv8-32-curve25519.c b/wolfcrypt/src/port/arm/armv8-32-curve25519.c index c2c73f3c3..607ad913e 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. * diff --git a/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S b/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S index 685f87cc7..23e67fa3d 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. * diff --git a/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c b/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c index 6786d30b0..a52cd75c6 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. * diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index 021ee7963..5f92cbe6f 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. * 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..b05f0a23b 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. * @@ -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__ diff --git a/wolfcrypt/src/port/arm/armv8-curve25519.c b/wolfcrypt/src/port/arm/armv8-curve25519.c index a72ae8fbd..213512297 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. * @@ -35,10 +35,7 @@ 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,15 +7209,11 @@ 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__ */ 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..de65ec2e6 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,10 @@ 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); AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); @@ -658,6 +666,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 +881,10 @@ 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); AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); @@ -1401,6 +1417,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..0236bb8a4 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. * @@ -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 diff --git a/wolfcrypt/src/port/arm/armv8-sha512-asm.c b/wolfcrypt/src/port/arm/armv8-sha512-asm.c index 49dffd778..21679d21e 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. * @@ -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" 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..46c25ae19 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. * 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..29f6d0f6f --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_qnx.c @@ -0,0 +1,1286 @@ +/* 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; +int 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) +{ + 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]] = ctp->rcvid; + 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) +{ + 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] = ctp->rcvid; + 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); + 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); + break; + + case WC_CAAM_FREE_PART: + caamFreePart(args[0]); + + pthread_mutex_lock(&sm_mutex); + sm_ownerId[args[0]] = -1; + 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] == ctp->rcvid) { + sm_ownerId[i] = -1; + 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] = -1; + } + + 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..c8efcae84 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. * diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index dd8a88098..6d601a407 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. * 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..78825bb85 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. * 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..2c23ed48c 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. * 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..ee82f003b 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. * 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..5ca96e6b6 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. * @@ -376,7 +376,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 +387,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 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 bd637173f..bac75203e 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); @@ -366,8 +367,10 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, if (ret == 0) #endif ret = wc_Sha256Update(sha, &ctr, sizeof(ctr)); - if (ret == 0) + 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 +554,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--) { @@ -2322,13 +2327,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; @@ -2336,25 +2342,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 */ 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..a6c18e6f2 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); } @@ -1666,7 +1666,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 +1686,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 +2204,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 +2235,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 +2266,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 @@ -2302,7 +2313,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 +3020,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 +3139,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 +3277,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 +3294,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 +3346,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 @@ -3727,7 +3739,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..789347528 --- /dev/null +++ b/wolfcrypt/src/sakke.c @@ -0,0 +1,6803 @@ +/* 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 ((err == 0) && (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 is montgomery form of b - base */ + if (err == 0) { + 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 = wc_HashGetDigestSize(hashType); + 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 */ + XMEMSET(h, 0, hashSz); + + /* 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 a280704dd..034f3d72d 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) && \ @@ -494,6 +495,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) && \ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 09af0f9bb..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. * @@ -167,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) @@ -175,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)) && \ @@ -395,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; @@ -581,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) @@ -839,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]; @@ -1364,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..dacbc0df6 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. * @@ -554,7 +554,7 @@ static word64 Load64BitBigEndian(const byte* a) return n; #else - return *(word64*)a; + return *(const word64*)a; #endif } @@ -636,30 +636,47 @@ 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) { +#if defined(BIG_ENDIAN_ORDER) + word32 q = (l + 7) / 8; +#endif + word32 k, rate = p * 8; 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) { 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[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); + ByteReverseWords64(sha3->s, sha3->s, (q > p) ? rate : q * 8); #endif - for (i = 0; i < l; i++) - hash[i] = state[i]; - + i = 0; + for (k = 0; k < l; k++) + { + if (i == rate) + { + i = 0; +#if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64(sha3->s, sha3->s, rate); + BlockSha3(sha3->s); + ByteReverseWords64(sha3->s, sha3->s, rate); +#else + BlockSha3(sha3->s); +#endif + } + hash[k] = state[i++]; + } return 0; } @@ -763,7 +780,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; diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index bc576da21..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) @@ -975,7 +976,8 @@ int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data) /* -------------------------------------------------------------------------- */ #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 50c883906..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. * diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index d2f8c8907..ba22e3828 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]; + 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, + 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,61 +36510,48 @@ 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; @@ -36847,8 +36559,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -36858,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) { @@ -36869,38 +36579,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 8, priv); sp_256_from_bin(e, 8, hash, (int)hashLen); - 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); + err = sp_256_calc_s_8(s, r, k, x, e, tmp); + } - /* 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; @@ -36918,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; } @@ -37224,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) @@ -37242,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 { @@ -37262,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; @@ -37278,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); @@ -37336,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) { @@ -37394,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; } @@ -37417,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); } @@ -37551,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) { @@ -37559,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; } @@ -37592,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); @@ -37639,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; @@ -37655,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); @@ -37673,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; } @@ -37689,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)); @@ -37743,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) { @@ -37760,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) { @@ -37773,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; } @@ -37812,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); @@ -37859,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; } @@ -37884,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) { @@ -37923,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; } @@ -37943,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) { @@ -37981,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; } @@ -37999,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 */ @@ -38058,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; @@ -38077,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); @@ -38134,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; @@ -38148,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; @@ -38220,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) * @@ -38624,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" @@ -38695,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" @@ -38709,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" @@ -38746,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" @@ -38774,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" @@ -38795,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" @@ -38846,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" @@ -38881,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" @@ -38930,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" @@ -38974,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" @@ -39016,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" @@ -39079,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" @@ -39130,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" @@ -39179,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" @@ -39242,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" @@ -39259,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" @@ -39286,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" @@ -39328,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" @@ -39377,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" @@ -39394,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" @@ -39414,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" @@ -39449,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" @@ -39470,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" @@ -39501,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" @@ -39514,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" @@ -39542,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" @@ -39556,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" @@ -39580,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" @@ -39607,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. * @@ -39804,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" @@ -39812,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" @@ -39826,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" @@ -39834,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" @@ -39843,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" @@ -39852,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" @@ -39861,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" @@ -39870,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" @@ -39879,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" @@ -39888,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" @@ -39897,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" @@ -39928,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); @@ -39943,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. @@ -40732,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); @@ -40757,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] = { @@ -41046,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; @@ -41082,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. @@ -41244,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. * @@ -41970,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]; @@ -42150,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. @@ -42165,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]; + 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, + 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; @@ -42254,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); @@ -42301,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. * @@ -42333,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; @@ -42414,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. @@ -42499,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. @@ -42531,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) { @@ -42595,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; } @@ -42672,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. @@ -42687,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. */ @@ -42705,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) { @@ -42739,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); @@ -42766,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; } @@ -42782,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 @@ -42799,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) { @@ -42910,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. @@ -42919,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) { @@ -42983,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; } @@ -43060,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. @@ -43075,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. */ @@ -43093,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) { @@ -43127,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); @@ -43154,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; } @@ -43170,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 @@ -43187,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) { @@ -43306,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); @@ -43338,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 }, @@ -43433,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. @@ -43448,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 }, @@ -44732,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. @@ -44757,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); @@ -44788,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; } @@ -44812,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. @@ -44871,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; @@ -44934,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) { @@ -44993,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; } @@ -45015,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; @@ -45056,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) { @@ -45095,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; } @@ -45267,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" @@ -45515,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 */ @@ -45663,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); } } @@ -45672,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 @@ -45712,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; @@ -45731,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); @@ -45765,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; } @@ -45821,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--; @@ -45853,61 +45728,48 @@ 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; @@ -45915,8 +45777,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 12, priv); sp_384_from_bin(e, 12, hash, (int)hashLen); - 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); + err = sp_384_calc_s_12(s, r, k, x, e, tmp); + } - /* 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; @@ -45986,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; } @@ -46335,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) @@ -46353,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 { @@ -46373,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; @@ -46389,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); @@ -46447,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) { @@ -46505,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; } @@ -46528,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); } @@ -46666,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) { @@ -46674,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; } @@ -46707,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); @@ -46754,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; @@ -46770,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); @@ -46788,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; } @@ -46804,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)); @@ -46858,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) { @@ -46875,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) { @@ -46888,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; } @@ -46927,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); @@ -46974,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; } @@ -46999,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) { @@ -47038,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; } @@ -47058,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) { @@ -47096,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; } @@ -47114,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 */ @@ -47210,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; @@ -47229,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); @@ -47286,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]; + 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, + 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 7e29ce1bc..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,61 +38072,48 @@ 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; @@ -37258,8 +38121,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -37269,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) { @@ -37280,38 +38141,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 4, priv); sp_256_from_bin(e, 4, hash, (int)hashLen); - 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); + err = sp_256_calc_s_4(s, r, k, x, e, tmp); + } - /* 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; @@ -37329,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; } @@ -37635,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) @@ -37653,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 { @@ -37673,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; @@ -37689,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); @@ -37747,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) { @@ -37805,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; } @@ -37828,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); } @@ -37958,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) { @@ -37966,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; } @@ -37999,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); @@ -38046,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; @@ -38062,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); @@ -38080,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; } @@ -38096,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)); @@ -38150,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) { @@ -38167,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) { @@ -38180,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; } @@ -38219,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); @@ -38266,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; } @@ -38291,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) { @@ -38330,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; } @@ -38350,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) { @@ -38388,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; } @@ -38406,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 */ @@ -38465,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; @@ -38484,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); @@ -38541,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; @@ -38555,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; @@ -38595,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 */ @@ -38620,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, @@ -38627,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) * @@ -39078,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) * @@ -39683,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. @@ -39690,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); @@ -39715,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] = { @@ -39909,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; @@ -39945,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. @@ -40028,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. * @@ -40391,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; @@ -40695,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]; @@ -40789,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; @@ -40801,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]; @@ -40817,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); @@ -40825,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); } @@ -41188,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. @@ -41314,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. @@ -41323,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) { @@ -41366,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]; @@ -41440,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. @@ -41455,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. */ @@ -41473,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 { @@ -41505,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 @@ -41534,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 @@ -41567,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) { @@ -41675,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. * @@ -41685,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); @@ -41717,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 }, @@ -43011,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. @@ -43025,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. * @@ -43034,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); @@ -43065,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; } @@ -43088,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. @@ -43124,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) { @@ -43198,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) { @@ -43257,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; } @@ -43279,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; @@ -43305,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) { @@ -43344,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; } @@ -43632,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 */ @@ -43780,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); } } @@ -43789,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 @@ -43829,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; @@ -43848,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); @@ -43882,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; } @@ -43938,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--; @@ -43970,61 +63815,48 @@ 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; @@ -44032,8 +63864,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 6, priv); sp_384_from_bin(e, 6, hash, (int)hashLen); - 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); + err = sp_384_calc_s_6(s, r, k, x, e, tmp); + } - /* 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; @@ -44103,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; } @@ -44292,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) @@ -44310,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 { @@ -44330,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; @@ -44346,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); @@ -44404,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) { @@ -44462,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; } @@ -44485,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); } @@ -44617,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) { @@ -44625,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; } @@ -44658,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); @@ -44705,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; @@ -44721,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); @@ -44739,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; } @@ -44755,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)); @@ -44809,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) { @@ -44826,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) { @@ -44839,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; } @@ -44878,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); @@ -44925,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; } @@ -44950,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) { @@ -44989,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; } @@ -45009,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) { @@ -45047,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; } @@ -45065,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 */ @@ -45161,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; @@ -45180,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); @@ -45237,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 42c44ad7c..e35809c90 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]; + 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, + 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,61 +21850,48 @@ 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; @@ -21620,8 +21899,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -21631,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) { @@ -21642,38 +21919,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 8, priv); sp_256_from_bin(e, 8, hash, (int)hashLen); - 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); + err = sp_256_calc_s_8(s, r, k, x, e, tmp); + } - /* 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; @@ -21691,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; } @@ -22286,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) @@ -22304,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 { @@ -22324,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; @@ -22340,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); @@ -22398,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) { @@ -22456,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; } @@ -22479,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); } @@ -22613,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) { @@ -22621,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; } @@ -22654,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); @@ -22701,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; @@ -22717,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); @@ -22735,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; } @@ -22751,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)); @@ -22805,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) { @@ -22822,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) { @@ -22835,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; } @@ -22874,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); @@ -22921,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; } @@ -22946,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) { @@ -22985,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; } @@ -23005,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) { @@ -23043,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; } @@ -23061,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 */ @@ -23120,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; @@ -23139,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); @@ -23196,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; @@ -23210,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; @@ -23282,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. @@ -23712,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. * @@ -23903,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. @@ -24065,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); @@ -24090,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] = { @@ -24239,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; @@ -24275,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. @@ -24431,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. * @@ -25094,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]; @@ -25274,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. @@ -25289,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]; + 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, + 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; @@ -25378,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); @@ -25425,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. * @@ -25457,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; @@ -25538,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. @@ -25623,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. @@ -25655,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) { @@ -25719,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; } @@ -25796,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. @@ -25811,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. */ @@ -25829,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) { @@ -25863,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); @@ -25890,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; } @@ -25906,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 @@ -25923,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) { @@ -26034,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. @@ -26043,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) { @@ -26107,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; } @@ -26184,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. @@ -26199,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. */ @@ -26217,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) { @@ -26251,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); @@ -26278,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; } @@ -26294,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 @@ -26311,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) { @@ -26430,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); @@ -26462,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 }, @@ -26557,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. @@ -26572,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 }, @@ -27856,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. @@ -27881,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); @@ -27912,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; } @@ -27936,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. @@ -27997,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; @@ -28060,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) { @@ -28119,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; } @@ -28141,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; @@ -28182,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) { @@ -28221,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; } @@ -28646,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 */ @@ -28794,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); } } @@ -28803,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 @@ -28843,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; @@ -28862,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); @@ -28896,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; } @@ -28952,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--; @@ -28984,61 +29525,48 @@ 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; @@ -29046,8 +29574,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 12, priv); sp_384_from_bin(e, 12, hash, (int)hashLen); - 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); + err = sp_384_calc_s_12(s, r, k, x, e, tmp); + } - /* 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; @@ -29117,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; } @@ -29919,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) @@ -29937,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 { @@ -29957,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; @@ -29973,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); @@ -30031,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) { @@ -30089,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; } @@ -30112,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); } @@ -30250,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) { @@ -30258,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; } @@ -30291,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); @@ -30338,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; @@ -30354,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); @@ -30372,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; } @@ -30388,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)); @@ -30442,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) { @@ -30459,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) { @@ -30472,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; } @@ -30511,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); @@ -30558,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; } @@ -30583,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) { @@ -30622,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; } @@ -30642,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) { @@ -30680,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; } @@ -30698,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 */ @@ -30794,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; @@ -30813,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); @@ -30870,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]; + 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, + 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 6abd9a64f..934b7d9c5 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,7 +1749,9 @@ 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); @@ -1781,68 +1780,60 @@ 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); @@ -1863,7 +1854,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 +1866,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 +1899,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 +1978,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 +2063,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 +2167,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 +2193,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 +2449,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 +2483,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 +2498,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 +2512,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 +2607,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 +2618,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,7 +2636,9 @@ 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); @@ -2731,68 +2667,60 @@ 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); @@ -2813,7 +2741,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 +2753,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 +2788,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 +2867,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 +2952,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 +3056,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 +3082,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 +3105,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 +3141,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 +3203,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 +3239,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 +3316,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 +3327,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 +3345,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 +3385,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 +3404,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 +3458,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 +3483,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 +3532,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); @@ -3625,17 +3577,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 +3622,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); @@ -3687,16 +3671,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 +3706,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 +3731,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 +3767,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 +3795,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 +3820,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 +3857,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 +3882,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 +3901,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 +3912,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 +4110,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 +4160,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 +4192,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 +4213,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 +4241,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 +4277,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 +4314,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 +4349,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 +4381,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 +4409,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 +4435,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 +4472,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 +4498,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 +4528,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 +4571,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 +4606,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 +4647,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 +4693,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 +4717,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 +4919,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 +4953,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 +5064,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 +5098,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 +5130,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 +5139,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 +5414,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 +5428,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 +5482,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 +5497,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 +5511,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,30 +5616,13 @@ 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); @@ -5643,62 +5651,55 @@ 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); @@ -5719,7 +5720,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 +5729,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 +5762,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 +5841,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 +5926,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 +6030,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 +6056,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 +6336,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 +6370,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 +6385,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 +6399,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 +6498,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 +6509,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,7 +6531,9 @@ 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); @@ -6616,68 +6562,60 @@ 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); @@ -6698,7 +6636,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 +6648,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 +6683,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 +6762,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 +6847,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 +6951,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 +6977,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 +7000,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 +7036,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 +7098,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 +7134,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 +7211,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 +7222,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 +7240,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 +7280,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 +7299,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 +7353,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 +7378,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 +7427,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); @@ -7510,17 +7472,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 +7517,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); @@ -7572,16 +7566,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 +7601,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 +7626,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 +7662,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 +7690,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 +7715,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 +7752,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 +7777,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 +7796,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 +7807,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 +8093,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 +8143,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 +8175,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 +8196,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 +8224,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 +8260,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 +8297,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 +8332,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 +8364,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 +8392,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 +8418,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 +8455,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 +8481,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 +8511,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 +8554,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 +8589,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 +8630,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 +8676,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 +8700,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 +8994,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 +9028,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 +9111,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 +9145,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 +9177,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 +9187,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 +9511,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 +9526,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 +9540,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 +9641,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 +9652,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,7 +9670,9 @@ 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); @@ -9704,68 +9701,60 @@ 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); @@ -9786,7 +9775,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 +9787,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 +9820,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 +9899,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 +9984,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 +10088,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 +10114,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 +10383,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 +10417,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 +10432,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 +10446,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 +10543,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 +10554,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,7 +10574,9 @@ 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); @@ -10671,68 +10605,60 @@ 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); @@ -10753,7 +10679,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 +10691,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 +10726,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 +10805,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 +10890,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 +10994,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 +11020,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 +11043,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 +11079,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 +11141,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 +11177,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 +11254,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 +11265,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 +11283,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 +11323,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 +11342,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 +11396,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 +11421,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 +11470,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); @@ -11565,17 +11515,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 +11560,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); @@ -11627,16 +11609,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 +11644,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 +11669,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 +11705,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 +11733,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 +11758,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 +11795,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 +11820,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 +11839,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 +11850,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 +12260,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 +12310,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 +12342,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 +12363,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 +12391,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 +12427,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 +12464,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 +12499,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 +12608,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 +12618,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 +12779,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 +13331,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 +13345,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 +13421,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 +13435,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 +13460,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 +13544,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 +13581,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 +13633,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. * @@ -13848,13 +13685,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 +14139,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 +14226,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 +14483,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 +14564,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 +14643,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 +14732,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 +14744,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 +14761,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 +14772,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 +15161,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 +15279,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 +15292,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 +15360,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 +15430,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 +15447,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 +15467,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 +15504,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 +15533,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 +15548,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 +15574,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 +15699,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 +15734,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 +15842,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 +17130,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 +17160,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 +17193,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 +17295,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 +17316,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 +17380,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 +17444,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 +17465,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 +17513,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 +17554,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,7 +17620,9 @@ 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); @@ -17478,62 +17675,55 @@ 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); @@ -17554,7 +17744,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 +17753,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 +17783,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 +17929,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 +17939,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 +17949,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 +17959,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 +17970,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 +18061,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 +18080,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 +18111,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 +18170,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,61 +18205,48 @@ 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; @@ -18024,8 +18254,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -18035,7 +18263,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) { @@ -18046,38 +18274,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 10, priv); sp_256_from_bin(e, 10, hash, (int)hashLen); - 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); + err = sp_256_calc_s_10(s, r, k, x, e, tmp); + } - /* 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; @@ -18095,20 +18300,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; } @@ -18158,20 +18367,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) @@ -18179,11 +18386,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); @@ -18261,7 +18466,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 @@ -18270,6 +18475,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) @@ -18288,8 +18585,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 { @@ -18308,8 +18604,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; @@ -18324,7 +18621,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); @@ -18382,57 +18679,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) { @@ -18440,22 +18713,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; } @@ -18463,132 +18737,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); } @@ -18599,7 +18804,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) { @@ -18607,26 +18812,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; } @@ -18640,34 +18845,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); @@ -18687,10 +18884,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; @@ -18703,16 +18899,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); @@ -18721,7 +18924,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; } @@ -18737,47 +18943,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)); @@ -18791,12 +18998,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) { @@ -18808,12 +19014,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) { @@ -18821,22 +19025,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; } @@ -18860,33 +19062,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); @@ -18907,13 +19111,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; } @@ -18932,25 +19135,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) { @@ -18971,12 +19177,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; } @@ -18991,32 +19197,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) { @@ -19029,12 +19239,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; } @@ -19047,31 +19257,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 */ @@ -19106,10 +19308,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; @@ -19125,31 +19326,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); @@ -19182,10 +19374,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; @@ -19196,23 +19387,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; @@ -19221,22 +19416,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) @@ -19248,22 +19443,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 */ @@ -19272,416 +19467,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) * @@ -19692,7 +19482,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]; @@ -19986,6 +19778,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. @@ -20211,7 +20493,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)); @@ -20227,212 +20508,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. @@ -20440,8 +20522,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); @@ -20465,7 +20547,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] = { @@ -20565,7 +20647,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; @@ -20601,54 +20684,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. @@ -20701,55 +20736,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. * @@ -20807,13 +20793,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); @@ -21267,8 +21253,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]; @@ -21354,10 +21340,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. @@ -21481,33 +21639,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) { @@ -21558,19 +21720,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; } @@ -21642,7 +21809,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; @@ -21730,8 +21898,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; @@ -21742,6 +21910,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]; @@ -21758,7 +21927,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); @@ -21766,14 +21938,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); } @@ -22183,14 +22357,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; } @@ -22303,6 +22475,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. @@ -22312,26 +22488,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) { @@ -22376,9 +22556,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; } @@ -22465,8 +22646,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. @@ -22480,17 +22663,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. */ @@ -22498,27 +22683,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) { @@ -22532,8 +22720,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); @@ -22559,13 +22749,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; } @@ -22575,16 +22764,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 @@ -22592,9 +22790,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) { @@ -22711,28 +22915,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); @@ -22743,12 +22950,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; } @@ -22771,6 +23058,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 }, @@ -24565,6 +24856,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. @@ -24590,28 +24886,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); @@ -24621,12 +24919,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; } @@ -24645,7 +25021,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. @@ -24666,7 +25042,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; @@ -24729,41 +25106,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) { @@ -24788,15 +25170,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; } @@ -24810,7 +25191,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; @@ -24855,33 +25239,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) { @@ -24894,12 +25280,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; } @@ -24970,7 +25356,9 @@ 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); @@ -25023,62 +25411,55 @@ 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); @@ -25099,7 +25480,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; @@ -25108,10 +25489,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; @@ -25141,7 +25521,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 */ @@ -25289,7 +25668,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); } } @@ -25298,12 +25677,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 @@ -25338,8 +25768,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; @@ -25357,13 +25787,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); @@ -25391,6 +25818,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; } @@ -25447,6 +25877,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--; @@ -25479,61 +25912,48 @@ 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; @@ -25541,8 +25961,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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 +25970,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 +25981,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 15, priv); sp_384_from_bin(e, 15, hash, (int)hashLen); - 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); + err = sp_384_calc_s_15(s, r, k, x, e, tmp); + } - /* 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; @@ -25612,20 +26007,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; } @@ -25675,20 +26074,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) @@ -25696,11 +26093,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); @@ -25778,7 +26173,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 @@ -25787,6 +26182,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) @@ -25805,8 +26297,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 { @@ -25825,8 +26316,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; @@ -25841,7 +26333,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); @@ -25899,57 +26391,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) { @@ -25957,22 +26425,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; } @@ -25980,137 +26449,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); } @@ -26121,7 +26516,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) { @@ -26129,26 +26524,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; } @@ -26162,34 +26557,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); @@ -26209,10 +26596,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; @@ -26225,16 +26611,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); @@ -26243,7 +26636,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; } @@ -26259,47 +26655,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)); @@ -26313,12 +26710,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) { @@ -26330,12 +26726,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) { @@ -26343,22 +26737,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; } @@ -26382,33 +26774,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); @@ -26429,13 +26823,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; } @@ -26454,25 +26847,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) { @@ -26493,12 +26889,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; } @@ -26513,32 +26909,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) { @@ -26551,12 +26951,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; } @@ -26569,43 +26969,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 */ @@ -26665,10 +27050,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; @@ -26684,31 +27068,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); @@ -26741,17 +27116,11310 @@ 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; + + 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); + 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 3842b58e0..d50d010dd 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,50 +1327,13 @@ 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); @@ -1440,62 +1418,55 @@ 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); @@ -1516,7 +1487,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 +1496,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 +1529,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 +1608,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 +1693,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 +1797,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 +1823,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 +2039,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 +2053,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 +2100,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 +2134,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 +2149,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 +2163,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,50 +2207,13 @@ 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); @@ -2381,62 +2298,55 @@ 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); @@ -2457,7 +2367,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 +2376,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 +2411,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 +2490,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 +2575,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 +2679,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 +2705,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 +2728,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 +2764,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 +2826,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 +2862,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 +2939,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 +2950,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 +2968,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 +3008,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 +3027,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 +3081,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 +3106,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 +3155,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); @@ -3266,17 +3200,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 +3245,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); @@ -3328,16 +3294,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 +3329,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 +3354,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 +3390,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 +3418,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 +3443,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 +3480,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 +3505,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 +3524,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 +3535,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 +3625,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 +3675,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 +3708,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 +3729,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 +3757,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 +3793,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 +3830,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 +3865,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 +3897,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 +3925,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 +3951,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 +3988,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 +4014,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 +4044,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 +4087,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 +4122,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 +4163,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 +4768,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 +4802,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 +4942,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 +4979,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 +5005,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 +5044,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 +5063,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 +5072,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 +5348,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 +5362,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 +5416,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 +5431,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 +5445,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,7 +5554,9 @@ 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); @@ -5632,62 +5641,55 @@ 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); @@ -5708,7 +5710,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 +5719,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 +5752,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 +5831,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 +5916,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 +6020,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 +6046,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 +6326,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 +6360,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 +6375,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 +6389,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,7 +6439,9 @@ 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); @@ -6541,62 +6526,55 @@ 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); @@ -6617,7 +6595,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 +6604,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 +6639,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 +6718,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 +6803,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 +6907,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 +6933,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 +6956,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 +6992,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 +7054,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 +7090,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 +7167,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 +7178,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 +7196,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 +7236,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 +7255,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 +7309,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 +7334,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 +7383,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); @@ -7426,17 +7428,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 +7473,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); @@ -7488,16 +7522,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 +7557,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 +7582,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 +7618,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 +7646,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 +7671,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 +7708,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 +7733,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 +7752,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 +7763,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 +7889,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 +7939,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 +7972,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 +7993,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 +8021,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 +8057,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 +8094,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 +8129,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 +8161,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 +8189,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 +8215,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 +8252,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 +8278,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 +8308,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 +8351,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 +8386,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 +8427,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 +9158,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 +9192,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 +9308,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 +9342,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 +9374,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 +9384,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 +9745,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 +9760,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 +9774,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 +9883,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 +9894,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,7 +9917,9 @@ 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); @@ -9917,68 +9972,60 @@ 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); @@ -9999,7 +10046,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 +10058,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 +10091,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 +10170,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 +10255,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 +10359,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 +10385,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 +10666,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 +10700,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 +10715,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 +10729,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 +10828,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 +10839,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,7 +10861,9 @@ 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); @@ -10924,68 +10916,60 @@ 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); @@ -11006,7 +10990,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 +11002,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 +11037,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 +11116,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 +11201,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 +11305,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 +11331,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 +11354,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 +11390,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 +11452,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 +11488,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 +11565,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 +11576,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 +11594,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 +11634,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 +11653,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 +11707,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 +11732,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 +11781,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); @@ -11818,17 +11826,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 +11871,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); @@ -11880,16 +11920,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 +11955,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 +11980,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 +12016,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 +12044,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 +12069,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 +12106,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 +12131,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 +12150,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 +12161,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 +12335,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 +12385,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 +12418,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 +12439,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 +12467,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 +12503,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 +12540,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 +12575,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 +12684,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 +12694,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 +12770,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 +13309,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 +13323,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 +13348,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 +13432,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 +13469,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 +13521,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. * @@ -13658,13 +13568,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 +14016,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 +14103,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 +14343,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 +14424,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 +14493,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 +14582,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 +14594,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 +14611,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 +14622,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 +14981,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 +15099,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 +15112,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 +15180,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 +15230,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 +15247,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 +15267,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 +15304,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 +15333,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 +15348,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 +15374,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 +15499,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 +15534,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 +15642,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 +16930,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 +16960,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 +16993,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 +17094,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 +17115,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 +17179,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 +17243,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 +17264,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 +17312,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 +17353,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,7 +17409,9 @@ 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); @@ -17203,62 +17456,55 @@ 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); @@ -17279,7 +17525,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 +17534,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 +17564,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 +17710,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 +17720,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 +17730,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 +17740,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 +17751,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 +17842,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 +17861,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 +17892,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 +17951,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,61 +17986,48 @@ 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; @@ -17749,8 +18035,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -17760,7 +18044,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) { @@ -17771,38 +18055,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 5, priv); sp_256_from_bin(e, 5, hash, (int)hashLen); - 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); + err = sp_256_calc_s_5(s, r, k, x, e, tmp); + } - /* 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; @@ -17820,20 +18081,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; } @@ -17888,20 +18153,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) @@ -17909,11 +18172,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); @@ -17991,7 +18252,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 @@ -18000,6 +18261,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) @@ -18018,8 +18366,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 { @@ -18038,8 +18385,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; @@ -18054,7 +18402,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); @@ -18112,57 +18460,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) { @@ -18170,22 +18494,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; } @@ -18193,127 +18518,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); } @@ -18324,7 +18585,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) { @@ -18332,26 +18593,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; } @@ -18365,34 +18626,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); @@ -18412,10 +18665,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; @@ -18428,16 +18680,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); @@ -18446,7 +18705,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; } @@ -18462,47 +18724,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)); @@ -18516,12 +18779,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) { @@ -18533,12 +18795,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) { @@ -18546,22 +18806,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; } @@ -18585,33 +18843,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); @@ -18632,13 +18892,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; } @@ -18657,25 +18916,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) { @@ -18696,12 +18958,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; } @@ -18716,32 +18978,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) { @@ -18754,12 +19020,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; } @@ -18772,31 +19038,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 */ @@ -18831,10 +19089,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; @@ -18850,31 +19107,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); @@ -18907,10 +19155,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; @@ -18921,9 +19168,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; @@ -18961,26 +19212,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 */ @@ -18993,384 +19244,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) * @@ -19381,7 +19254,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]; @@ -19483,6 +19358,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. @@ -19662,7 +19903,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)); @@ -19678,104 +19918,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. @@ -19783,8 +19932,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); @@ -19808,7 +19957,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] = { @@ -19908,7 +20057,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; @@ -19944,46 +20094,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. @@ -20036,47 +20146,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. * @@ -20126,13 +20195,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); @@ -20576,8 +20645,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]; @@ -20663,10 +20732,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. @@ -20790,33 +21004,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) { @@ -20867,19 +21085,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; } @@ -20935,7 +21158,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; @@ -21023,8 +21247,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; @@ -21035,6 +21259,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]; @@ -21051,7 +21276,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); @@ -21059,14 +21287,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); } @@ -21428,14 +21658,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; } @@ -21548,6 +21776,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. @@ -21557,26 +21789,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) { @@ -21621,9 +21857,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; } @@ -21678,8 +21915,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. @@ -21693,17 +21932,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. */ @@ -21711,27 +21952,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) { @@ -21745,8 +21989,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); @@ -21772,13 +22018,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; } @@ -21788,16 +22033,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 @@ -21805,9 +22059,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) { @@ -21924,28 +22184,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); @@ -21956,12 +22219,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; } @@ -21984,6 +22327,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 }, @@ -23778,6 +24125,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. @@ -23803,28 +24155,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); @@ -23834,12 +24188,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; } @@ -23857,7 +24289,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. @@ -23878,7 +24310,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; @@ -23941,41 +24374,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) { @@ -24000,15 +24438,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; } @@ -24022,7 +24459,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; @@ -24067,33 +24507,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) { @@ -24106,12 +24548,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; } @@ -24166,7 +24608,9 @@ 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); @@ -24227,62 +24671,55 @@ 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); @@ -24303,7 +24740,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; @@ -24312,10 +24749,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; @@ -24345,7 +24781,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 */ @@ -24493,7 +24928,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); } } @@ -24502,12 +24937,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 @@ -24542,8 +25028,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; @@ -24561,13 +25047,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); @@ -24595,6 +25078,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; } @@ -24651,6 +25137,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--; @@ -24683,61 +25172,48 @@ 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; @@ -24745,8 +25221,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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 +25230,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 +25241,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 7, priv); sp_384_from_bin(e, 7, hash, (int)hashLen); - 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); + err = sp_384_calc_s_7(s, r, k, x, e, tmp); + } - /* 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; @@ -24816,20 +25267,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; } @@ -24884,20 +25339,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) @@ -24905,11 +25358,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); @@ -24987,7 +25438,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 @@ -24996,6 +25447,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) @@ -25014,8 +25554,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 { @@ -25034,8 +25573,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; @@ -25050,7 +25590,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); @@ -25108,57 +25648,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) { @@ -25166,22 +25682,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; } @@ -25189,129 +25706,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); } @@ -25322,7 +25773,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) { @@ -25330,26 +25781,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; } @@ -25363,34 +25814,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); @@ -25410,10 +25853,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; @@ -25426,16 +25868,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); @@ -25444,7 +25893,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; } @@ -25460,47 +25912,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)); @@ -25514,12 +25967,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) { @@ -25531,12 +25983,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) { @@ -25544,22 +25994,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; } @@ -25583,33 +26031,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); @@ -25630,13 +26080,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; } @@ -25655,25 +26104,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) { @@ -25694,12 +26146,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; } @@ -25714,32 +26166,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) { @@ -25752,12 +26208,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; } @@ -25770,43 +26226,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 */ @@ -25866,10 +26307,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; @@ -25885,31 +26325,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); @@ -25942,17 +26373,10381 @@ 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; + + 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); + 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_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 45310f711..b243b851f 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]; + 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, + 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,61 +21856,48 @@ 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; @@ -21626,8 +21905,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -21637,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) { @@ -21648,38 +21925,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 8, priv); sp_256_from_bin(e, 8, hash, (int)hashLen); - 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); + err = sp_256_calc_s_8(s, r, k, x, e, tmp); + } - /* 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; @@ -21697,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; } @@ -22001,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) @@ -22019,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 { @@ -22039,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; @@ -22055,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); @@ -22113,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) { @@ -22171,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; } @@ -22194,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); } @@ -22328,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) { @@ -22336,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; } @@ -22369,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); @@ -22416,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; @@ -22432,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); @@ -22450,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; } @@ -22466,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)); @@ -22520,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) { @@ -22537,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) { @@ -22550,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; } @@ -22589,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); @@ -22636,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; } @@ -22661,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) { @@ -22700,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; } @@ -22720,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) { @@ -22758,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; } @@ -22776,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 */ @@ -22835,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; @@ -22854,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); @@ -22911,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; @@ -22925,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; @@ -22997,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. @@ -23412,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. * @@ -23566,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. @@ -23704,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); @@ -23729,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] = { @@ -23882,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; @@ -23918,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. @@ -24060,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. * @@ -24718,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]; @@ -24898,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. @@ -24913,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]; + 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, + 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; @@ -25002,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); @@ -25049,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. * @@ -25081,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; @@ -25184,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. @@ -25270,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. @@ -25279,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) { @@ -25343,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; } @@ -25420,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. @@ -25435,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. */ @@ -25453,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) { @@ -25487,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); @@ -25514,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; } @@ -25530,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 @@ -25547,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) { @@ -25658,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. @@ -25667,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) { @@ -25731,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; } @@ -25808,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. @@ -25823,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. */ @@ -25841,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) { @@ -25875,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); @@ -25902,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; } @@ -25918,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 @@ -25935,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) { @@ -26054,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); @@ -26086,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 }, @@ -26181,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. @@ -26196,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 }, @@ -27480,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. @@ -27505,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); @@ -27536,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; } @@ -27560,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. @@ -27621,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; @@ -27684,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) { @@ -27743,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; } @@ -27765,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; @@ -27806,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) { @@ -27845,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; } @@ -28140,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 */ @@ -28288,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); } } @@ -28297,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 @@ -28337,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; @@ -28356,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); @@ -28390,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; } @@ -28446,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--; @@ -28478,61 +29019,48 @@ 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; @@ -28540,8 +29068,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 12, priv); sp_384_from_bin(e, 12, hash, (int)hashLen); - 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); + err = sp_384_calc_s_12(s, r, k, x, e, tmp); + } - /* 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; @@ -28611,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; } @@ -28959,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) @@ -28977,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 { @@ -28997,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; @@ -29013,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); @@ -29071,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) { @@ -29129,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; } @@ -29152,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); } @@ -29290,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) { @@ -29298,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; } @@ -29331,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); @@ -29378,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; @@ -29394,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); @@ -29412,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; } @@ -29428,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)); @@ -29482,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) { @@ -29499,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) { @@ -29512,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; } @@ -29551,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); @@ -29598,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; } @@ -29623,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) { @@ -29662,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; } @@ -29682,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) { @@ -29720,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; } @@ -29738,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 */ @@ -29834,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; @@ -29853,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); @@ -29910,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]; + 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, + 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 77a59b3ae..d22dd82bc 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. * @@ -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. */ @@ -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; @@ -2686,7 +2691,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; @@ -2997,7 +3002,8 @@ int sp_cmp_d(sp_int* a, sp_int_digit d) #if defined(WOLFSSL_SP_INT_NEGATIVE) || !defined(NO_PWDBASED) || \ defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || \ - (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) + ((defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_RSA)) && \ + !defined(WOLFSSL_RSA_VERIFY_ONLY)) /* Add a one digit number to the multi-precision number. * * @param [in] a SP integer be added to. @@ -3104,25 +3110,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 +3160,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 } @@ -3487,7 +3508,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 * @@ -3958,7 +3979,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 +4024,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 @@ -4696,7 +4719,7 @@ 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, a->used + 1); err = sp_div(a, m, NULL, t); @@ -4747,7 +4770,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]; @@ -4823,7 +4847,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]; @@ -4900,7 +4925,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]; @@ -7679,7 +7705,8 @@ 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) /* Multiply a by b mod m and store in r: r = (a * b) mod m * * @param [in] a SP integer to multiply. @@ -9278,7 +9305,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]; @@ -9387,7 +9414,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]; @@ -11667,7 +11694,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. @@ -12063,7 +12091,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. @@ -12078,7 +12107,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; @@ -12118,9 +12147,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; diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index fd8a9897e..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,33 +23822,27 @@ 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; @@ -23346,8 +23850,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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); @@ -23362,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) { @@ -23373,58 +23875,15 @@ 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); - - /* 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); + sp_256_from_mp(x, 4, priv); sp_256_from_bin(e, 4, hash, (int)hashLen); - 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); + err = sp_256_calc_s_4(s, r, k, x, e, tmp); + } - /* 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; @@ -23442,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; } @@ -23465,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) @@ -23483,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 { @@ -23503,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; @@ -23519,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); @@ -23577,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) { @@ -23635,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; } @@ -23658,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); } @@ -23847,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) { @@ -23855,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; } @@ -23888,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); @@ -23935,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; @@ -23951,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); @@ -23969,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; } @@ -23985,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)); @@ -24042,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) { @@ -24064,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) { @@ -24082,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; } @@ -24121,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); @@ -24176,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; } @@ -24201,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) { @@ -24248,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; } @@ -24268,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) { @@ -24306,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; } @@ -24324,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)) { @@ -24420,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; @@ -24439,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); @@ -24506,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; @@ -24520,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; @@ -24560,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 */ @@ -24585,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, @@ -24592,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. @@ -24645,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; @@ -24748,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; @@ -24773,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; @@ -24807,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++) { @@ -24843,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)); @@ -24870,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; } @@ -24893,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; @@ -24941,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); @@ -24954,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. @@ -24969,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); @@ -24994,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] = { @@ -25101,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; @@ -25137,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. @@ -25185,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). * @@ -25406,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; @@ -25710,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]; @@ -25804,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; @@ -25816,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]; @@ -25832,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); @@ -25840,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); } @@ -26151,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 @@ -26177,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); @@ -26194,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); @@ -26220,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) @@ -26307,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; @@ -26327,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) ? @@ -26337,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); @@ -26349,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. @@ -26511,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. @@ -26551,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; @@ -26567,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); @@ -26580,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 */ @@ -26601,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. @@ -26842,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]; @@ -26869,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; @@ -26907,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); @@ -26918,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); } } @@ -26936,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; @@ -26948,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]; @@ -26960,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); @@ -27059,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. @@ -27097,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) { @@ -27199,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); } @@ -27211,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; } @@ -27230,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. @@ -27338,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. @@ -27347,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) { @@ -27390,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 { @@ -27489,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 @@ -27518,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 @@ -27551,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) { @@ -27660,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. @@ -27691,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; @@ -27723,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 */ @@ -27733,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); } } @@ -27768,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. @@ -27777,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; @@ -27820,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 { @@ -27917,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 @@ -27946,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. * @@ -28020,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); @@ -28060,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 } }, @@ -28080,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. @@ -29372,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. @@ -29387,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. * @@ -29396,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); @@ -29435,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; } @@ -29458,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); @@ -29471,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); } } @@ -29519,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) { @@ -29593,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; } @@ -29617,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); } } @@ -29639,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(); @@ -29657,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) { @@ -29686,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; } @@ -29703,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. @@ -29725,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. @@ -29761,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(); @@ -29815,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); } @@ -29832,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 */ @@ -29980,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); } } @@ -30134,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); } } @@ -30144,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 @@ -30184,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; @@ -30203,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); @@ -30237,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; } @@ -30293,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--; @@ -30325,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(); @@ -30356,33 +48311,27 @@ 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; @@ -30390,8 +48339,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, } 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,15 @@ 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); - - /* 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); + sp_384_from_mp(x, 6, priv); sp_384_from_bin(e, 6, hash, (int)hashLen); - 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); + err = sp_384_calc_s_6(s, r, k, x, e, tmp); + } - /* 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; @@ -30486,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; } @@ -30590,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) @@ -30608,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 { @@ -30628,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; @@ -30644,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); @@ -30702,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) { @@ -30760,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; } @@ -30783,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); } @@ -30970,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) { @@ -30978,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; } @@ -31011,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); @@ -31058,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; @@ -31074,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); @@ -31092,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; } @@ -31108,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)); @@ -31165,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) { @@ -31187,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) { @@ -31205,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; } @@ -31244,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); @@ -31299,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; } @@ -31324,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) { @@ -31371,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; } @@ -31391,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) { @@ -31429,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; } @@ -31447,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)) { @@ -31605,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; @@ -31624,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); @@ -31691,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..9de68792b 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. * @@ -122,6 +122,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 +208,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 +328,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 +416,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 +3194,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 +3263,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 +3340,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 +3365,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 +3442,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 +3460,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 +3468,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 +3544,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 +3558,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 +3571,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 +3626,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 +3647,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 +3674,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 +3728,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 +3749,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 +3777,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 +3830,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 +3849,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 +3880,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 +3932,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 +3947,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 +3983,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 +4014,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 +4035,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 +4086,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 +4116,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 +4137,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 +4189,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 +4218,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 +4237,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 +4292,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 +4320,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 +4335,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 +4395,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 +4423,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 +4498,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 +4525,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 +4601,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 +4625,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 +4704,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 +4723,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 +4868,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 +4964,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 +5040,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 +5051,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 +5127,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 +5138,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 +5150,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 +5215,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 +5226,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 +5238,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 +5250,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 +5303,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 +5314,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 +5326,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 +5338,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 +5350,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 +5391,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 +5402,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 +5414,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 +5426,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 +5439,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 +5451,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 +5480,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 +5491,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 +5503,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 +5516,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 +5528,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 +5540,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 +5552,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 +5580,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 +5593,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 +5605,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 +5617,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 +5629,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 +5641,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 +5653,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 +5746,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 +5755,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 +5766,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 +5777,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 +5788,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 +5799,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 +5810,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 +5821,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 +5832,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 +6339,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 +7072,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 +7577,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 +7738,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 +8256,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 +8354,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 +8827,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 +9176,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 +9344,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 +9507,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 +9534,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 +9641,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 +9820,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 +9913,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 +10120,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 +10141,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 +10230,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 +10242,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 +10331,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 +10716,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 +11039,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 +11066,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 +11253,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 +11283,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 +11472,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 +11927,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 +11948,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 +12133,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 +12458,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 +12565,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 +12584,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 +12792,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 +12878,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 +13046,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 +13166,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 +14826,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 +14879,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 +14942,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 +14957,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 +15010,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 +15021,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 +15036,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 +15088,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 +15099,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 +15115,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 +15156,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 +15167,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 +15194,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 +15234,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 +15245,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 +15273,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 +15302,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 +15313,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 +15352,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 +15380,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 +15391,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 +15431,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 +15448,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 +15459,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 +15510,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 +15526,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 +15537,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 +15589,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 +15605,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 +15668,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 +15683,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 +15802,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 +15874,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 +15926,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 +15937,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 +15989,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 +16053,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 +16117,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 +16311,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 +16320,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 +16331,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 +16342,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 +16353,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 +16364,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 +16375,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 +16795,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 +17370,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 +17756,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 +17893,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 +18289,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 +18375,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 +18737,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 +19282,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 +20325,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 +21071,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 +21280,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 +22036,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 +22158,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 +22856,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 +23486,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 +23729,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 +23756,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 +23903,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 +24146,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 +24287,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 +24558,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 +24579,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 +24716,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 +25253,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 +25736,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 +25763,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 +26030,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 +26060,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 +26345,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 +26976,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 +26997,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 +27278,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 +27739,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 +27886,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 +27905,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 +28161,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 +28247,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 +28463,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 +28615,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 +29304,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 +30661,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 +31646,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 +31903,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 +32901,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 +33047,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 +33968,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 +35006,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 +35649,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 +35676,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 +36023,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 +36053,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 +36434,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 +37241,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 +37262,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 +37639,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 +38236,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 +38423,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 +38442,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 +39525,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 +39668,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 +39719,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 +39772,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 +39791,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 +39843,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 +39976,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 +40010,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 +40022,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 +40054,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 +40207,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 +40377,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 +40683,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 +40706,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 +40739,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 +40748,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 +40792,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 +40815,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 +40848,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 +40857,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 +40983,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 +41069,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 +41105,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 +41137,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 +41158,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 +41248,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 +41290,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 +41372,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 +41393,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 +41443,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 +41527,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 +41552,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 +41577,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 +41602,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 +41642,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 +41733,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 +41758,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 +41783,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 +41808,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 +41858,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 +42086,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 +42190,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 +42286,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 +42353,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 +42373,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 +42415,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 +42690,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 +42914,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 +43492,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 +43533,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 +43622,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 +43780,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 +43817,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 +43838,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 +44073,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 +44404,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 +44567,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 +44713,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 +44738,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 +44762,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 +44771,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 +44782,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 +44805,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 +44822,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 +45082,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 +45168,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 +45210,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 +45246,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 +45282,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 +45380,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 +45413,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 +45618,9133 @@ 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 */ #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..f4ed57470 --- /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 r8b, 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 r8b, 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 r8b, 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: + movslq rax, eax + shl r9, 26 + add rax, r9 + movslq r10, r10d + shl r11, 26 + add r10, r11 + movslq r12, r12d + shl r13, 26 + add r12, r13 + movslq r14, r14d + shl r15, 26 + add r14, r15 + movslq 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..a891f588a 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. * diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 4352567cc..155695936 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. * @@ -1468,12 +1468,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 +3581,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 +3590,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 +3604,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 +3617,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 +3635,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 +3643,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 +3664,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 +3718,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 +3762,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)); @@ -3843,7 +3850,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; @@ -4290,7 +4297,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 +4351,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 +4397,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 +4413,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); } 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..3c4600e5e 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. * @@ -2584,6 +2584,9 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) 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"); @@ -3508,6 +3511,8 @@ 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 @@ -3533,6 +3538,8 @@ 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 diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index cc7022e14..9e119eb61 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; } @@ -415,6 +415,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 */ @@ -485,11 +517,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 +545,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 +572,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; @@ -615,11 +634,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 +656,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 +677,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; 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 0d3166bc4..34524fea0 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 @@ -164,6 +163,19 @@ _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__) #else #ifdef XMALLOC_USER #include /* we're using malloc / free direct here */ @@ -238,6 +250,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 @@ -327,7 +345,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"; @@ -440,6 +462,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 @@ -1237,9 +1265,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) @@ -1335,7 +1376,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 @@ -10002,6 +10044,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); @@ -11720,6 +11859,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 @@ -13561,8 +13703,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); } @@ -14569,7 +14710,7 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) const word32 inLen = (word32)TEST_STRING_SZ; const word32 outSz = RSA_TEST_BYTES; const word32 plainSz = RSA_TEST_BYTES; - byte* res; + byte* res = NULL; #ifndef NO_SIG_WRAPPER int modLen; #endif @@ -20796,7 +20937,8 @@ 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); @@ -20857,6 +20999,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); @@ -20871,6 +21014,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); @@ -21903,7 +22047,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; @@ -22033,7 +22179,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) { @@ -22201,13 +22347,14 @@ 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) @@ -23102,7 +23249,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); @@ -23186,7 +23333,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 @@ -23196,8 +23343,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); @@ -26577,6 +26724,2091 @@ 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 (ret != 0) + 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; + WC_RNG rng; + EccsiKey* priv; + EccsiKey* pub; + mp_int* ssk; + ecc_point* pvt; + + priv = (EccsiKey*)XMALLOC(sizeof(EccsiKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + return -10205; + } + pub = (EccsiKey*)XMALLOC(sizeof(EccsiKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -10206; + } + ssk = (mp_int*)XMALLOC(sizeof(mp_int), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (ssk == NULL) { + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -10207; + } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -10200; + + pvt = wc_ecc_new_point(); + if (pvt == NULL) + return -10201; + ret = mp_init(ssk); + if (ret != 0) + return -10202; + + ret = eccsi_api_test(&rng, priv, ssk, pvt); + if (ret != 0) + return ret; + + ret = wc_InitEccsiKey(pub, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + return -10203; + + ret = wc_InitEccsiKey(priv, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + return -10204; + + ret = eccsi_kat_verify_test(pub, pvt); + if (ret != 0) + return ret; + + ret = eccsi_make_key_test(priv, pub, &rng, ssk, pvt); + if (ret != 0) + return ret; + + ret = eccsi_sign_verify_test(priv, pub, &rng, ssk, pvt); + if (ret != 0) + return ret; + + wc_FreeEccsiKey(priv); + wc_FreeEccsiKey(pub); + mp_free(ssk); + wc_ecc_del_point(pvt); + wc_FreeRng(&rng); + XFREE(ssk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return 0; +} +#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; + WC_RNG rng; + SakkeKey* priv; + SakkeKey* pub; + SakkeKey* key; + ecc_point* rsk = NULL; + + priv = (SakkeKey*)XMALLOC(sizeof(SakkeKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + return -10404; + } + pub = (SakkeKey*)XMALLOC(sizeof(SakkeKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -10405; + } + key = (SakkeKey*)XMALLOC(sizeof(SakkeKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -10406; + } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -10400; + + rsk = wc_ecc_new_point(); + if (rsk == NULL) + return -10401; + + ret = wc_InitSakkeKey(pub, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + return -10402; + + ret = wc_InitSakkeKey(priv, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + return -10403; + + ret = sakke_api_test(&rng, key, rsk); + if (ret != 0) + return ret; + + ret = sakke_kat_derive_test(pub, rsk); + if (ret != 0) + return ret; + + ret = sakke_kat_encapsulate_test(pub); + if (ret != 0) + return ret; + + ret = sakke_make_key_test(priv, pub, key, &rng, rsk); + if (ret != 0) + return ret; + + ret = sakke_op_test(priv, pub, &rng, rsk); + if (ret != 0) + return ret; + + wc_FreeSakkeKey(priv); + wc_FreeSakkeKey(pub); + wc_ecc_forcezero_point(rsk); + wc_ecc_del_point(rsk); + wc_FreeRng(&rng); + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return 0; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + + #if defined(WOLFSSL_CMAC) && !defined(NO_AES) typedef struct CMAC_Test_Case { @@ -26755,8 +28987,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) @@ -34105,6 +36345,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) { @@ -34557,6 +36798,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..2a993ade0 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. * 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 25c22b449..a02d696da 100644 --- a/wolfssl.vcxproj +++ b/wolfssl.vcxproj @@ -361,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/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 68ace3053..4e2ab6e38 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. * diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7c3491546..1d55b3afe 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. * @@ -1605,11 +1605,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 @@ -1684,6 +1684,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 { @@ -2066,6 +2081,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 */ @@ -2284,9 +2304,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) \ @@ -2588,7 +2608,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); @@ -2642,7 +2662,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, @@ -3691,6 +3711,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 @@ -3716,6 +3738,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; @@ -4811,6 +4835,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 edafd2152..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. * 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 338af64e1..dc8fdf614 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. * 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..de21ab7fe 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. * 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..db407610c 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. * 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 98cc122f0..118553c88 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. * 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 08cbd527e..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. * diff --git a/wolfssl/openssl/obj_mac.h b/wolfssl/openssl/obj_mac.h index 6d0f90047..3c5df52f2 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. * 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..0605a3e8b 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. * 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..d62ee9337 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. * diff --git a/wolfssl/openssl/sha.h b/wolfssl/openssl/sha.h index c8ee6d4c6..56d1a706f 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. * 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 fcc2df1e6..e9b201720 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. * @@ -681,11 +681,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 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..e8411af4b 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. * diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 9116dff7a..cee9baf51 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 @@ -276,8 +280,6 @@ struct WOLFSSL_X509V3_CTX { WOLFSSL_X509* x509; }; - - struct WOLFSSL_ASN1_OBJECT { void* heap; const unsigned char* obj; @@ -531,6 +533,8 @@ struct WOLFSSL_X509_LOOKUP_METHOD { struct WOLFSSL_X509_LOOKUP { WOLFSSL_X509_STORE *store; + int type; + WOLFSSL_BY_DIR* dirs; }; struct WOLFSSL_X509_STORE { @@ -639,6 +643,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 */ @@ -682,6 +705,28 @@ 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 + */ +#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 */ @@ -1342,6 +1387,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); @@ -1397,6 +1444,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 @@ -1475,6 +1524,8 @@ 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 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*); @@ -1566,6 +1617,8 @@ 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( @@ -3476,11 +3529,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); @@ -3573,6 +3621,7 @@ WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio); +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**); @@ -3597,7 +3646,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, @@ -3749,7 +3798,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); diff --git a/wolfssl/test.h b/wolfssl/test.h index 50a5c96a2..16fe232ce 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -349,6 +349,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 +383,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" diff --git a/wolfssl/version.h b/wolfssl/version.h index 0bc820cbf..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. * 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 508084111..446148a7a 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. * @@ -1173,6 +1173,8 @@ 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); @@ -1272,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, diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 450f845eb..f55312c12 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. * @@ -516,6 +516,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, 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 88b1caf94..fd5562183 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..4c5ea8abd 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. * 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..75a86beb3 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 @@ -397,6 +408,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,7 +453,7 @@ 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) mp_int *sign_k; #endif @@ -546,7 +563,7 @@ 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 +#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 +647,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 +659,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 +741,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 +755,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..73da12f6e 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,11 @@ 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 */ - WC_LAST_E = -275, /* Update this to indicate last error */ + WC_LAST_E = -278, /* 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 44b505da4..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. * 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..d4637af1e 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,13 @@ 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/caam_error.h \ + wolfssl/wolfcrypt/port/caam/caam_qnx.h \ 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 \ wolfssl/wolfcrypt/port/silabs/silabs_aes.h \ wolfssl/wolfcrypt/port/silabs/silabs_ecc.h \ wolfssl/wolfcrypt/port/silabs/silabs_hash.h \ diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 59a366bb1..8a04000cc 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. * @@ -286,7 +286,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); @@ -297,10 +297,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 290c5ec91..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. * @@ -74,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 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 f025deda6..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. * 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..bdb4d8302 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. * 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..53497bb6a 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. * 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..f8f08d4fc 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. * 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 f704d7705..4e47fd6e5 100644 --- a/wolfssl/wolfcrypt/port/ti/ti-ccm.h +++ b/wolfssl/wolfcrypt/port/ti/ti-ccm.h @@ -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/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 31a33a57b..ee7caec50 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. * @@ -1240,7 +1240,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 +1294,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 +1346,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 @@ -1652,6 +1656,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 diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index f074f28c4..10c447115 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. * @@ -102,7 +102,7 @@ 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) diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 93c794f31..01228834d 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. * @@ -122,7 +122,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" #elif defined(WOLFSSL_AFALG_HASH) #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h" 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 6b6ad84e9..25410a814 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. * @@ -114,7 +114,7 @@ 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" 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..dc9307a40 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,8 @@ #ifdef WOLFSSL_HAVE_SP_RSA +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 + 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 +82,37 @@ 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 */ + #endif /* WOLFSSL_HAVE_SP_RSA */ #if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA) +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 + 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 +124,27 @@ 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 */ + #endif #ifdef WOLFSSL_HAVE_SP_DH +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 + 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 +152,23 @@ 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 */ + #endif /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 + 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 +212,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 */ + #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 163dcdad0..8083e6404 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,7 +113,7 @@ extern "C" { #error "Size of unsigned long not detected" #endif -#if ULLONG_MAX == 18446744073709551615UL +#if ULLONG_MAX == 18446744073709551615ULL #define SP_ULLONG_BITS 64 #if SP_ULLONG_BITS > SP_ULONG_BITS @@ -155,11 +156,16 @@ extern "C" { #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 +256,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 +343,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 +355,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) @@ -756,7 +770,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); @@ -769,7 +783,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 @@ -795,8 +809,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) @@ -841,7 +859,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); diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index bb6aa203a..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. * diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 3f4c43276..c7fae484e 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. * @@ -443,7 +443,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 */ @@ -646,10 +646,10 @@ 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); @@ -774,17 +774,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..0032884a0 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. * @@ -556,17 +556,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 +597,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 +659,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 +791,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 */ 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..e3b276ea8 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. * @@ -616,6 +616,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 @@ -676,14 +692,32 @@ 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(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 +753,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; @@ -732,7 +767,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #else struct dirent* entry; DIR* dir; - struct stat s; + struct XSTAT s; #endif char name[MAX_FILENAME_SZ]; } ReadDirCtx; @@ -743,6 +778,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 +796,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 */ @@ -859,9 +901,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..c92f44b31 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. * 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