diff --git a/.beads/.gitignore b/.beads/.gitignore deleted file mode 100644 index c4f9d34..0000000 --- a/.beads/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -# Dolt database (managed by Dolt, not git) -dolt/ -dolt-access.lock - -# Runtime files -bd.sock -bd.sock.startlock -sync-state.json -last-touched -.exclusive-lock - -# Daemon runtime (lock, log, pid) -daemon.* - -# Interactions log (runtime, not versioned) -interactions.jsonl - -# Push state (runtime, per-machine) -push-state.json - -# Lock files (various runtime locks) -*.lock - -# Credential key (encryption key for federation peer auth โ€” never commit) -.beads-credential-key - -# Local version tracking (prevents upgrade notification spam after git ops) -.local_version - -# Worktree redirect file (contains relative path to main repo's .beads/) -# Must not be committed as paths would be wrong in other clones -redirect - -# Sync state (local-only, per-machine) -# These files are machine-specific and should not be shared across clones -.sync.lock -export-state/ -export-state.json - -# Ephemeral store (SQLite - wisps/molecules, intentionally not versioned) -ephemeral.sqlite3 -ephemeral.sqlite3-journal -ephemeral.sqlite3-wal -ephemeral.sqlite3-shm - -# Dolt server management (auto-started by bd) -dolt-server.pid -dolt-server.log -dolt-server.lock -dolt-server.port -dolt-server.activity - -# Corrupt backup directories (created by bd doctor --fix recovery) -*.corrupt.backup/ - -# Backup data (auto-exported JSONL, local-only) -backup/ - -# Per-project environment file (Dolt connection config, GH#2520) -.env - -# Legacy files (from pre-Dolt versions) -*.db -*.db?* -*.db-journal -*.db-wal -*.db-shm -db.sqlite -bd.db -# NOTE: Do NOT add negation patterns here. -# They would override fork protection in .git/info/exclude. -# Config files (metadata.json, config.yaml) are tracked by git by default -# since no pattern above ignores them. diff --git a/.beads/README.md b/.beads/README.md deleted file mode 100644 index dbfe363..0000000 --- a/.beads/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Beads - AI-Native Issue Tracking - -Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code. - -## What is Beads? - -Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git. - -**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads) - -## Quick Start - -### Essential Commands - -```bash -# Create new issues -bd create "Add user authentication" - -# View all issues -bd list - -# View issue details -bd show - -# Update issue status -bd update --claim -bd update --status done - -# Sync with Dolt remote -bd dolt push -``` - -### Working with Issues - -Issues in Beads are: -- **Git-native**: Stored in Dolt database with version control and branching -- **AI-friendly**: CLI-first design works perfectly with AI coding agents -- **Branch-aware**: Issues can follow your branch workflow -- **Always in sync**: Auto-syncs with your commits - -## Why Beads? - -โœจ **AI-Native Design** -- Built specifically for AI-assisted development workflows -- CLI-first interface works seamlessly with AI coding agents -- No context switching to web UIs - -๐Ÿš€ **Developer Focused** -- Issues live in your repo, right next to your code -- Works offline, syncs when you push -- Fast, lightweight, and stays out of your way - -๐Ÿ”ง **Git Integration** -- Automatic sync with git commits -- Branch-aware issue tracking -- Dolt-native three-way merge resolution - -## Get Started with Beads - -Try Beads in your own projects: - -```bash -# Install Beads -curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash - -# Initialize in your repo -bd init - -# Create your first issue -bd create "Try out Beads" -``` - -## Learn More - -- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs) -- **Quick Start Guide**: Run `bd quickstart` -- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples) - ---- - -*Beads: Issue tracking that moves at the speed of thought* โšก diff --git a/.beads/config.yaml b/.beads/config.yaml deleted file mode 100644 index 232b151..0000000 --- a/.beads/config.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# Beads Configuration File -# This file configures default behavior for all bd commands in this repository -# All settings can also be set via environment variables (BD_* prefix) -# or overridden with command-line flags - -# Issue prefix for this repository (used by bd init) -# If not set, bd init will auto-detect from directory name -# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc. -# issue-prefix: "" - -# Use no-db mode: JSONL-only, no Dolt database -# When true, bd will use .beads/issues.jsonl as the source of truth -# no-db: false - -# Enable JSON output by default -# json: false - -# Feedback title formatting for mutating commands (create/update/close/dep/edit) -# 0 = hide titles, N > 0 = truncate to N characters -# output: -# title-length: 255 - -# Default actor for audit trails (overridden by BEADS_ACTOR or --actor) -# actor: "" - -# Export events (audit trail) to .beads/events.jsonl on each flush/sync -# When enabled, new events are appended incrementally using a high-water mark. -# Use 'bd export --events' to trigger manually regardless of this setting. -# events-export: false - -# Multi-repo configuration (experimental - bd-307) -# Allows hydrating from multiple repositories and routing writes to the correct database -# repos: -# primary: "." # Primary repo (where this database lives) -# additional: # Additional repos to hydrate from (read-only) -# - ~/beads-planning # Personal planning repo -# - ~/work-planning # Work planning repo - -# JSONL backup (periodic export for off-machine recovery) -# Auto-enabled when a git remote exists. Override explicitly: -# backup: -# enabled: false # Disable auto-backup entirely -# interval: 15m # Minimum time between auto-exports -# git-push: false # Disable git push (export locally only) -# git-repo: "" # Separate git repo for backups (default: project repo) - -# Integration settings (access with 'bd config get/set') -# These are stored in the database, not in this file: -# - jira.url -# - jira.project -# - linear.url -# - linear.api-key -# - github.org -# - github.repo diff --git a/.beads/hooks/post-checkout b/.beads/hooks/post-checkout deleted file mode 100755 index cacfeda..0000000 --- a/.beads/hooks/post-checkout +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v0.63.3 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run post-checkout "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'post-checkout' timed out after ${_bd_timeout}s โ€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run post-checkout "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized โ€” skipping hook 'post-checkout'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v0.63.3 --- diff --git a/.beads/hooks/post-merge b/.beads/hooks/post-merge deleted file mode 100755 index fd349bf..0000000 --- a/.beads/hooks/post-merge +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v0.63.3 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run post-merge "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'post-merge' timed out after ${_bd_timeout}s โ€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run post-merge "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized โ€” skipping hook 'post-merge'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v0.63.3 --- diff --git a/.beads/hooks/pre-commit b/.beads/hooks/pre-commit deleted file mode 100755 index 5bee03c..0000000 --- a/.beads/hooks/pre-commit +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v0.63.3 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run pre-commit "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'pre-commit' timed out after ${_bd_timeout}s โ€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run pre-commit "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized โ€” skipping hook 'pre-commit'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v0.63.3 --- diff --git a/.beads/hooks/pre-push b/.beads/hooks/pre-push deleted file mode 100755 index 6042948..0000000 --- a/.beads/hooks/pre-push +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v0.63.3 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run pre-push "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'pre-push' timed out after ${_bd_timeout}s โ€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run pre-push "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized โ€” skipping hook 'pre-push'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v0.63.3 --- diff --git a/.beads/hooks/prepare-commit-msg b/.beads/hooks/prepare-commit-msg deleted file mode 100755 index ae93b95..0000000 --- a/.beads/hooks/prepare-commit-msg +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v0.63.3 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run prepare-commit-msg "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'prepare-commit-msg' timed out after ${_bd_timeout}s โ€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run prepare-commit-msg "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized โ€” skipping hook 'prepare-commit-msg'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v0.63.3 --- diff --git a/.beads/metadata.json b/.beads/metadata.json deleted file mode 100644 index 8442438..0000000 --- a/.beads/metadata.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "database": "dolt", - "backend": "dolt", - "dolt_mode": "embedded", - "dolt_database": "wolfssl_rs", - "project_id": "1299f254-e978-4088-abb3-0e2479136124" -} \ No newline at end of file diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 30fca96..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,38 +0,0 @@ -[alias] -test-caliptra = "test -p wolfcrypt-dpe-hw --features caliptra-2x,testing-hooks" -test-caliptra-mldsa = "test -p wolfcrypt-dpe-hw --features caliptra-2x,mldsa87-hw,testing-hooks" -conformance-caliptra = "run -p wolfcrypt-conformance --bin caliptra_hw_conformance --features wolfcrypt-conformance/caliptra-hw" -# Build the minimal CryptoCb-only wolfSSL for the Caliptra riscv32 firmware target. -# Activate on wolfcrypt-dpe (not wolfcrypt-dpe-hw) because wolfcrypt-dpe owns -# the wolfssl-src chain. Excludes sp_int.c / sp_c32.c / sp_c64.c / wolfmath.c; -# only the CryptoCb dispatch infrastructure is compiled in. -build-caliptra-fw = "build -p wolfcrypt-dpe --features cryptocb-only --target riscv32imc-unknown-none-elf" -# Build wolfcrypt-dpe-hw with the absolute-minimum wolfSSL (CryptoCb routing -# only, no OPENSSL_EXTRA / HKDF / ASN). wolfcrypt-dpe-hw is the only crate -# in the build; wolfcrypt-sys is compiled with cryptocb-pure. -build-caliptra-hw-pure = "build -p wolfcrypt-dpe-hw --features caliptra-2x,cryptocb-pure" - -[target.riscv32imc-unknown-none-elf] -rustflags = ["-C", "link-arg=-Tmemory.x", "-C", "link-arg=-Tlink.x"] - -[env] -# Use the local wolfssl build that has HAVE_DILITHIUM and WOLF_CRYPTO_CB enabled. -# Built from ~/wolfssl with -DWOLFSSL_CRYPTOCB=yes -DWOLFSSL_DILITHIUM=yes. -# Overrides the system pkg-config installation at /usr/local (which lacks these flags). -WOLFSSL_DIR = "/home/mark/wolfssl-rs/wolfssl-install" -# wolfSSL source tree for the vendored build (cryptocb-only / riscv-bare-metal features). -# When those features are active, wolfcrypt-sys bypasses WOLFSSL_DIR and compiles -# wolfSSL from source via wolfssl-src using this path. -WOLFSSL_SRC = "/home/mark/wolfssl-rs/wolfssl-src/wolfssl" -# riscv32 C cross-compiler via zig cc. -# Used by the cc crate when compiling wolfssl-src for the riscv32imc-unknown-none-elf target. -CC_riscv32imc_unknown_none_elf = { value = ".cargo/riscv32-cc", relative = true } - -[target.x86_64-unknown-linux-gnu] -# Embed RPATH (DT_RPATH, not DT_RUNPATH) so the runtime linker loads the new wolfssl -# (libwolfssl.so.44.1.0) from ~/wolfssl-install instead of the older libwolfssl.so.44.0.1 -# at /usr/local/lib. Both have SONAME libwolfssl.so.44; without the rpath the ldconfig -# cache entry for /usr/local/lib wins. -# --disable-new-dtags is required: modern binutils defaults to DT_RUNPATH which loses -# to the ldconfig cache, while DT_RPATH takes priority before everything. -rustflags = ["-C", "link-arg=-Wl,--disable-new-dtags,-rpath,/home/mark/wolfssl-rs/wolfssl-install/lib"] diff --git a/.cargo/riscv32-cc b/.cargo/riscv32-cc deleted file mode 100755 index 33e686f..0000000 --- a/.cargo/riscv32-cc +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# Cross-compiler wrapper: riscv32imc-unknown-none-elf via zig cc. -# Used by the cc crate (via CC_riscv32imc_unknown_none_elf) when building -# C sources (wolfssl-src) for the Caliptra riscv32 firmware target. -# -# cc-rs appends --target=riscv32 (incomplete triple) which zig rejects. -# Filter it out and let our -target flag take precedence. -filtered=() -for arg in "$@"; do - case "$arg" in - --target=*) ;; - *) filtered+=("$arg") ;; - esac -done -exec zig cc -target riscv32-freestanding-none -mcpu=generic_rv32 -mabi=ilp32 "${filtered[@]}" diff --git a/.gitignore b/.gitignore index 1fd84c5..0d3d006 100644 --- a/.gitignore +++ b/.gitignore @@ -13,427 +13,10 @@ Cargo.lock # MacOS .DS_Store +# Added by cargo + **/target /Cargo.lock lcov.info /.zed/ - -# Beads / Dolt files (added by bd init) -.dolt/ -*.db -.beads-credential-key - -# Local wolfSSL build artifacts (not part of the repo) -wolfssl-install/ -wolfssl-repo/ -wolfssl-repo-install/ - -# --------------------------------------------------------------------------- -# Merged from upstream wolfssl/.gitignore -# --------------------------------------------------------------------------- -ctaocrypt/src/src/ -*.swp -*.lo -*.la -*.o -*.deps -*.d -*.libs -*.cache -.dirstamp -*.user -!*-VS2022.vcxproj.user -configure -config.* -!cmake/config.in -*Debug/ -*Release/ -*.ncb -*.suo -*.sdf -*.opensdf -*.cmd -ipch/ -build-aux/ -rpm/spec -*.rpm -stamp-h -cyassl/options.h -wolfssl/options.h -.build_params -libtool.m4 -aclocal.m4 -aminclude.am -lt*.m4 -Makefile.in -/Makefile -depcomp -missing -libtool -tags -.tags* -cyassl-config -wolfssl-config -cmake/wolfssl-config.cmake -cmake/wolfssl-config-version.cmake -cmake/wolfssl-targets.cmake -cyassl.sublime* -fips.h -fips.c -fips_test.c -fips -wolfcrypt_first.c -wolfcrypt_last.c -selftest.c -fipsv2.c -ctaocrypt/benchmark/benchmark -ctaocrypt/test/testctaocrypt -wolfcrypt/benchmark/benchmark -wolfcrypt/test/testwolfcrypt -examples/async/async_client -examples/async/async_server -examples/benchmark/tls_bench -examples/client/client -examples/echoclient/echoclient -examples/echoserver/echoserver -examples/server/server -examples/sctp/sctp-server -examples/sctp/sctp-server-dtls -examples/sctp/sctp-client -examples/sctp/sctp-client-dtls -examples/asn1/asn1 -examples/pem/pem -examples/ocsp_responder/ocsp_responder -server_ready -snifftest -output -mcapi/test -testsuite/testsuite -testsuite/testsuite.test -testsuite/*.der -testsuite/*.pem -testsuite/*.raw -testsuite/*.obj -testsuite/*.pdb -testsuite/*.idb -tests/unit -tests/unit.test -tests/bio_write_test.txt -tests/test-log-dump-to-file.txt -tests/cert_cache.tmp -test-write-dhparams.pem -cert.der -cert.pem -certecc.der -certecc.pem -othercert.der -othercert.pem -certeccrsa.der -certeccrsa.pem -ntru-cert.der -ntru-cert.pem -ntru-key.raw -key.der -key.pem -ecc-public-key.der -ecc-key-pkcs8.der -ecc-key.der -ecc-key.pem -certreq.der -certreq.pem -crlRsaOut.pem -crlRsaOut.der -crlEccOut.pem -crlEccOut.der -pkcs7cert.der -pkcs7authEnvelopedDataAES128GCM.der -pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der -pkcs7authEnvelopedDataAES128GCM_KEKRI.der -pkcs7authEnvelopedDataAES128GCM_ORI.der -pkcs7authEnvelopedDataAES128GCM_PWRI.der -pkcs7authEnvelopedDataAES192GCM.der -pkcs7authEnvelopedDataAES256GCM.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der -pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der -pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der -pkcs7authEnvelopedDataAES256GCM_IANDS.der -pkcs7authEnvelopedDataAES256GCM_SKID.der -pkcs7compressedData_data_zlib.der -pkcs7compressedData_firmwarePkgData_zlib.der -pkcs7encryptedDataAES128CBC.der -pkcs7encryptedDataAES192CBC.der -pkcs7encryptedDataAES256CBC.der -pkcs7encryptedDataAES256CBC_attribs.der -pkcs7encryptedDataAES256CBC_firmwarePkgData.der -pkcs7encryptedDataAES256CBC_multi_attribs.der -pkcs7encryptedDataDES.der -pkcs7encryptedDataDES3.der -pkcs7envelopedDataAES128CBC.der -pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der -pkcs7envelopedDataAES128CBC_KEKRI.der -pkcs7envelopedDataAES128CBC_PWRI.der -pkcs7envelopedDataAES128CBC_ORI.der -pkcs7envelopedDataAES192CBC.der -pkcs7envelopedDataAES256CBC.der -pkcs7envelopedDataAES256CBC_IANDS.der -pkcs7envelopedDataAES256CBC_SKID.der -pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der -pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der -pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der -pkcs7envelopedDataDES3.der -pkcs7signedData_ECDSA_SHA224.der -pkcs7signedData_ECDSA_SHA256_custom_contentType.der -pkcs7signedData_ECDSA_SHA256.der -pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der -pkcs7signedData_ECDSA_SHA256_SKID.der -pkcs7signedData_ECDSA_SHA384.der -pkcs7signedData_ECDSA_SHA512.der -pkcs7signedData_ECDSA_SHA.der -pkcs7signedData_ECDSA_SHA_noattr.der -pkcs7signedData_RSA_SHA224.der -pkcs7signedData_RSA_SHA256_custom_contentType.der -pkcs7signedData_RSA_SHA256.der -pkcs7signedData_RSA_SHA256_firmwarePkgData.der -pkcs7signedData_RSA_SHA256_SKID.der -pkcs7signedData_RSA_SHA256_with_ca_cert.der -pkcs7signedData_RSA_SHA256_detachedSig.der -pkcs7signedData_RSA_SHA384.der -pkcs7signedData_RSA_SHA512.der -pkcs7signedData_RSA_SHA.der -pkcs7signedData_RSA_SHA_noattr.der -pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der -pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der -pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der -pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der -pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der -pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der -pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der -pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der -pkcs7signedFirmwarePkgData_ECDSA_SHA256.der -pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der -pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der -pkcs7signedFirmwarePkgData_RSA_SHA256.der -pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der -pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der -pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der -pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der -pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der -pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der -pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der -diff -sslSniffer/sslSnifferTest/tracefile.txt -tracefile.txt -*.gz -*.zip -*.bak -*.dummy -*.xcworkspace -xcuserdata -compile -NTRU_algorithm/ -NTRU/ -build-test/ -build/ -cyassl.xcodeproj/ -cyassl*rc* -autoscan.log -TAGS -support/cyassl.pc -support/wolfssl.pc -cyassl/ctaocrypt/stamp-h1 -stamp-h1 -clang_output_* -internal.plist -cov-int -cyassl.tgz -*.log -*.trs -IDE/MDK-ARM/Projects/ -IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/inc -IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/src -IDE/MDK-ARM/LPC43xx/Drivers/ -IDE/MDK-ARM/LPC43xx/LPC43xx/ -*.gcno -*.gcda -*.gcov -*.dgcov -!linuxkm/Makefile -/Kbuild -linuxkm/*.ko -linuxkm/*.ko.signed -linuxkm/Module.symvers -linuxkm/built-in.a -linuxkm/modules.order -linuxkm/wolfcrypt -linuxkm/libwolfssl.mod -linuxkm/libwolfssl.mod.c -linuxkm/libwolfssl.lds -linuxkm/module_exports.c -linuxkm/linuxkm/get_thread_size -linuxkm/linuxkm -linuxkm/src -linuxkm/patches/src -linuxkm/libwolfssl-user-build -linuxkm/linuxkm-fips-hash -*.nds -bsdkm/export_syms -bsdkm/i386 -bsdkm/libwolfssl.ko -bsdkm/machine -bsdkm/opt_global.h -bsdkm/x86 -bsdkm/bus_if.h -bsdkm/cryptodev_if.h -bsdkm/device_if.h -scripts/unit.test -wolfcrypt/test/test_paths.h -mcapi/wolfcrypt_mcapi.X/nbproject/Makefile-* -mcapi/wolfcrypt_mcapi.X/nbproject/Package-default.bash -mcapi/wolfcrypt_test.X/nbproject/Makefile-* -mcapi/wolfcrypt_test.X/nbproject/Package-default.bash -mcapi/wolfssl.X/nbproject/Makefile-* -mcapi/wolfssl.X/nbproject/Package-default.bash -mcapi/zlib.X/nbproject/Makefile-* -mcapi/zlib.X/nbproject/Package-default.bash -mplabx/wolfcrypt_benchmark.X/nbproject/Makefile-* -mplabx/wolfcrypt_benchmark.X/nbproject/Package-default.bash -mplabx/wolfcrypt_test.X/nbproject/Makefile-* -mplabx/wolfcrypt_test.X/nbproject/Package-default.bash -mplabx/wolfssl.X/nbproject/Makefile-* -mplabx/wolfssl.X/nbproject/Package-default.bash -mplabx/wolfssl.X/nbproject/private -mplabx/wolfcrypt_test.X/nbproject/private -mplabx/wolfcrypt_benchmark.X/nbproject/private -mplabx/wolfssl.X/dist/default/ -mplabx/wolfcrypt_test.X/dist/default/ -mplabx/wolfcrypt_benchmark.X/dist/default/ -*.dSYM -.vagrant/ -mqx/cyassl/.settings -mqx/cyassl_client/.settings -mqx/cyassl_client/.cwGeneratedFileSetLog -mqx/cyassl_client/SaAnalysispointsManager.apconfig -mqx/util_lib/.settings -mqx/wolfcrypt_test/.settings -mqx/wolfcrypt_test/.cwGeneratedFileSetLog -mqx/wolfcrypt_test/SaAnalysispointsManager.apconfig -mqx/wolfcrypt_benchmark/.settings -mqx/wolfcrypt_benchmark/.cwGeneratedFileSetLog -mqx/wolfcrypt_benchmark/SaAnalysispointsManager.apconfig -wrapper/CSharp/x64/ -*.vscode -*.userprefs -*.exe -*.dll -.vs -Backup -UpgradeLog.htm -*.aps -*.VC.db -*.filters -IDE/INTIME-RTOS/Debug_* -IDE/VS-ARM/.vs -IDE/HEXIWEAR/wolfSSL_HW/Debug -IDE/LINUX-SGX/*.a -IDE/iotsafe/*.map -IDE/iotsafe/*.elf -IDE/iotsafe/*.bin -wolfcrypt/src/port/intel/qat_test -/mplabx/wolfssl.X/dist/default/ -/mplabx/wolfcrypt_test.X/dist/default/ -/IDE/ARDUINO/wolfSSL -scripts/memtest.txt -/IDE/ARDUINO/Arduino_README_prepend.md.tmp -/IDE/ARDUINO/library.properties.tmp -/IDE/ARDUINO/library.properties.tmp.backup -/IDE/ARDUINO/PREPENDED_README.md -doc/doxygen_warnings -doc/html -doc/pdf -IDE/XCODE/Index -IDE/**/xcshareddata -IDE/**/DerivedData -\.settings/ -\.cproject -\.project -\.autotools -/IDE/Renesas/e2studio/Projects/test/src/smc_gen -/IDE/Renesas/e2studio/Projects/test/trash -/IDE/Renesas/e2studio/Projects/test/*.launch -/IDE/Renesas/e2studio/Projects/test/*.scfg -/IDE/Renesas/e2studio/RX65N/GR-ROSE/.metadata -/IDE/Renesas/e2studio/RX65N/GR-ROSE/smc/src -/IDE/Renesas/e2studio/RX65N/GR-ROSE/smc/trash -/IDE/Renesas/e2studio/RX65N/GR-ROSE/test/src/smc_gen -/IDE/Renesas/e2studio/RX65N/GR-ROSE/test/generate -/IDE/Renesas/e2studio/RX65N/RSK/.metadata -/IDE/Renesas/e2studio/RX65N/RSK/smc/src -/IDE/Renesas/e2studio/RX65N/RSK/smc/trash -/IDE/Renesas/e2studio/RX65N/RSK/test/src/smc_gen -/IDE/Renesas/e2studio/RX65N/RSK/test/generate -/IDE/Renesas/e2studio/RX72N/EnvisionKit/.metadata -/IDE/Renesas/e2studio/RX72N/EnvisionKit/smc/src -/IDE/Renesas/e2studio/RX72N/EnvisionKit/smc/trash -/IDE/Renesas/e2studio/RX72N/EnvisionKit/test/src/smc_gen -/IDE/Renesas/e2studio/RX72N/EnvisionKit/test/generate -/IDE/QNX/example-server/server-tls -/IDE/QNX/example-client/client-tls -/IDE/QNX/example-cmac/cmac-test -/IDE/QNX/CAAM-DRIVER/wolfCrypt -/IDE/XilinxSDK/data -*~ -CMakeFiles/ -CMakeCache.txt -cmake_install.cmake -!cmake/Config.cmake.in -\.gdbinit -libFuzzer -\.idea -XXX-fips-test -/wolfAsyncCrypt -/async -user_settings_asm.h -**/.visualgdb -/IDE/Espressif/**/sdkconfig -/IDE/Espressif/**/sdkconfig.old -/IDE/Espressif/**/sdkconfig.debug -/IDE/Espressif/**/sdkconfig.release -/IDE/Espressif/**/sdkconfig-debug -/IDE/Espressif/**/sdkconfig-release -!/IDE/Espressif/**/Makefile -!/IDE/Espressif/**/component.mk -/IDE/Espressif/ESP-IDF/examples/**/logs/* -/IDE/MPLABX16/wolfssl.X/dist/default/ -/IDE/MPLABX16/wolfssl.X/.generated_files -/IDE/MPLABX16/wolfcrypt_test.X/dist/default/ -/IDE/MPLABX16/wolfcrypt_test.X/.generated_files -**/CMakeLists.txt.old -MagicCrypto -/out -/out_temp -debian/changelog -debian/control -debian/rules -*.deb -wrapper/Ada/alire/ -wrapper/Ada/config/ -wrapper/Ada/lib/ -wrapper/Ada/obj/ -/wrapper/rust/*/target/ -/**/.pio -/**/.vscode/.browse.c_cpp.db* -/**/.vscode/c_cpp_properties.json -/**/.vscode/launch.json -/**/.vscode/ipch -/**/sdkconfig.esp32dev -wolfssl/debug-trace-error-codes.h -wolfssl/debug-untrace-error-codes.h -.ai/ -compile_commands.json -__pycache__/ diff --git a/.gitmodules b/.gitmodules index 7909376..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "wolfssl-src/wolfssl"] - path = wolfssl-src/wolfssl - url = https://github.com/wolfSSL/wolfssl.git diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 2080244..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,84 +0,0 @@ -# Agent Instructions - -This project uses **bd** (beads) for issue tracking. Run `bd onboard` to get started. - -## Quick Reference - -```bash -bd ready # Find available work -bd show # View issue details -bd update --claim # Claim work atomically -bd close # Complete work -bd dolt push # Push beads data to remote -``` - -## Non-Interactive Shell Commands - -**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts. - -Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input. - -**Use these forms instead:** -```bash -# Force overwrite without prompting -cp -f source dest # NOT: cp source dest -mv -f source dest # NOT: mv source dest -rm -f file # NOT: rm file - -# For recursive operations -rm -rf directory # NOT: rm -r directory -cp -rf source dest # NOT: cp -r source dest -``` - -**Other commands that may prompt:** -- `scp` - use `-o BatchMode=yes` for non-interactive -- `ssh` - use `-o BatchMode=yes` to fail instead of prompting -- `apt-get` - use `-y` flag -- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var - - -## Beads Issue Tracker - -This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands. - -### Quick Reference - -```bash -bd ready # Find available work -bd show # View issue details -bd update --claim # Claim work -bd close # Complete work -``` - -### Rules - -- Use `bd` for ALL task tracking โ€” do NOT use TodoWrite, TaskCreate, or markdown TODO lists -- Run `bd prime` for detailed command reference and session close protocol -- Use `bd remember` for persistent knowledge โ€” do NOT use MEMORY.md files - -## Session Completion - -**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. - -**MANDATORY WORKFLOW:** - -1. **File issues for remaining work** - Create issues for anything that needs follow-up -2. **Run quality gates** (if code changed) - Tests, linters, builds -3. **Update issue status** - Close finished work, update in-progress items -4. **PUSH TO REMOTE** - This is MANDATORY: - ```bash - git pull --rebase - bd dolt push - git push - git status # MUST show "up to date with origin" - ``` -5. **Clean up** - Clear stashes, prune remote branches -6. **Verify** - All changes committed AND pushed -7. **Hand off** - Provide context for next session - -**CRITICAL RULES:** -- Work is NOT complete until `git push` succeeds -- NEVER stop before pushing - that leaves work stranded locally -- NEVER say "ready to push when you are" - YOU must push -- If push fails, resolve and retry until it succeeds - diff --git a/CLAUDE.md b/CLAUDE.md index 2a942fc..328f1c8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,165 +1,9 @@ -# CLAUDE.md +Think out loud before writing code. State your assumptions, your +chosen approach, and at least one alternative you rejected and +why. Flag anything uncertain. -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +Before each action, state what you're about to do and why. After each +action, state what you observed and what it implies for next steps. If +you hit something unexpected, stop and explain before proceeding. -## What This Is - -A Rust workspace providing bindings to wolfSSL/wolfCrypt. There are two API surfaces: -- **wolfcrypt**: RustCrypto trait implementations (digest, aead, cipher, signature, etc.) backed by wolfCrypt -- **wolfcrypt-ring-compat**: Drop-in `ring` v0.16 replacement via `[patch]` - -The workspace also contains Caliptra hardware integration crates for RISC-V firmware. - -## Tech Stack - -- Language: Rust (edition 2021; `wolfcrypt-wrapper` uses 2024) -- MSRV: 1.71.0 (core crates: `wolfcrypt-rs`, `wolfcrypt`) -- C layer: wolfSSL/wolfCrypt (compiled via `cc` crate or linked as pre-built) -- `no_std + alloc`: `wolfcrypt`, `wolfcrypt-dpe`, `wolfcrypt-dpe-hw` - -## Build & Library Discovery - -wolfSSL discovery order (controlled by `wolfcrypt-sys/build.rs`): -1. `WOLFSSL_LIB_DIR` + `WOLFSSL_INCLUDE_DIR` (pre-built, split paths) -2. `WOLFSSL_DIR` (install prefix, default from `.cargo/config.toml`: `~/wolfssl-install`) -3. `vendored` feature / `WOLFSSL_SRC` env โ€” compiles wolfSSL from source via `wolfssl-src` -4. pkg-config - -The pre-built install at `~/wolfssl-install` must have `HAVE_DILITHIUM` and `WOLF_CRYPTO_CB` enabled. The source tree at `~/wolfssl` is used for vendored/bare-metal builds. - -## Commands - -```bash -# Build (workspace) -cargo build - -# Test a single crate -cargo test -p wolfcrypt --all-targets -cargo test -p wolfcrypt-conformance - -# Test with both debug and release (as done in CI) -cargo test --all-targets -cargo test --release --all-targets - -# Lint -cargo +nightly clippy --all-targets -- -W clippy::all -W clippy::pedantic - -# Caliptra hardware tests (requires caliptra sw-emulator) -cargo test-caliptra # alias: test -p wolfcrypt-dpe-hw --features caliptra-2x,testing-hooks -cargo test-caliptra-mldsa # includes mldsa87-hw feature - -# RISC-V firmware build (bare-metal, cross-compiled via zig cc) -cargo build-caliptra-fw # alias: build -p wolfcrypt-dpe --features cryptocb-only --target riscv32imc-unknown-none-elf -cargo build-caliptra-hw-pure # alias: build -p wolfcrypt-dpe-hw --features caliptra-2x,cryptocb-pure - -# Hardware conformance binary -cargo conformance-caliptra # alias: run -p wolfcrypt-conformance --bin caliptra_hw_conformance --features wolfcrypt-conformance/caliptra-hw -``` - -## Crate Architecture - -``` -wolfssl-src Compiles wolfSSL C source (cc crate); selects user_settings.h per feature - โ†“ -wolfcrypt-sys FFI bindings (bindgen); emits 60+ cfg flags (wolfssl_aes_gcm, wolfssl_ecc_p384, โ€ฆ) - โ†“ -wolfcrypt-rs Low-level Rust wrapper + compat_shim.c; re-exports metadata via `links = "wolfssl"` - โ†“ -โ”œโ”€โ”€ wolfcrypt RustCrypto trait impls (no_std + alloc) -โ”œโ”€โ”€ wolfcrypt-ring-compat Drop-in ring replacement (published as `ring` via [patch]) -โ”œโ”€โ”€ wolfcrypt-dpe Caliptra DPE crypto trait impl (no_std + alloc) -โ””โ”€โ”€ wolfcrypt-dpe-hw Caliptra hardware backend; CryptoCb dispatch to caliptra-drivers -``` - -`wolfcrypt-conformance` is the primary test crate: NIST CAVP vectors, Wycheproof, and cross-validation against pure-Rust RustCrypto implementations. - -## Feature Flag System - -`wolfssl-src` features select which `user_settings.h` is compiled: -- *(default)*: full-featured build (OpenSSL compat, all algorithms, WOLF_CRYPTO_CB) -- `cryptocb-only`: CryptoCb dispatch only; software stubs compiled but all calls dispatched to callbacks; excludes SP math -- `cryptocb-pure`: absolute minimum โ€” CryptoCb + type defs, no OPENSSL_EXTRA/HKDF/ASN; intended for pure HW routing -- `riscv-bare-metal`: bare-metal platform stubs, no stdio/pthread - -`wolfcrypt-sys` parses the compiled wolfSSL defines and emits corresponding `rustc-cfg` flags (e.g. `wolfssl_aes_gcm`, `wolfssl_dilithium`). Downstream crates gate code on these cfg flags. - -`wolfcrypt` exposes 60+ Cargo features, one per algorithm/trait group. `require-dev-id` removes the software `WolfRng::new()` path, forcing CryptoCb hardware device ID usage. - -## Metadata Propagation - -Cargo's `links` mechanism carries build metadata across crate boundaries: -- `wolfcrypt-sys` (links = `wolfcrypt_sys`) โ†’ emits `DEP_WOLFCRYPT_SYS_{CFGS,INCLUDE,ROOT,VERSION,โ€ฆ}` -- `wolfcrypt-rs` (links = `wolfssl`) โ†’ re-exports as `DEP_WOLFSSL_*` for `wolfcrypt-ring-compat` and others -- Downstream build scripts read these via `env!("DEP_โ€ฆ")` to avoid redundant discovery - -## Conventions - -- Cargo features are additive and map 1:1 to algorithm groups; never enable an algorithm unconditionally in `Cargo.toml` โ€” gate it behind a feature. -- `wolfcrypt-sys` cfg flags (`wolfssl_*`) are the source of truth for what the linked wolfSSL supports; use them to `#[cfg]`-gate code rather than duplicating Cargo feature checks. -- All `unsafe` blocks must be in `wolfcrypt-rs` or `wolfcrypt-sys`; higher-level crates (`wolfcrypt`, `wolfcrypt-dpe`) must be safe Rust. -- Workspace resolver v2 is required; do not change to v1. - -## Test Design Constraint - -Tests must use an independent oracle: known test vectors from an external source (NIST CAVP, Wycheproof) or cross-validation between wolfcrypt and a pure-Rust RustCrypto implementation. Do not write tests that encrypt with wolfcrypt and decrypt with wolfcrypt โ€” that proves nothing. - -## Key External Dependencies - -- `~/wolfssl` โ€” wolfSSL C source tree (must be checked out separately) -- `~/wolfssl-install` โ€” pre-built wolfSSL with `HAVE_DILITHIUM` + `WOLF_CRYPTO_CB` -- `../../caliptra/` โ€” caliptra repo (sibling) for `caliptra-drivers` and sw-emulator -- RISC-V cross-compiler: `.cargo/riscv32-cc` (zig cc wrapper, committed) - -## Version Constraints - -RustCrypto trait versions are pinned: `digest 0.10`, `cipher 0.4`, `aead 0.5`, `signature 2.2`. Upgrades are blocked on the upstream `generic-array โ†’ hybrid-array` migration (digest 0.11, cipher 0.5). Do not bump these without checking the full trait migration chain. - -Several git dependencies (caliptra-dpe, ssh-encoding/ssh-cipher) are pinned to exact commits because they are not yet published to crates.io. - - - -## Beads Issue Tracker - -This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands. - -### Quick Reference - -```bash -bd ready # Find available work -bd show # View issue details -bd update --claim # Claim work -bd close # Complete work -``` - -### Rules - -- Use `bd` for ALL task tracking โ€” do NOT use TodoWrite, TaskCreate, or markdown TODO lists -- Run `bd prime` for detailed command reference and session close protocol -- Use `bd remember` for persistent knowledge โ€” do NOT use MEMORY.md files - -## Session Completion - -**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. - -**MANDATORY WORKFLOW:** - -1. **File issues for remaining work** - Create issues for anything that needs follow-up -2. **Run quality gates** (if code changed) - Tests, linters, builds -3. **Update issue status** - Close finished work, update in-progress items -4. **PUSH TO REMOTE** - This is MANDATORY: - ```bash - git pull --rebase - bd dolt push - git push - git status # MUST show "up to date with origin" - ``` -5. **Clean up** - Clear stashes, prune remote branches -6. **Verify** - All changes committed AND pushed -7. **Hand off** - Provide context for next session - -**CRITICAL RULES:** -- Work is NOT complete until `git push` succeeds -- NEVER stop before pushing - that leaves work stranded locally -- NEVER say "ready to push when you are" - YOU must push -- If push fails, resolve and retry until it succeeds - +Always ultrathink. diff --git a/Cargo.toml b/Cargo.toml index 557eec7..66a47e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,8 +21,8 @@ members = [ "wolfcrypt", "wolfcrypt-ring-testing", "links-testing", + "builder-test", "wolfcrypt-dpe", - "wolfcrypt-dpe-hw", "wolfcrypt-sys", "wolfssl-src", "wolfcrypt-wrapper", @@ -50,7 +50,7 @@ cmake = "0.1.54" dunce = "1.0.5" fs_extra = "1.3.0" regex = "1.11.1" -untrusted = "0.7.1" +untrusted = "0.9.0" spin = "0.9.8" zeroize = "1.8.1" diff --git a/README.md b/README.md index 9a38b0d..9b28ad9 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ stable 0.3 releases. | `wolfcrypt-ring-testing` | Integration tests for the ring-compatible API. | | `wolfcrypt-dpe-conformance` | Cross-validates wolfcrypt-dpe against the caliptra-dpe reference implementation. | | `links-testing` | Validates the cargo metadata propagation chain. | +| `builder-test` | Tests build script modules as a library. | ## Building @@ -86,21 +87,6 @@ wolfSSL source discovery (in priority order): 3. `vendored` feature on `wolfcrypt-sys` (default: compile from source) 4. `pkg-config` -### Pre-built installs with `user_settings.h` - -If you built wolfSSL with `--enable-usersettings` (i.e. `-DWOLFSSL_USER_SETTINGS`), -the installed `wolfssl/options.h` will define `WOLFSSL_USER_SETTINGS`, causing -`wolfssl/wolfcrypt/settings.h` to `#include "user_settings.h"` at build time. -When using `WOLFSSL_DIR` to point at such an install, `user_settings.h` must be -findable on the include path โ€” copy it into the install's `include/` directory: - -```sh -cp /path/to/user_settings.h $WOLFSSL_DIR/include/ -``` - -wolfSSL installs built with plain `./configure` flags (no `--enable-usersettings`) -do not have this requirement; their `options.h` is self-contained. - ## FIPS 140-3 These crates expose a `fips` feature flag that enables the wolfSSL FIPS 140-3 diff --git a/builder-test/Cargo.toml b/builder-test/Cargo.toml new file mode 100644 index 0000000..a7cef37 --- /dev/null +++ b/builder-test/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "builder-test" +version = "0.1.0" +edition = "2021" +license = "MIT" +publish = false +description = "Test harness for wolfcrypt-rs builder modules - does not duplicate code" + +# Silence warnings that are expected when compiling builder code as a library. +# The builder code is designed to run as a build script, so many functions +# appear "unused" when compiled as a library for testing purposes. +[lints.rust] +dead_code = "allow" +unused = "allow" + +# Point to the actual builder/main.rs as the library source +# The #[cfg(test)] module in main.rs will be compiled and run +[lib] +name = "builder" +path = "../builder/main.rs" + +[dependencies] +# All dependencies that builder/main.rs requires +cc = { workspace = true, features = ["parallel"] } +cmake = { workspace = true } +dunce = { workspace = true } +fs_extra = { workspace = true } +bindgen = { workspace = true, optional = true } + +[features] +default = [] +# Mirror the features from wolfcrypt-rs that affect builder compilation +bindgen = ["dep:bindgen"] +fips = ["dep:bindgen"] +ssl = ["bindgen"] +all-bindings = [] +prebuilt-nasm = [] +disable-prebuilt-nasm = [] +asan = [] diff --git a/rustcrypto-issue-drafts.md b/rustcrypto-issue-drafts.md deleted file mode 100644 index 69db8f8..0000000 --- a/rustcrypto-issue-drafts.md +++ /dev/null @@ -1,894 +0,0 @@ -# RustCrypto Issue Drafts - -These issues were discovered while implementing the `wolfcrypt` crate -([`wolfSSL/wolfssl-rs`](https://github.com/wolfSSL/wolfssl-rs)), which wraps -wolfCrypt โ€” a widely-deployed, FIPS 140-3 validated C cryptographic library โ€” -behind the standard RustCrypto trait interfaces (`digest`, `cipher`, `aead`, -`signature`, `rand_core`). - -wolfCrypt is unusual among RustCrypto backends in two ways. First, it is a C -FFI backend, so operations that are infallible in pure Rust (allocation, state -initialization) can fail at the C layer. Second, it supports hardware -dispatch via its `WOLF_CRYPTO_CB` callback mechanism, which routes individual -algorithm operations to hardware accelerators or HSMs at runtime. This means -that *every* crypto operation โ€” not just key generation โ€” can fail with a -device-specific error code at any point. - -Together these two properties exposed gaps in the RustCrypto trait design that -pure-Rust implementations never encounter. Each issue below documents one gap, -the exact workaround we were forced to use, and a proposed fix. Code links -point to commit `0f3af10` of `wolfSSL/wolfssl-rs`. - -If any of these are already tracked elsewhere, please point us to the existing -issue. - ---- - -## Issue 1: Infallible constructors prevent FFI and hardware backends from reporting initialization failures - -**Repo:** `RustCrypto/traits` -**Labels:** `api-design`, `digest`, `cipher`, `aead` - -### Background - -Several RustCrypto traits define constructors that return `Self` rather than -`Result`: - -- `KeyInit::new(key: &Key) -> Self` (used by `cipher`, `aead`, `mac`) -- `Digest::new() -> Self` (via `Default::default()`) -- `KeyIvInit::new(key: &Key, iv: &Iv) -> Self` - -This is a reasonable design for pure-Rust implementations: once the key bytes -are valid (enforced by the type-level `GenericArray`), construction -cannot fail. There is nothing else to go wrong. - -### The problem - -For an FFI or hardware backend, "key bytes are valid" is necessary but not -sufficient. Construction can fail for reasons that have nothing to do with the -key material: - -- **C heap allocation failure** โ€” wolfCrypt heap-allocates its hash and HMAC - context structs (`wc_Sha256`, `Hmac`, etc.) because their sizes are not - stable across wolfSSL versions. If the allocator returns NULL, there is - nothing the Rust type can do except panic or return zeroed memory. -- **Library not yet initialized** โ€” wolfCrypt requires `wolfCrypt_Init()` to be - called once at program startup. Constructing a hash context before that - returns an error code. -- **Hardware device unavailable** โ€” when `WOLF_CRYPTO_CB` is active and a - hardware device ID is registered, key schedule setup is dispatched to the - hardware. If the HSM is offline or busy, `wc_AesGcmSetKey` returns a - non-zero error code. - -The trait's `Self` return type gives us nowhere to put that error. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -Every constructor in the `wolfcrypt` crate that implements an infallible trait -method must `assert!` on the C return code, converting all initialization -failures into panics: - -- AES-GCM `KeyInit::new` asserts on `wc_AesInit` and `wc_AesGcmSetKey`: - [`wolfcrypt/src/aead.rs:60-70`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/aead.rs#L60-L70) -- SHA-256 `Default::default` asserts that the heap-allocated context pointer is - non-null: [`wolfcrypt/src/digest.rs:57`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/digest.rs#L57) -- HMAC `KeyInit::new` (via `init_with_key`) asserts on the allocator return: - [`wolfcrypt/src/hmac.rs:64`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/hmac.rs#L64) -- The crate-level documentation explains the policy and why it was unavoidable: - [`wolfcrypt/src/lib.rs:75-85`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L75-L85) - -### Why the obvious alternative doesn't work - -`KeyInit::new_from_slice` returns `Result`, but its error type is -`InvalidLength` โ€” it signals that the key bytes were the wrong size. It is -not an appropriate channel for "the C allocator returned NULL" or "the HSM is -offline." - -### Proposed change - -Add a fallible constructor to the affected traits, leaving the infallible -version in place for pure-Rust implementations: - -```rust -// In KeyInit: -fn try_new(key: &Key) -> Result; - -// Or as a separate trait with a blanket impl: -pub trait TryKeyInit: Sized { - type Error: Error; - fn try_new(key: &Key) -> Result; -} - -impl TryKeyInit for T { - type Error = Infallible; - fn try_new(key: &Key) -> Result { - Ok(Self::new(key)) - } -} -``` - -The separate-trait approach avoids any breaking change: existing code using -`KeyInit::new` continues to compile, and FFI backends implement `TryKeyInit` -instead of (or in addition to) `KeyInit`. - ---- - -## Issue 2: `KeyInit` and related traits impose no `ZeroizeOnDrop` requirement on key-holding types - -**Repo:** `RustCrypto/traits` -**Labels:** `api-design`, `security`, `zeroize` - -### Background - -`KeyInit::new` and `KeyIvInit::new` create values that hold secret key -material โ€” AES key schedules, HMAC keys, ECDSA signing keys. The `zeroize` -crate provides `ZeroizeOnDrop`, a marker trait that guarantees memory holding -secret material is overwritten before it is freed. - -### The problem - -The `KeyInit` trait has no `ZeroizeOnDrop` supertrait bound and no -documentation requirement that implementors zeroize on drop. Every implementor -must independently remember to add the guarantee. The compiler does not warn -if it is missing. - -This is a latent correctness problem for the ecosystem. A crate that -implements `KeyInit` but forgets `ZeroizeOnDrop` compiles, passes tests, and -leaks key material from freed memory โ€” silently. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -The `wolfcrypt` crate has at least ten distinct `impl Drop` blocks that call -the appropriate wolfCrypt free function and/or zeroize backing memory. Each -one was written by hand, with no trait-level prompt that it was necessary: - -- `Ed25519SigningKey::drop` calls `wc_ed25519_free` and `wc_FreeRng`: - [`wolfcrypt/src/ed25519.rs:158-167`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ed25519.rs#L158-L167) -- `Ed25519VerifyingKey::drop` calls `wc_ed25519_free`: - [`wolfcrypt/src/ed25519.rs:243-251`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ed25519.rs#L243-L251) -- `EccKey::drop` calls `wc_ecc_key_free`: - [`wolfcrypt/src/ecc.rs:332-341`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ecc.rs#L332-L341) -- HMAC `Drop` calls `wolfcrypt_hmac_free`: - [`wolfcrypt/src/hmac.rs:38-45`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/hmac.rs#L38-L45) -- Digest macro-generated `Drop` calls the appropriate `wc_Sha*_Free`: - [`wolfcrypt/src/digest.rs:73-79`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/digest.rs#L73-L79) - -### Proposed change - -Add `ZeroizeOnDrop` as a supertrait on `KeyInit`: - -```rust -pub trait KeyInit: KeySizeUser + Sized + ZeroizeOnDrop { - fn new(key: &Key) -> Self; - // ... -} -``` - -This is a breaking change for any existing `KeyInit` impl that does not already -derive or implement `ZeroizeOnDrop`. For most pure-Rust crates, adding -`#[derive(ZeroizeOnDrop)]` or `impl ZeroizeOnDrop for MyKey {}` is a -one-line fix. - -If a full supertrait bound is too disruptive for this release cycle, an -intermediate option is to document the requirement explicitly (with a -`#[must_implement = "ZeroizeOnDrop"]` lint or clippy rule) so that missing -implementations are at least detectable. - ---- - -## Issue 3: No non-allocating separate-input/output AEAD interface; `AeadInPlace` is the only option for allocation-free code - -**Repo:** `RustCrypto/traits` -**Labels:** `api-design`, `aead`, `no-alloc` - -### Background - -The `aead` crate provides two interfaces: - -- `Aead::encrypt(nonce, payload) -> Result>` โ€” allocates a `Vec` for - the output. -- `AeadInPlace::encrypt_in_place_detached(nonce, aad, buffer)` โ€” mutates the - plaintext buffer in-place; no allocation. - -For `no_std + no alloc` code, `Aead::encrypt` is unavailable because it -requires `alloc`. The only option is `AeadInPlace`. - -### The problem - -`AeadInPlace` requires that the plaintext and ciphertext occupy the *same* -buffer. For some hardware and C library backends, this is not possible: - -- **DMA-based hardware accelerators** write output to a separate DMA destination - buffer. They physically cannot write the ciphertext back over the plaintext - in the same memory region. -- **C one-shot APIs** โ€” wolfCrypt's `wc_ChaCha20Poly1305_Encrypt` takes - separate `inData` and `outData` pointers. There is no API contract that - `inData == outData` is safe; the function may read from `inData` and write - to `outData` simultaneously in ways that are undefined if they overlap. - -The net result: a backend with a separate-buffer C API or DMA engine has no -allocation-free path to satisfy `AeadInPlace`. Either it allocates a staging -buffer (negating the purpose of `AeadInPlace`) or it is ineligible to -implement the trait at all. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -We discovered this when implementing ChaCha20-Poly1305. wolfCrypt's one-shot -API (`wc_ChaCha20Poly1305_Encrypt`) requires separate source and destination -pointers. Wiring it to `AeadInPlace` would have required a heap allocation per -call to stage the output before copying it back over the input. - -We worked around it by switching to wolfCrypt's streaming ChaCha20-Poly1305 API -(`wc_ChaCha20Poly1305_Init` / `UpdateData` / `Final`), which explicitly -supports identical `input == output` pointers via XOR-based keystream -application. That escape hatch happened to exist for ChaCha20-Poly1305. It -will not exist for every algorithm or every hardware backend. - -- Comment explaining the streaming API choice: - [`wolfcrypt/src/aead.rs:198-207`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/aead.rs#L198-L207) -- The streaming `wc_ChaCha20Poly1305_Init` call replacing the one-shot API: - [`wolfcrypt/src/aead.rs:255-265`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/aead.rs#L255-L265) -- Crate-level docs explain the tradeoff: - [`wolfcrypt/src/lib.rs:97-108`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L97-L108) - -### Why `Aead::encrypt` doesn't solve this - -`Aead::encrypt` takes separate input and output, but returns `Vec`. It -requires `alloc` and is not available in `no_std` firmware targets. A -DMA-backed hardware accelerator running on bare metal cannot use it. - -### Proposed change - -Add a non-allocating, separate-buffer AEAD trait alongside `AeadInPlace`: - -```rust -pub trait AeadOutOfPlace: AeadCore + KeySizeUser { - fn encrypt_into( - &self, - nonce: &Nonce, - aad: &[u8], - plaintext: &[u8], - ciphertext_out: &mut [u8], // must be >= plaintext.len() + Self::TagSize - ) -> Result<(), Error>; - - fn decrypt_into( - &self, - nonce: &Nonce, - aad: &[u8], - ciphertext: &[u8], - plaintext_out: &mut [u8], - ) -> Result<(), Error>; -} -``` - -A blanket `impl AeadOutOfPlace for T` would give existing -implementations the two-buffer interface automatically (at the cost of one -`copy_from_slice`), while hardware backends that can do better implement it -directly. No existing code breaks. - ---- - -## Issue 4: No traits for HKDF or PBKDF2; alternative backends cannot interoperate with generic callers - -**Repo:** `RustCrypto/traits` -**Labels:** `api-design`, `hkdf`, `pbkdf2` - -### Background - -The `digest`, `cipher`, and `aead` crates define traits (`Digest`, `KeyInit`, -`AeadInPlace`) that any implementation can satisfy, making backends -interchangeable. The `hkdf` and `pbkdf2` crates are different: they provide -concrete implementations, not traits. - -There is no `HkdfExpand` trait, no `Pbkdf2` trait. A function that needs -"some HKDF implementation" must name `hkdf::Hkdf` explicitly. - -### The problem - -This makes it impossible to swap in an alternative HKDF or PBKDF2 backend -without forking calling code. The two most important cases where an -alternative backend matters are: - -1. **FIPS 140-3 validated builds** โ€” the validated HKDF and PBKDF2 - implementations are in wolfCrypt, not in the pure-Rust `hkdf`/`pbkdf2` - crates. A validated build must route through wolfCrypt's `wc_HKDF` and - `wc_PBKDF2`. Without a trait, any library that calls `hkdf::Hkdf::expand` - directly cannot be used with a FIPS-validated backend. - -2. **Hardware-accelerated key derivation** โ€” some HSMs provide HKDF and PBKDF2 - as hardware-accelerated primitives. There is no way to dispatch through - them from generic Rust code that uses the `hkdf` or `pbkdf2` crates. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -The `wolfcrypt` crate's `hkdf` and `pbkdf2` modules expose bespoke APIs whose -method names mirror the `hkdf` and `pbkdf2` crates by convention, not by -trait: - -- `hkdf` module header explains the absence of a trait: - [`wolfcrypt/src/hkdf.rs:1-21`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/hkdf.rs#L1-L21) -- Bespoke `new` / `extract` / `expand` API that mirrors `hkdf::Hkdf` by name - only: [`wolfcrypt/src/hkdf.rs:46-134`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/hkdf.rs#L46-L134) -- `pbkdf2` module and standalone functions: - [`wolfcrypt/src/pbkdf2.rs:1-92`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/pbkdf2.rs#L1-L92) -- Crate-level docs explain why these are bespoke: - [`wolfcrypt/src/lib.rs:110-121`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L110-L121) - -### Proposed change - -Define traits in a `kdf-traits` crate (or in `RustCrypto/traits`): - -```rust -pub trait HkdfExpand { - type Error; - fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), Self::Error>; -} - -pub trait HkdfExtract { - type Prk: HkdfExpand; - fn extract(salt: Option<&[u8]>, ikm: &[u8]) -> Self::Prk; -} - -pub trait Pbkdf2 { - type Error; - fn pbkdf2(password: &[u8], salt: &[u8], rounds: u32, output: &mut [u8]) -> Result<(), Self::Error>; -} -``` - -The concrete `hkdf::Hkdf` and `pbkdf2::pbkdf2_hmac` would implement these -traits. Alternative backends (wolfCrypt, BoringSSL, HSMs) implement them -independently. Generic code parameterizes over `impl HkdfExpand` instead of -naming a concrete type. - ---- - -## Issue 5: `pbkdf2_hmac` requires low-level digest internals that opaque FFI backends structurally cannot provide - -**Repo:** `RustCrypto/traits` (affects `pbkdf2` crate) -**Labels:** `api-design`, `pbkdf2`, `digest` - -### Background - -The `digest` crate has two implementation tiers: - -**High-level tier** โ€” the public API: -- `digest::Update::update(&mut self, data: &[u8])` -- `digest::FixedOutput::finalize_into(self, out: &mut Output)` -- The blanket `Digest` impl combines these with `Clone + Default + HashMarker`. - -**Low-level (`core_api`) tier** โ€” the composable building blocks: -- `UpdateCore::update_blocks(&mut self, blocks: &[Block])` โ€” processes - data one fixed-size block at a time. -- `FixedOutputCore::finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output)` -- `BufferKindUser` โ€” specifies how the type buffers partial blocks. -- `CoreProxy` โ€” a supertrait that bundles these together. - -The low-level tier exists so that `hmac::SimpleHmac` can be built from any -digest without knowing the concrete type. `SimpleHmac` is bounded on -`D: CoreProxy`. `pbkdf2_hmac` builds a `SimpleHmac` internally, so it -transitively requires `D: CoreProxy`. - -### The problem - -An opaque FFI wrapper structurally cannot implement the `core_api` tier. -`UpdateCore::update_blocks` requires processing data *exactly one fixed-size -block at a time*, handing partial blocks to a `Buffer` abstraction. wolfCrypt's -`wc_Sha256Update` accepts arbitrary-length slices and handles its own internal -buffering in C. There is no C API to call with individual 64-byte SHA-256 -blocks and get back a partially-updated state. - -This is not a matter of effort โ€” the block-level API simply does not exist in -the C library. The C implementation buffers internally and exposes only the -`update(data: *const u8, len: u32)` / `final(out: *mut u8)` interface. - -Note: our digest types *do* implement `BlockSizeUser` (block size is a compile- -time constant we know) and the full high-level `Digest` trait: -[`wolfcrypt/src/digest.rs:87-89`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/digest.rs#L87-L89). -The gap is specifically `UpdateCore` and `FixedOutputCore` โ€” the block-granular -streaming API that `CoreProxy` requires. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -Despite implementing the complete high-level `Digest` trait, our types cannot -be used with `pbkdf2_hmac`: - -``` -error[E0277]: the trait bound `WolfSha256: CoreProxy` is not satisfied -``` - -We cannot satisfy this bound because `CoreProxy` requires `UpdateCore`, which -requires a block-level C API that wolfCrypt does not expose. - -- `pbkdf2` module header explains the `CoreProxy` block: - [`wolfcrypt/src/pbkdf2.rs:6-9`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/pbkdf2.rs#L6-L9) -- Crate-level docs ยง "The `CoreProxy` cliff": - [`wolfcrypt/src/lib.rs:123-134`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L123-L134) -- Workaround โ€” native `pbkdf2_hmac_sha256` calling `wc_PBKDF2` directly: - [`wolfcrypt/src/pbkdf2.rs:28-92`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/pbkdf2.rs#L28-L92) - -### Proposed change - -The root cause is that `pbkdf2_hmac` forces the construction of `SimpleHmac` -internally, pulling in the `CoreProxy` requirement. A version that accepts a -`Mac` directly (already keyed with the password) would remove this: - -```rust -pub fn pbkdf2_with_mac( - password: &[u8], - salt: &[u8], - rounds: u32, - res: &mut [u8], -) -> Result<(), InvalidLength> -``` - -Callers who currently use `pbkdf2_hmac::(password, salt, rounds, out)` -could migrate to `pbkdf2_with_mac::(password, salt, rounds, out)`. -FFI backends implement `Mac` (the high-level MAC trait, which only requires -`update` and `finalize_into`) and become immediately usable. - ---- - -## Issue 6: `pbkdf2::pbkdf2` has an unconditional `PRF: Sync` bound; correctly `!Sync` MAC types cannot use it even single-threaded - -**Repo:** `RustCrypto/traits` (affects `pbkdf2` crate) -**Labels:** `api-design`, `pbkdf2` - -### Background - -`pbkdf2::pbkdf2` has this signature (simplified): - -```rust -pub fn pbkdf2(prf: PRF, salt: &[u8], rounds: u32, res: &mut [u8]) - -> Result<(), InvalidLength> -``` - -The `Sync` bound exists to support the `parallel` feature, which distributes -PBKDF2 rounds across a thread pool. When multiple threads run rounds -concurrently, they need to share the PRF instance โ€” hence `Sync`. - -### The problem - -The `Sync` bound is present unconditionally, even when the `parallel` feature -is disabled and the function runs entirely on a single thread. A type that is -correctly `!Sync` โ€” because it holds interior mutable state that is unsafe to -share โ€” cannot call `pbkdf2`, even in a single-threaded program with -`parallel = false`. - -This is a logic error in the API: `Sync` is a *sharing* guarantee, and no -sharing occurs when `parallel` is off. Requiring it in that case excludes -legitimate types for no benefit. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -wolfCrypt's EVP-based digest types (`WolfSha256`, etc.) are `!Sync`. The -`EVP_MD_CTX` C struct contains interior mutable state โ€” counter values, partial -block buffers โ€” that is updated on every call. It is not safe to read from two -threads simultaneously. Marking these types `Sync` would be unsound. - -Because `pbkdf2::pbkdf2` requires `PRF: Sync` unconditionally, this does not -compile even in a single-threaded binary with `parallel = false`: - -```rust -pbkdf2::pbkdf2::>(password, salt, rounds, &mut out)?; -// error[E0277]: `WolfSha256` cannot be shared between threads safely -// = help: the trait `Sync` is not implemented for `WolfSha256` -// note: required by a bound in `pbkdf2` -``` - -- Crate-level docs ยง "`pbkdf2::pbkdf2` requires `Sync` unconditionally": - [`wolfcrypt/src/lib.rs:136-145`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L136-L145) -- `pbkdf2` module explains why `SimpleHmac` is blocked: - [`wolfcrypt/src/pbkdf2.rs:8-16`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/pbkdf2.rs#L8-L16) -- AES-GCM documents why the types are `!Sync`: - [`wolfcrypt/src/aead.rs:22-27`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/aead.rs#L22-L27) - -### Proposed change - -Gate the `Sync` bound on the `parallel` feature flag: - -```rust -#[cfg(feature = "parallel")] -pub fn pbkdf2( - prf: PRF, salt: &[u8], rounds: u32, res: &mut [u8], -) -> Result<(), InvalidLength> { ... } - -#[cfg(not(feature = "parallel"))] -pub fn pbkdf2( - prf: PRF, salt: &[u8], rounds: u32, res: &mut [u8], -) -> Result<(), InvalidLength> { ... } -``` - -This is fully backward-compatible: all existing callers use `Sync` types and -are unaffected. Callers with `!Sync` types gain access to the function when -`parallel` is not enabled. This is the smallest and most self-contained change -in this set of issues. - ---- - -## Issue 7: `SignatureEncoding::Repr` cannot represent variable-length or large post-quantum signatures - -**Repo:** `RustCrypto/traits` -**Labels:** `api-design`, `signature`, `post-quantum` - -### Background - -`signature::SignatureEncoding` allows a signature type to describe its wire -encoding: - -```rust -pub trait SignatureEncoding: Clone + Sized + for<'a> TryFrom<&'a [u8]> { - type Repr: 'static + AsRef<[u8]> + Clone + Send + Sync; -} -``` - -For classical signature schemes, `Repr` is always a fixed-size array. -Ed25519 signatures are exactly 64 bytes, so `type Repr = [u8; 64]`. -ECDSA-P256 (DER) is bounded and small. The fixed-size array approach -compiles to stack allocation with no indirection. - -### The problem - -Post-quantum signature schemes break this model in two ways: - -**1. Large sizes.** ML-DSA-87 (FIPS 204) signatures are 4,627 bytes. A -`[u8; 4627]` Repr is technically valid Rust, but it is 4 KB of stack space -per signature โ€” enough to overflow typical embedded stacks. Stack-allocating -signatures is inappropriate for PQC. - -**2. Parameter-set variation.** The ML-DSA family has three parameter sets -with different signature sizes: ML-DSA-44 (2,420 bytes), ML-DSA-65 (3,309 -bytes), ML-DSA-87 (4,627 bytes). A generic `MlDsaSignature` type that -covers all three cannot have a single `[u8; N]` Repr because `N` is not a -single constant โ€” it varies with `L`. The `typenum`-based const-generic -approach works for key sizes but becomes unwieldy for unifying signature sizes -across a generic parameter. - -**3. SPHINCS+, XMSS, and other schemes** have variable-length or -parameter-set-dependent sizes for the same reasons. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -We implemented ML-DSA (FIPS 204) signing and verifying keys behind `Signer` -and `Verifier`. We use `Repr = Box<[u8]>` as the only workable choice: - -- `type Repr = Box<[u8]>` in the ML-DSA `SignatureEncoding` impl: - [`wolfcrypt/src/mldsa.rs:71-73`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/mldsa.rs#L71-L73) -- `From> for Box<[u8]>` conversion: - [`wolfcrypt/src/mldsa.rs:87-91`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/mldsa.rs#L87-L91) -- Crate-level docs ยง "`SignatureEncoding::Repr` assumes fixed-size signatures": - [`wolfcrypt/src/lib.rs:147-155`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L147-L155) - -`Box<[u8]>` satisfies the `'static + AsRef<[u8]> + Clone + Send + Sync` bounds, -so it compiles. But it heap-allocates on every `Into` conversion, and -downstream code that calls `sig.to_bytes()` gets a `Box<[u8]>` with no -compile-time size information. - -### Proposed change - -There are several options of increasing complexity: - -1. **Document `Box<[u8]>` as the blessed `Repr` for variable-length schemes** - and add an example. Zero API change, but clarifies intent. - -2. **Add a `VariableLengthSignature` marker trait** that opts a signature type - out of fixed-size assumptions, so downstream code can branch: - - ```rust - pub trait VariableLengthSignature: SignatureEncoding> {} - ``` - -3. **Add a `MAX_SIZE: usize` associated constant** to `SignatureEncoding` so - that callers can stack-allocate a worst-case buffer without heap allocation, - while still accommodating variable-length encoding. - -As PQC standardisation continues (FIPS 204, 205, and beyond are now published), -the ecosystem will need a principled answer here. Leaving it to per-crate -workarounds (`Box<[u8]>`) means every PQC implementor rediscovers the same -problem independently. - ---- - -## Issue 8 (Documentation): The `UnsafeCell` pattern for FFI-backed `Signer`/`Verifier` is correct but undocumented - -**Repo:** `RustCrypto/traits` -**Labels:** `documentation`, `ffi`, `signature` - -### Background - -`signature::Verifier::verify` takes `&self`: - -```rust -fn verify(&self, msg: &[u8], signature: &S) -> Result<(), Error>; -``` - -This is correct for pure-Rust implementations: a verifying key is logically -immutable, and a shared reference communicates that no mutation occurs. - -### The problem - -wolfCrypt's C API requires `*mut` pointers for verification, even though the -operation is logically read-only: - -```c -int wc_ed25519_verify_msg( - const byte* sig, word32 sigLen, - const byte* msg, word32 msgLen, - int* res, - ed25519_key* key // <-- *mut, not *const -); -``` - -The C function signature requires mutability even for pure verification because -the wolfCrypt implementation uses the key struct's scratch fields internally. -Rust cannot see through the C ABI to know that no observable mutation occurs. - -The only way to obtain a `*mut key` from a `&self` reference is via -`UnsafeCell`. This is the correct solution, but it is not obvious, and it is -not documented anywhere in the `signature` crate or RustCrypto trait -documentation. Each FFI implementor must discover it independently. - -`UnsafeCell` has the useful side effect of making the type `!Sync`, which is -*also* correct: C key handles are not safe to share across threads, so a type -wrapping one should not be `Sync`. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -Every signing and verifying key type in the `wolfcrypt` crate uses `UnsafeCell` -for this reason: - -- `Ed25519SigningKey` and `Ed25519VerifyingKey`: - [`wolfcrypt/src/ed25519.rs:30`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ed25519.rs#L30) - and - [`wolfcrypt/src/ed25519.rs:207`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ed25519.rs#L207), - with `// SAFETY:` comments at - [L176](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ed25519.rs#L176) - and - [L264](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ed25519.rs#L264) -- `EcdsaSigningKey` and `EcdsaVerifyingKey`: - [`wolfcrypt/src/ecdsa_native.rs:293`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ecdsa_native.rs#L293) - and - [`wolfcrypt/src/ecdsa_native.rs:470`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/ecdsa_native.rs#L470) -- `RsaPrivateKey` and `RsaPublicKey`: - [`wolfcrypt/src/rsa.rs:407`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/rsa.rs#L407) - and - [`wolfcrypt/src/rsa.rs:586`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/rsa.rs#L586) -- `MlDsaSigningKey` and `MlDsaVerifyingKey`: - [`wolfcrypt/src/mldsa.rs:151`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/mldsa.rs#L151) - and - [`wolfcrypt/src/mldsa.rs:284`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/mldsa.rs#L284), - with `// SAFETY:` at - [L351](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/mldsa.rs#L351) -- AES-GCM key: - [`wolfcrypt/src/aead.rs:36`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/aead.rs#L36) -- Crate-level docs ยง "Interior mutability for FFI verification calls": - [`wolfcrypt/src/lib.rs:157-170`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/lib.rs#L157-L170) - -### Proposed change - -No API change is needed. `UnsafeCell` is the correct solution and requires no -modification to the trait. - -We ask that a documentation section be added to the `signature` crate (or a -RustCrypto FFI implementation guide, if one exists) covering: - -- Why `Verifier::verify` taking `&self` creates the interior-mutability - requirement when the underlying C function takes `*mut`. -- The `UnsafeCell` pattern as the standard solution. -- Why `UnsafeCell` makes the type `!Sync` and why this is correct for C key handles. -- The `// SAFETY:` comment obligation at each call site explaining why - single-threaded access is guaranteed. - -A worked example would save every future FFI implementor from having to reason -through this from scratch. - ---- - -## Issue 9: `digest::Update`, `FixedOutput`, and `Mac` are infallible; hardware backends are forced to panic when operations fail - -**Repo:** `RustCrypto/traits` -**Labels:** `api-design`, `digest`, `hardware` - -### Background - -Issue 1 covers infallible *constructors*. This issue covers infallible *runtime -operations*. - -The core streaming traits define methods that return `()`: - -- `digest::Update::update(&mut self, data: &[u8])` -- `digest::FixedOutput::finalize_into(self, out: &mut Output)` -- `digest::FixedOutputReset::finalize_into_reset(&mut self, out: &mut Output)` -- `universal_hash::UniversalHash::update(&mut self, blocks: &[Block])` - -For a pure-Rust software implementation, these are genuinely infallible. -A SHA-256 `update` call is a few arithmetic operations; it cannot fail. -Making the return type `Result<(), E>` for software implementations would be -noise โ€” the `Err` branch is unreachable. - -### The problem - -For a hardware backend, every one of these operations dispatches to a driver, -HSM, or hardware accelerator that can fail at runtime: - -| Trait | Method | Return type | Hardware failure mode | -|-------|--------|-------------|-----------------------| -| `digest::Update` | `update(&mut self, data: &[u8])` | `()` | HSM busy, DMA fault, CryptoCb error | -| `digest::FixedOutput` | `finalize_into(self, out: &mut Output)` | `()` | Hardware finalization error | -| `digest::FixedOutputReset` | `finalize_into_reset(&mut self, out: &mut Output)` | `()` | Finalization + re-init failure | -| `universal_hash::UniversalHash` | `update(&mut self, blocks)` | `()` | Hardware MAC block fault | -| `digest::FixedOutput` | `finalize_into` (used by `Mac` via blanket) | `()` | Hardware MAC finalization error | -| `cipher::StreamCipher` | `apply_keystream(&mut self, buf: &mut [u8])` | `()` | Hardware cipher fault | - -wolfCrypt's `WOLF_CRYPTO_CB` mechanism routes each algorithm operation through a -registered C callback. That callback can return `WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)` -when the hardware device is busy, or a device-specific error code if the -hardware operation fails. The trait gives us nowhere to put that error. - -### In our implementation - -*Discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`.* - -In every case, we are forced to `assert!` on the C return code, converting -hardware failures into panics: - -- `digest::Update::update` asserts on `wc_Sha256Update`: - [`wolfcrypt/src/digest.rs:94-97`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/digest.rs#L94-L97) -- `digest::FixedOutput::finalize_into` asserts on `wc_Sha256Final`: - [`wolfcrypt/src/digest.rs:103-105`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/digest.rs#L103-L105) -- `digest::FixedOutputReset::finalize_into_reset` asserts on both finalize and - re-init: [`wolfcrypt/src/digest.rs:119-124`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/digest.rs#L119-L124) -- `Mac` (HMAC) `Update::update` asserts on `wolfcrypt_hmac_update`: - [`wolfcrypt/src/hmac.rs:88-91`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/hmac.rs#L88-L91) -- `Mac` (HMAC) `FixedOutput::finalize_into` asserts on `wolfcrypt_hmac_final`: - [`wolfcrypt/src/hmac.rs:99-102`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/hmac.rs#L99-L102) -- `Mac` (CMAC) `Update::update` asserts on `wolfcrypt_cmac_update`: - [`wolfcrypt/src/cmac.rs:90-93`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/cmac.rs#L90-L93) -- `UniversalHash::update` (Poly1305) asserts on `wc_Poly1305Update`: - [`wolfcrypt/src/poly1305.rs:96-99`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/poly1305.rs#L96-L99) -- `UniversalHash` finalize (Poly1305) asserts on `wc_Poly1305Final`: - [`wolfcrypt/src/poly1305.rs:111-114`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/poly1305.rs#L111-L114) - -### Proposed change - -Add `Try*` variants of the affected traits with fallible signatures and blanket -impls for existing software implementations: - -```rust -pub trait TryUpdate { - type Error; - fn try_update(&mut self, data: &[u8]) -> Result<(), Self::Error>; -} - -// Blanket impl: all existing Update implementors get TryUpdate for free -impl TryUpdate for T { - type Error = core::convert::Infallible; - fn try_update(&mut self, data: &[u8]) -> Result<(), Infallible> { - self.update(data); - Ok(()) - } -} - -pub trait TryFixedOutput: TryUpdate { - fn try_finalize_into(self, out: &mut Output) -> Result<(), Self::Error>; -} -``` - -Hardware backends implement `TryUpdate` and `TryFixedOutput` directly. -Software implementations get them via the blanket impls at zero cost. The -existing `Update` and `FixedOutput` traits are unchanged; no existing code -breaks. - -### Prior art - -`rand_core` 0.9 already solved this exact problem for the RNG case by adding -`TryCryptoRng` with a fallible `try_fill_bytes` method (see companion -Issue 10). We are asking for the same pattern to be applied to `digest::Update` -and `digest::FixedOutput`. - -The `embedded-hal` crate uses `type Error` associated types on all peripheral -traits for the same reason: hardware peripherals can fail at any method call, -not just at construction time. - ---- - -## Issue 10: `RngCore::fill_bytes` is infallible; hardware RNG failure cannot be surfaced โ€” `TryCryptoRng` is the fix and needs to be the primary recommended path - -**Repo:** `RustCrypto/traits` (affects `rand_core`) -**Labels:** `api-design`, `rand`, `hardware`, `fips` - -### Background - -`rand_core::RngCore::fill_bytes(&mut self, dest: &mut [u8])` returns `()`. -For a software PRNG (ChaCha20, DRBG backed by a software seed), this is -fine โ€” filling bytes from a seeded generator cannot fail. - -For a *hardware* entropy source, failure is a normal operational condition, -not a programmer error: - -- The hardware may not be ready (power-on self-test still running). -- The entropy pool may be temporarily exhausted (valid in some designs). -- The hardware may report a fault that must be handled โ€” this is precisely what - FIPS 140-3's Continuous Random Bit Generator (CRBG) test is designed to - detect. - -`rand_core` 0.9 added `TryCryptoRng` with a fallible `try_fill_bytes` to -address exactly this. We have adopted it, and it solves the problem for our -crate. - -### What remains - -The issue is adoption and discoverability: - -**1. `TryCryptoRng` is not the documented primary interface for hardware RNG -backends.** The `rand_core` documentation and ecosystem treat it as an -advanced feature. A developer writing a new hardware entropy driver will reach -for `RngCore` first and implement `fill_bytes` with a panic or a silent -discard of errors, because that is what the documentation implies. - -**2. Key generation APIs still take `impl CryptoRng`**, not `impl TryCryptoRng`. -For example: - -```rust -// In signature crates: -pub fn generate(rng: &mut impl CryptoRng) -> Self; - -// In KeyInit: -pub fn generate(rng: &mut impl CryptoRng) -> Self; -``` - -A hardware RNG backend correctly implements `TryCryptoRng` but has no -`CryptoRng` blanket impl (or the blanket impl panics on failure, defeating the -purpose). Key generation from a hardware source that can fail cannot propagate -errors through these APIs. - -**In our codebase** *(discovered while implementing [`wolfcrypt`](https://github.com/wolfSSL/wolfssl-rs), a RustCrypto backend wrapping wolfCrypt โ€” a FIPS 140-3 validated C cryptographic library with hardware dispatch via `WOLF_CRYPTO_CB`)*: - -Our `WolfRng` type implements `TryCryptoRng`. The `fill_bytes` implementation -is forced to `assert!` because `RngCore::fill_bytes` returns `()`, and the code -comment explicitly documents why: - -> *"RNG failure is unrecoverable" as a direct consequence of the trait signature* - -[`wolfcrypt/src/rand.rs:80-90`](https://github.com/wolfSSL/wolfssl-rs/blob/0f3af10/wolfcrypt/src/rand.rs#L80-L90) - -### What we are asking for - -1. **Document `TryCryptoRng` as the *required* interface for hardware entropy - sources**, not just an optional extra. A hardware RNG backend that - implements only `RngCore::fill_bytes` with a panic is not a correct - implementation; this should be stated clearly. - -2. **Audit key generation entry points** โ€” `KeyInit::generate`, - `SigningKey::generate`, and similar โ€” and add `TryCryptoRng`-accepting - variants so that hardware entropy sources can propagate failures through key - generation without panicking. - -3. **Apply the same `Try*` pattern to `digest::Update` and `Mac`** (see - companion Issue 9) to complete the hardware-dispatch story: if entropy, - hashing, and MACing can all fail and propagate errors, a hardware-backed - crypto pipeline becomes first-class. - -### Prior art - -- `rand_core` 0.9: `TryCryptoRng` / `try_fill_bytes` โ€” already shipped; this - is exactly the right design. -- `embedded-hal` 1.0: fallible `type Error` on all peripheral traits, including - RNG. -- `embedded-hal-async`: async + fallible, showing the pattern composes with - async hardware dispatch. diff --git a/rustcrypto-trait-gaps.md b/rustcrypto-trait-gaps.md deleted file mode 100644 index 9b79a4d..0000000 --- a/rustcrypto-trait-gaps.md +++ /dev/null @@ -1,229 +0,0 @@ -# RustCrypto Trait Ecosystem Gaps - -Discovered while implementing the `wolfcrypt` crate, which wraps wolfCrypt's C -FFI behind standard RustCrypto trait interfaces. Each gap is a design -limitation that pure-Rust implementations never encounter โ€” either because they -compose Rust types rather than wrapping a C library, or because they do not have -hardware-dispatch or key-handle lifecycle concerns. - -The gaps are documented here as a reference for anyone proposing upstream -improvements to the RustCrypto trait crates. - ---- - -## 1. Infallible constructors for fallible operations - -**Affected traits:** `digest::Digest` (via `Default`), `cipher::KeyInit`, -`aead::KeyInit` - -These traits define constructors that return `Self`, not `Result`. Any -FFI backend can fail for reasons outside the caller's control: OOM in the C -allocator, hardware device unavailable, or the library not yet initialized. The -trait signature gives no way to surface that failure. - -**Workaround in `wolfcrypt`:** We `assert!` on the wolfCrypt return code. In -practice this panics only on OOM or device-init failure, never on valid input of -the correct key length. Fallible alternatives (`new_from_slice`, `generate`, -`from_seed`) return `Result` wherever the trait allows. - -**Upstream fix:** Make constructors return `Result`, or add a parallel -`TryKeyInit` / `TryDigestNew` trait set with fallible constructors. - ---- - -## 2. No `ZeroizeOnDrop` bound on key types - -**Affected traits:** `cipher::KeyInit`, `aead::KeyInit`, `signature::Keypair`, -and all traits that create types holding secret key material. - -The traits create types that hold key material (AES key schedules, AEAD keys, -signing keys) but impose no cleanup guarantee. There is no `ZeroizeOnDrop` or -similar bound; each implementor must remember to add it manually. This is an -easy thing to miss and makes it possible to publish a crate that leaks key -material from freed memory. - -**Workaround in `wolfcrypt`:** We manually implement `Drop` with the appropriate -wolfCrypt free function (`wc_AesFree`, `wc_HmacFree`, etc.) and/or `zeroize` -calls on every type that holds key material. - -**Upstream fix:** Add a `ZeroizeOnDrop` supertrait bound (or at minimum a -documentation requirement with a linting mechanism) to all `KeyInit`-producing -traits. - ---- - -## 3. `AeadInPlace` is the only AEAD trait - -**Affected trait:** `aead::AeadInPlace` - -The `aead` crate provides only an in-place encrypt/decrypt interface โ€” the -plaintext/ciphertext buffer is mutated in-place. There is no variant that takes -separate input and output buffers. - -This caused an allocation problem with wolfCrypt's one-shot -ChaCha20-Poly1305 API (`wc_ChaCha20Poly1305_Encrypt`), which requires -separate source and destination buffers. Adapting it to the in-place trait -would have required a heap allocation per call to hold the output before -copying back. - -**Workaround in `wolfcrypt`:** We use wolfCrypt's streaming -ChaCha20-Poly1305 API (`wc_ChaCha20Poly1305_Init` / `UpdateData` / -`Final`), which accepts `input == output` pointers and works natively in-place. -A backend with no in-place path โ€” for example, a DMA-based hardware accelerator -โ€” would have no such escape hatch and would be forced to allocate. - -**Upstream fix:** Add an `Aead` trait variant with separate input and output -slices, or provide a blanket adapter from `AeadInPlace` to a two-buffer variant. - ---- - -## 4. No HKDF or PBKDF2 traits - -**Affected crates:** `hkdf`, `pbkdf2` - -These crates expose concrete implementations, not traits. There is no trait -that an alternative backend can implement to plug in a different HKDF or PBKDF2 -engine. Any generic code that needs to accept "an HKDF implementation" must -pick one concrete type. - -**Workaround in `wolfcrypt`:** The `hkdf` module exposes a bespoke API whose -method names match `hkdf::Hkdf` (`new`, `extract`, `expand`). The `pbkdf2` -module exposes standalone functions matching `pbkdf2::pbkdf2_hmac`'s signature. -For callers that need the actual `hkdf` or `pbkdf2` crate types, our digest -types compose with `hkdf::SimpleHkdf` and `hmac::SimpleHmac`. - -**Upstream fix:** Define `HkdfExpand` / `HkdfExtract` and `Pbkdf2` traits in -the respective crates so that alternative backends (wolfCrypt, BoringSSL, HSMs) -can implement them. - ---- - -## 5. The `CoreProxy` cliff - -**Affected trait:** `digest::Digest` (specifically `pbkdf2::pbkdf2_hmac`'s -`CoreProxy` bound) - -The `digest` crate has two implementation tiers: -- **High-level:** `Digest`, `Update`, `FixedOutput` โ€” the public-facing API. -- **Low-level:** `CoreProxy`, `UpdateCore`, `FixedOutputCore` โ€” the internal - composable building blocks. - -Our EVP-based digest types implement the high-level tier, which is sufficient -for almost all uses. However, `pbkdf2::pbkdf2_hmac` requires its hash argument -to implement `CoreProxy` (the low-level tier). An opaque FFI wrapper cannot -satisfy `CoreProxy` because the trait requires exposing the block size and -internal state as associated types at compile time. - -**Workaround in `wolfcrypt`:** Callers needing `pbkdf2_hmac` should use -`hmac::SimpleHmac` (which bridges from high-level digest to -low-level HMAC) or use our native `pbkdf2_hmac_sha256` function, which calls -wolfCrypt's `wc_PBKDF2` directly. - -**Upstream fix:** Remove the `CoreProxy` bound from `pbkdf2::pbkdf2_hmac` and -accept any `Mac` directly, which is the actual requirement. - ---- - -## 6. `pbkdf2::pbkdf2` requires `Sync` unconditionally - -**Affected function:** `pbkdf2::pbkdf2` (the lower-level function, distinct from -`pbkdf2_hmac`) - -The function signature is: - -```rust -pub fn pbkdf2(prf: PRF, ...) { ... } -``` - -The `Sync` bound exists to support the `parallel` feature, which distributes -PBKDF2 rounds across threads. However, the bound is present unconditionally โ€” -even when the `parallel` feature is disabled and the function runs entirely -single-threaded. - -Our EVP-based digest types are correctly `!Sync`: `EVP_MD_CTX` contains -interior mutable state that is not safe to share across threads. This means -`pbkdf2::>(...)` does not compile, even in a -single-threaded context where `Sync` is semantically unnecessary. - -**Workaround in `wolfcrypt`:** Use our native `pbkdf2_hmac_sha256` function -instead, which calls wolfCrypt's `wc_PBKDF2` directly. - -**Upstream fix:** Gate the `Sync` bound on the `parallel` feature: - -```rust -#[cfg(feature = "parallel")] -pub fn pbkdf2(prf: PRF, ...) { ... } -#[cfg(not(feature = "parallel"))] -pub fn pbkdf2(prf: PRF, ...) { ... } -``` - -This is the clearest actionable upstream fix of the eight gaps documented here. - ---- - -## 7. `SignatureEncoding::Repr` assumes fixed-size signatures - -**Affected trait:** `signature::SignatureEncoding` - -The trait requires: - -```rust -type Repr: 'static + AsRef<[u8]> + Clone + Send + Sync; -``` - -In practice, implementations use `[u8; N]` โ€” a fixed-size stack-allocated array. -This works for classical signature schemes (Ed25519 is always 64 bytes, ECDSA-P256 -is always 64 bytes) but breaks down for post-quantum signatures, which are -variable-length. ML-DSA-87 signatures are 4,627 bytes; SPHINCS+ variants vary -by parameter set. - -A `[u8; 4627]` associated type loses the "variable length" property (it forces -the largest possible allocation even for small signatures) and is not composable -across parameter sets. - -**Workaround in `wolfcrypt`:** We use `Repr = Box<[u8]>`, which satisfies the -trait bounds, but at the cost of a heap allocation per signature and the loss of -compile-time size guarantees. - -**Upstream fix:** Introduce a `VariableLengthSignature` marker trait or change -`Repr` to allow `Vec` / `Box<[u8]>` without prejudicing fixed-size -implementations. As PQC becomes standard across the RustCrypto ecosystem, this -will need to be revisited. - ---- - -## 8. Interior mutability required for FFI verification calls - -**Affected traits:** `signature::Verifier`, `signature::Signer` - -wolfCrypt's C API takes `*mut` pointers for operations that are logically -read-only, including signature verification and public-key export. The -`Verifier::verify` and `Signer::sign` traits take `&self` (a shared reference), -which cannot be coerced to `*mut` without interior mutability. - -```rust -// Trait requires &self: -fn verify(&self, msg: &[u8], signature: &S) -> Result<(), Error>; - -// wolfCrypt requires *mut: -wc_Ed25519Verify(sig, sig_len, msg, msg_len, &mut result, &mut key as *mut _); -// ^^^^ -``` - -This is not a correctness concern for single-threaded use โ€” wolfCrypt's verify -functions do not actually mutate the key โ€” but Rust's type system cannot see -into the C ABI to know that. - -**Workaround in `wolfcrypt`:** Signing and verifying key types wrap their C key -handle in `UnsafeCell`. This allows obtaining `*mut` from `&self` for FFI -calls while making the type `!Sync`, which is correct โ€” wolfCrypt key handles -are not safe to share across threads. Each `UnsafeCell` usage has a `// SAFETY:` -comment at the call site explaining why single-threaded access is guaranteed. -Affected types: `Ed25519SigningKey`, `Ed25519VerifyingKey`, `Ed448SigningKey`, -`Ed448VerifyingKey`, `EcdsaSigningKey`, `EcdsaVerifyingKey`, `RsaPrivateKey`, -`RsaPublicKey`, `MlDsa*SigningKey`, `MlDsa*VerifyingKey`. - -**Upstream fix:** No change to the trait API is needed. This is an inherent -tension between Rust's aliasing rules and C FFI. The `UnsafeCell` pattern is -the correct solution. Documenting it as a known pattern for FFI-backed -implementations would help future implementors. diff --git a/wolfcrypt-conformance/Cargo.toml b/wolfcrypt-conformance/Cargo.toml index c6c0ab2..93780ad 100644 --- a/wolfcrypt-conformance/Cargo.toml +++ b/wolfcrypt-conformance/Cargo.toml @@ -10,17 +10,8 @@ repository = "https://github.com/wolfSSL/wolfssl-rs" readme = "README.md" keywords = ["wolfcrypt", "wolfssl", "fips", "testing", "cryptography"] categories = ["cryptography"] -# Test-only crate โ€” not published to crates.io. -publish = false exclude = ["third_party/**", "vectors/**"] -[features] -# Activate the Caliptra hardware backend for conformance testing. -# Enables wolfcrypt-dpe-hw with caliptra-2x so the caliptra_hw_conformance -# binary can route operations through the hardware dispatch path and assert -# counters after each suite. -caliptra-hw = ["wolfcrypt-dpe-hw/caliptra-2x", "dep:caliptra-emu-periph"] - [lib] # Test-only crate; lib.rs exists only so integration tests can share helpers path = "src/lib.rs" @@ -30,26 +21,11 @@ path = "src/lib.rs" # dev-dependencies) solely so build.rs can read DEP_WOLFSSL_CFGS metadata. # Cargo only exposes `links` metadata to build scripts of direct dependents, # and dev-dependencies don't qualify. -wolfcrypt-rs = { version = "0.1.2", path = "../wolfcrypt-rs" } - -# Hardware backend: optional, activated by the caliptra-hw feature. -# Provides HW_DEVICE_ID, init(), and dispatch-counter accessors used by -# caliptra_hw_conformance. -wolfcrypt-dpe-hw = { path = "../wolfcrypt-dpe-hw", optional = true } - -# sw-emulator required by caliptra_hw_conformance to instantiate -# CaliptraRootBus during hardware conformance testing. -caliptra-emu-periph = { path = "../../caliptra/sw-emulator/lib/periph", optional = true } - -[target.'cfg(not(target_arch = "riscv32"))'.dependencies] -# wolfcrypt-sys is already transitively present via wolfcrypt-rs but must be -# declared directly so caliptra_hw_conformance can call wc_Hash_ex, -# wc_HmacInit, wc_AesGcmEncrypt, wc_ecc_sign_hash, etc. -wolfcrypt-sys = { version = "0.1.2", path = "../wolfcrypt-sys" } +wolfcrypt-rs = { version = "0.1.1", path = "../wolfcrypt-rs" } [dev-dependencies] # === Wolf side === -wolfcrypt = { version = "0.1.2", path = "../wolfcrypt", features = [ +wolfcrypt = { version = "0.1.1", path = "../wolfcrypt", features = [ "digest", "hmac", "cmac", "hkdf", "pbkdf2", "aead", "cipher", "poly1305", "signature", "ecdsa", "ed25519", "ed448", "rsa", "mldsa", "mlkem", "keywrap", "dh", "des3", "ecdh", "rand", diff --git a/wolfcrypt-conformance/src/bin/caliptra_hw_conformance.rs b/wolfcrypt-conformance/src/bin/caliptra_hw_conformance.rs deleted file mode 100644 index 922a473..0000000 --- a/wolfcrypt-conformance/src/bin/caliptra_hw_conformance.rs +++ /dev/null @@ -1,494 +0,0 @@ -//! Caliptra hardware conformance binary. -//! -//! Verifies that SHA-256/384/512, HMAC-384, AES-256-GCM, and ECDSA P-384 -//! operations route through the Caliptra hardware dispatch path (CryptoCb) -//! and produce correct output. -//! -//! Build and run: -//! cargo conformance-caliptra -//! # (alias defined in .cargo/config.toml) -//! -//! Requires: --features wolfcrypt-conformance/caliptra-hw - -fn main() { - #[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] - run_conformance(); - - #[cfg(not(all(feature = "caliptra-hw", not(target_arch = "riscv32"))))] - { - eprintln!( - "caliptra_hw_conformance requires \ - --features wolfcrypt-conformance/caliptra-hw on a non-riscv32 target." - ); - std::process::exit(1); - } -} - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn run_conformance() { - use std::process; - - // ----------------------------------------------------------------------- - // Step 1 โ€” Initialize the sw-emulator - // ----------------------------------------------------------------------- - let _emu = caliptra_emu_periph::CaliptraRootBus::new( - caliptra_emu_periph::CaliptraRootBusArgs::default(), - ); - - // ----------------------------------------------------------------------- - // Step 2 โ€” wolfCrypt init + hardware backend registration - // ----------------------------------------------------------------------- - let wc_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - wc_rc == 0 || wc_rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {wc_rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - - let dev_id = wolfcrypt_dpe_hw::HW_DEVICE_ID; - - // ----------------------------------------------------------------------- - // Step 3 โ€” SHA-256 conformance - // ----------------------------------------------------------------------- - wolfcrypt_dpe_hw::reset_hw_dispatch_count(); - let sha256_count = run_sha_suite( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA256, - 32, - "sha256", - "shavs/SHA256ShortMsg.rsp", - "shavs/SHA256LongMsg.rsp", - dev_id, - ); - let sha256_dispatches = wolfcrypt_dpe_hw::hw_dispatch_count(); - if sha256_dispatches != sha256_count { - eprintln!("HARDWARE PATH NOT TAKEN FOR SHA-256"); - eprintln!(" expected dispatches: {sha256_count}, got: {sha256_dispatches}"); - process::exit(1); - } - - // ----------------------------------------------------------------------- - // Step 3 โ€” SHA-384 conformance - // ----------------------------------------------------------------------- - wolfcrypt_dpe_hw::reset_hw_dispatch_count(); - let sha384_count = run_sha_suite( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - 48, - "sha384", - "shavs/SHA384ShortMsg.rsp", - "shavs/SHA384LongMsg.rsp", - dev_id, - ); - let sha384_dispatches = wolfcrypt_dpe_hw::hw_dispatch_count(); - if sha384_dispatches != sha384_count { - eprintln!("HARDWARE PATH NOT TAKEN FOR SHA-384"); - eprintln!(" expected dispatches: {sha384_count}, got: {sha384_dispatches}"); - process::exit(1); - } - - // ----------------------------------------------------------------------- - // Step 3 โ€” SHA-512 conformance - // ----------------------------------------------------------------------- - wolfcrypt_dpe_hw::reset_hw_dispatch_count(); - let sha512_count = run_sha_suite( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA512, - 64, - "sha512", - "shavs/SHA512ShortMsg.rsp", - "shavs/SHA512LongMsg.rsp", - dev_id, - ); - let sha512_dispatches = wolfcrypt_dpe_hw::hw_dispatch_count(); - if sha512_dispatches != sha512_count { - eprintln!("HARDWARE PATH NOT TAKEN FOR SHA-512"); - eprintln!(" expected dispatches: {sha512_count}, got: {sha512_dispatches}"); - process::exit(1); - } - - // ----------------------------------------------------------------------- - // Step 3 โ€” HMAC-384 conformance (RFC 4231 test cases, NIST-confirmed) - // ----------------------------------------------------------------------- - wolfcrypt_dpe_hw::reset_hw_dispatch_count(); - let hmac_count = run_hmac384_suite(dev_id); - let hmac_dispatches = wolfcrypt_dpe_hw::hw_dispatch_count(); - if hmac_dispatches != hmac_count { - eprintln!("HARDWARE PATH NOT TAKEN FOR HMAC-384"); - eprintln!(" expected dispatches: {hmac_count}, got: {hmac_dispatches}"); - process::exit(1); - } - - // ----------------------------------------------------------------------- - // Step 3 โ€” AES-256-GCM conformance (NIST SP 800-38D vectors) - // ----------------------------------------------------------------------- - wolfcrypt_dpe_hw::reset_aes_dispatch_count(); - let aes_count = run_aes256gcm_suite(dev_id); - let aes_dispatches = wolfcrypt_dpe_hw::aes_dispatch_count(); - if aes_dispatches != aes_count { - eprintln!("HARDWARE PATH NOT TAKEN FOR AES-256-GCM"); - eprintln!(" expected dispatches: {aes_count}, got: {aes_dispatches}"); - process::exit(1); - } - - // ----------------------------------------------------------------------- - // Step 3 โ€” ECDSA P-384 sign/verify conformance - // ----------------------------------------------------------------------- - wolfcrypt_dpe_hw::reset_ecc_dispatch_count(); - let ecc_count = run_ecdsa384_suite(dev_id); - let ecc_dispatches = wolfcrypt_dpe_hw::ecc_dispatch_count(); - if ecc_dispatches != ecc_count { - eprintln!("HARDWARE PATH NOT TAKEN FOR ECDSA P-384"); - eprintln!(" expected dispatches: {ecc_count}, got: {ecc_dispatches}"); - process::exit(1); - } - - // ----------------------------------------------------------------------- - // Step 5 โ€” Summary - // ----------------------------------------------------------------------- - println!("=== caliptra_hw_conformance PASSED ==="); - println!("SHA-256 : {sha256_count} vectors โ€” HW dispatch verified"); - println!("SHA-384 : {sha384_count} vectors โ€” HW dispatch verified"); - println!("SHA-512 : {sha512_count} vectors โ€” HW dispatch verified"); - println!("HMAC-384 : {hmac_count} vectors โ€” HW dispatch verified"); - println!("AES-256-GCM : {aes_count} dispatches (encrypt+decrypt) โ€” HW dispatch verified"); - println!("ECDSA P-384 : {ecc_count} dispatches (sign+verify rounds) โ€” HW dispatch verified"); -} - -// --------------------------------------------------------------------------- -// Vector directory helper -// --------------------------------------------------------------------------- - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn vector_dir() -> String { - std::env::var("CONFORMANCE_VECTORS_DIR") - .unwrap_or_else(|_| concat!(env!("CARGO_MANIFEST_DIR"), "/vectors").to_string()) -} - -// --------------------------------------------------------------------------- -// Minimal SHAVS parser -// --------------------------------------------------------------------------- -// Format (per NIST SHAVS spec): -// Len = -// Msg = -// MD = -// Consecutive blank-line-separated blocks; entries with Len = 0 use the -// 00 byte pad (we include the message but treat length=0 as empty slice). - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn parse_shavs(content: &str) -> Vec<(Vec, Vec)> { - let mut result = Vec::new(); - let mut len_bits: Option = None; - let mut msg_hex: Option = None; - - for line in content.lines() { - let line = line.trim(); - if let Some(v) = line.strip_prefix("Len = ") { - len_bits = v.trim().parse().ok(); - } else if let Some(h) = line.strip_prefix("Msg = ") { - msg_hex = Some(h.trim().to_string()); - } else if let Some(h) = line.strip_prefix("MD = ") { - if let (Some(len), Some(ref mh)) = (len_bits.take(), msg_hex.take()) { - let byte_len = len / 8; - let msg_bytes = hex_decode(mh); - let trimmed = msg_bytes[..byte_len.min(msg_bytes.len())].to_vec(); - result.push((trimmed, hex_decode(h.trim()))); - } - } - } - result -} - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn hex_decode(s: &str) -> Vec { - let s = s.trim(); - (0..s.len()) - .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("invalid hex in test vector")) - .collect() -} - -// --------------------------------------------------------------------------- -// SHA suite runner -// --------------------------------------------------------------------------- - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn run_sha_suite( - hash_type: wolfcrypt_sys::wc_HashType, - digest_len: usize, - name: &str, - short_file: &str, - long_file: &str, - dev_id: core::ffi::c_int, -) -> usize { - let dir = vector_dir(); - let mut total = 0usize; - - for file in &[short_file, long_file] { - let path = format!("{dir}/{file}"); - let content = match std::fs::read_to_string(&path) { - Ok(c) => c, - Err(e) => { - eprintln!("Warning: cannot load {path}: {e} โ€” skipping"); - continue; - } - }; - let vectors = parse_shavs(&content); - for (msg, expected_md) in &vectors { - let mut digest = vec![0u8; digest_len]; - let rc = unsafe { - wolfcrypt_sys::wc_Hash_ex( - hash_type, - if msg.is_empty() { core::ptr::null() } else { msg.as_ptr() }, - msg.len() as u32, - digest.as_mut_ptr(), - digest.len() as u32, - core::ptr::null_mut(), - dev_id, - ) - }; - assert_eq!(rc, 0, "{name}: wc_Hash_ex failed: {rc}"); - assert_eq!( - &digest[..expected_md.len()], - expected_md.as_slice(), - "{name}: digest mismatch for msg len={}", - msg.len() - ); - total += 1; - } - } - total -} - -// --------------------------------------------------------------------------- -// HMAC-384 suite โ€” RFC 4231 test cases (NIST CAVP confirmed) -// --------------------------------------------------------------------------- - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn run_hmac384_suite(dev_id: core::ffi::c_int) -> usize { - // RFC 4231 test cases for HMAC-SHA-384. - // Each entry: (key_hex, data_hex, expected_mac_hex). - // TC1 and TC2 are short-key; TC6-7 use longer keys. - const CASES: &[(&str, &str, &str)] = &[ - // TC 1 - ( - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "4869205468657265", - "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6", - ), - // TC 2 - ( - "4a656665", - "7768617420646f2079612077616e7420666f72206e6f7468696e673f", - "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649", - ), - // TC 3 (data repeated) - ( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", - "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27", - ), - // TC 4 (combined key+data) - ( - "0102030405060708090a0b0c0d0e0f10111213141516171819", - "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", - "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb", - ), - ]; - - let mut total = 0usize; - - for &(key_hex, data_hex, expected_hex) in CASES { - let key = hex_decode(key_hex); - let data = hex_decode(data_hex); - let expected = hex_decode(expected_hex); - let mut output = vec![0u8; 48]; - - unsafe { - let mut hmac: wolfcrypt_sys::Hmac = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_HmacInit(&mut hmac, core::ptr::null_mut(), dev_id); - assert_eq!(rc, 0, "hmac384: wc_HmacInit failed: {rc}"); - - let rc = wolfcrypt_sys::wc_HmacSetKey( - &mut hmac, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384 as i32, - key.as_ptr(), - key.len() as u32, - ); - assert_eq!(rc, 0, "hmac384: wc_HmacSetKey failed: {rc}"); - - let rc = wolfcrypt_sys::wc_HmacUpdate(&mut hmac, data.as_ptr(), data.len() as u32); - assert_eq!(rc, 0, "hmac384: wc_HmacUpdate failed: {rc}"); - - let rc = wolfcrypt_sys::wc_HmacFinal(&mut hmac, output.as_mut_ptr()); - assert_eq!(rc, 0, "hmac384: wc_HmacFinal failed: {rc}"); - - wolfcrypt_sys::wc_HmacFree(&mut hmac); - } - - assert_eq!(&output[..], expected.as_slice(), "hmac384: MAC mismatch"); - total += 1; - } - - total -} - -// --------------------------------------------------------------------------- -// AES-256-GCM suite โ€” NIST SP 800-38D vectors -// --------------------------------------------------------------------------- - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn run_aes256gcm_suite(dev_id: core::ffi::c_int) -> usize { - // Two AES-256-GCM test vectors from wolfSSL aesgcm_test() / McGrew-Viega GCM spec. - // TC15: 256-bit key, 64-byte PT, empty AAD โ†’ Tag b094dac5d93471bdec1a502270e3cc6c - // TC16: 256-bit key, 60-byte PT, non-empty AAD โ†’ Tag 76fc6ece0f4e1768cddf8853bb2d551b - // Each entry: (key, iv, aad, plaintext, expected_ct, expected_tag) - const CASES: &[(&str, &str, &str, &str, &str, &str)] = &[ - // TC16 (GCM spec) โ€” 256-bit key, 60-byte PT, non-empty AAD - ( - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662", - "76fc6ece0f4e1768cddf8853bb2d551b", - ), - // TC15 (NIST SP 800-38D / GCM spec) โ€” 256-bit key, 64-byte PT, empty AAD - ( - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", - "b094dac5d93471bdec1a502270e3cc6c", - ), - ]; - - let mut total = 0usize; // counts individual encrypt + decrypt dispatches - - for &(key_hex, iv_hex, aad_hex, pt_hex, expected_ct_hex, expected_tag_hex) in CASES { - let key_bytes = hex_decode(key_hex); - let iv_bytes = hex_decode(iv_hex); - let aad_bytes = hex_decode(aad_hex); - let pt_bytes = hex_decode(pt_hex); - let expected_ct = hex_decode(expected_ct_hex); - let expected_tag = hex_decode(expected_tag_hex); - - assert_eq!(key_bytes.len(), 32); - assert_eq!(iv_bytes.len(), 12); - assert_eq!(expected_tag.len(), 16); - - let mut key = [0u8; 32]; - key.copy_from_slice(&key_bytes); - let mut iv = [0u8; 12]; - iv.copy_from_slice(&iv_bytes); - let mut tag_out = [0u8; 16]; - - // Encrypt - let mut ct = vec![0u8; pt_bytes.len()]; - let rc = unsafe { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), 32); - let rc = wolfcrypt_sys::wc_AesGcmEncrypt( - &mut aes, - if ct.is_empty() { core::ptr::null_mut() } else { ct.as_mut_ptr() }, - if pt_bytes.is_empty() { core::ptr::null() } else { pt_bytes.as_ptr() }, - pt_bytes.len() as u32, - iv.as_ptr(), 12, - tag_out.as_mut_ptr(), 16, - if aad_bytes.is_empty() { core::ptr::null() } else { aad_bytes.as_ptr() }, - aad_bytes.len() as u32, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - rc - }; - assert_eq!(rc, 0, "aes256gcm: encrypt failed: {rc}"); - assert_eq!(ct, expected_ct, "aes256gcm: ciphertext mismatch"); - assert_eq!(&tag_out[..], expected_tag.as_slice(), "aes256gcm: tag mismatch"); - total += 1; - - // Decrypt and verify round-trip - let mut pt_dec = vec![0u8; ct.len()]; - let rc = unsafe { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), 32); - let rc = wolfcrypt_sys::wc_AesGcmDecrypt( - &mut aes, - if pt_dec.is_empty() { core::ptr::null_mut() } else { pt_dec.as_mut_ptr() }, - if ct.is_empty() { core::ptr::null() } else { ct.as_ptr() }, - ct.len() as u32, - iv.as_ptr(), 12, - tag_out.as_ptr(), 16, - if aad_bytes.is_empty() { core::ptr::null() } else { aad_bytes.as_ptr() }, - aad_bytes.len() as u32, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - rc - }; - assert_eq!(rc, 0, "aes256gcm: decrypt failed: {rc}"); - assert_eq!(pt_dec, pt_bytes, "aes256gcm: round-trip plaintext mismatch"); - total += 1; - } - - total -} - -// --------------------------------------------------------------------------- -// ECDSA P-384 suite โ€” keygen + sign + verify rounds -// --------------------------------------------------------------------------- - -#[cfg(all(feature = "caliptra-hw", not(target_arch = "riscv32")))] -fn run_ecdsa384_suite(dev_id: core::ffi::c_int) -> usize { - const ROUNDS: usize = 4; - let mut total = 0usize; // counts sign + verify dispatches - - unsafe { - let mut rng: wolfcrypt_sys::WC_RNG = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_InitRng_ex(&mut rng, core::ptr::null_mut(), dev_id); - assert_eq!(rc, 0, "ecdsa384: wc_InitRng_ex failed: {rc}"); - - for round in 0..ROUNDS { - // Generate key pair with HW_DEVICE_ID - let mut key: wolfcrypt_sys::ecc_key = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_ecc_init_ex(&mut key, core::ptr::null_mut(), dev_id); - assert_eq!(rc, 0, "ecdsa384: wc_ecc_init_ex failed: {rc}"); - let rc = wolfcrypt_sys::wc_ecc_make_key_ex( - &mut rng, - 48, - &mut key, - wolfcrypt_sys::ecc_curve_ids_ECC_SECP384R1 as core::ffi::c_int, - ); - assert_eq!(rc, 0, "ecdsa384: wc_ecc_make_key_ex failed on round {round}: {rc}"); - - // Sign a 48-byte hash (use round index to vary the input) - let mut hash = [0x5au8; 48]; - hash[0] = round as u8; - let mut sig = vec![0u8; 128]; - let mut sig_len: wolfcrypt_sys::word32 = 128; - let rc = wolfcrypt_sys::wc_ecc_sign_hash( - hash.as_ptr(), 48, - sig.as_mut_ptr(), &mut sig_len, - &mut rng, &mut key, - ); - assert_eq!(rc, 0, "ecdsa384: wc_ecc_sign_hash failed on round {round}: {rc}"); - sig.truncate(sig_len as usize); - total += 1; // sign counted - - // Verify the signature - let mut verify_result: core::ffi::c_int = 0; - let rc = wolfcrypt_sys::wc_ecc_verify_hash( - sig.as_ptr(), sig.len() as wolfcrypt_sys::word32, - hash.as_ptr(), 48, - &mut verify_result, &mut key, - ); - assert_eq!(rc, 0, "ecdsa384: wc_ecc_verify_hash failed on round {round}: {rc}"); - assert_eq!(verify_result, 1, "ecdsa384: signature verification failed on round {round}"); - total += 1; // verify counted - - wolfcrypt_sys::wc_ecc_free(&mut key); - } - - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - - total -} diff --git a/wolfcrypt-conformance/tests/cipher_cfb.rs b/wolfcrypt-conformance/tests/cipher_cfb.rs index 3055aba..ce9cfab 100644 --- a/wolfcrypt-conformance/tests/cipher_cfb.rs +++ b/wolfcrypt-conformance/tests/cipher_cfb.rs @@ -199,7 +199,7 @@ cfb_equiv!( cfb_mode::Encryptor, cfb_mode::Decryptor, 16, - [wolfssl_aes_cfb] + [wolfssl_openssl_extra, wolfssl_aes_cfb] ); cfb_equiv!( @@ -209,7 +209,7 @@ cfb_equiv!( cfb_mode::Encryptor, cfb_mode::Decryptor, 24, - [wolfssl_aes_cfb, wolfssl_aes_192] + [wolfssl_openssl_extra, wolfssl_aes_cfb, wolfssl_aes_192] ); cfb_equiv!( @@ -219,5 +219,5 @@ cfb_equiv!( cfb_mode::Encryptor, cfb_mode::Decryptor, 32, - [wolfssl_aes_cfb] + [wolfssl_openssl_extra, wolfssl_aes_cfb] ); diff --git a/wolfcrypt-conformance/tests/ecdsa.rs b/wolfcrypt-conformance/tests/ecdsa.rs index cc81eb9..29023ff 100644 --- a/wolfcrypt-conformance/tests/ecdsa.rs +++ b/wolfcrypt-conformance/tests/ecdsa.rs @@ -1,4 +1,4 @@ -#![cfg(wolfssl_ecc)] +#![cfg(all(wolfssl_openssl_extra, wolfssl_ecc))] mod helpers; @@ -273,21 +273,12 @@ macro_rules! ecdsa_cross { pure_vk.verify(msg, &pure_sig2) .expect(concat!(stringify!($mod_name), ": pure must verify second wolf sig")); - // wolfCrypt's wc_ecc_sign_hash is randomized (not RFC 6979 by - // default). Identical signatures over the same message with - // different RNG calls indicate the RNG returned the same nonce - // twice โ€” a catastrophic signing failure. Emit a loud warning - // so it is never silently ignored. (Deterministic RFC-6979 - // builds will trigger this warning spuriously; that is - // acceptable because the alternative is a silent blind spot.) - if sig1.as_bytes() == sig2.as_bytes() { - eprintln!( - "WARNING ({}): two ECDSA signatures over the same message \ - are identical โ€” this indicates an RNG nonce reuse, which \ - is a catastrophic signing failure. Investigate immediately.", - stringify!($mod_name) - ); + if sig1.as_bytes() != sig2.as_bytes() { + // Good: randomized ECDSA produced different signatures. + // This is the expected case. } + // We don't assert_ne because deterministic ECDSA (RFC 6979) + // would produce the same sig, and that's also valid. } } }; @@ -300,7 +291,7 @@ ecdsa_cross!( p256::ecdsa::VerifyingKey, p256::ecdsa::Signature, 32, - [wolfssl_ecc] + [wolfssl_openssl_extra, wolfssl_ecc] ); ecdsa_cross!( @@ -310,13 +301,13 @@ ecdsa_cross!( p384::ecdsa::VerifyingKey, p384::ecdsa::Signature, 48, - [wolfssl_ecc, wolfssl_ecc_p384] + [wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p384] ); // P-521: the pure-Rust `p521` crate uses newtype wrappers (not type aliases) // for SigningKey/VerifyingKey, so the `ecdsa_cross!` macro doesn't fit. // Write the cross-validation tests directly. -#[cfg(all(wolfssl_ecc, wolfssl_ecc_p521, wolfssl_sha512))] +#[cfg(all(wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p521))] mod p521_cross { use wolfcrypt::{EcdsaSigningKey, EcdsaVerifyingKey, EcdsaSignature, P521}; use signature::{Signer, Verifier}; diff --git a/wolfcrypt-conformance/tests/helpers/wycheproof.rs b/wolfcrypt-conformance/tests/helpers/wycheproof.rs index 8785bdf..26596be 100644 --- a/wolfcrypt-conformance/tests/helpers/wycheproof.rs +++ b/wolfcrypt-conformance/tests/helpers/wycheproof.rs @@ -248,46 +248,6 @@ pub struct RsaSigTestCase { pub flags: Vec, } -// --------------------------------------------------------------------------- -// RSA-OAEP decryption -// --------------------------------------------------------------------------- - -/// Test group for RSA-OAEP decryption vectors (rsa_oaep_*_test.json). -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RsaOaepTestGroup { - pub key_size: usize, - pub sha: String, - pub mgf: String, - pub mgf_sha: String, - /// Hex-encoded PKCS#8 PrivateKeyInfo DER containing the RSA private key. - #[serde(rename = "privateKeyPkcs8")] - pub private_key_pkcs8: String, - pub tests: Vec, -} - -impl HasTests for RsaOaepTestGroup { - fn test_count(&self) -> usize { - self.tests.len() - } -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RsaOaepTestCase { - pub tc_id: usize, - pub comment: String, - /// Expected plaintext (hex). - pub msg: String, - /// Ciphertext to decrypt (hex). - pub ct: String, - /// OAEP label (hex; empty string "" means no label). - pub label: String, - pub result: WycheproofResult, - #[serde(default)] - pub flags: Vec, -} - // --------------------------------------------------------------------------- // ECDSA P1363 verification // --------------------------------------------------------------------------- @@ -325,41 +285,3 @@ pub struct EcdsaP1363TestCase { #[serde(default)] pub flags: Vec, } - -// --------------------------------------------------------------------------- -// ECDH ecpoint-format test vectors -// --------------------------------------------------------------------------- -// -// Matches the `ecdh_*_ecpoint_test.json` schema: -// group: { curve, encoding, tests } -// test: { tcId, comment, flags, public (hex EC point), private (hex scalar), -// shared (hex expected x-coord), result } - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct EcdhEcpointTestGroup { - pub curve: String, - pub tests: Vec, -} - -impl HasTests for EcdhEcpointTestGroup { - fn test_count(&self) -> usize { - self.tests.len() - } -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct EcdhEcpointTestCase { - pub tc_id: usize, - pub comment: String, - /// Hex-encoded uncompressed public point: `04 || x || y`. - pub public: String, - /// Hex-encoded raw private scalar (big-endian, padded to field size). - pub private: String, - /// Hex-encoded expected shared secret (x-coordinate of result point). - pub shared: String, - pub result: WycheproofResult, - #[serde(default)] - pub flags: Vec, -} diff --git a/wolfcrypt-conformance/tests/rsa.rs b/wolfcrypt-conformance/tests/rsa.rs index bd4bad1..270a020 100644 --- a/wolfcrypt-conformance/tests/rsa.rs +++ b/wolfcrypt-conformance/tests/rsa.rs @@ -2,7 +2,7 @@ // is provided by wycheproof_rsa.rs (Wycheproof PKCS#1v1.5 and PSS vectors). // TODO: add cross-validation against the pure-Rust `rsa` crate when its // API stabilises enough for signing interop. -#![cfg(wolfssl_rsa)] +#![cfg(all(wolfssl_openssl_extra, wolfssl_rsa))] mod helpers; @@ -304,77 +304,3 @@ fn pkcs1v15_cross_scheme_rejected() { "rsa: PSS signature must not verify as PKCS#1v1.5" ); } - -// --------------------------------------------------------------------------- -// OAEP encrypt/decrypt round-trip diagnostics -// --------------------------------------------------------------------------- - -const PRIV_2048_DER: &[u8] = include_bytes!("../vectors/rsa/priv_2048.der"); - -/// OAEP round-trip with a freshly generated 2048-bit key. -/// -/// This establishes that OAEP encrypt + decrypt works at all when both -/// operations use the same in-memory key object. -#[test] -fn oaep_roundtrip_generated_key() { - let sk = RsaPrivateKey::generate(2048) - .expect("rsa: 2048-bit key generation should succeed"); - let pk = sk.public_key(); - - let plaintext = b"oaep round-trip test with generated key"; - let ct = pk.encrypt_oaep(plaintext) - .expect("rsa: OAEP encrypt with generated key should succeed"); - assert_ne!(ct, plaintext, "rsa: OAEP ciphertext must differ from plaintext"); - assert_eq!(ct.len(), 256, "rsa: OAEP ciphertext for 2048-bit key must be 256 bytes"); - - let dec = sk.decrypt_oaep(&ct) - .expect("rsa: OAEP decrypt with generated key should succeed"); - assert_eq!(&dec, plaintext as &[u8], "rsa: OAEP round-trip must recover original plaintext"); -} - -/// OAEP round-trip with a key imported from PKCS#1 DER. -/// -/// This tests the specific code path used by the Wycheproof OAEP tests: -/// load a private key from external DER, then encrypt + decrypt. -#[test] -fn oaep_roundtrip_imported_key() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("rsa: should import 2048-bit private key from PKCS#1 DER"); - let pk = sk.public_key(); - - let plaintext = b"oaep round-trip test with imported key"; - let ct = pk.encrypt_oaep(plaintext) - .expect("rsa: OAEP encrypt with imported key should succeed"); - assert_ne!(ct, plaintext, "rsa: OAEP ciphertext must differ from plaintext"); - - let dec = sk.decrypt_oaep(&ct) - .expect("rsa: OAEP decrypt with imported key should succeed"); - assert_eq!(&dec, plaintext as &[u8], "rsa: OAEP round-trip with imported key must recover original plaintext"); -} - -/// Verify that OAEP decrypt with the wrong key fails. -#[test] -fn oaep_wrong_key_rejected() { - let sk1 = RsaPrivateKey::generate(2048) - .expect("rsa: key1 generation should succeed"); - let pk1 = sk1.public_key(); - let sk2 = RsaPrivateKey::generate(2048) - .expect("rsa: key2 generation should succeed"); - - let plaintext = b"oaep cross-key rejection test"; - let ct = pk1.encrypt_oaep(plaintext) - .expect("rsa: OAEP encrypt should succeed"); - - let result = sk2.decrypt_oaep(&ct); - assert!(result.is_err(), "rsa: OAEP decrypt with wrong key must fail"); -} - -/// Verify that OAEP decrypt of garbage returns an error. -#[test] -fn oaep_garbage_ciphertext_rejected() { - let sk = RsaPrivateKey::generate(2048) - .expect("rsa: key generation should succeed"); - let garbage = vec![0xAAu8; 256]; - let result = sk.decrypt_oaep(&garbage); - assert!(result.is_err(), "rsa: OAEP decrypt of garbage must fail"); -} diff --git a/wolfcrypt-conformance/tests/rsa_pkcs1v15_baseline.rs b/wolfcrypt-conformance/tests/rsa_pkcs1v15_baseline.rs deleted file mode 100644 index 3baef73..0000000 --- a/wolfcrypt-conformance/tests/rsa_pkcs1v15_baseline.rs +++ /dev/null @@ -1,362 +0,0 @@ -//! PKCS#1v1.5 signing baseline vectors. -//! -//! Captures deterministic PKCS#1v1.5 signature bytes from the native -//! wc_*-based implementation. These bytes MUST remain stable across -//! refactors โ€” any mismatch indicates a bug in DigestInfo construction -//! or the RSA private-key operation. -//! -//! # How to capture / update vectors -//! -//! Run with `CAPTURE=1` to print all signature bytes in Rust literal format: -//! -//! ```sh -//! CAPTURE=1 cargo test -p wolfcrypt-conformance rsa_pkcs1v15_baseline -- --nocapture 2>&1 | grep -A999 'CAPTURE BEGIN' -//! ``` -//! -//! Copy the printed bytes into the `EXPECTED_*` constants below, then re-run -//! without `CAPTURE=1` to verify the hardcoded values are correct. -//! -//! # Key provenance -//! -//! The private keys in `vectors/rsa/priv_2048.der` and `priv_4096.der` are -//! extracted from the Wycheproof `rsa_oaep_*_sha256_mgf1sha256_test.json` -//! files (PKCS#8 outer wrapper stripped to PKCS#1 inner key). These are -//! test keys only โ€” never use them for any real application. - -#![cfg(wolfssl_rsa)] - -use wolfcrypt::rsa::{RsaDigest, RsaPrivateKey, RsaPkcs1v15Signature}; - -// --------------------------------------------------------------------------- -// Known private keys (PKCS#1 RSAPrivateKey DER, binary files) -// --------------------------------------------------------------------------- - -/// 2048-bit RSA private key. Source: Wycheproof rsa_oaep_2048_sha256_mgf1sha256. -const PRIV_2048_DER: &[u8] = include_bytes!("../vectors/rsa/priv_2048.der"); - -/// 4096-bit RSA private key. Source: Wycheproof rsa_oaep_4096_sha256_mgf1sha256. -const PRIV_4096_DER: &[u8] = include_bytes!("../vectors/rsa/priv_4096.der"); - -/// Fixed test message used for all signing vectors. -const MSG: &[u8] = b"The quick brown fox jumps over the lazy dog"; - -// --------------------------------------------------------------------------- -// Expected signature bytes (populated after first capture run) -// --------------------------------------------------------------------------- -// -// These are the EXACT bytes that the EVP-based implementation produces for -// PKCS#1v1.5 signing. They are deterministic: RSA with a fixed private key -// and a fixed message always produces the same output. -// -// To repopulate: run with `CAPTURE=1` (see module doc) and paste the output. - -// 2048-bit key -static EXPECTED_2048_SHA256: &[u8] = &[ - 0x62,0x63,0x71,0x64,0x8c,0xb1,0x16,0x34,0x13,0xdb,0x01,0xf3,0xaf,0xe3,0xd2,0x1c, - 0xa9,0xf4,0xdd,0x38,0xfa,0x7c,0xae,0x8f,0x85,0x3f,0x34,0x1b,0x98,0x2c,0x66,0x8a, - 0xdf,0x41,0x3c,0x94,0xeb,0xe4,0x03,0xad,0xaf,0xce,0x46,0x31,0x6d,0xca,0x7c,0xda, - 0x85,0x02,0x02,0xb3,0x60,0x79,0x1d,0x3e,0x61,0x1a,0x9d,0xba,0x17,0x4d,0x39,0xbb, - 0x31,0xce,0x9f,0x9d,0xaa,0xcc,0x9a,0x02,0xd2,0x6a,0x4e,0x2b,0x4a,0xbe,0x97,0xb6, - 0xbc,0xee,0x2a,0xe7,0xd8,0xfe,0x04,0x34,0xff,0x29,0x2d,0xf1,0x19,0x74,0x5a,0xd7, - 0x47,0x50,0x5a,0xd9,0x16,0xa8,0xd2,0x42,0x3e,0x29,0xbd,0x9e,0x09,0x3b,0x18,0xae, - 0xfb,0xc1,0x7e,0xf1,0x83,0x21,0xe1,0xac,0x52,0x45,0xef,0xda,0x0e,0xe7,0x0f,0xbd, - 0x38,0x27,0xd5,0xf9,0xf3,0xbc,0x7f,0x02,0xa0,0xa8,0x70,0xe7,0xbe,0x47,0x1a,0x17, - 0x73,0x85,0x20,0x04,0x13,0xd6,0x4d,0x4c,0xb1,0x03,0xb6,0x9e,0x09,0x84,0xe7,0xf0, - 0x87,0x6d,0x38,0x36,0x52,0xa9,0x9e,0x1e,0x65,0xee,0xe3,0xfc,0x58,0xd7,0xb6,0x0f, - 0x5a,0x04,0x33,0xaa,0x03,0x87,0x2c,0xdc,0xd5,0x54,0x45,0xff,0xe0,0x12,0x36,0x67, - 0xa6,0x3e,0x7e,0x5a,0x2c,0x1a,0xf6,0x2c,0x7e,0x96,0xe0,0xe3,0xdb,0x49,0xeb,0xf0, - 0x86,0xed,0xac,0xe2,0xf4,0xc6,0x9c,0xbe,0x66,0x1d,0x34,0x83,0x8f,0xbb,0x8c,0xe0, - 0xc1,0x20,0x3f,0xdd,0xe1,0xf2,0x8b,0x0c,0x50,0xfd,0x1e,0x6e,0xa6,0x55,0x8d,0x18, - 0xfd,0xf1,0x7b,0x94,0x12,0xcc,0x5c,0x71,0x48,0x0a,0xfc,0x19,0x05,0x8f,0x95,0x53, -]; -static EXPECTED_2048_SHA384: &[u8] = &[ - 0x99,0x50,0x95,0x33,0xa2,0x09,0x43,0xc2,0xf1,0xb7,0x52,0x92,0x56,0x13,0xcb,0x8c, - 0x6a,0xc4,0xb0,0xa8,0xbc,0xf3,0xc7,0x80,0x13,0x73,0x5e,0x91,0xd7,0xaa,0xe3,0x45, - 0x09,0xdc,0x17,0x4b,0x7a,0x7b,0x1c,0x76,0x45,0x79,0x11,0xb0,0xb3,0xc6,0xe7,0xc4, - 0x90,0x64,0x5b,0x03,0x3c,0x3d,0x6d,0xdd,0x5d,0x65,0x1f,0xdb,0x1c,0x94,0xc6,0x79, - 0x7e,0xd0,0x55,0x91,0x7c,0xde,0x1c,0x7b,0x31,0x3e,0xe5,0xba,0xac,0x71,0x55,0x72, - 0x52,0x2c,0x66,0x9a,0xf7,0x27,0x32,0x2f,0x6c,0xea,0x76,0xd5,0x18,0x41,0xd5,0xeb, - 0x12,0x99,0x46,0x72,0x9b,0x16,0xc2,0x54,0x1b,0x9c,0xdb,0x94,0x57,0xc7,0x10,0x41, - 0xe0,0x8d,0x89,0x5d,0x7a,0xc1,0xfb,0xd2,0x27,0x4b,0x89,0x58,0xc9,0x2a,0xf3,0x05, - 0x97,0xa6,0xe5,0x62,0xbb,0x37,0x0e,0x6f,0x7e,0x18,0xd4,0xa8,0xfd,0x71,0xaa,0xc4, - 0x89,0x02,0xd1,0xdb,0x0b,0xf8,0x95,0x82,0xc7,0x5e,0x3a,0x42,0xdb,0x09,0x15,0x14, - 0xfa,0xf2,0x01,0xd1,0x45,0x3d,0x68,0x38,0x4f,0x2c,0x31,0x07,0x29,0xc7,0x2d,0xee, - 0xbe,0xa2,0x40,0x11,0x3d,0x7e,0xb3,0x47,0x49,0x05,0xe5,0xb6,0xd0,0x8b,0x10,0x84, - 0xc7,0xa1,0xdb,0xc1,0x43,0x5b,0x9c,0xc7,0x01,0x5f,0x90,0x1d,0xb4,0xa0,0xf5,0xce, - 0xc5,0xaf,0x8e,0xe9,0x7a,0x00,0x12,0x2d,0x43,0x27,0xef,0x19,0x43,0xe6,0xef,0x9f, - 0xfb,0xe6,0x5f,0x2e,0x25,0x1f,0xe5,0x58,0x12,0x2a,0x05,0x40,0xe0,0x4a,0x27,0xe1, - 0xdf,0x51,0x4f,0x87,0x14,0x01,0xd5,0x68,0x4b,0xeb,0x8d,0x38,0x71,0x86,0xf5,0x63, -]; -static EXPECTED_2048_SHA512: &[u8] = &[ - 0x8f,0x53,0x4e,0x70,0x4c,0x62,0xfa,0x17,0x0d,0x5f,0xea,0xd2,0x0e,0x68,0x12,0x30, - 0x7d,0x26,0x76,0x5b,0x84,0xde,0x2d,0x35,0xba,0xf9,0xad,0xcf,0xa7,0x3b,0xf1,0x95, - 0x7f,0xd1,0xad,0x0d,0x47,0xb0,0x14,0x7b,0x01,0x1b,0xc3,0x74,0xd6,0x58,0xaa,0x11, - 0xe5,0x8c,0x8d,0x88,0xf2,0xe7,0xdf,0x65,0x62,0xef,0xfc,0x3d,0xa2,0x0f,0x42,0x75, - 0x4b,0x1e,0x7e,0x15,0xbd,0x49,0x03,0x76,0x2b,0x69,0xf5,0xc8,0x0b,0x7e,0xaa,0xc9, - 0xbd,0xd5,0xc8,0x23,0x95,0xb6,0x8e,0xaf,0x3e,0x90,0x20,0x15,0x98,0x3d,0xf5,0x34, - 0xf1,0xe5,0xfc,0x9f,0x06,0xdb,0x46,0x1e,0xb1,0x20,0x0f,0x6e,0xf4,0x14,0x9c,0xe2, - 0x5a,0x99,0x19,0x4e,0xe8,0x59,0x54,0x5a,0x71,0xc5,0x71,0xef,0xfd,0x68,0x40,0x3d, - 0xc6,0xa3,0xca,0x65,0xe5,0x52,0xe6,0x40,0xca,0xb6,0x98,0x6b,0x1a,0x7e,0x1a,0xb4, - 0x23,0xfe,0xb9,0xd6,0xd1,0x9d,0xc4,0xc7,0x3b,0xd8,0x46,0x62,0x12,0x58,0x9b,0x08, - 0x58,0x94,0x37,0x48,0x66,0x64,0x64,0xcf,0x84,0x25,0x1f,0x58,0x35,0xca,0xc5,0x15, - 0x87,0x30,0x4c,0xaa,0x00,0x1e,0xc8,0x7a,0x5e,0xc6,0xae,0x96,0x18,0xa2,0xa3,0xa3, - 0x5e,0xd2,0x11,0x73,0x1f,0x83,0x7f,0x08,0x02,0xa3,0x02,0x1e,0xb8,0x9e,0x8a,0xd5, - 0x2a,0xd1,0x9c,0x95,0x45,0xe2,0x0c,0x5b,0xa5,0x62,0x19,0xe8,0x98,0x4b,0x6d,0xd9, - 0x1b,0xe2,0x43,0xd1,0x66,0x04,0x81,0x62,0xcb,0x4e,0x6a,0x33,0x39,0xcd,0x00,0x98, - 0x1f,0xa9,0xb9,0x59,0x53,0xfa,0x2f,0x5c,0x27,0xc1,0xd3,0xb7,0x5a,0xf9,0x60,0x87, -]; - -// 4096-bit key -static EXPECTED_4096_SHA256: &[u8] = &[ - 0x45,0xa9,0xd0,0x65,0xa5,0x32,0xbe,0xf8,0x92,0x7b,0x8a,0xba,0xc0,0x5b,0x9a,0x00, - 0xfa,0x49,0x18,0x3d,0xe5,0x90,0x88,0xa1,0xc0,0xaf,0x1d,0x44,0xb1,0xc0,0xa8,0xee, - 0x48,0x70,0xaf,0xed,0x37,0x12,0xa9,0xf0,0xc2,0x75,0xc2,0xf6,0x89,0xce,0x69,0xb5, - 0x58,0x68,0x6f,0x67,0x27,0x62,0x41,0x1a,0x8a,0x5e,0x5b,0xad,0xa1,0xbe,0x3d,0xd8, - 0xc6,0x82,0xd8,0x07,0xde,0xde,0x55,0x83,0xe6,0xf0,0x4d,0x6f,0x24,0xdb,0x55,0x47, - 0xd0,0x32,0x82,0xb6,0x54,0x4b,0xbe,0x60,0x7f,0xa8,0xd0,0xec,0x82,0x6f,0xfb,0xea, - 0x7d,0xdc,0x67,0xbb,0x00,0x7e,0x82,0x48,0x3c,0x97,0x16,0x68,0xe2,0xb2,0x5e,0x13, - 0xc2,0x6f,0xaf,0x63,0x83,0x88,0xc9,0x63,0xb6,0x49,0xae,0x07,0xf4,0xb6,0xdd,0xea, - 0x91,0x84,0x13,0xfd,0xb9,0x42,0x1b,0x06,0xae,0xbd,0x8f,0xb2,0xea,0x4f,0xe8,0xeb, - 0x5f,0x1e,0x5f,0x25,0x11,0x49,0x6a,0xbf,0x91,0x4f,0xcc,0xce,0x02,0xc9,0x11,0xd1, - 0x2b,0x3f,0xe8,0x57,0x4c,0xd4,0x42,0xdb,0x05,0x64,0x39,0x4d,0xbc,0x88,0x89,0x42, - 0xdc,0xc9,0x9c,0xb6,0xb3,0x19,0x0b,0x4f,0xe3,0xad,0xb0,0x96,0x1e,0xf0,0xf4,0xd3, - 0xcd,0x6c,0xc1,0x87,0xc0,0xa8,0x92,0xcb,0x5b,0x62,0xe2,0xe5,0xc4,0xd7,0x8f,0x33, - 0x60,0xd0,0xb6,0x82,0x3b,0x97,0x79,0x6c,0xc1,0x85,0x49,0x91,0xff,0x21,0x7b,0x1c, - 0xc4,0xa2,0x67,0x98,0xec,0x0a,0xda,0x7c,0x61,0x0c,0xc6,0xd1,0x1c,0xee,0xa2,0x74, - 0x33,0xbe,0x2b,0x80,0x52,0xaa,0xef,0x53,0x14,0xeb,0x40,0x4e,0x6b,0x96,0x0f,0x38, - 0x7a,0x32,0xfe,0x12,0x8f,0x2d,0x34,0x79,0x7c,0xf4,0x74,0x82,0x2b,0x93,0x63,0x98, - 0x3d,0xc5,0x62,0xb4,0x71,0x40,0x5c,0x33,0x2f,0x7a,0x49,0x06,0xa3,0x6a,0x25,0x2a, - 0x07,0x5b,0x86,0x85,0xcb,0xb4,0x1b,0xdb,0x0f,0xc2,0xdd,0xa1,0xf9,0xe2,0xd4,0x4d, - 0x40,0x32,0x84,0xfb,0xf1,0x69,0x1c,0x28,0xdf,0x26,0xd2,0x9e,0x6d,0xea,0x45,0xb8, - 0xf7,0x4a,0xc2,0x61,0x79,0x56,0x0d,0xe8,0x9a,0x18,0xf2,0xbf,0x62,0xc1,0xee,0xa1, - 0xd3,0x94,0xdc,0x08,0x6b,0xb6,0x1f,0xce,0x81,0x08,0xa1,0x3d,0xcd,0x14,0x53,0x7a, - 0x79,0x0b,0xf5,0x2b,0xa7,0x42,0x3e,0xa4,0xf9,0x3e,0x82,0x81,0x92,0x9e,0x62,0x0e, - 0xc0,0xd7,0x13,0xda,0x94,0xd5,0x0b,0x74,0xc1,0x15,0x10,0xed,0xb3,0xcf,0xb0,0xd4, - 0x29,0x30,0x44,0x54,0x05,0xe9,0xf4,0xdc,0x2a,0x02,0x33,0x63,0x12,0x21,0x7f,0xcc, - 0xad,0x21,0xbf,0xe5,0xd7,0x64,0x7a,0xb9,0x9a,0xca,0xfa,0x0b,0x63,0xfa,0x09,0x52, - 0x25,0x0a,0x38,0xbf,0x4e,0x1b,0xad,0x6e,0xf8,0x36,0x57,0x88,0xf1,0x5b,0x98,0x8f, - 0x71,0xbe,0x3f,0x94,0x85,0xbd,0x24,0x4a,0xdc,0xe1,0xa3,0x07,0x1a,0x24,0x51,0xb5, - 0x09,0xa6,0x3a,0x9c,0x6f,0x84,0xc2,0xce,0x42,0xb3,0x46,0x25,0xc3,0xde,0x93,0x2f, - 0xf9,0x00,0x4e,0x35,0x5e,0x1c,0xc6,0x23,0x5b,0x1f,0x51,0x3c,0x67,0x6e,0xfc,0xb1, - 0xa1,0xc3,0xb9,0xe4,0xdd,0xa5,0x6a,0x02,0x5d,0x79,0xe2,0x59,0xd0,0xe7,0xc1,0x26, - 0xf8,0xf8,0x60,0x03,0xc7,0x94,0xf2,0x4a,0x19,0x8e,0x5f,0x53,0xf4,0x9d,0x43,0xac, -]; -static EXPECTED_4096_SHA384: &[u8] = &[ - 0x10,0x83,0x29,0x1f,0xb6,0xe7,0x6a,0x69,0xf3,0xaa,0x62,0x6d,0x2d,0x45,0xf0,0x7d, - 0x37,0x99,0x96,0x0b,0x5d,0xc9,0xa0,0x4e,0x31,0xdd,0x68,0x2c,0x1f,0x75,0xbe,0xda, - 0xcf,0xb0,0x93,0x97,0xa5,0x3c,0x0d,0x11,0x80,0x21,0xe8,0x47,0x90,0x9f,0x73,0x39, - 0x5f,0x40,0x02,0x13,0xd8,0x61,0x32,0x75,0x19,0x6d,0x71,0x4e,0xf4,0x74,0x93,0x26, - 0x61,0x30,0x5b,0x1a,0x8a,0xe8,0x6d,0x93,0xa5,0xa6,0x4c,0xca,0x1f,0xdd,0xf2,0x6f, - 0x2a,0x0c,0x84,0xf9,0xcc,0x71,0x4c,0xdf,0xe9,0x39,0x2c,0xe6,0x07,0x72,0xc1,0x4e, - 0xb7,0xff,0x6f,0xa8,0x26,0x9c,0x23,0x0b,0xf6,0xfb,0xbc,0x64,0x5b,0x3d,0x4c,0x1a, - 0x98,0x42,0x04,0x97,0x97,0x3b,0x5e,0xd4,0x3f,0x0a,0x6b,0xd9,0x2f,0xbe,0x94,0x76, - 0x21,0xaf,0x05,0x0e,0x30,0x2f,0x3a,0x1b,0x9b,0xb4,0x77,0x20,0xf9,0x0f,0x99,0x0a, - 0xd7,0x4d,0xbb,0x1b,0xd3,0xb9,0xd0,0xc5,0x0e,0x73,0x6a,0x67,0x6e,0xb4,0x18,0x39, - 0x44,0x86,0x0e,0xfb,0x1a,0xea,0xc3,0xa5,0x7f,0x39,0x3e,0xf0,0x0e,0x01,0x92,0x61, - 0x82,0x3f,0xff,0x56,0x7b,0x0e,0x80,0x8e,0xcd,0x76,0x81,0xeb,0x9b,0xeb,0xba,0x4d, - 0xd3,0x15,0x44,0xb5,0xdf,0x7b,0xb5,0x20,0xf0,0xc5,0xbf,0x3f,0xb9,0x9b,0x1c,0x8b, - 0x71,0x85,0xe9,0xe2,0xfe,0x6d,0xa3,0x69,0x04,0xb2,0x0b,0x1a,0x03,0x0e,0x60,0x2b, - 0x3b,0xe5,0x72,0x30,0x32,0xab,0x0a,0x9f,0x22,0x3e,0x87,0xf0,0xbf,0xcb,0x8f,0xfd, - 0x8a,0x78,0xb1,0xa9,0x51,0x61,0x11,0x15,0xbb,0xe0,0x00,0x79,0x0d,0x99,0x9c,0x05, - 0x58,0xda,0x96,0x85,0x69,0x66,0x41,0x5c,0x26,0xbf,0xed,0x71,0x17,0x39,0x61,0xb8, - 0xc5,0xb3,0xba,0x9d,0xbd,0xb3,0x52,0xbb,0xf7,0x33,0x7f,0x40,0xf2,0x88,0x10,0x7a, - 0x8f,0xbb,0xbb,0x4d,0xd6,0xf0,0xbb,0x40,0x23,0x4e,0x29,0xbf,0x1b,0xa0,0x35,0xca, - 0x56,0x40,0x28,0x3b,0x29,0xe8,0xfa,0xe9,0x70,0x0e,0x2f,0x7d,0x71,0x43,0xe6,0xc4, - 0xad,0x30,0x28,0xbd,0x56,0x01,0x0f,0x42,0x8d,0xaa,0xeb,0x42,0x73,0xed,0x01,0x5b, - 0x25,0x79,0x0c,0xc6,0x36,0xb7,0x72,0x68,0x37,0x99,0x48,0x0a,0x61,0xf0,0x65,0x3d, - 0xec,0x8a,0x20,0xf4,0x0c,0xf2,0xf1,0x1c,0x1c,0xda,0xdb,0x50,0xf5,0x30,0x6c,0x3b, - 0xb2,0xb8,0xe9,0xd5,0xd1,0xfc,0x78,0x0f,0xdf,0xe3,0xa5,0xeb,0xe5,0x60,0x99,0x11, - 0x23,0x2c,0xd8,0x33,0x7c,0xe5,0x33,0x5a,0x79,0x29,0x1f,0x00,0xa4,0xb3,0x25,0x26, - 0x5d,0x8b,0x6b,0xc4,0x1f,0xd4,0x6b,0x65,0x6d,0xc1,0xf5,0x55,0xcb,0x39,0x6c,0xba, - 0xe7,0xfa,0xf9,0xa5,0xc4,0xf3,0xa1,0x3a,0x12,0xd9,0xa6,0x24,0xa0,0x44,0x13,0xfa, - 0x78,0x9c,0xbf,0xa4,0x88,0xd9,0xce,0xef,0x5b,0xa8,0xd0,0x89,0x95,0xad,0xe8,0xbe, - 0x05,0x92,0xfd,0x75,0x14,0x1c,0xee,0xd2,0xcd,0xa6,0x84,0x19,0xb8,0x3a,0x19,0x59, - 0xa6,0xe4,0x83,0xfd,0x18,0x2f,0x74,0x39,0xa0,0xc0,0x19,0x81,0xc8,0x62,0x36,0x19, - 0xf0,0x49,0xfc,0x06,0xa1,0x39,0x43,0x91,0x76,0xdc,0x4c,0x12,0x8a,0xdd,0x79,0xfd, - 0xd8,0x8a,0x37,0x40,0x81,0x15,0x8a,0x68,0xa8,0xda,0xde,0x00,0x2d,0x54,0x90,0xab, -]; -static EXPECTED_4096_SHA512: &[u8] = &[ - 0x51,0x81,0x4e,0xc6,0xaf,0xf4,0x65,0xab,0x0c,0x29,0x04,0x80,0xa1,0x64,0x73,0x2e, - 0x60,0xa3,0xa2,0xdf,0xf1,0xbe,0x3d,0xdb,0x99,0xb5,0x88,0xcb,0x75,0x45,0x53,0x2a, - 0x74,0x27,0xb8,0x40,0x39,0xf6,0x6c,0x71,0xe4,0xf4,0x2a,0xee,0xa4,0x6b,0x0d,0xc4, - 0x39,0x69,0x95,0x7c,0xa5,0xe7,0x6f,0x77,0x4a,0xec,0x01,0x8c,0xe7,0x31,0x18,0x13, - 0xc1,0x73,0x8b,0x92,0x5a,0xd0,0x76,0xb0,0x2e,0x94,0x33,0x5a,0x5d,0xa7,0xf8,0xbc, - 0x67,0xa3,0x45,0x33,0xb0,0xf3,0xd4,0x97,0xd3,0x0b,0x4e,0x41,0x3d,0xbe,0x0a,0x68, - 0x7f,0x82,0x97,0xbf,0xb1,0xe4,0x1e,0x0c,0x69,0xc2,0xaa,0x1d,0x19,0x21,0x96,0x0b, - 0xa2,0xe6,0x0a,0xe0,0x3c,0x82,0xce,0x84,0x47,0x7c,0x9d,0xd9,0x1b,0x19,0x9a,0x89, - 0xae,0x61,0xab,0xe7,0xd3,0x4a,0xb2,0xaa,0x84,0x16,0x97,0xf4,0xc4,0x2b,0x87,0x16, - 0x2e,0xd2,0x6e,0x15,0xfc,0xca,0xac,0x74,0xe1,0xd8,0x3e,0x4f,0xf6,0xaa,0xa0,0x4d, - 0x5e,0x2e,0x6d,0xac,0x75,0x20,0x59,0x39,0x41,0xa7,0xec,0x59,0x8e,0x3e,0xb0,0x3d, - 0x5f,0x7e,0x23,0x94,0xe7,0x55,0x16,0x09,0x98,0xd5,0x96,0xc6,0x46,0xe3,0x72,0xc1, - 0x59,0xf1,0xc7,0x03,0x37,0x6e,0x4d,0x10,0xe3,0x5f,0xb9,0xa4,0x09,0x47,0xb5,0x72, - 0x8f,0xf3,0x23,0xaf,0x48,0x21,0xfa,0x17,0x57,0xb7,0xfd,0x82,0x79,0x62,0x2d,0x9e, - 0x84,0x21,0xe9,0x4b,0x3b,0x59,0xf2,0xdc,0x2e,0xc8,0xcb,0x3a,0x05,0xa5,0x80,0x11, - 0xe4,0x30,0x6e,0xde,0x00,0xf9,0x35,0xa3,0x00,0x94,0x2e,0xfa,0x76,0xce,0xf0,0x41, - 0x98,0x91,0xb5,0xf7,0x84,0x2a,0x3a,0x09,0xc7,0x9a,0x9d,0x58,0xcd,0xee,0x1a,0x32, - 0xf9,0x43,0xd4,0x31,0x76,0xa7,0x2c,0x03,0x60,0xa6,0x76,0x0c,0xcd,0xf9,0x68,0x08, - 0x5d,0x5a,0xa3,0x8b,0xe2,0xb8,0xb2,0xe9,0x47,0x12,0xc5,0xcd,0x96,0x0a,0x13,0x94, - 0xb4,0xc1,0x7a,0x4c,0x2a,0xa1,0xc9,0x8a,0xbc,0x7b,0x97,0x8d,0x5f,0xf4,0x93,0x07, - 0x70,0xee,0xe5,0xf7,0xb7,0x84,0x98,0xc2,0xc5,0xb5,0x2d,0x4f,0xf5,0xc5,0xcf,0x72, - 0x13,0x94,0x48,0x5f,0x94,0x5a,0x05,0xa2,0xce,0xdb,0x54,0x21,0xca,0x3d,0x24,0xed, - 0x7a,0x1f,0xc5,0xed,0x41,0xbd,0x0c,0x3d,0x30,0x94,0xe9,0x12,0x97,0x29,0x7f,0xd3, - 0x1b,0xcc,0x09,0xaa,0xe9,0x0b,0x54,0x5b,0x9a,0x0d,0xe6,0xb5,0x3b,0x7d,0x5f,0xaa, - 0xf1,0xb0,0x4b,0x1a,0x95,0x74,0xdc,0xf5,0x4a,0xd1,0x4e,0xdf,0xda,0x69,0x6d,0x93, - 0x87,0x5f,0x60,0x48,0x77,0xe5,0x62,0xf2,0xa8,0xe5,0x8c,0x1f,0x2b,0xda,0xbb,0x3c, - 0xc1,0xd9,0x11,0x47,0x75,0x76,0x7b,0x06,0x38,0x5d,0xbd,0x6a,0x45,0x89,0xde,0xfb, - 0xb6,0x80,0x23,0xa1,0x9b,0x28,0x21,0xf9,0x72,0x61,0x0b,0xc1,0x84,0x5b,0x5e,0x90, - 0x4a,0xf3,0x78,0x5a,0x80,0xa7,0x42,0xae,0xd7,0xa6,0xc0,0x38,0x7e,0xc1,0x67,0xa6, - 0x75,0xc9,0x87,0x79,0xeb,0xe3,0x39,0xe4,0x54,0x4a,0x9b,0xcb,0x46,0xc1,0xcf,0xb2, - 0xcc,0xd2,0x71,0x56,0x4c,0x8a,0x33,0x15,0x2a,0x4b,0x48,0x77,0xf9,0x6b,0xe6,0x22, - 0xf5,0x76,0x5c,0xb7,0x3f,0xde,0x17,0xd4,0x4e,0xf9,0x70,0x60,0x2a,0xa8,0xa7,0x13, -]; - -// --------------------------------------------------------------------------- -// Core signing helper -// --------------------------------------------------------------------------- - -fn sign_and_assert(sk: &RsaPrivateKey, digest: RsaDigest, expected: &[u8], label: &str) { - let sig_result = sk.sign_pkcs1v15_with_digest(MSG, digest); - let sig = sig_result.unwrap_or_else(|e| { - panic!("{label}: sign_pkcs1v15_with_digest({digest:?}) failed: {e:?}"); - }); - - // Verify the signature with the corresponding public key (independent round-trip). - let pk = sk.public_key(); - let sig_obj = RsaPkcs1v15Signature::try_from(sig.as_ref()) - .expect("failed to create RsaPkcs1v15Signature from sig bytes"); - pk.verify_pkcs1v15_with_digest(MSG, &sig_obj, digest).unwrap_or_else(|e| { - panic!("{label}: verify_pkcs1v15_with_digest({digest:?}) failed on own signature: {e:?}"); - }); - - let capture_mode = std::env::var("CAPTURE").map(|v| v == "1").unwrap_or(false); - - if capture_mode { - // Print bytes in Rust literal format for easy copy-paste. - print!(" static {label}: &[u8] = &["); - for (i, b) in sig.as_ref().iter().enumerate() { - if i % 16 == 0 { print!("\n "); } - print!("0x{b:02x},"); - } - println!("\n ];"); - } else if !expected.is_empty() { - // Byte-exact comparison โ€” only active once expected bytes are populated. - assert_eq!( - sig.as_ref(), - expected, - "{label}: PKCS#1v1.5 signature bytes changed! \ - This indicates a regression in the signing implementation.\n\ - If this is intentional (e.g., migration to native shims), \ - regenerate expected bytes with CAPTURE=1.", - ); - } - // If expected is empty and CAPTURE is off: sign + verify round-trip only. -} - -// --------------------------------------------------------------------------- -// 2048-bit key vectors -// --------------------------------------------------------------------------- - -#[test] -fn pkcs1v15_baseline_2048_sha256() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("failed to load 2048-bit private key"); - sign_and_assert(&sk, RsaDigest::Sha256, EXPECTED_2048_SHA256, "EXPECTED_2048_SHA256"); -} - -#[cfg(wolfssl_sha384)] -#[test] -fn pkcs1v15_baseline_2048_sha384() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("failed to load 2048-bit private key"); - sign_and_assert(&sk, RsaDigest::Sha384, EXPECTED_2048_SHA384, "EXPECTED_2048_SHA384"); -} - -#[cfg(wolfssl_sha512)] -#[test] -fn pkcs1v15_baseline_2048_sha512() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("failed to load 2048-bit private key"); - sign_and_assert(&sk, RsaDigest::Sha512, EXPECTED_2048_SHA512, "EXPECTED_2048_SHA512"); -} - -// --------------------------------------------------------------------------- -// 4096-bit key vectors -// --------------------------------------------------------------------------- - -#[test] -fn pkcs1v15_baseline_4096_sha256() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_4096_DER) - .expect("failed to load 4096-bit private key"); - sign_and_assert(&sk, RsaDigest::Sha256, EXPECTED_4096_SHA256, "EXPECTED_4096_SHA256"); -} - -#[cfg(wolfssl_sha384)] -#[test] -fn pkcs1v15_baseline_4096_sha384() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_4096_DER) - .expect("failed to load 4096-bit private key"); - sign_and_assert(&sk, RsaDigest::Sha384, EXPECTED_4096_SHA384, "EXPECTED_4096_SHA384"); -} - -#[cfg(wolfssl_sha512)] -#[test] -fn pkcs1v15_baseline_4096_sha512() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_4096_DER) - .expect("failed to load 4096-bit private key"); - sign_and_assert(&sk, RsaDigest::Sha512, EXPECTED_4096_SHA512, "EXPECTED_4096_SHA512"); -} - -// --------------------------------------------------------------------------- -// Determinism self-check: sign the same message twice, must get same bytes -// --------------------------------------------------------------------------- - -#[test] -fn pkcs1v15_is_deterministic() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("failed to load 2048-bit private key"); - let sig1 = sk.sign_pkcs1v15_with_digest(MSG, RsaDigest::Sha256) - .expect("first sign failed"); - let sig2 = sk.sign_pkcs1v15_with_digest(MSG, RsaDigest::Sha256) - .expect("second sign failed"); - assert_eq!( - sig1.as_ref(), - sig2.as_ref(), - "PKCS#1v1.5 produced different bytes on two calls โ€” this is a serious bug!" - ); -} - -// --------------------------------------------------------------------------- -// Different messages produce different signatures -// --------------------------------------------------------------------------- - -#[test] -fn pkcs1v15_different_messages_differ() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("failed to load 2048-bit private key"); - let sig1 = sk.sign_pkcs1v15_with_digest(b"message one", RsaDigest::Sha256) - .expect("sign failed"); - let sig2 = sk.sign_pkcs1v15_with_digest(b"message two", RsaDigest::Sha256) - .expect("sign failed"); - assert_ne!( - sig1.as_ref(), - sig2.as_ref(), - "Different messages produced identical signatures โ€” hash collision or bug" - ); -} - -// --------------------------------------------------------------------------- -// SHA-1 baseline (for ssh-rsa compatibility path) -// --------------------------------------------------------------------------- - -#[cfg(wolfssl_sha1)] -#[test] -fn pkcs1v15_baseline_2048_sha1_roundtrip() { - let sk = RsaPrivateKey::from_pkcs1_der(PRIV_2048_DER) - .expect("failed to load 2048-bit private key"); - let sig = sk.sign_pkcs1v15_with_digest(MSG, RsaDigest::Sha1) - .expect("SHA-1 sign failed"); - let pk = sk.public_key(); - let sig_obj = RsaPkcs1v15Signature::try_from(sig.as_ref()).unwrap(); - pk.verify_pkcs1v15_with_digest(MSG, &sig_obj, RsaDigest::Sha1) - .expect("SHA-1 verify failed on own signature"); -} diff --git a/wolfcrypt-conformance/tests/wycheproof_ecdh.rs b/wolfcrypt-conformance/tests/wycheproof_ecdh.rs deleted file mode 100644 index b7f3aa8..0000000 --- a/wolfcrypt-conformance/tests/wycheproof_ecdh.rs +++ /dev/null @@ -1,230 +0,0 @@ -//! Wycheproof ECDH conformance tests (ecpoint format). -//! -//! Verifies that `NistEcdhSecret::from_private_scalar` + `diffie_hellman` -//! correctly handles the Wycheproof ECDH ecpoint test vectors for P-256, -//! P-384, and P-521. -//! -//! The ecpoint vector format carries the private key as a raw big-endian -//! scalar and the peer public key as an uncompressed EC point (04 || x || y). -//! No DER/PKCS#8 parsing is required. -//! -//! For each valid vector the computed shared secret must equal the expected -//! x-coordinate exactly. For each invalid vector the operation must return -//! an error. Acceptable vectors are skipped. - -#![cfg(wolfssl_ecc)] - -mod helpers; -use helpers::wycheproof::*; - -use wolfcrypt::ecdh::{NistEcdhPublicKey, NistEcdhSecret, NistP256}; - -#[cfg(wolfssl_ecc_p384)] -use wolfcrypt::ecdh::NistP384; - -#[cfg(wolfssl_ecc_p521)] -use wolfcrypt::ecdh::NistP521; - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -/// Normalize a big-endian integer to exactly `field_size` bytes. -/// -/// Wycheproof private scalars are sometimes DER-padded with a leading `00` -/// byte to indicate a positive integer (e.g. 33 bytes for a P-256 scalar). -/// This strips leading zeros and re-pads to `field_size`, returning `None` -/// if the value is wider than `field_size` (out of range). -fn normalize_scalar(bytes: &[u8], field_size: usize) -> Option> { - let first_nonzero = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len()); - let stripped = &bytes[first_nonzero..]; - if stripped.len() > field_size { - return None; // wider than field element encoding; treat as invalid - } - let mut padded = vec![0u8; field_size]; - padded[field_size - stripped.len()..].copy_from_slice(stripped); - Some(padded) -} - -// --------------------------------------------------------------------------- -// Core runner -// --------------------------------------------------------------------------- - -fn run_wycheproof_ecdh_ecpoint( - json: &str, - expected_curve: &str, -) where - C: wolfcrypt::ecdh::NistCurve, -{ - let file: WycheproofFile = - serde_json::from_str(json).expect("failed to parse Wycheproof ECDH ecpoint JSON"); - file.assert_vector_count(); - - let mut valid_count: usize = 0; - let mut invalid_count: usize = 0; - let mut skip_count: usize = 0; - - for group in &file.test_groups { - if group.curve != expected_curve { - skip_count += group.tests.len(); - continue; - } - - for tc in &group.tests { - let pub_bytes = hex_decode(&tc.public, "public"); - let priv_bytes = hex_decode(&tc.private, "private"); - let expected_shared = hex_decode(&tc.shared, "shared"); - - // --- Parse the peer public key --- - let peer_pub = match NistEcdhPublicKey::::from_bytes(&pub_bytes) { - Ok(pk) => pk, - Err(e) => { - match tc.result { - WycheproofResult::Valid => panic!( - "tc {}: key import failed for valid vector \ - (flags: {:?}, error: {:?}), comment: {}", - tc.tc_id, tc.flags, e, tc.comment - ), - WycheproofResult::Invalid => { - invalid_count += 1; - continue; - } - WycheproofResult::Acceptable => { - skip_count += 1; - continue; - } - } - } - }; - - // --- Normalize private scalar (Wycheproof may DER-pad with leading 00) --- - let priv_normalized = match normalize_scalar(&priv_bytes, C::FIELD_SIZE) { - Some(v) => v, - None => { - // Scalar wider than field โ€” definitively invalid. - match tc.result { - WycheproofResult::Valid => panic!( - "tc {}: scalar wider than field for valid vector, comment: {}", - tc.tc_id, tc.comment - ), - _ => { invalid_count += 1; continue; } - } - } - }; - - // --- Import the private scalar --- - let sk = match NistEcdhSecret::::from_private_scalar(&priv_normalized) { - Ok(k) => k, - Err(_) => { - match tc.result { - WycheproofResult::Valid => panic!( - "tc {}: private scalar import failed for valid vector, comment: {}", - tc.tc_id, tc.comment - ), - WycheproofResult::Invalid => { - invalid_count += 1; - continue; - } - WycheproofResult::Acceptable => { - skip_count += 1; - continue; - } - } - } - }; - - // --- Compute shared secret --- - let result = sk.diffie_hellman(&peer_pub); - - match tc.result { - WycheproofResult::Valid => { - let shared = result.unwrap_or_else(|e| { - panic!( - "tc {}: ECDH failed for valid vector (flags: {:?}): {e:?}\n\ - comment: {}", - tc.tc_id, tc.flags, tc.comment - ) - }); - assert_eq!( - shared.as_bytes(), - expected_shared.as_slice(), - "tc {}: shared secret mismatch (comment: {})", - tc.tc_id, - tc.comment - ); - valid_count += 1; - } - WycheproofResult::Invalid => { - assert!( - result.is_err(), - "tc {}: ECDH SUCCEEDED for invalid vector! \ - flags: {:?}, comment: {}", - tc.tc_id, tc.flags, tc.comment - ); - invalid_count += 1; - } - WycheproofResult::Acceptable => { - skip_count += 1; - } - } - } - } - - assert!( - valid_count > 0, - "no valid ECDH vectors were exercised (curve={expected_curve}, skipped={skip_count})" - ); - assert!( - invalid_count > 0, - "no invalid ECDH vectors were exercised (curve={expected_curve}, skipped={skip_count})" - ); - - if skip_count > 0 { - eprintln!( - " wycheproof_ecdh: skipped {skip_count} vectors \ - (non-matching curve or acceptable)" - ); - } - eprintln!( - " wycheproof_ecdh ({expected_curve}): {valid_count} valid, \ - {invalid_count} invalid passed" - ); -} - -// --------------------------------------------------------------------------- -// P-256 tests -// --------------------------------------------------------------------------- - -#[test] -fn ecdh_p256_ecpoint() { - run_wycheproof_ecdh_ecpoint::( - &helpers::load_wycheproof("ecdh_secp256r1_ecpoint_test.json"), - "secp256r1", - ); -} - -// --------------------------------------------------------------------------- -// P-384 tests -// --------------------------------------------------------------------------- - -#[cfg(wolfssl_ecc_p384)] -#[test] -fn ecdh_p384_ecpoint() { - run_wycheproof_ecdh_ecpoint::( - &helpers::load_wycheproof("ecdh_secp384r1_ecpoint_test.json"), - "secp384r1", - ); -} - -// --------------------------------------------------------------------------- -// P-521 tests -// --------------------------------------------------------------------------- - -#[cfg(wolfssl_ecc_p521)] -#[test] -fn ecdh_p521_ecpoint() { - run_wycheproof_ecdh_ecpoint::( - &helpers::load_wycheproof("ecdh_secp521r1_ecpoint_test.json"), - "secp521r1", - ); -} diff --git a/wolfcrypt-conformance/tests/wycheproof_ecdsa.rs b/wolfcrypt-conformance/tests/wycheproof_ecdsa.rs index 4f50030..81db1e8 100644 --- a/wolfcrypt-conformance/tests/wycheproof_ecdsa.rs +++ b/wolfcrypt-conformance/tests/wycheproof_ecdsa.rs @@ -1,4 +1,4 @@ -#![cfg(wolfssl_ecc)] +#![cfg(all(wolfssl_openssl_extra, wolfssl_ecc))] mod helpers; use helpers::wycheproof::*; @@ -141,7 +141,7 @@ wycheproof_ecdsa_test!( wolfcrypt::EcdsaSignature, "secp256r1", "SHA-256", - [wolfssl_ecc] + [wolfssl_openssl_extra, wolfssl_ecc] ); wycheproof_ecdsa_test!( @@ -152,7 +152,7 @@ wycheproof_ecdsa_test!( wolfcrypt::EcdsaSignature, "secp384r1", "SHA-384", - [wolfssl_ecc, wolfssl_ecc_p384] + [wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p384] ); wycheproof_ecdsa_test!( @@ -163,5 +163,5 @@ wycheproof_ecdsa_test!( wolfcrypt::EcdsaSignature, "secp521r1", "SHA-512", - [wolfssl_ecc, wolfssl_ecc_p521, wolfssl_sha512] + [wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p521] ); diff --git a/wolfcrypt-conformance/tests/wycheproof_keywrap.rs b/wolfcrypt-conformance/tests/wycheproof_keywrap.rs index 801121d..345c25b 100644 --- a/wolfcrypt-conformance/tests/wycheproof_keywrap.rs +++ b/wolfcrypt-conformance/tests/wycheproof_keywrap.rs @@ -1,4 +1,4 @@ -#![cfg(wolfssl_aes_keywrap)] +#![cfg(all(wolfssl_openssl_extra, wolfssl_aes_keywrap))] mod helpers; use helpers::wycheproof::*; diff --git a/wolfcrypt-conformance/tests/wycheproof_rsa.rs b/wolfcrypt-conformance/tests/wycheproof_rsa.rs index b693594..2a484de 100644 --- a/wolfcrypt-conformance/tests/wycheproof_rsa.rs +++ b/wolfcrypt-conformance/tests/wycheproof_rsa.rs @@ -1,4 +1,4 @@ -#![cfg(wolfssl_rsa)] +#![cfg(all(wolfssl_openssl_extra, wolfssl_rsa))] mod helpers; use helpers::wycheproof::*; diff --git a/wolfcrypt-conformance/tests/wycheproof_rsa_oaep.rs b/wolfcrypt-conformance/tests/wycheproof_rsa_oaep.rs deleted file mode 100644 index 3c20117..0000000 --- a/wolfcrypt-conformance/tests/wycheproof_rsa_oaep.rs +++ /dev/null @@ -1,240 +0,0 @@ -//! Wycheproof RSA-OAEP decryption conformance tests. -//! -//! Verifies that `RsaPrivateKey::decrypt_oaep` (SHA-256, empty label) correctly -//! handles the Wycheproof OAEP test vectors. -//! -//! The current implementation hardcodes SHA-256 for the OAEP hash. We filter test -//! groups to sha == "SHA-256" and mgfSha == "SHA-256", and skip test cases that -//! carry a non-empty OAEP label (the API does not expose a label parameter). -//! -//! These tests form a critical oracle for the RSA migration: after switching from -//! the EVP-based API to native wc_* shims, every test that passes here must -//! continue to pass with identical plaintext output. - -#![cfg(wolfssl_rsa)] - -mod helpers; -use helpers::wycheproof::*; - -use wolfcrypt::rsa::RsaPrivateKey; - -// --------------------------------------------------------------------------- -// PKCS#8 โ†’ PKCS#1 extractor -// --------------------------------------------------------------------------- - -/// Extract the inner RSAPrivateKey (PKCS#1) DER from a PKCS#8 PrivateKeyInfo DER. -/// -/// PKCS#8 PrivateKeyInfo structure: -/// ```text -/// SEQUENCE { -/// INTEGER (version = 0) -/// SEQUENCE { OID rsaEncryption, NULL } -/// OCTET STRING { } -/// } -/// ``` -/// -/// Panics on malformed input (defensive: Wycheproof keys are always valid DER). -fn pkcs8_extract_rsa_pkcs1(pkcs8: &[u8]) -> Vec { - fn read_len(data: &[u8], pos: &mut usize) -> usize { - let b = data[*pos]; - *pos += 1; - if b & 0x80 == 0 { - return b as usize; - } - let num_bytes = (b & 0x7f) as usize; - assert!(num_bytes <= 4, "DER length too large"); - let mut len = 0usize; - for _ in 0..num_bytes { - len = (len << 8) | (data[*pos] as usize); - *pos += 1; - } - len - } - - let mut pos = 0; - - // Outer SEQUENCE - assert_eq!(pkcs8[pos], 0x30, "Expected outer SEQUENCE tag (0x30), got 0x{:02x}", pkcs8[pos]); - pos += 1; - read_len(pkcs8, &mut pos); // outer length (skip) - - // INTEGER version (02 01 00) - assert_eq!(pkcs8[pos], 0x02, "Expected INTEGER tag for version"); - pos += 1; - let ver_len = read_len(pkcs8, &mut pos); - pos += ver_len; - - // AlgorithmIdentifier SEQUENCE - assert_eq!(pkcs8[pos], 0x30, "Expected AlgorithmIdentifier SEQUENCE"); - pos += 1; - let algo_len = read_len(pkcs8, &mut pos); - pos += algo_len; - - // OCTET STRING containing PKCS#1 RSAPrivateKey - assert_eq!(pkcs8[pos], 0x04, "Expected OCTET STRING for private key content"); - pos += 1; - let content_len = read_len(pkcs8, &mut pos); - - assert_eq!( - pos + content_len, - pkcs8.len(), - "PKCS#8 trailing bytes after OCTET STRING โ€” unexpected structure" - ); - - pkcs8[pos..pos + content_len].to_vec() -} - -// --------------------------------------------------------------------------- -// Core runner -// --------------------------------------------------------------------------- - -/// Run Wycheproof RSA-OAEP decryption vectors from a JSON string. -/// -/// Filters to groups with matching sha / mgfSha. Skips groups whose private -/// key cannot be loaded and test cases with a non-empty OAEP label (the -/// current API does not expose a label parameter). -fn run_wycheproof_oaep(json: &str, expected_sha: &str, expected_mgf_sha: &str) { - let file: WycheproofFile = - serde_json::from_str(json).expect("failed to parse Wycheproof RSA-OAEP JSON"); - file.assert_vector_count(); - - let mut valid_count: usize = 0; - let mut invalid_count: usize = 0; - let mut skip_count: usize = 0; - - for group in &file.test_groups { - if group.sha != expected_sha || group.mgf_sha != expected_mgf_sha { - skip_count += group.tests.len(); - continue; - } - - let pkcs8 = hex_decode(&group.private_key_pkcs8, "privateKeyPkcs8"); - let pkcs1 = pkcs8_extract_rsa_pkcs1(&pkcs8); - let sk = match RsaPrivateKey::from_pkcs1_der(&pkcs1) { - Ok(k) => k, - Err(e) => { - eprintln!( - " wycheproof_rsa_oaep: skip group (key_size={}, key load failed: {e:?})", - group.key_size - ); - skip_count += group.tests.len(); - continue; - } - }; - - for tc in &group.tests { - let label = hex_decode(&tc.label, "label"); - if !label.is_empty() { - // Current decrypt_oaep API does not support non-empty OAEP labels. - skip_count += 1; - continue; - } - - let ct = hex_decode(&tc.ct, "ct"); - let expected_msg = hex_decode(&tc.msg, "msg"); - - if expected_msg.is_empty() && tc.result == WycheproofResult::Valid { - // wolfSSL requires WOLFSSL_RSA_DECRYPT_TO_0_LEN to return 0 bytes - // from wc_RsaPrivateDecrypt_ex for a valid empty OAEP plaintext; - // without it the function returns RSA_BUFFER_E (-131) instead. - // The pre-built wolfSSL library at ~/wolfssl-install does not have - // this flag. Source builds (wolfssl-src/user_settings.h) do include it. - // Skip these vectors to avoid false failures against the pre-built lib. - skip_count += 1; - continue; - } - - let result = sk.decrypt_oaep(&ct); - - match tc.result { - WycheproofResult::Valid => { - let plaintext = result.unwrap_or_else(|e| { - panic!( - "tc {}: OAEP decrypt failed for valid vector (flags: {:?}): {e:?}\n\ - comment: {}", - tc.tc_id, tc.flags, tc.comment, - ) - }); - assert_eq!( - plaintext, - expected_msg, - "tc {}: OAEP decrypted plaintext mismatch (comment: {})", - tc.tc_id, - tc.comment, - ); - valid_count += 1; - } - WycheproofResult::Invalid => { - assert!( - result.is_err(), - "tc {}: OAEP decrypt SUCCEEDED for invalid vector! \ - flags: {:?}, comment: {}", - tc.tc_id, - tc.flags, - tc.comment, - ); - invalid_count += 1; - } - WycheproofResult::Acceptable => { - // Acceptable vectors are implementation-defined; skip. - skip_count += 1; - } - } - } - } - - assert!( - valid_count > 0, - "no valid RSA-OAEP vectors were exercised \ - (sha={expected_sha}, mgfSha={expected_mgf_sha}, skipped={skip_count}). \ - Does the current implementation match this hash configuration?" - ); - assert!( - invalid_count > 0, - "no invalid RSA-OAEP vectors were exercised \ - (sha={expected_sha}, mgfSha={expected_mgf_sha}, skipped={skip_count})" - ); - - if skip_count > 0 { - eprintln!( - " wycheproof_rsa_oaep: skipped {skip_count} vectors \ - (non-matching hash, empty-label filter, or key load failure)" - ); - } - - eprintln!( - " wycheproof_rsa_oaep: {valid_count} valid, {invalid_count} invalid passed" - ); -} - -// --------------------------------------------------------------------------- -// RSA-OAEP SHA-256 / MGF1-SHA-256 -// --------------------------------------------------------------------------- - -#[test] -fn rsa_oaep_2048_sha256_mgf1sha256() { - run_wycheproof_oaep( - &helpers::load_wycheproof("rsa_oaep_2048_sha256_mgf1sha256_test.json"), - "SHA-256", - "SHA-256", - ); -} - -#[test] -fn rsa_oaep_3072_sha256_mgf1sha256() { - run_wycheproof_oaep( - &helpers::load_wycheproof("rsa_oaep_3072_sha256_mgf1sha256_test.json"), - "SHA-256", - "SHA-256", - ); -} - -#[test] -fn rsa_oaep_4096_sha256_mgf1sha256() { - run_wycheproof_oaep( - &helpers::load_wycheproof("rsa_oaep_4096_sha256_mgf1sha256_test.json"), - "SHA-256", - "SHA-256", - ); -} - diff --git a/wolfcrypt-conformance/vectors/rsa/priv_2048.der b/wolfcrypt-conformance/vectors/rsa/priv_2048.der deleted file mode 100644 index b19c252..0000000 Binary files a/wolfcrypt-conformance/vectors/rsa/priv_2048.der and /dev/null differ diff --git a/wolfcrypt-conformance/vectors/rsa/priv_4096.der b/wolfcrypt-conformance/vectors/rsa/priv_4096.der deleted file mode 100644 index 1c3da29..0000000 Binary files a/wolfcrypt-conformance/vectors/rsa/priv_4096.der and /dev/null differ diff --git a/wolfcrypt-dpe-hw/Cargo.toml b/wolfcrypt-dpe-hw/Cargo.toml deleted file mode 100644 index 95c623c..0000000 --- a/wolfcrypt-dpe-hw/Cargo.toml +++ /dev/null @@ -1,120 +0,0 @@ -[package] -name = "wolfcrypt-dpe-hw" -authors = ["WolfSSL Inc"] -version = "0.1.0" -edition = "2021" -license = "MIT" -description = "Caliptra hardware backend for wolfcrypt-dpe" -homepage = "http://wolfssl.com" -repository = "https://github.com/wolfSSL/wolfssl-rs" -keywords = ["wolfcrypt", "wolfssl", "caliptra", "dpe", "hardware"] -categories = ["cryptography", "embedded", "no-std"] -publish = false - -[lib] -name = "wolfcrypt_dpe_hw" - -[features] -default = [] -caliptra-2x = [ - "dep:caliptra-drivers", - "dep:sha2", "dep:hmac", - "dep:aes", "dep:ghash", "dep:cbc", - "dep:subtle", "dep:zeroize", - "dep:p384", -] -# Build wolfSSL with only the CryptoCb callback infrastructure. -# wolfcrypt-dpe-hw does not own the wolfSSL build chain (wolfcrypt-sys is only -# a non-riscv32 dep here); activate this feature on wolfcrypt-dpe instead, -# which propagates it through wolfcrypt โ†’ wolfcrypt-rs โ†’ wolfcrypt-sys โ†’ -# wolfssl-src. This entry keeps the feature name visible at the top of the -# crate graph for documentation purposes. -cryptocb-only = [] -# Absolute-minimum wolfSSL build for wolfcrypt-dpe-hw: CryptoCb routing only, -# no OPENSSL_EXTRA, no HKDF, no ASN template. See wolfssl-src/cryptocb-pure. -# Use this instead of cryptocb-only when wolfcrypt-dpe-hw is the only consumer -# of wolfcrypt-sys (i.e. wolfcrypt-dpe is not in the dep graph). -cryptocb-pure = ["wolfcrypt-sys/cryptocb-pure"] -# ML-DSA-87 hardware dispatch via Adams Bridge. -# Off by default (even within caliptra-2x) โ€” wire-format compatibility between -# wolfCrypt ML-DSA-87 and caliptra-drivers Adams Bridge has not been verified. -# Enable only after the cross-validation tests in phase4_mldsa.rs pass. -mldsa87-hw = ["caliptra-2x"] -# Test/development error-injection hooks. -# MUST NOT be enabled in production builds. Exposes INJECT_TRNG_ERROR, which -# disables the entropy source when set โ€” a FIPS 140-3 disqualifying hook if -# present in a production binary. Integration tests that exercise fault -# injection must be compiled with --features testing-hooks. -testing-hooks = [] - -# wolfcrypt-sys is only needed on host / non-RISC-V targets (where the wolfSSL -# library is available). On riscv32 bare-metal the caliptra-drivers crate -# provides hardware acceleration directly; there is no system wolfSSL. -[target.'cfg(not(target_arch = "riscv32"))'.dependencies] -wolfcrypt-sys = { version = "0.1.2", path = "../wolfcrypt-sys" } - -[dependencies] -# Requires the chipsalliance/caliptra repo checked out at ../caliptra relative -# to this workspace root (i.e. wolfssl-rs and caliptra are siblings). -# Only resolved when `caliptra-2x` feature is enabled. -caliptra-drivers = { path = "../../caliptra/drivers", optional = true } - -# no_std-compatible spin mutex for streaming hash/HMAC state. -spin = { workspace = true } - -# Cryptographic primitives used for host-side (non-riscv32) dispatch. -# On riscv32 firmware, caliptra-drivers hardware registers are used instead. -# Both crates are no_std-compatible with default-features = false. -sha2 = { version = "0.10", default-features = false, features = ["force-soft"], optional = true } -hmac = { version = "0.12", default-features = false, optional = true } - -# Phase 3: AES-GCM/CBC hardware dispatch (host path via RustCrypto primitives). -# On riscv32 firmware the caliptra-drivers crate provides hardware registers -# directly; these crates are not needed on that target. -# All are no_std-compatible with default-features = false. -aes = { version = "0.8", default-features = false, features = ["zeroize"], optional = true } -ghash = { version = "0.5", default-features = false, optional = true } -cbc = { version = "0.1", default-features = false, features = ["block-padding"], optional = true } -subtle = { version = "2", default-features = false, optional = true } -zeroize = { workspace = true, optional = true } - -# Phase 4: ECC-384 hardware dispatch (host path via RustCrypto p384 primitives). -# caliptra-drivers Ecc384 hardware dispatch is deferred to a future phase; -# the host path uses p384 + ecdsa for correctness testing. -# p384 is no_std-compatible with default-features = false. -p384 = { version = "0.13", default-features = false, features = ["ecdsa", "ecdh"], optional = true } - -[[test]] -name = "phase2_rng" -required-features = ["caliptra-2x", "testing-hooks"] - -[[test]] -name = "link_probe_hash" -harness = false - -[[test]] -name = "link_probe_rng" -harness = false - -[[test]] -name = "link_probe_aes" -harness = false - -[[test]] -name = "link_probe_pk" -harness = false - -[[test]] -name = "link_probe_integration" -harness = false - -[build-dependencies] -cc = { workspace = true } - -[dev-dependencies] -# sw-emulator for test harness โ€” see caliptra-prompts/caliptra-phase1.md. -# Tests "instantiate the caliptra sw-emulator" via CaliptraRootBus::new(). -caliptra-emu-periph = { path = "../../caliptra/sw-emulator/lib/periph" } -hex = { workspace = true } -sha2 = { version = "0.10", features = ["force-soft"] } -hmac = { version = "0.12" } diff --git a/wolfcrypt-dpe-hw/FIPS_BOUNDARY.md b/wolfcrypt-dpe-hw/FIPS_BOUNDARY.md deleted file mode 100644 index 8065ba9..0000000 --- a/wolfcrypt-dpe-hw/FIPS_BOUNDARY.md +++ /dev/null @@ -1,186 +0,0 @@ -# FIPS Module Boundary โ€” wolfcrypt-dpe-hw - -## 1. Module Boundary Statement - -**This document describes two distinct compilation targets. They have different -module boundaries. Do not conflate them.** - -### Host / non-riscv32 build (`--features caliptra-2x`, `target_arch != riscv32`) - -On this target, the cryptographic algorithms execute entirely in **RustCrypto -software crates** (`sha2`, `hmac`, `aes`, `ghash`, `cbc`, `p384`). No -caliptra-drivers hardware registers are accessed during algorithm dispatch. -The `CaliptraRootBus` sw-emulator is instantiated in integration tests for -infrastructure testing only; it is not invoked by any of the dispatch -functions (`hw_hash.rs`, `hw_aes.rs`, `hw_pk.rs`). - -**This build is NOT a FIPS boundary.** It is used for host-side integration -testing and conformance vector verification only. - -### RISC-V / Caliptra silicon build (`--features caliptra-2x`, `target_arch = riscv32`) - -On this target, the intended FIPS boundary extends to include the Caliptra 2.x -hardware accelerators accessible via caliptra-drivers. The software boundary -(wolfCrypt) and hardware boundary (Caliptra silicon) are connected through the -wc_CryptoCb mechanism. - -The boundary is established at registration time by `wolfcrypt_dpe_hw::init()`, -which calls `wc_CryptoCb_RegisterDevice(HW_DEVICE_ID, hw_callback, NULL)`. -All wolfCrypt operations initiated with `devId = HW_DEVICE_ID` pass through -`hw_callback` and are dispatched to the Caliptra hardware. - -**Note:** any operation initiated with `INVALID_DEVID` (for example, via -`wc_InitRng` without an explicit devId) bypasses the boundary entirely and -uses wolfSSL's internal software DRBG. Callers must use -`wc_InitRng_ex(&rng, NULL, HW_DEVICE_ID)` for ITRNG dispatch to be active. - -This riscv32/Caliptra silicon build is the build subject to FIPS 140-3 -evaluation. The host build is not. - ---- - -## 2. Algorithm Table - -The table below covers both compilation paths. The "Non-riscv32 host -implementation" column shows what actually executes today (for testing). -The "riscv32 Caliptra implementation" column shows the intended production -implementation (pending silicon certification). - -| Algorithm | Non-riscv32 host implementation | riscv32 Caliptra implementation | FIPS 140-3 approved? | Notes | -|-------------|--------------------------------|---------------------------------|----------------------|-------| -| SHA-256 | RustCrypto `sha2` crate | caliptra-drivers hash engine | Yes (FIPS 180-4) | Dispatch via `dispatch_hash` | -| SHA-384 | RustCrypto `sha2` crate | caliptra-drivers hash engine | Yes (FIPS 180-4) | Dispatch via `dispatch_hash` | -| SHA-512 | RustCrypto `sha2` crate | caliptra-drivers hash engine | Yes (FIPS 180-4) | Dispatch via `dispatch_hash` | -| HMAC-384 | RustCrypto `hmac` + `sha2` | caliptra-drivers hash engine | Yes (FIPS 198-1) | Dispatch via `dispatch_hmac`; KAT uses RFC 4231 TC1 hardcoded vector | -| AES-256-GCM | RustCrypto `aes` + `ghash` | caliptra-drivers AES engine | Yes (FIPS 197, SP 800-38D) | Dispatch via `dispatch_cipher` | -| AES-256-CBC | RustCrypto `cbc` crate | caliptra-drivers AES engine | Yes (FIPS 197, SP 800-38A) | Dispatch via `dispatch_cipher` | -| ECDSA P-384 | RustCrypto `p384` crate | caliptra-drivers Ecc384 | Yes (FIPS 186-4) | Dispatch via `dispatch_pk` | -| ECDH P-384 | RustCrypto `p384` crate | caliptra-drivers Ecc384 | Yes (SP 800-56A) | Dispatch via `dispatch_pk`; riscv32 path deferred | -| ITRNG/RNG | OS entropy via `wc_GenerateSeed` (non-riscv32: `/dev/urandom`) | caliptra-drivers ITRNG via `caliptra_hw_generate_seed` | Yes (SP 800-90B, SP 800-90A CTR-DRBG seeding) | Dispatch via `dispatch_rng` (non-riscv32) or `caliptra_seed.c` shim (riscv32) | -| ML-DSA-87 | Stub โ€” returns `CRYPTOCB_UNAVAILABLE` | Stub โ€” not yet implemented | Conditional (FIPS 204) | Wire-format compatibility with Adams Bridge not yet verified; see Section 5 | - ---- - -## 3. Testing Gaps - -### What the sw-emulator does NOT test - -The Caliptra sw-emulator (`caliptra-emu-periph` / `CaliptraRootBus`) exercises -the hardware register interface at the Rust API level. It does NOT test: - -- **Side-channel resistance**: timing attacks, power analysis, electromagnetic - emanations are hardware properties not observable in simulation. -- **Power analysis**: simple/differential power analysis (SPA/DPA) requires - silicon-level measurements. -- **Silicon timing**: the emulator runs on host-CPU clocks; real silicon latency - and timing jitter are not modelled. -- **Physical tamper response**: Caliptra's tamper-detection and key-zeroization - circuitry are silicon-only features. -- **True entropy quality**: the sw-emulator's ITRNG returns pseudo-random bytes, - not entropy from a physical noise source. - -**Requires real silicon or FPGA for full FIPS 140-3 testing**: -- Entropy source quality testing (NIST SP 800-90B) -- Conditional algorithm self-tests (CAST) on actual hardware -- Physical security testing (Levels 3โ€“4) - -### ITRNG bypass in TLS simulation test - -`test_full_tls_handshake_simulation` (`phase5_integration.rs`) calls -`wc_InitRng(&mut rng)` without a `devId` argument. This uses `INVALID_DEVID` -internally and routes RNG calls through wolfSSL's internal software DRBG. -`TRNG_DISPATCH_COUNT` does not increment during this test. The ITRNG dispatch -path is exercised separately in `phase2_rng.rs` tests 1โ€“5. A FIPS submission -must document this: the TLS simulation test does not exercise the approved -entropy source. - -### Single hash context limitation - -`hw_hash.rs` supports exactly one in-flight SHA context at a time. If two SHA -contexts are interleaved on the same `HW_DEVICE_ID` (one context Update, then -another context Update before the first context Final), the first context's -partial state is silently discarded. The Caliptra firmware is single-threaded -and wolfSSL does not interleave SHA contexts in the firmware usage pattern. -This constraint is documented in `hw_hash.rs` and must be disclosed in any -FIPS submission for deployments where concurrent SHA operations are possible. - -### ML-DSA-87 wire-format status - -Wire-format compatibility between wolfCrypt ML-DSA-87 and the Caliptra Adams -Bridge has not been confirmed. ML-DSA-87 hardware dispatch remains a stub. -See Section 5 open issue 1. - ---- - -## 4. Key Material Handling - -- **Ephemeral keys only**: all ECC-384 key pairs generated by `hw_pk.rs` are - ephemeral; key bytes are in process memory only and are not persisted. -- **No key vault integration**: Caliptra's hardware key vault (KV) is not yet - wired into this layer. Future phases will add `wc_ecc_import_key_from_kv()` - or equivalent. -- **Key zeroization**: `test_key_material_zeroized` in `phase3_aes.rs` uses a - stack scan heuristic to check that AES key bytes are cleared after use. - This test provides heuristic evidence only; register allocation may prevent - the key from appearing on the scanned stack region. ECC key zeroization - is handled by wolfCrypt's `wc_ecc_free()` and explicit `zeroize::Zeroize` - calls on intermediate buffers in `hw_pk.rs`. -- **ITRNG seeding**: `hw_rng.rs` seeds wolfCrypt's DRBG from the ITRNG callback. - The DRBG itself runs in software (CTR-DRBG per SP 800-90A) seeded from - hardware entropy. Callers must use `wc_InitRng_ex` with `HW_DEVICE_ID` for - ITRNG dispatch to be active (see Section 1, ITRNG bypass note). - ---- - -## 5. Open Issues - -### TODO / FIXME / HACK scan โ€” wolfcrypt-dpe-hw/src/ - -No TODO, FIXME, or HACK comments found in `wolfcrypt-dpe-hw/src/` at time of -this writing. - -### Escalated issues โ€” audit/ - -No `*_escalated.md` files exist in `audit/` at time of this writing. - -### Known future work and open items - -1. **ML-DSA-87 wire format** โ€” `hw_pk.rs`: stub returns `CRYPTOCB_UNAVAILABLE` - until cross-validation with Adams Bridge is performed. The build flag - `HAVE_DILITHIUM` is already enabled in the local wolfSSL build (see - `.cargo/config.toml`, `WOLFSSL_DIR`). The actual blocker is wire-format - compatibility: the signature format used by caliptra-drivers Adams Bridge - must be confirmed compatible with wolfCrypt ML-DSA-87 before hardware - dispatch can be enabled. - -2. **ECC riscv32 path** โ€” `hw_pk.rs`: all ECC operations (ECDSA sign/verify and - ECDH) on riscv32 bare-metal use caliptra-drivers Ecc384 hardware primitives. - Integration with caliptra-drivers 2.x is deferred to a future phase. None - of the ECC dispatch functions are currently implemented for riscv32. - -3. **Key vault integration** โ€” `hw_pk.rs`: ephemeral key material is not stored - in the Caliptra hardware key vault. KV integration is required before - long-term identity keys can be protected at FIPS Level 3. - -4. **True RNG on riscv32** โ€” `hw_rng.rs`: the ITRNG path on riscv32 calls - `caliptra_drivers::Trng::generate()`. Entropy quality certification per - SP 800-90B requires hardware characterisation beyond what the sw-emulator - provides. - -5. **ECC invalid-curve attack mitigation** โ€” `hw_pk.rs` (riscv32 path, future): - when the riscv32 hardware ECC path is implemented, all public key inputs must - be validated on-curve before being passed to `caliptra_drivers::Ecc384`. Off- - curve public keys can be used to extract private key scalars via Pohlig-Hellman - variants. This check is required before any riscv32 ECC dispatch is enabled. - -6. **HMAC-384 KAT source** โ€” confirmed: `test_hmac384_nist_vector` uses a - hardcoded RFC 4231 Test Case 1 vector (`const HMAC384_RFC4231_TC1: [u8; 48]`) - as the expected value. The expected MAC is not computed at runtime from the - implementation under test. The FIPS CAVP/ACVTS KAT requirement (independent - known-answer source) is satisfied. - -7. **`ECC_DISPATCH_COUNT` semantics** โ€” the counter increments on successful - sign, successful verify, and successful ECDH. It does NOT increment on - `VERIFY_SIGN_ERROR` (verify failure). Counter-based dispatch evidence will - count fewer dispatches than total invocations when reject paths are exercised. - This must be disclosed when using counters as FIPS dispatch proof. diff --git a/wolfcrypt-dpe-hw/audit/phase2_link_probe.txt b/wolfcrypt-dpe-hw/audit/phase2_link_probe.txt deleted file mode 100644 index 65540f4..0000000 --- a/wolfcrypt-dpe-hw/audit/phase2_link_probe.txt +++ /dev/null @@ -1,3 +0,0 @@ -link_probe_rng: PASS -rc=0 -output[0]=0xf4 diff --git a/wolfcrypt-dpe-hw/audit/phase3_link_probe.txt b/wolfcrypt-dpe-hw/audit/phase3_link_probe.txt deleted file mode 100644 index 2de8cd0..0000000 --- a/wolfcrypt-dpe-hw/audit/phase3_link_probe.txt +++ /dev/null @@ -1 +0,0 @@ -LINK OK diff --git a/wolfcrypt-dpe-hw/audit/phase4_link_probe.txt b/wolfcrypt-dpe-hw/audit/phase4_link_probe.txt deleted file mode 100644 index 2de8cd0..0000000 --- a/wolfcrypt-dpe-hw/audit/phase4_link_probe.txt +++ /dev/null @@ -1 +0,0 @@ -LINK OK diff --git a/wolfcrypt-dpe-hw/build.rs b/wolfcrypt-dpe-hw/build.rs deleted file mode 100644 index d8a5b3e..0000000 --- a/wolfcrypt-dpe-hw/build.rs +++ /dev/null @@ -1,36 +0,0 @@ -// wolfcrypt-dpe-hw build script. -// -// Compiles `caliptra_seed.c` only when both: -// - the `caliptra-2x` feature is enabled, AND -// - the target architecture is `riscv32`. -// -// On non-riscv32 (host / test) targets, the CryptoCb WC_ALGO_TYPE_RNG -// callback in hw_rng.rs handles TRNG dispatch without a C shim. - -fn main() { - let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); - let caliptra_2x = std::env::var("CARGO_FEATURE_CALIPTRA_2X").is_ok(); - - if caliptra_2x && target_arch == "riscv32" { - // Locate the wolfSSL include dirs via DEP_WOLFSSL env vars propagated - // from wolfcrypt-rs (which has `links = "wolfssl"`). - let include = std::env::var("DEP_WOLFSSL_INCLUDE").unwrap_or_default(); - let settings_include = - std::env::var("DEP_WOLFSSL_SETTINGS_INCLUDE").unwrap_or_default(); - - let mut build = cc::Build::new(); - build - .file("src/caliptra_seed.c") - .define("WOLFSSL_USER_SETTINGS", None); - - if !include.is_empty() { - build.include(&include); - } - if !settings_include.is_empty() { - build.include(&settings_include); - } - - build.compile("caliptra_seed"); - println!("cargo:rerun-if-changed=src/caliptra_seed.c"); - } -} diff --git a/wolfcrypt-dpe-hw/src/caliptra_seed.c b/wolfcrypt-dpe-hw/src/caliptra_seed.c deleted file mode 100644 index 1a7822c..0000000 --- a/wolfcrypt-dpe-hw/src/caliptra_seed.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * wolfcrypt-dpe-hw/src/caliptra_seed.c - * - * Implements `caliptra_generate_random_block` for wolfSSL random generation. - * Compiled only for riscv32imc-unknown-none-elf with the `caliptra-2x` feature. - * - * wolfSSL calls this function directly for random bytes because - * `user_settings_cryptocb_only.h` defines: - * #define CUSTOM_RAND_GENERATE_BLOCK caliptra_generate_random_block - * - * This bypasses wolfSSL's software HASH-DRBG entirely. The Caliptra hardware - * implements an AES-256-CTR-DRBG (SP 800-90A) in silicon; FIPS 140-3 / - * SP 800-90C requires using the hardware DRBG directly rather than stacking a - * second software DRBG on top of it. - * - * This shim delegates to `caliptra_hw_generate_seed` (Rust, in hw_rng.rs) - * which calls the Caliptra ITRNG via caliptra-drivers `Trng::generate()`. - * - * Firmware must call `wolfcrypt_dpe_hw::hw_rng::register_trng(trng)` before - * any call to `wc_RNG_GenerateBlock()` so that `caliptra_hw_generate_seed` - * has a live Trng instance. - */ - -#include -#include - -/* Forward declaration of the Rust implementation in hw_rng.rs. */ -extern int caliptra_hw_generate_seed(unsigned char *output, unsigned int sz); - -/* - * caliptra_generate_random_block โ€” direct hardware DRBG output for wolfSSL. - * - * Called by wc_RNG_GenerateBlock() via CUSTOM_RAND_GENERATE_BLOCK. - * No software DRBG state is involved; bytes come straight from the - * Caliptra iTRNG / CSRNG hardware. - * - * @output: Destination buffer for random bytes. - * @sz: Number of bytes requested. - * - * Returns 0 on success, non-zero on error (ITRNG unavailable or failure). - */ -int caliptra_generate_random_block(unsigned char *output, unsigned int sz) -{ - return caliptra_hw_generate_seed(output, sz); -} diff --git a/wolfcrypt-dpe-hw/src/hw_aes.rs b/wolfcrypt-dpe-hw/src/hw_aes.rs deleted file mode 100644 index f52c814..0000000 --- a/wolfcrypt-dpe-hw/src/hw_aes.rs +++ /dev/null @@ -1,506 +0,0 @@ -//! Hardware AES-GCM/CBC dispatch for the Caliptra CryptoCb backend. -//! -//! Only compiled when `caliptra-2x` feature is active on non-RISC-V targets. -//! RISC-V firmware dispatch (using caliptra-drivers registers directly) is -//! deferred to a future phase. -//! -//! # Endianness -//! -//! caliptra-drivers handles endianness internally via Array4x* types and -//! explicit `.swap_bytes()` calls where required by hardware (see -//! `recon_caliptra_drivers.md` ยง10). No ENDIAN_TOGGLE register manipulation -//! is needed at this layer. On the host (non-riscv32) path the `aes`, `ghash`, -//! and `cbc` RustCrypto crates use standard big-endian byte-oriented interfaces; -//! no byte-swapping is needed. -//! -//! # IV uniqueness (AES-GCM) -//! -//! This layer does NOT enforce IV uniqueness. Reusing an (key, IV) pair under -//! AES-GCM is catastrophic โ€” it reveals the GHASH subkey and breaks -//! confidentiality of all messages encrypted under that key. IV uniqueness is -//! the caller's responsibility. wolfSSL enforces it through its own key and -//! nonce management APIs (`wc_AesGcmSetExtIV`, `wc_AesGcmSetIV`, -//! `wc_AesGcmSetNonceLen`); the CryptoCb dispatch path receives an IV that -//! wolfSSL has already selected. Callers that supply their own IVs via the -//! CryptoCb interface must ensure uniqueness per NIST SP 800-38D ยง8.2. -//! -//! # Key handling -//! -//! wolfSSL populates `Aes.devKey` (raw 32 bytes for AES-256) when -//! `WOLF_CRYPTO_CB` is defined. Each dispatch function copies those bytes to a -//! stack-local `[u8; 32]`, passes it to the hardware driver, then calls -//! `zeroize::Zeroize` on the stack copy after use. The `aes` crate's -//! `zeroize` feature is explicitly enabled so that the expanded AES key -//! schedule (round keys) is also zeroed on drop. -//! -//! Key vault integration is a future phase โ€” keys are ephemeral and transit -//! Caliptra-internal SRAM only during operation. -//! -//! # AES-256-CBC availability -//! -//! AES-256-CBC is confirmed available in caliptra-drivers (`aes_256_cbc()` -//! in `drivers/src/aes.rs`, see `recon_caliptra_drivers.md` ยง11). Both -//! encrypt and decrypt are dispatched to hardware. - -use core::ffi::c_int; -use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; - -use aes::Aes256; -use aes::cipher::{BlockEncrypt, KeyInit, KeyIvInit}; -use ghash::{GHash, universal_hash::UniversalHash}; -use cbc::cipher::{block_padding::NoPadding, BlockEncryptMut, BlockDecryptMut}; -use subtle::ConstantTimeEq; -use zeroize::Zeroize; - -use wolfcrypt_sys::{ - wc_CryptoInfo, - wc_CipherType_WC_CIPHER_AES_GCM, - wc_CipherType_WC_CIPHER_AES_CBC, - wolfCrypt_ErrorCodes_AES_GCM_AUTH_E, - wc_CryptoCb_AesAuthEnc, - wc_CryptoCb_AesAuthDec, -}; - -// Type alias for the very long bindgen-generated AES-CBC info struct name. -type WcAesCbcInfo = - wolfcrypt_sys::wc_CryptoInfo__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1; - -// --------------------------------------------------------------------------- -// AES dispatch counter -// --------------------------------------------------------------------------- - -/// Counts successful hardware AES dispatches since the last -/// [`reset_aes_dispatch_count`]. -/// -/// Incremented after a hardware dispatch completes (including when decrypt -/// fails authentication โ€” the hardware RAN, it just rejected the tag). -/// NOT incremented when the callback returns `CRYPTOCB_UNAVAILABLE` (input -/// validation failed before reaching hardware). -static AES_DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0); - -/// Returns the current AES dispatch count. -pub fn aes_dispatch_count() -> usize { - AES_DISPATCH_COUNT.load(Relaxed) -} - -/// Resets the AES dispatch counter to zero. -/// -/// Call at the start of every AES integration test to prevent counter -/// leaks from prior tests. -pub fn reset_aes_dispatch_count() { - AES_DISPATCH_COUNT.store(0, Relaxed); -} - -// --------------------------------------------------------------------------- -// dispatch_cipher โ€” entry point called from hw_callback -// --------------------------------------------------------------------------- - -/// Dispatch a `WC_ALGO_TYPE_CIPHER` CryptoCb callback. -/// -/// Routes AES-256-GCM and AES-256-CBC operations to the hardware-backed -/// implementations. All other cipher types return `CRYPTOCB_UNAVAILABLE` so -/// wolfCrypt falls through to software. -/// -/// # Safety -/// `info` must be a valid `wc_CryptoInfo` with -/// `algo_type == WC_ALGO_TYPE_CIPHER`. Pointer fields within the struct must -/// be valid for their stated sizes. -pub(crate) unsafe fn dispatch_cipher(info: &mut wc_CryptoInfo) -> c_int { - // SAFETY: caller verified algo_type == WC_ALGO_TYPE_CIPHER. - let cipher = &info.__bindgen_anon_1.cipher; - let cipher_type = cipher.type_ as u32; - let enc = cipher.enc; - - if cipher_type == wc_CipherType_WC_CIPHER_AES_GCM { - if enc != 0 { - dispatch_aesgcm_encrypt(&cipher.__bindgen_anon_1.aesgcm_enc) - } else { - dispatch_aesgcm_decrypt(&cipher.__bindgen_anon_1.aesgcm_dec) - } - } else if cipher_type == wc_CipherType_WC_CIPHER_AES_CBC { - dispatch_aescbc(enc, &cipher.__bindgen_anon_1.aescbc) - } else { - crate::CRYPTOCB_UNAVAILABLE - } -} - -// --------------------------------------------------------------------------- -// AES-256-GCM โ€” encrypt -// --------------------------------------------------------------------------- - -unsafe fn dispatch_aesgcm_encrypt(gcm: &wc_CryptoCb_AesAuthEnc) -> c_int { - // Null-check the AES context. - if gcm.aes.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Verify AES-256: keylen must be 32 bytes. - let keylen = (*gcm.aes).keylen; - if keylen != 32 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Only support standard 96-bit (12-byte) GCM nonces. - if gcm.ivSz != 12 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Require at least one output byte or zero-length (empty PT is valid GCM). - if gcm.sz > 0 && gcm.out.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - if gcm.authTag.is_null() || gcm.authTagSz < 16 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Extract key: devKey is [word32; 8] = 32 raw key bytes. - // Key vault integration is a future phase โ€” keys are ephemeral and transit - // Caliptra-internal SRAM only during operation. - let mut key = [0u8; 32]; - core::ptr::copy_nonoverlapping( - (*gcm.aes).devKey.as_ptr() as *const u8, - key.as_mut_ptr(), - 32, - ); - - let iv_ptr = gcm.iv as *const [u8; 12]; - let iv: &[u8; 12] = &*iv_ptr; - - let plaintext: &[u8] = if !gcm.in_.is_null() && gcm.sz > 0 { - core::slice::from_raw_parts(gcm.in_ as *const u8, gcm.sz as usize) - } else { - &[] - }; - let aad: &[u8] = if !gcm.authIn.is_null() && gcm.authInSz > 0 { - core::slice::from_raw_parts(gcm.authIn as *const u8, gcm.authInSz as usize) - } else { - &[] - }; - let out: &mut [u8] = if gcm.sz > 0 { - core::slice::from_raw_parts_mut(gcm.out, gcm.sz as usize) - } else { - &mut [] - }; - - // Perform AES-256-GCM encryption. - gcm_encrypt_256(&key, iv, aad, plaintext, out, gcm.authTag, 16); - - // Zeroize key copy after use. - key.zeroize(); - - AES_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 -} - -// --------------------------------------------------------------------------- -// AES-256-GCM โ€” decrypt -// --------------------------------------------------------------------------- - -unsafe fn dispatch_aesgcm_decrypt(gcm: &wc_CryptoCb_AesAuthDec) -> c_int { - if gcm.aes.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - - let keylen = (*gcm.aes).keylen; - if keylen != 32 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - if gcm.ivSz != 12 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - if gcm.sz > 0 && gcm.out.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - if gcm.authTag.is_null() || gcm.authTagSz < 16 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Extract key. - let mut key = [0u8; 32]; - core::ptr::copy_nonoverlapping( - (*gcm.aes).devKey.as_ptr() as *const u8, - key.as_mut_ptr(), - 32, - ); - - let iv_ptr = gcm.iv as *const [u8; 12]; - let iv: &[u8; 12] = &*iv_ptr; - - let ciphertext: &[u8] = if !gcm.in_.is_null() && gcm.sz > 0 { - core::slice::from_raw_parts(gcm.in_ as *const u8, gcm.sz as usize) - } else { - &[] - }; - let aad: &[u8] = if !gcm.authIn.is_null() && gcm.authInSz > 0 { - core::slice::from_raw_parts(gcm.authIn as *const u8, gcm.authInSz as usize) - } else { - &[] - }; - let out: &mut [u8] = if gcm.sz > 0 { - core::slice::from_raw_parts_mut(gcm.out, gcm.sz as usize) - } else { - &mut [] - }; - let provided_tag: &[u8; 16] = &*(gcm.authTag as *const [u8; 16]); - - let rc = gcm_decrypt_256(&key, iv, aad, ciphertext, out, provided_tag); - - // Zeroize key copy after use, regardless of auth outcome. - key.zeroize(); - - // Increment counter: the hardware ran (computed GHASH + compared tag). - // A test that increments the count ONLY on auth success would allow an - // implementation to short-circuit before calling hardware โ€” that is wrong. - AES_DISPATCH_COUNT.fetch_add(1, Relaxed); - - rc -} - -// --------------------------------------------------------------------------- -// AES-256-CBC โ€” encrypt / decrypt -// --------------------------------------------------------------------------- - -unsafe fn dispatch_aescbc(enc: c_int, cbc: &WcAesCbcInfo) -> c_int { - if cbc.aes.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - - let keylen = (*cbc.aes).keylen; - if keylen != 32 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Data must be block-aligned for CBC (wolfSSL guarantees this). - if cbc.sz == 0 || cbc.sz % 16 != 0 { - return crate::CRYPTOCB_UNAVAILABLE; - } - if cbc.in_.is_null() || cbc.out.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Extract key. - let mut key = [0u8; 32]; - core::ptr::copy_nonoverlapping( - (*cbc.aes).devKey.as_ptr() as *const u8, - key.as_mut_ptr(), - 32, - ); - - // Extract IV from aes->reg (current IV/chaining register, 16 bytes). - // wolfSSL stores the IV in reg as a flat byte copy via XMEMCPY; reading - // the [word32; 4] field as bytes gives the IV in wire order. - let mut iv = [0u8; 16]; - core::ptr::copy_nonoverlapping( - (*cbc.aes).reg.as_ptr() as *const u8, - iv.as_mut_ptr(), - 16, - ); - - let input = core::slice::from_raw_parts(cbc.in_ as *const u8, cbc.sz as usize); - let output = core::slice::from_raw_parts_mut(cbc.out, cbc.sz as usize); - - let rc = if enc != 0 { - cbc_encrypt_256(&key, &iv, input, output) - } else { - cbc_decrypt_256(&key, &iv, input, output) - }; - - key.zeroize(); - - if rc != 0 { - return rc; - } - - // Update aes->reg with the last ciphertext block for chaining correctness. - // For encrypt: last 16 bytes of ciphertext; for decrypt: last 16 bytes of - // the original ciphertext (which becomes the IV for the next decrypt block). - let last_ct = if enc != 0 { &output[output.len() - 16..] } else { &input[input.len() - 16..] }; - core::ptr::copy_nonoverlapping( - last_ct.as_ptr(), - (*cbc.aes).reg.as_mut_ptr() as *mut u8, - 16, - ); - - AES_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 -} - -// --------------------------------------------------------------------------- -// GCM implementation helpers -// --------------------------------------------------------------------------- - -/// AES-256-GCM encrypt in place. -/// -/// Encrypts `plaintext` into `out`, writes the 16-byte auth tag to -/// `tag_out[..16]`. Caller must ensure output slices are the right size. -fn gcm_encrypt_256( - key: &[u8; 32], - iv: &[u8; 12], - aad: &[u8], - plaintext: &[u8], - out: &mut [u8], - tag_out: *mut wolfcrypt_sys::byte, - tag_sz: usize, -) { - let cipher = Aes256::new_from_slice(key).expect("valid 32-byte AES-256 key"); - - // Encrypt using AES-CTR keystream starting from J1 = IV || 0x00000002. - gcm_ctr_process(&cipher, iv, plaintext, out); - - // Compute authentication tag from (AAD, ciphertext). - let tag = compute_gcm_auth_tag(&cipher, iv, aad, out); - - // Write tag to output. - let write_len = tag_sz.min(16); - // SAFETY: tag_out points to a buffer of at least tag_sz bytes (validated by caller). - unsafe { - core::ptr::copy_nonoverlapping(tag.as_ptr(), tag_out, write_len); - } -} - -/// AES-256-GCM decrypt with explicit constant-time tag verification. -/// -/// Returns 0 on success, `AES_GCM_AUTH_E` (-180) on tag mismatch. -/// -/// Uses "authenticate-then-decrypt": the tag is verified BEFORE the ciphertext -/// is decrypted and written to `out`. This prevents leaking partially -/// decrypted plaintext when the tag is invalid. -fn gcm_decrypt_256( - key: &[u8; 32], - iv: &[u8; 12], - aad: &[u8], - ciphertext: &[u8], - out: &mut [u8], - expected_tag: &[u8; 16], -) -> c_int { - let cipher = Aes256::new_from_slice(key).expect("valid 32-byte AES-256 key"); - - // Step 1 โ€” Compute the expected authentication tag from (key, IV, AAD, ciphertext). - let computed_tag = compute_gcm_auth_tag(&cipher, iv, aad, ciphertext); - - // Step 2 โ€” Constant-time tag comparison. - // - // A non-constant-time comparison (e.g., a byte-by-byte early-exit loop or - // `== on slices`) is a timing oracle: an attacker observing Caliptra's - // power consumption can determine when the first mismatching byte occurs, - // and use repeated decryption queries to recover the expected tag one nibble - // at a time. This applies even inside the Caliptra secure boundary because - // the MCU's power trace is an independent, physical side-channel โ€” unrelated - // to any network timing attack. - let tag_ok: bool = computed_tag.ct_eq(expected_tag).into(); - if !tag_ok { - return wolfCrypt_ErrorCodes_AES_GCM_AUTH_E as c_int; - } - - // Step 3 โ€” Tag matched; safe to decrypt. - gcm_ctr_process(&cipher, iv, ciphertext, out); - - 0 -} - -/// Compute the GCM authentication tag for (AAD, ciphertext). -/// -/// Tag = E_K(J0) XOR GHASH_H(AAD || ciphertext || lengths) -/// where J0 = IV || 0x00000001 and H = E_K(0^128). -fn compute_gcm_auth_tag( - cipher: &Aes256, - iv: &[u8; 12], - aad: &[u8], - ciphertext: &[u8], -) -> [u8; 16] { - // H = AES_K(0^128): the GHASH key. - let mut h = aes::cipher::Block::::default(); // 16 zero bytes - cipher.encrypt_block(&mut h); - - // Compute GHASH over (AAD padded, ciphertext padded, lengths block). - let mut mac = GHash::new(&h); - mac.update_padded(aad); - mac.update_padded(ciphertext); - - // GHASH lengths block: [len(AAD) * 8]_64be || [len(CT) * 8]_64be - let mut len_block = aes::cipher::Block::::default(); - let aad_bits = (aad.len() as u64).wrapping_mul(8); - let ct_bits = (ciphertext.len() as u64).wrapping_mul(8); - len_block[..8].copy_from_slice(&aad_bits.to_be_bytes()); - len_block[8..].copy_from_slice(&ct_bits.to_be_bytes()); - // update_padded with exactly 16 bytes: processes as one block, no padding added. - mac.update_padded(len_block.as_slice()); - - let ghash_out = mac.finalize(); - - // E_K(J0): encrypt J0 = IV || 0x00000001. - let mut j0 = aes::cipher::Block::::default(); - j0[..12].copy_from_slice(iv.as_slice()); - j0[15] = 0x01; // big-endian 32-bit counter = 1 - cipher.encrypt_block(&mut j0); - - // Tag = E_K(J0) XOR GHASH - let mut tag = [0u8; 16]; - for i in 0..16 { - tag[i] = j0[i] ^ ghash_out[i]; - } - tag -} - -/// AES-CTR keystream for GCM (counter starts at J1 = IV || 0x00000002). -/// -/// GCM spec (NIST SP 800-38D ยง6.2): the keystream for encryption starts at -/// J1 = incr(J0), where J0 = IV || 0x00000001 for 96-bit IVs. -/// The 32-bit counter in bytes [12..16] is big-endian and wraps on overflow. -fn gcm_ctr_process(cipher: &Aes256, iv: &[u8; 12], input: &[u8], output: &mut [u8]) { - // J1 = IV || 0x00000002 - let mut counter = aes::cipher::Block::::default(); - counter[..12].copy_from_slice(iv.as_slice()); - counter[15] = 0x02; // big-endian 32-bit counter = 2 - - let mut pos = 0; - while pos < input.len() { - // Encrypt the current counter block to produce a keystream block. - let mut ks = counter; - cipher.encrypt_block(&mut ks); - - // XOR keystream with input to produce output. - let block_len = (input.len() - pos).min(16); - for i in 0..block_len { - output[pos + i] = input[pos + i] ^ ks[i]; - } - - // Increment the 32-bit big-endian counter (GCM uses last 4 bytes). - let ctr_val = u32::from_be_bytes([counter[12], counter[13], counter[14], counter[15]]); - let new_ctr = ctr_val.wrapping_add(1).to_be_bytes(); - counter[12] = new_ctr[0]; - counter[13] = new_ctr[1]; - counter[14] = new_ctr[2]; - counter[15] = new_ctr[3]; - - pos += block_len; - } -} - -// --------------------------------------------------------------------------- -// CBC implementation helpers -// --------------------------------------------------------------------------- - -fn cbc_encrypt_256(key: &[u8; 32], iv: &[u8; 16], input: &[u8], output: &mut [u8]) -> c_int { - let enc = match cbc::Encryptor::::new_from_slices(key, iv) { - Ok(e) => e, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - match enc.encrypt_padded_b2b_mut::(input, output) { - Ok(_) => 0, - Err(_) => crate::CRYPTOCB_UNAVAILABLE, - } -} - -fn cbc_decrypt_256(key: &[u8; 32], iv: &[u8; 16], input: &[u8], output: &mut [u8]) -> c_int { - let dec = match cbc::Decryptor::::new_from_slices(key, iv) { - Ok(d) => d, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - match dec.decrypt_padded_b2b_mut::(input, output) { - Ok(_) => 0, - Err(_) => crate::CRYPTOCB_UNAVAILABLE, - } -} diff --git a/wolfcrypt-dpe-hw/src/hw_hash.rs b/wolfcrypt-dpe-hw/src/hw_hash.rs deleted file mode 100644 index 3bb6be3..0000000 --- a/wolfcrypt-dpe-hw/src/hw_hash.rs +++ /dev/null @@ -1,346 +0,0 @@ -//! Hardware hash and HMAC dispatch for the Caliptra CryptoCb backend. -//! -//! Only compiled when `caliptra-2x` feature is active on non-RISC-V targets. -//! RISC-V firmware dispatch (using caliptra-drivers registers directly) is -//! deferred to a future phase. -//! -//! # Endianness -//! -//! ## Host / sha2-crate path (what this file currently compiles to) -//! The sha2 and hmac crates (RustCrypto) produce FIPS 180-4 big-endian digest -//! bytes, which is the byte order wolfSSL uses for all SHA/HMAC output buffers. -//! No conversion is needed and none is performed. -//! -//! ## riscv32 / caliptra-drivers path (future) -//! When the RISC-V firmware path is implemented, caliptra-drivers will handle -//! endianness internally via Array4x* types and explicit `.swap_bytes()` calls -//! where required by the hardware. No ENDIAN_TOGGLE register manipulation will -//! be needed in this layer for that path either. -//! -//! # Single-threaded streaming state -//! `HW_HASH_STATE` and `HW_HMAC_STATE` are global `spin::Mutex` singletons. -//! This is safe because: -//! - The VeeR core (Caliptra RISC-V MCU) has a single hardware thread. -//! wolfCrypt hash/HMAC operations are never re-entered from ISRs, so at -//! most one streaming operation is live at a time. -//! - On non-riscv32 (host test) targets `spin::Mutex` provides mutual -//! exclusion, but tests MUST run sequentially (`--test-threads=1`) because -//! the global state cannot distinguish concurrent operations from different -//! test threads. - -use core::ffi::c_int; -use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; - -use spin::Mutex; - -use sha2::Digest as _; -use hmac::Mac as _; - -use wolfcrypt_sys::{ - wc_HashType_WC_HASH_TYPE_SHA256, - wc_HashType_WC_HASH_TYPE_SHA384, - wc_HashType_WC_HASH_TYPE_SHA512, - wc_CryptoInfo, -}; - -// --------------------------------------------------------------------------- -// HW dispatch counter -// --------------------------------------------------------------------------- - -/// Counts successful hardware-dispatched hash/HMAC operations (incremented on -/// each successful `wc_HashFinal` or `wc_HmacFinal` callback invocation). -/// -/// Private โ€” access only through [`hw_dispatch_count`] and -/// [`reset_hw_dispatch_count`]. Keeping the static private prevents external -/// callers from calling `.store()` or `.fetch_add()` directly, which would -/// undermine counter integrity as FIPS dispatch evidence. -static HASH_DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0); - -/// Returns the current value of the hardware hash/HMAC dispatch counter. -pub fn hw_dispatch_count() -> usize { - HASH_DISPATCH_COUNT.load(Relaxed) -} - -/// Resets the hardware hash/HMAC dispatch counter to zero. -/// -/// Tests call this at the start of each test to detect counter leaks -/// from previous tests. -pub fn reset_hw_dispatch_count() { - HASH_DISPATCH_COUNT.store(0, Relaxed); -} - -// --------------------------------------------------------------------------- -// Streaming hash state -// --------------------------------------------------------------------------- - -/// In-flight SHA-256/384/512 state for streaming (multi-update) operations. -/// -/// Stored in a `spin::Mutex` because wolfCrypt calls the CryptoCb callback -/// once per `wc_Sha256Update` and once per `wc_Sha256Final`, requiring the -/// partial digest to survive across calls. -enum HwHashState { - Sha256(sha2::Sha256), - Sha384(sha2::Sha384), - Sha512(sha2::Sha512), -} - -// SAFETY: sha2 hash types contain only arrays of primitive integers; all -// are Send. spin::Mutex: Sync when T: Send, satisfying the static requirement. -static HW_HASH_STATE: Mutex> = Mutex::new(None); - -// --------------------------------------------------------------------------- -// Streaming HMAC state -// --------------------------------------------------------------------------- - -type HmacSha384Inner = hmac::Hmac; - -/// In-flight HMAC-SHA-384 state for streaming operations. -struct HwHmacState { - mac: HmacSha384Inner, -} - -static HW_HMAC_STATE: Mutex> = Mutex::new(None); - -// --------------------------------------------------------------------------- -// dispatch_hash -// --------------------------------------------------------------------------- - -/// Dispatch a `WC_ALGO_TYPE_HASH` CryptoCb callback. -/// -/// wolfSSL calls this function twice per hash operation: -/// 1. Update: `hash.digest == NULL`, `hash.in_` and `hash.inSz` carry data. -/// 2. Final: `hash.digest != NULL`; writes result and increments counter. -/// -/// # Safety -/// `info` must be a valid `wc_CryptoInfo` with `algo_type == WC_ALGO_TYPE_HASH`. -/// Pointer fields within the struct must be valid for their stated sizes. -pub(crate) unsafe fn dispatch_hash(info: &mut wc_CryptoInfo) -> c_int { - // SAFETY: caller verified algo_type == WC_ALGO_TYPE_HASH. - let hash = &info.__bindgen_anon_1.hash; - let hash_type = hash.type_ as u32; - - // Only SHA-256, SHA-384, SHA-512 are dispatched to hardware. - if hash_type != wc_HashType_WC_HASH_TYPE_SHA256 - && hash_type != wc_HashType_WC_HASH_TYPE_SHA384 - && hash_type != wc_HashType_WC_HASH_TYPE_SHA512 - { - return crate::CRYPTOCB_UNAVAILABLE; - } - - let in_ptr = hash.in_; - let in_sz = hash.inSz as usize; - let digest_ptr = hash.digest; - - // Build a safe data slice (may be empty on the final call). - let data: &[u8] = if !in_ptr.is_null() && in_sz > 0 { - core::slice::from_raw_parts(in_ptr.cast::(), in_sz) - } else { - &[] - }; - - if digest_ptr.is_null() { - // ---- Update call ------------------------------------------------ - let mut guard = HW_HASH_STATE.lock(); - - if guard.is_none() { - // First update for this operation โ€” create a fresh state. - *guard = Some(make_hash_state(hash_type)); - } else { - // DESIGN CONSTRAINT: This implementation supports exactly one - // in-flight hash operation at a time per device. If wolfCrypt - // issues a second SHA context update before the first context's - // Final (i.e., two interleaved hash contexts on the same devId), - // the first context's partial state is silently discarded here and - // the caller receives return code 0. This is correct only because - // the Caliptra VeeR firmware is single-threaded and wolfSSL does - // not interleave SHA contexts in the firmware's usage pattern. - // If this crate is ever used in a multi-context scenario (e.g., - // TLS handshake transcript hashing), this must be redesigned to - // key state by the individual Sha context pointer. - if !hash_type_matches(guard.as_ref().unwrap(), hash_type) { - *guard = Some(make_hash_state(hash_type)); - } - } - - if !data.is_empty() { - hash_update(guard.as_mut().unwrap(), data); - } - 0 // success, no output written - } else { - // ---- Final call ------------------------------------------------- - let state = HW_HASH_STATE.lock().take() - .unwrap_or_else(|| make_hash_state(hash_type)); - - hash_finalize(state, digest_ptr.cast::()); - - // Increment ONLY after a successful hardware dispatch. - HASH_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 - } -} - -// --------------------------------------------------------------------------- -// dispatch_hmac -// --------------------------------------------------------------------------- - -/// Dispatch a `WC_ALGO_TYPE_HMAC` CryptoCb callback. -/// -/// wolfSSL calls this function twice per HMAC-SHA-384 operation: -/// 1. Update (from `wc_HmacUpdate`): `hmac.digest == NULL`. -/// `hmac.in_`/`inSz` carry message data. The HMAC key is always -/// accessible via `(*hmac.hmac).keyRaw` / `keyLen` (set by `wc_HmacSetKey`). -/// 2. Final (from `wc_HmacFinal`): `hmac.digest != NULL`. -/// -/// All other macType values return `CRYPTOCB_UNAVAILABLE` so wolfSSL falls -/// through to its software HMAC implementation. -/// -/// # Safety -/// `info` must be a valid `wc_CryptoInfo` with `algo_type == WC_ALGO_TYPE_HMAC`. -pub(crate) unsafe fn dispatch_hmac(info: &mut wc_CryptoInfo) -> c_int { - // SAFETY: caller verified algo_type == WC_ALGO_TYPE_HMAC. - let hmac_info = &info.__bindgen_anon_1.hmac; - let mac_type = hmac_info.macType; - - // Only HMAC-SHA-384 dispatched to hardware in Phase 1. - if mac_type != wc_HashType_WC_HASH_TYPE_SHA384 as i32 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - let in_ptr = hmac_info.in_; - let in_sz = hmac_info.inSz as usize; - let digest_ptr = hmac_info.digest; - let hmac_ptr = hmac_info.hmac; - - let data: &[u8] = if !in_ptr.is_null() && in_sz > 0 { - core::slice::from_raw_parts(in_ptr.cast::(), in_sz) - } else { - &[] - }; - - if digest_ptr.is_null() { - // ---- Update call ------------------------------------------------ - let mut guard = HW_HMAC_STATE.lock(); - - if guard.is_none() { - // First update: initialize HMAC with the key stored in the - // wolfSSL Hmac struct (written there by wc_HmacSetKey). - let key = extract_hmac_key(hmac_ptr); - let mac = match HmacSha384Inner::new_from_slice(key) { - Ok(m) => m, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - *guard = Some(HwHmacState { mac }); - } - - if !data.is_empty() { - guard.as_mut().unwrap().mac.update(data); - } - 0 - } else { - // ---- Final call ------------------------------------------------- - let state = HW_HMAC_STATE.lock().take(); - let state = match state { - Some(s) => s, - None => { - // Final without a prior Update (empty-data HMAC). - let key = extract_hmac_key(hmac_ptr); - let mac = match HmacSha384Inner::new_from_slice(key) { - Ok(m) => m, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - HwHmacState { mac } - } - }; - - let result = state.mac.finalize(); - let result_bytes = result.into_bytes(); - // SAFETY: digest_ptr points to a buffer of at least 48 bytes, - // guaranteed by wolfSSL (HMAC-SHA-384 output is exactly 48 bytes). - core::ptr::copy_nonoverlapping( - result_bytes.as_ptr(), - digest_ptr.cast::(), - 48, - ); - - HASH_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 - } -} - -// --------------------------------------------------------------------------- -// Helpers (hash) -// --------------------------------------------------------------------------- - -fn make_hash_state(hash_type: u32) -> HwHashState { - match hash_type { - x if x == wc_HashType_WC_HASH_TYPE_SHA256 => HwHashState::Sha256(sha2::Sha256::new()), - x if x == wc_HashType_WC_HASH_TYPE_SHA384 => HwHashState::Sha384(sha2::Sha384::new()), - x if x == wc_HashType_WC_HASH_TYPE_SHA512 => HwHashState::Sha512(sha2::Sha512::new()), - _ => unreachable!("dispatch_hash must filter hash_type to {{6,7,8}} before calling make_hash_state"), - } -} - -fn hash_type_matches(state: &HwHashState, hash_type: u32) -> bool { - match state { - HwHashState::Sha256(_) => hash_type == wc_HashType_WC_HASH_TYPE_SHA256, - HwHashState::Sha384(_) => hash_type == wc_HashType_WC_HASH_TYPE_SHA384, - HwHashState::Sha512(_) => hash_type == wc_HashType_WC_HASH_TYPE_SHA512, - } -} - -fn hash_update(state: &mut HwHashState, data: &[u8]) { - match state { - HwHashState::Sha256(h) => h.update(data), - HwHashState::Sha384(h) => h.update(data), - HwHashState::Sha512(h) => h.update(data), - } -} - -/// Write the finalized digest to `out_ptr`. -/// -/// # Safety -/// `out_ptr` must point to a writable buffer of sufficient size: -/// - SHA-256: 32 bytes -/// - SHA-384: 48 bytes -/// - SHA-512: 64 bytes -unsafe fn hash_finalize(state: HwHashState, out_ptr: *mut u8) { - match state { - HwHashState::Sha256(h) => { - let r = h.finalize(); - core::ptr::copy_nonoverlapping(r.as_ptr(), out_ptr, r.len()); - } - HwHashState::Sha384(h) => { - let r = h.finalize(); - core::ptr::copy_nonoverlapping(r.as_ptr(), out_ptr, r.len()); - } - HwHashState::Sha512(h) => { - let r = h.finalize(); - core::ptr::copy_nonoverlapping(r.as_ptr(), out_ptr, r.len()); - } - } -} - -// --------------------------------------------------------------------------- -// Helpers (HMAC) -// --------------------------------------------------------------------------- - -/// Extract the raw HMAC key from the wolfSSL `Hmac` struct written by -/// `wc_HmacSetKey`. Returns an empty slice if the pointer is null. -/// -/// # Safety -/// `hmac_ptr` must either be null or point to a valid `wolfcrypt_sys::Hmac`. -unsafe fn extract_hmac_key(hmac_ptr: *mut wolfcrypt_sys::Hmac) -> &'static [u8] { - if hmac_ptr.is_null() { - return &[]; - } - let key_ptr = (*hmac_ptr).keyRaw; - let key_len = (*hmac_ptr).keyLen as usize; - if key_ptr.is_null() || key_len == 0 { - return &[]; - } - // SAFETY: keyRaw points into or alongside the Hmac struct; it is valid - // for the lifetime of the Hmac object, which outlives this callback. - // We extend to 'static here because we never store this slice โ€” it is - // consumed immediately within the same lock-holding closure. - core::slice::from_raw_parts(key_ptr.cast::(), key_len) -} diff --git a/wolfcrypt-dpe-hw/src/hw_pk.rs b/wolfcrypt-dpe-hw/src/hw_pk.rs deleted file mode 100644 index 22c1db0..0000000 --- a/wolfcrypt-dpe-hw/src/hw_pk.rs +++ /dev/null @@ -1,566 +0,0 @@ -//! Hardware ECC-384 and ML-DSA-87 PK dispatch for the Caliptra CryptoCb backend. -//! -//! Only compiled when `caliptra-2x` feature is active on non-RISC-V targets. -//! RISC-V firmware dispatch (using caliptra-drivers Ecc384 registers directly) is -//! deferred to a future phase. -//! -//! # ECC-384 sign/verify โ€” digest path -//! -//! Per `phase4_reconciliation.md ยง1`: -//! wolfCrypt passes a **pre-computed SHA-384 digest** (48 bytes) to both the eccsign -//! and eccverify CryptoCb callbacks. caliptra-drivers ECC-384 sign/verify also -//! operate on pre-computed digests. No additional hash step is needed. -//! -//! Dispatch returns `CRYPTOCB_UNAVAILABLE` if the hash length is not exactly 48 bytes -//! (i.e. the operation uses a non-SHA-384 hash) so wolfCrypt falls back to software. -//! -//! # ECC-384 endianness -//! -//! Per `phase4_reconciliation.md ยง2`: -//! wolfCrypt key export functions (`wc_ecc_export_private_only`, -//! `wc_ecc_export_public_raw`) produce big-endian unsigned byte strings. -//! caliptra-drivers `Ecc384Scalar = Array4x12` stores big-endian u32 words. -//! Both representations have identical byte layout โ€” **no byte swap is needed**. -//! -//! # ECC-384 signature format -//! -//! Per `phase4_reconciliation.md ยง3`: -//! wolfCrypt CryptoCb eccsign output is a **DER-encoded** ECDSA signature. -//! wolfCrypt CryptoCb eccverify input is a **DER-encoded** ECDSA signature. -//! caliptra-drivers (and p384 on the host path) use raw (r, s) 48-byte integers. -//! Conversion uses `wc_ecc_rs_raw_to_sig` (encode) and `wc_ecc_sig_to_rs` (decode). -//! -//! # ML-DSA-87 (Adams Bridge) -//! -//! **WARNING: Wire-format compatibility between wolfCrypt ML-DSA-87 and Adams Bridge -//! has not been independently verified. Enable `mldsa87-hw` only after the -//! cross-validation tests in phase4_mldsa.rs pass.** -//! -//! wolfSSL has been rebuilt with `WOLFSSL_DILITHIUM=yes` so the `pqc_sign` and -//! `pqc_verify` sub-structs are now present in the bindings. The remaining -//! blocker is wire-format compatibility verification between wolfCrypt ML-DSA-87 -//! and Adams Bridge (see `phase4_reconciliation.md ยง5`). Until that is verified, -//! all ML-DSA dispatch stubs return `CRYPTOCB_UNAVAILABLE`. -//! -//! # Host path vs riscv32 -//! -//! On the non-riscv32 host path (current scope) ECC operations use RustCrypto's -//! `p384` crate. caliptra-drivers `Ecc384` hardware integration is deferred to the -//! riscv32 firmware path in a future phase. - -use core::ffi::c_int; -use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; - -use p384::ecdsa::signature::hazmat::{PrehashSigner, PrehashVerifier}; -use zeroize::Zeroize; - -use wolfcrypt_sys::{ - wc_CryptoInfo, - wc_PkType_WC_PK_TYPE_ECDSA_SIGN, - wc_PkType_WC_PK_TYPE_ECDSA_VERIFY, - wc_PkType_WC_PK_TYPE_ECDH, - ecc_curve_ids_ECC_SECP384R1, - wolfSSL_ErrorCodes_VERIFY_SIGN_ERROR, - wc_ecc_export_private_only, - wc_ecc_export_public_raw, - wc_ecc_rs_raw_to_sig, - wc_ecc_sig_to_rs, -}; - -// PQC pk-type constants only exist when wolfSSL is built with HAVE_DILITHIUM. -#[cfg(wolfssl_dilithium)] -use wolfcrypt_sys::{ - wc_PkType_WC_PK_TYPE_PQC_SIG_SIGN, - wc_PkType_WC_PK_TYPE_PQC_SIG_VERIFY, -}; - -// --------------------------------------------------------------------------- -// ECC dispatch counter -// --------------------------------------------------------------------------- - -/// Counts successful hardware ECC dispatches since the last -/// [`reset_ecc_dispatch_count`]. -/// -/// Incremented ONLY after the driver call succeeds (sign, verify, or ECDH -/// all the way through without returning CRYPTOCB_UNAVAILABLE or an error). -/// A verify that returns VERIFY_SIGN_ERROR is NOT counted โ€” the hardware ran -/// but signature validation failed; that is not a successful dispatch. -static ECC_DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0); - -/// Returns the current ECC dispatch count. -pub fn ecc_dispatch_count() -> usize { - ECC_DISPATCH_COUNT.load(Relaxed) -} - -/// Resets the ECC dispatch counter to zero. -/// -/// Call at the start of every ECC integration test to prevent counter leaks. -pub fn reset_ecc_dispatch_count() { - ECC_DISPATCH_COUNT.store(0, Relaxed); -} - -// --------------------------------------------------------------------------- -// ML-DSA dispatch counter -// --------------------------------------------------------------------------- - -/// Counts successful hardware ML-DSA dispatches since the last -/// [`reset_mldsa_dispatch_count`]. -/// -/// Currently always remains zero because `mldsa87-hw` dispatch is blocked by -/// the system wolfSSL lacking HAVE_DILITHIUM (see module doc). -static MLDSA_DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0); - -/// Returns the current ML-DSA dispatch count. -pub fn mldsa_dispatch_count() -> usize { - MLDSA_DISPATCH_COUNT.load(Relaxed) -} - -/// Resets the ML-DSA dispatch counter to zero. -pub fn reset_mldsa_dispatch_count() { - MLDSA_DISPATCH_COUNT.store(0, Relaxed); -} - -// --------------------------------------------------------------------------- -// dispatch_pk โ€” entry point called from hw_callback -// --------------------------------------------------------------------------- - -/// Dispatch a `WC_ALGO_TYPE_PK` CryptoCb callback. -/// -/// Routes ECC-384 sign, verify, and ECDH operations to the hardware-backed -/// implementations. ML-DSA-87 is routed only when `mldsa87-hw` is enabled. -/// All other PK types return `CRYPTOCB_UNAVAILABLE` so wolfCrypt falls through -/// to software. -/// -/// Named field access (`pk.eccsign`, `pk.eccverify`, `pk.ecdh`) is stable -/// across wolfSSL build configurations; individual field components are -/// extracted here and passed to the dispatch functions so those functions -/// never need to name the bindgen anonymous struct types (whose numeric -/// suffixes shift with HAVE_DILITHIUM and other options). -/// -/// # Safety -/// `info` must be a valid `wc_CryptoInfo` with -/// `algo_type == WC_ALGO_TYPE_PK`. Pointer fields within the struct must -/// be valid for their stated sizes. -pub(crate) unsafe fn dispatch_pk(info: &mut wc_CryptoInfo) -> c_int { - let pk = &info.__bindgen_anon_1.pk; - let pk_type = pk.type_ as u32; - - if pk_type == wc_PkType_WC_PK_TYPE_ECDSA_SIGN { - let s = &pk.__bindgen_anon_1.eccsign; - return dispatch_ecc384_sign(s.key, s.in_, s.inlen, s.out, s.outlen); - } - if pk_type == wc_PkType_WC_PK_TYPE_ECDSA_VERIFY { - let v = &pk.__bindgen_anon_1.eccverify; - return dispatch_ecc384_verify(v.key, v.sig, v.siglen, v.hash, v.hashlen, v.res); - } - if pk_type == wc_PkType_WC_PK_TYPE_ECDH { - let e = &pk.__bindgen_anon_1.ecdh; - return dispatch_ecdh384(e.private_key, e.public_key, e.out, e.outlen); - } - // PQC constants and the pqc_sign/pqc_verify sub-structs only exist when - // wolfSSL is built with HAVE_DILITHIUM. Gate the entire branch. - #[cfg(wolfssl_dilithium)] - if pk_type == wc_PkType_WC_PK_TYPE_PQC_SIG_SIGN - || pk_type == wc_PkType_WC_PK_TYPE_PQC_SIG_VERIFY - { - return dispatch_mldsa87_pqc(pk_type); - } - crate::CRYPTOCB_UNAVAILABLE -} - -// --------------------------------------------------------------------------- -// ECC-384 โ€” Sign -// --------------------------------------------------------------------------- - -/// Dispatch an ECDSA P-384 sign operation via the hardware backend. -/// -/// wolfCrypt passes a pre-computed SHA-384 digest (48 bytes) in `in_`. -/// On the host path (non-riscv32), signing uses RustCrypto's `p384` crate. -/// On riscv32 firmware, caliptra-drivers `Ecc384::sign()` would be called -/// (deferred to a future phase). -/// -/// Key marshaling (per reconciliation ยง2): -/// wolfCrypt `wc_ecc_export_private_only` โ†’ big-endian 48 bytes. -/// p384 `FieldBytes` = big-endian 48 bytes. -/// No byte swap is required. -/// -/// Signature marshaling (per reconciliation ยง3): -/// p384 `Signature` โ†’ raw (r, s) bytes โ†’ DER via `wc_ecc_rs_raw_to_sig`. -unsafe fn dispatch_ecc384_sign( - key: *mut wolfcrypt_sys::ecc_key, - in_: *const wolfcrypt_sys::byte, - inlen: wolfcrypt_sys::word32, - out: *mut wolfcrypt_sys::byte, - outlen: *mut wolfcrypt_sys::word32, -) -> c_int { - // Null-check the key pointer. - if key.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - // Verify this is a P-384 key. - // dp->id == 15 means ECC_SECP384R1 (from generated ecc_curve_ids constants). - if (*key).dp.is_null() - || (*(*key).dp).id != ecc_curve_ids_ECC_SECP384R1 as i32 - { - return crate::CRYPTOCB_UNAVAILABLE; - } - // Verify hash length: must be exactly 48 bytes (SHA-384 digest size). - // caliptra-drivers Ecc384::sign() takes Ecc384Scalar = 48 bytes. - // wolfCrypt passes inlen == hash output size; other sizes fall back to software. - if inlen != 48 { - return crate::CRYPTOCB_UNAVAILABLE; - } - if in_.is_null() || out.is_null() || outlen.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - - let hash = core::slice::from_raw_parts(in_, 48); - - // Export private key: 48 big-endian bytes. - // Zeroized after use to avoid leaving key material on the stack. - let mut priv_bytes = [0u8; 48]; - let mut priv_len: wolfcrypt_sys::word32 = 48; - let rc = wc_ecc_export_private_only( - key as *mut _, - priv_bytes.as_mut_ptr(), - &mut priv_len, - ); - if rc != 0 || priv_len != 48 { - priv_bytes.zeroize(); - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Build p384 signing key from the 48 big-endian private key bytes. - // FieldBytes is GenericArray โ€” the conversion is infallible for - // valid 48-byte slices. - let secret_key = - match p384::SecretKey::from_bytes(p384::FieldBytes::from_slice(&priv_bytes)) { - Ok(k) => k, - Err(_) => { - priv_bytes.zeroize(); - return crate::CRYPTOCB_UNAVAILABLE; - } - }; - priv_bytes.zeroize(); - - let signing_key = p384::ecdsa::SigningKey::from(&secret_key); - - // Sign the pre-computed digest. - // PrehashSigner::sign_prehash operates on the raw hash bytes, matching - // the ECDSA standard where the hash is used directly as the message representative. - let sig: p384::ecdsa::Signature = match signing_key.sign_prehash(hash) { - Ok(s) => s, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - - // Extract raw (r, s) bytes (each 48 bytes, big-endian). - let (r_bytes, s_bytes) = sig.split_bytes(); - - // DER-encode the signature into the output buffer provided by wolfCrypt. - // wc_ecc_rs_raw_to_sig takes big-endian r and s byte strings and produces - // the DER SEQUENCE { INTEGER r; INTEGER s } encoding. - let avail = *outlen; - let rc = wc_ecc_rs_raw_to_sig( - r_bytes.as_ptr(), - 48, - s_bytes.as_ptr(), - 48, - out, - outlen as *mut _, - ); - if rc != 0 { - // Restore the output length to the available size on failure. - *outlen = avail; - return crate::CRYPTOCB_UNAVAILABLE; - } - - ECC_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 -} - -// --------------------------------------------------------------------------- -// ECC-384 โ€” Verify -// --------------------------------------------------------------------------- - -/// Dispatch an ECDSA P-384 verify operation via the hardware backend. -/// -/// wolfCrypt passes the DER-encoded signature in `sig` and the -/// pre-computed SHA-384 digest in `hash`. -/// -/// On verify failure this function MUST return `VERIFY_SIGN_ERROR` (-330). -/// Callers distinguish VERIFY_SIGN_ERROR from other errors for retry/fallback -/// logic โ€” returning a generic error code silently breaks callers. -/// -/// Key marshaling (per reconciliation ยง2): same as sign. -/// Signature marshaling (per reconciliation ยง3): -/// DER โ†’ raw (r, s) via `wc_ecc_sig_to_rs` โ†’ p384 `Signature`. -unsafe fn dispatch_ecc384_verify( - key: *mut wolfcrypt_sys::ecc_key, - sig: *const wolfcrypt_sys::byte, - siglen: wolfcrypt_sys::word32, - hash: *const wolfcrypt_sys::byte, - hashlen: wolfcrypt_sys::word32, - res: *mut c_int, -) -> c_int { - if key.is_null() || res.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - if (*key).dp.is_null() - || (*(*key).dp).id != ecc_curve_ids_ECC_SECP384R1 as i32 - { - return crate::CRYPTOCB_UNAVAILABLE; - } - // Hash length: must be exactly 48 bytes. - if hashlen != 48 { - return crate::CRYPTOCB_UNAVAILABLE; - } - if sig.is_null() || hash.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - - let hash_bytes = core::slice::from_raw_parts(hash, 48); - - // Decode DER signature โ†’ raw (r, s) big-endian bytes. - let mut r_bytes = [0u8; 48]; - let mut s_bytes = [0u8; 48]; - let mut r_len: wolfcrypt_sys::word32 = 48; - let mut s_len: wolfcrypt_sys::word32 = 48; - let rc = wc_ecc_sig_to_rs( - sig, - siglen, - r_bytes.as_mut_ptr(), - &mut r_len, - s_bytes.as_mut_ptr(), - &mut s_len, - ); - if rc != 0 || r_len > 48 || s_len > 48 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // wc_ecc_sig_to_rs may return a shorter buffer if the high bit is clear; - // right-justify into 48-byte arrays (zero-pad on the left). - let mut r_padded = [0u8; 48]; - let mut s_padded = [0u8; 48]; - let r_offset = 48 - r_len as usize; - let s_offset = 48 - s_len as usize; - r_padded[r_offset..].copy_from_slice(&r_bytes[..r_len as usize]); - s_padded[s_offset..].copy_from_slice(&s_bytes[..s_len as usize]); - - // Build p384 Signature from raw (r, s) scalars. - let sig_obj = match p384::ecdsa::Signature::from_scalars( - *p384::FieldBytes::from_slice(&r_padded), - *p384::FieldBytes::from_slice(&s_padded), - ) { - Ok(s) => s, - Err(_) => { - // Signature scalar is out of range [1, n-1]: definitively invalid. - // Set *res = 0 before returning VERIFY_SIGN_ERROR so callers always - // see *res == 0 when this error code is returned (matches the - // verify_prehash failure branch below). - *res = 0; - return wolfSSL_ErrorCodes_VERIFY_SIGN_ERROR as c_int; - } - }; - - // Export public key: Qx and Qy, each 48 big-endian bytes. - let mut qx = [0u8; 48]; - let mut qy = [0u8; 48]; - let mut qx_len: wolfcrypt_sys::word32 = 48; - let mut qy_len: wolfcrypt_sys::word32 = 48; - let rc = wc_ecc_export_public_raw( - key as *mut _, - qx.as_mut_ptr(), - &mut qx_len, - qy.as_mut_ptr(), - &mut qy_len, - ); - if rc != 0 || qx_len != 48 || qy_len != 48 { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Build uncompressed SEC1 public key: 0x04 || Qx (48 bytes) || Qy (48 bytes). - let mut pub_bytes = [0u8; 97]; - pub_bytes[0] = 0x04; - pub_bytes[1..49].copy_from_slice(&qx); - pub_bytes[49..97].copy_from_slice(&qy); - - let verifying_key = match p384::ecdsa::VerifyingKey::from_sec1_bytes(&pub_bytes) { - Ok(k) => k, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - - // Verify the signature against the pre-hash. - // PrehashVerifier::verify_prehash matches the ECDSA standard. - match verifying_key.verify_prehash(hash_bytes, &sig_obj) { - Ok(()) => { - // Signature verified: set res = 1 (wolfCrypt convention). - *res = 1; - ECC_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 - } - Err(_) => { - // Signature invalid: set res = 0 and return VERIFY_SIGN_ERROR. - // Callers MUST receive VERIFY_SIGN_ERROR (not a generic error) to - // correctly trigger retry/fallback logic. - *res = 0; - wolfSSL_ErrorCodes_VERIFY_SIGN_ERROR as c_int - } - } -} - -// --------------------------------------------------------------------------- -// ECC-384 โ€” ECDH -// --------------------------------------------------------------------------- - -/// Dispatch an ECDH P-384 shared-secret computation via the hardware backend. -/// -/// wolfCrypt provides the private key in `private_key` and the peer's -/// public key in `public_key`. The 48-byte shared secret (x-coordinate -/// of the product point) is written to `out`. -/// -/// The shared secret stack copy is zeroized after writing to the output buffer. -unsafe fn dispatch_ecdh384( - private_key: *mut wolfcrypt_sys::ecc_key, - public_key: *mut wolfcrypt_sys::ecc_key, - out: *mut wolfcrypt_sys::byte, - outlen: *mut wolfcrypt_sys::word32, -) -> c_int { - if private_key.is_null() || public_key.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - if out.is_null() || outlen.is_null() { - return crate::CRYPTOCB_UNAVAILABLE; - } - // Both keys must be P-384. - if (*private_key).dp.is_null() - || (*(*private_key).dp).id != ecc_curve_ids_ECC_SECP384R1 as i32 - { - return crate::CRYPTOCB_UNAVAILABLE; - } - if (*public_key).dp.is_null() - || (*(*public_key).dp).id != ecc_curve_ids_ECC_SECP384R1 as i32 - { - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Export private key (48 bytes, big-endian). - let mut priv_bytes = [0u8; 48]; - let mut priv_len: wolfcrypt_sys::word32 = 48; - let rc = wc_ecc_export_private_only( - private_key as *mut _, - priv_bytes.as_mut_ptr(), - &mut priv_len, - ); - if rc != 0 || priv_len != 48 { - priv_bytes.zeroize(); - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Export peer public key (Qx, Qy, each 48 bytes, big-endian). - let mut qx = [0u8; 48]; - let mut qy = [0u8; 48]; - let mut qx_len: wolfcrypt_sys::word32 = 48; - let mut qy_len: wolfcrypt_sys::word32 = 48; - let rc = wc_ecc_export_public_raw( - public_key as *mut _, - qx.as_mut_ptr(), - &mut qx_len, - qy.as_mut_ptr(), - &mut qy_len, - ); - if rc != 0 || qx_len != 48 || qy_len != 48 { - priv_bytes.zeroize(); - return crate::CRYPTOCB_UNAVAILABLE; - } - - // Build p384 private key. - let secret_key = - match p384::SecretKey::from_bytes(p384::FieldBytes::from_slice(&priv_bytes)) { - Ok(k) => k, - Err(_) => { - priv_bytes.zeroize(); - return crate::CRYPTOCB_UNAVAILABLE; - } - }; - priv_bytes.zeroize(); - - // Build uncompressed SEC1 public key for peer: 0x04 || Qx || Qy. - let mut peer_pub_bytes = [0u8; 97]; - peer_pub_bytes[0] = 0x04; - peer_pub_bytes[1..49].copy_from_slice(&qx); - peer_pub_bytes[49..97].copy_from_slice(&qy); - - let peer_pub_key = match p384::PublicKey::from_sec1_bytes(&peer_pub_bytes) { - Ok(k) => k, - Err(_) => return crate::CRYPTOCB_UNAVAILABLE, - }; - - // Compute ECDH shared secret: x-coordinate of private_key * peer_public_key. - // The result is the 48-byte big-endian x-coordinate of the product point. - let shared = p384::ecdh::diffie_hellman( - secret_key.to_nonzero_scalar(), - peer_pub_key.as_affine(), - ); - let shared_bytes = shared.raw_secret_bytes(); // &FieldBytes = 48 bytes - - // Write the shared secret to the output buffer. - let out_len = *outlen as usize; - if out_len < 48 { - return crate::CRYPTOCB_UNAVAILABLE; - } - core::ptr::copy_nonoverlapping(shared_bytes.as_ptr(), out, 48); - *outlen = 48; - - // Zeroize shared secret stack copy. - // shared_bytes is from the SharedSecret held on the stack; zeroize via drop. - // (SharedSecret implements Zeroize on Drop in elliptic-curve โ‰ฅ 0.13.) - drop(shared); - - ECC_DISPATCH_COUNT.fetch_add(1, Relaxed); - 0 -} - -// --------------------------------------------------------------------------- -// ML-DSA-87 โ€” route through real binding constants -// --------------------------------------------------------------------------- -// WC_PK_TYPE_PQC_SIG_SIGN (22) and WC_PK_TYPE_PQC_SIG_VERIFY (23) are now -// present in wolfcrypt-sys since wolfssl was rebuilt with WOLFSSL_DILITHIUM=yes. -// Use the binding constants directly; the hardcoded fallbacks are removed. - -// --------------------------------------------------------------------------- -// ML-DSA-87 โ€” Sign / Verify stubs -// --------------------------------------------------------------------------- - -/// Route a PQC signature CryptoCb call. -/// -/// Returns `CRYPTOCB_UNAVAILABLE` until ML-DSA-87 wire-format compatibility -/// between wolfCrypt and Adams Bridge has been verified and dispatch is -/// implemented (see `phase4_reconciliation.md ยง5`). -/// -/// wolfSSL has been rebuilt with `WOLFSSL_DILITHIUM=yes`; the `pqc_sign` and -/// `pqc_verify` sub-structs are present in the bindings. When dispatch is -/// implemented, gate the active path behind `#[cfg(feature = "mldsa87-hw")]` here. -fn dispatch_mldsa87_pqc(pk_type: u32) -> c_int { - let _ = pk_type; - crate::CRYPTOCB_UNAVAILABLE -} - -/// Dispatch an ML-DSA-87 sign operation. -/// -/// Stub โ€” wire-format compatibility with Adams Bridge is unverified. -/// Gated behind `mldsa87-hw` feature so it is never compiled by default. -#[cfg(feature = "mldsa87-hw")] -#[allow(dead_code)] -pub(crate) unsafe fn dispatch_mldsa87_sign(_info: &mut wc_CryptoInfo) -> c_int { - crate::CRYPTOCB_UNAVAILABLE -} - -/// Dispatch an ML-DSA-87 verify operation. -/// -/// Stub โ€” wire-format compatibility with Adams Bridge is unverified. -/// Gated behind `mldsa87-hw` feature so it is never compiled by default. -#[cfg(feature = "mldsa87-hw")] -#[allow(dead_code)] -pub(crate) unsafe fn dispatch_mldsa87_verify(_info: &mut wc_CryptoInfo) -> c_int { - crate::CRYPTOCB_UNAVAILABLE -} diff --git a/wolfcrypt-dpe-hw/src/hw_rng.rs b/wolfcrypt-dpe-hw/src/hw_rng.rs deleted file mode 100644 index 0bbbc9e..0000000 --- a/wolfcrypt-dpe-hw/src/hw_rng.rs +++ /dev/null @@ -1,235 +0,0 @@ -//! Hardware RNG dispatch for the Caliptra ITRNG. -//! -//! # Intercept point choice -//! -//! ## Why `CUSTOM_RAND_GENERATE_BLOCK` on riscv32 (firmware target) -//! -//! The Caliptra hardware implements an AES-256-CTR-DRBG (SP 800-90A) in -//! silicon. FIPS 140-3 / SP 800-90C requires using the hardware DRBG -//! directly rather than stacking a second software DRBG on top of it. -//! - `user_settings_cryptocb_only.h` defines -//! `CUSTOM_RAND_GENERATE_BLOCK = caliptra_generate_random_block`, which -//! wolfSSL calls on every `wc_RNG_GenerateBlock`, bypassing HASH-DRBG. -//! - The C shim in `caliptra_seed.c` (compiled for riscv32 + caliptra-2x) -//! forwards `caliptra_generate_random_block(output, sz)` to -//! `caliptra_hw_generate_seed(output, sz)` (this file). -//! -//! ## Why CryptoCb `WC_ALGO_TYPE_RNG = 4` on non-riscv32 (host / test) -//! -//! Phase 1 added `WOLF_CRYPTO_CB` to `user_settings.h` and the -//! `cryptocb.h` header to `headers.h`. The generated bindings now expose -//! `wc_CryptoInfo.__bindgen_anon_1.rng` with fields `{rng, out, sz}`. -//! wolfSSL routes `wc_RNG_GenerateBlock` through CryptoCb with -//! `WC_ALGO_TYPE_RNG` when the `WC_RNG` was initialised via -//! `wc_InitRng_ex` with a non-`INVALID_DEVID`. This enables per-call -//! ITRNG dispatch without touching the riscv32 build. -//! -//! ## Rejected alternative: CryptoCb `WC_ALGO_TYPE_SEED = 5` -//! -//! `WC_ALGO_TYPE_SEED` fires during `wc_InitRng` (seed-time only). -//! Per-block dispatch is not possible through that path. -//! `WC_ALGO_TYPE_RNG` fires on every `wc_RNG_GenerateBlock` call, which -//! is required by the test spec (TRNG_DISPATCH_COUNT must increment once -//! per generate call). -//! -//! # Host-path ITRNG simulation -//! -//! On the host (non-riscv32) the "ITRNG" is simulated by calling -//! `wolfcrypt_sys::wc_GenerateSeed` with a fresh `OS_Seed`. This reads -//! `/dev/urandom` on Linux, providing the same quality of entropy the -//! hardware would produce, while keeping the implementation no_std -//! compatible (no extra crate dependencies). -//! -//! # Software PRNG fallback -//! -//! There is none. If the ITRNG call fails (or `INJECT_TRNG_ERROR` is -//! set), `dispatch_rng` returns a non-zero error code. The caller -//! receives an error from `wc_RNG_GenerateBlock`. - -use core::sync::atomic::{AtomicUsize, Ordering}; - -// --------------------------------------------------------------------------- -// TRNG dispatch counter -// --------------------------------------------------------------------------- - -/// Number of successful ITRNG calls since the last [`reset_trng_dispatch_count`]. -/// -/// Incremented **only** after the ITRNG call completes successfully and bytes -/// have been written to the output buffer. Never incremented on error or -/// on the software DRBG path (`INVALID_DEVID`). -static TRNG_DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0); - -/// Returns the current TRNG dispatch count. -pub fn trng_dispatch_count() -> usize { - TRNG_DISPATCH_COUNT.load(Ordering::Relaxed) -} - -/// Resets the TRNG dispatch counter to zero. -/// -/// Call at the start of every test to prevent counter leaks from prior tests. -pub fn reset_trng_dispatch_count() { - TRNG_DISPATCH_COUNT.store(0, Ordering::Relaxed); -} - -// --------------------------------------------------------------------------- -// Test error injection hook -// --------------------------------------------------------------------------- - -// The phase spec calls for `thread_local!{static INJECT_TRNG_ERROR: Cell}`. -// This crate is `#![no_std]`; `thread_local!` requires std and is unavailable. -// An `AtomicBool` provides identical semantics (set before the call, clear after) -// and is no_std-compatible. Integration tests in tests/ access it via -// `wolfcrypt_dpe_hw::INJECT_TRNG_ERROR.store(true, Ordering::Relaxed)`. -// -// Not gated on `#[cfg(test)]` because integration tests compile the library -// without cfg(test) and cannot see cfg(test) items. Instead gated on the -// `testing-hooks` feature so this symbol is absent from production builds. -// Any binary compiled without `--features testing-hooks` will not have this -// symbol in its public ABI, satisfying FIPS 140-3 software integrity -// requirements that prohibit production-accessible entropy-disabling hooks. -#[cfg(all(not(target_arch = "riscv32"), feature = "testing-hooks"))] -pub static INJECT_TRNG_ERROR: core::sync::atomic::AtomicBool = - core::sync::atomic::AtomicBool::new(false); - -// --------------------------------------------------------------------------- -// Non-riscv32: CryptoCb WC_ALGO_TYPE_RNG dispatch -// --------------------------------------------------------------------------- - -/// Dispatch a `WC_ALGO_TYPE_RNG` CryptoCb callback. -/// -/// Called from [`crate::hw_callback`] when `info.algo_type == WC_ALGO_TYPE_RNG`. -/// -/// Reads `info.__bindgen_anon_1.rng.{out, sz}`, fills the output with ITRNG -/// bytes, and increments [`TRNG_DISPATCH_COUNT`] on success. -/// -/// Returns 0 on success, non-zero on error. Never returns -/// [`crate::CRYPTOCB_UNAVAILABLE`] โ€” the hardware path is always attempted. -/// -/// # Safety -/// `info` must be a valid `wc_CryptoInfo` with `algo_type == WC_ALGO_TYPE_RNG`. -#[cfg(not(target_arch = "riscv32"))] -pub(crate) unsafe fn dispatch_rng( - info: &mut wolfcrypt_sys::wc_CryptoInfo, -) -> core::ffi::c_int { - let rng_info = &info.__bindgen_anon_1.rng; - let out = rng_info.out; - let sz = rng_info.sz; - - if sz == 0 { - // Zero-length request: benign no-op. - return 0; - } - if out.is_null() { - // Null pointer with non-zero size: caller bug; return error so wolfSSL - // sees a failure rather than silently delivering no bytes. - return -1; - } - - // Test injection: simulate ITRNG hardware fault. - // TRNG_DISPATCH_COUNT must NOT increment on error. - // Only compiled when `testing-hooks` feature is active. - #[cfg(feature = "testing-hooks")] - if INJECT_TRNG_ERROR.load(Ordering::Acquire) { - return -1; - } - - // Host-path ITRNG simulation: obtain entropy from the OS via wolfSSL's - // wc_GenerateSeed (reads /dev/urandom / getrandom on Linux). A fresh - // OS_Seed is created each call so there is no shared state with the - // wolfSSL DRBG. devId is set to INVALID_DEVID (-2) so that - // wc_GenerateSeed skips its own CryptoCb lookup and goes directly to the - // OS entropy path โ€” avoids infinite re-entry through our own callback. - let mut os_seed: wolfcrypt_sys::OS_Seed = core::mem::zeroed(); - os_seed.devId = wolfcrypt_sys::INVALID_DEVID; - let rc = wolfcrypt_sys::wc_GenerateSeed(&mut os_seed, out, sz); - if rc != 0 { - return rc; - } - - // Increment ONLY after a successful ITRNG call. - TRNG_DISPATCH_COUNT.fetch_add(1, Ordering::Relaxed); - 0 -} - -// --------------------------------------------------------------------------- -// riscv32: caliptra_generate_random_block โ†’ caliptra_hw_generate_seed -// --------------------------------------------------------------------------- -// -// On riscv32, wolfSSL calls `caliptra_generate_random_block(output, sz)` for -// every `wc_RNG_GenerateBlock` call because `user_settings_cryptocb_only.h` -// defines: -// #define CUSTOM_RAND_GENERATE_BLOCK caliptra_generate_random_block -// -// This bypasses wolfSSL's software HASH-DRBG entirely. The Caliptra hardware -// implements an AES-256-CTR-DRBG (SP 800-90A) in silicon; the hardware DRBG -// IS the FIPS-approved randomness source. -// -// The C shim in `caliptra_seed.c` (compiled only for riscv32 + caliptra-2x) -// delegates to `caliptra_hw_generate_seed(output, sz)` defined below. -// -// Firmware must call `wolfcrypt_dpe_hw::hw_rng::register_trng(trng)` before -// any call to `wc_RNG_GenerateBlock()`. - -#[cfg(target_arch = "riscv32")] -use caliptra_drivers::Trng; - -/// Global Trng instance registered by the firmware before wolfSSL is used. -#[cfg(target_arch = "riscv32")] -static REGISTERED_TRNG: spin::Mutex> = spin::Mutex::new(None); - -/// Register the Caliptra TRNG for use by wolfSSL's DRBG seed function. -/// -/// **Must be called before `wc_InitRng()` in the firmware startup sequence.** -/// Takes ownership of the `Trng` instance. -#[cfg(target_arch = "riscv32")] -pub fn register_trng(trng: Trng) { - *REGISTERED_TRNG.lock() = Some(trng); -} - -/// Called by `caliptra_generate_random_block()` in `caliptra_seed.c`. -/// -/// Fills `output[0..sz]` with entropy from the Caliptra ITRNG. -/// Returns 0 on success, -1 (`HwError::TrngUnavailable`) on error. -/// -/// # Safety -/// `output` must be writable for `sz` bytes. -#[cfg(target_arch = "riscv32")] -#[no_mangle] -pub unsafe extern "C" fn caliptra_hw_generate_seed(output: *mut u8, sz: u32) -> i32 { - let sz = sz as usize; - if sz == 0 { - return 0; - } - if output.is_null() { - return -1; - } - - let mut guard = REGISTERED_TRNG.lock(); - let trng = match guard.as_mut() { - Some(t) => t, - // Trng not registered โ€” firmware did not call register_trng() before - // wc_InitRng(). Return error so wolfSSL does not silently use bad state. - None => return -1, - }; - - let mut filled = 0usize; - while filled < sz { - let chunk = match trng.generate() { - Ok(arr) => arr, - Err(_) => return -1, - }; - // SAFETY: caliptra_drivers::Array4x12 is a [u32; 12] (48 bytes). - // Reading it as bytes is safe; we copy only what is needed. - let chunk_bytes = core::slice::from_raw_parts( - &chunk as *const _ as *const u8, - core::mem::size_of_val(&chunk), - ); - let to_copy = (sz - filled).min(chunk_bytes.len()); - core::ptr::copy_nonoverlapping(chunk_bytes.as_ptr(), output.add(filled), to_copy); - filled += to_copy; - } - - // Increment ONLY after all requested bytes have been generated. - TRNG_DISPATCH_COUNT.fetch_add(1, Ordering::Relaxed); - 0 -} diff --git a/wolfcrypt-dpe-hw/src/lib.rs b/wolfcrypt-dpe-hw/src/lib.rs deleted file mode 100644 index 9cdd3e7..0000000 --- a/wolfcrypt-dpe-hw/src/lib.rs +++ /dev/null @@ -1,249 +0,0 @@ -//! wolfcrypt-dpe-hw: Caliptra hardware backend for wolfcrypt-dpe. -//! -//! This crate provides hardware-accelerated crypto via caliptra-drivers, -//! wired into wolfCrypt through the CryptoCb callback mechanism. -//! -//! The `caliptra-2x` feature activates all hardware paths. Without it, -//! every function is a no-op / pure-software passthrough. -//! -//! # Target notes -//! -//! On `riscv32` bare-metal targets (e.g. `riscv32imc-unknown-none-elf`) -//! wolfSSL is not available as a linked library. The `wolfcrypt-sys` crate -//! is therefore excluded for that architecture. The CryptoCb registration -//! path is also excluded; a future phase will wire up caliptra-drivers -//! directly for RISC-V. - -#![no_std] - -use core::ffi::c_int; - -// c_void is used by the hw_callback (caliptra-2x, non-riscv32 only). -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -use core::ffi::c_void; - -// hw_hash implements SHA-256/384/512 and HMAC-384 dispatch, the HW dispatch -// counter, and the streaming state. Only compiled when both caliptra-2x is -// active AND the target is non-riscv32 (wolfcrypt-sys is required). -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod hw_hash; - -// Re-export the counter accessors so integration tests in tests/ can use them. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -pub use hw_hash::{hw_dispatch_count, reset_hw_dispatch_count}; - -// hw_rng implements the TRNG dispatch counter, the test error injection hook, -// and per-architecture ITRNG dispatch: -// - non-riscv32: CryptoCb WC_ALGO_TYPE_RNG callback -// - riscv32: caliptra_hw_generate_seed (called from caliptra_seed.c) -#[cfg(feature = "caliptra-2x")] -pub mod hw_rng; - -// hw_aes implements AES-256-GCM and AES-256-CBC dispatch via the `aes`, -// `ghash`, and `cbc` RustCrypto crates on the non-riscv32 host path. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod hw_aes; - -// hw_pk implements ECC-384 sign/verify/ECDH dispatch and ML-DSA-87 stubs via -// RustCrypto's `p384` crate on the non-riscv32 host path. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod hw_pk; - -// Re-export TRNG counter accessors and the error injection hook. -#[cfg(feature = "caliptra-2x")] -pub use hw_rng::{trng_dispatch_count, reset_trng_dispatch_count}; -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32"), feature = "testing-hooks"))] -pub use hw_rng::INJECT_TRNG_ERROR; - -// Re-export AES dispatch counter accessors. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -pub use hw_aes::{aes_dispatch_count, reset_aes_dispatch_count}; - -// Re-export ECC and ML-DSA dispatch counter accessors. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -pub use hw_pk::{ecc_dispatch_count, reset_ecc_dispatch_count, mldsa_dispatch_count, reset_mldsa_dispatch_count}; - -// --------------------------------------------------------------------------- -// Public constants -// --------------------------------------------------------------------------- - -/// Device ID used when registering the Caliptra CryptoCb backend. -pub const HW_DEVICE_ID: c_int = 1; - -/// Return value a CryptoCb callback uses to signal "not handled here; -/// fall through to software". Mirrors wolfSSL's `CRYPTOCB_UNAVAILABLE` (-271, -/// confirmed from `wolfssl/wolfcrypt/error-crypt.h` and the generated bindings). -pub const CRYPTOCB_UNAVAILABLE: c_int = -271; - -// --------------------------------------------------------------------------- -// Error type -// --------------------------------------------------------------------------- - -/// Errors returned by wolfcrypt-dpe-hw functions. -/// -/// Non-exhaustive: future hardware phases will add variants. -#[non_exhaustive] -#[derive(Debug)] -pub enum HwError { - /// wolfCrypt global initialisation failed (wolfCrypt_Init returned this - /// code). In FIPS builds this means the mandatory power-on self-test did - /// not complete. `init()` returns this before attempting CryptoCb - /// registration. - WolfCryptInitFailed(i32), - /// CryptoCb device registration failed. Inner value is the wolfSSL error - /// code returned by `wc_CryptoCb_RegisterDevice`. - InitFailed(i32), - /// The Caliptra ITRNG was unavailable at initialisation time or returned - /// an error during entropy generation. - /// - /// On riscv32: `register_trng()` was not called before `wc_InitRng`, or - /// `caliptra_drivers::Trng::generate()` returned an error. - /// On non-riscv32: the OS entropy source (`wc_GenerateSeed`) failed. - TrngUnavailable, -} - -// Error category for HwError in the wolfcrypt-dpe CryptoError space. -// Uses the next available high-byte after 0x07_0000. -#[allow(dead_code)] -const ERR_HW_BASE: u32 = 0x08_0000; - -// --------------------------------------------------------------------------- -// State query -// --------------------------------------------------------------------------- - -/// Returns `true` when the `caliptra-2x` feature is active AND the current -/// target architecture supports wolfSSL-backed CryptoCb registration. -/// -/// `init()` registers a CryptoCb device if and only if this returns `true`. -/// Tests use this to assert that init() is a true no-op on unsupported -/// configurations without relying on `WOLFSSL_LOCAL` internal symbols. -pub const fn has_caliptra_hw_backend() -> bool { - cfg!(all(feature = "caliptra-2x", not(target_arch = "riscv32"))) -} - -// --------------------------------------------------------------------------- -// init() -// --------------------------------------------------------------------------- - -/// Initialize the wolfCrypt hardware backend. -/// -/// Without the `caliptra-2x` feature this is a no-op and always returns -/// `Ok(())`. -/// -/// With `caliptra-2x` on non-RISC-V targets this: -/// 1. Calls `wolfCrypt_Init()` (idempotent; triggers FIPS POST in FIPS builds). -/// 2. Registers a CryptoCb device (ID [`HW_DEVICE_ID`]) whose callback -/// dispatches SHA-256/384/512 and HMAC-384 to the hardware path; all -/// other algorithms return [`CRYPTOCB_UNAVAILABLE`] causing wolfCrypt to -/// fall through to software. -/// -/// On `riscv32` bare-metal targets this is always a no-op regardless of -/// features; the caliptra-drivers integration for RISC-V will be wired up -/// in a future phase. -pub fn init() -> Result<(), HwError> { - #[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] - { - // wolfCrypt_Init is required before any CryptoCb registration. - // It is idempotent: returns 0 on the first call, 1 on subsequent calls. - // In FIPS builds this also triggers the mandatory power-on self-test - // (POST); skipping it means FIPS self-tests have not run. - // SAFETY: wolfCrypt_Init has no preconditions. - let wc_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - if wc_rc != 0 && wc_rc != 1 { - return Err(HwError::WolfCryptInitFailed(wc_rc)); - } - - // SAFETY: wc_CryptoCb_RegisterDevice stores (devId, cb, ctx) in a - // global table; hw_callback is a static function so the pointer - // is valid for the process lifetime. - let rc = unsafe { - wolfcrypt_sys::wc_CryptoCb_RegisterDevice( - HW_DEVICE_ID, - Some(hw_callback), - core::ptr::null_mut(), - ) - }; - if rc != 0 { - return Err(HwError::InitFailed(rc)); - } - } - Ok(()) -} - -// --------------------------------------------------------------------------- -// Hardware CryptoCb callback (caliptra-2x only, non-riscv32 only) -// --------------------------------------------------------------------------- - -/// Main CryptoCb callback. Dispatches hash and HMAC operations to the -/// hardware-backed implementations in `hw_hash`. Returns -/// [`CRYPTOCB_UNAVAILABLE`] for all other algorithm types so wolfCrypt falls -/// through to software. -/// -/// Only compiled when `caliptra-2x` feature is active on non-RISC-V targets. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -pub unsafe extern "C" fn hw_callback( - _dev_id: c_int, - info: *mut wolfcrypt_sys::wc_CryptoInfo, - _ctx: *mut c_void, -) -> c_int { - if info.is_null() { - return CRYPTOCB_UNAVAILABLE; - } - let info = &mut *info; - let algo_type = info.algo_type as u32; - - if algo_type == wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_HASH { - hw_hash::dispatch_hash(info) - } else if algo_type == wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_HMAC { - hw_hash::dispatch_hmac(info) - } else if algo_type == wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_RNG { - hw_rng::dispatch_rng(info) - } else if algo_type == wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_CIPHER { - hw_aes::dispatch_cipher(info) - } else if algo_type == wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_PK { - hw_pk::dispatch_pk(info) - } else { - CRYPTOCB_UNAVAILABLE - } -} - -// --------------------------------------------------------------------------- -// Stub callback (kept for Phase 0 integration tests) -// --------------------------------------------------------------------------- - -/// Stub CryptoCb callback. Returns [`CRYPTOCB_UNAVAILABLE`] for every -/// operation so wolfCrypt falls through to software. -/// -/// # Why `pub` -/// -/// Integration tests live in `tests/` and form separate Rust crates; they -/// cannot access `pub(crate)` items. `pub` is required for -/// `test_stub_callback_returns_unavailable` to take the function pointer -/// directly. This symbol is not part of the stable public API. -/// -/// Only compiled when `caliptra-2x` feature is active on non-RISC-V targets. -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -pub unsafe extern "C" fn stub_hw_callback( - _dev_id: c_int, - _info: *mut wolfcrypt_sys::wc_CryptoInfo, - _ctx: *mut c_void, -) -> c_int { - CRYPTOCB_UNAVAILABLE -} - -/// Test-support helpers: counter reset aggregation. -/// -/// Exposed as a public module so integration tests in `tests/` can call -/// `wolfcrypt_dpe_hw::test_support::reset_all_counters()`. -pub mod test_support; - -/// Probe symbol: only present when `caliptra-2x` is active. -/// -/// Used by `test_feature_flag_compile_guard` to verify the feature gate is -/// real at the linker level โ€” the symbol must be absent from a library -/// compiled without `caliptra-2x`. -#[cfg(feature = "caliptra-2x")] -#[no_mangle] -pub unsafe extern "C" fn wolfcrypt_dpe_hw_caliptra2x_probe() -> c_int { - CRYPTOCB_UNAVAILABLE -} diff --git a/wolfcrypt-dpe-hw/src/test_support.rs b/wolfcrypt-dpe-hw/src/test_support.rs deleted file mode 100644 index 0af7923..0000000 --- a/wolfcrypt-dpe-hw/src/test_support.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! Test-support utilities for wolfcrypt-dpe-hw integration tests. -//! -//! These functions are public so integration tests in `tests/` can call them -//! as `wolfcrypt_dpe_hw::test_support::reset_all_counters()`. They are NOT -//! part of the stable public API. - -/// Reset every dispatch counter to zero. -/// -/// Call at the start of each integration test to prevent counter leakage from -/// prior tests. Equivalent to calling each `reset_*_dispatch_count()` -/// individually. -/// -/// Only available with `caliptra-2x` on non-RISC-V targets (the counters only -/// exist on those configurations). -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -pub fn reset_all_counters() { - crate::reset_hw_dispatch_count(); - crate::reset_trng_dispatch_count(); - crate::reset_aes_dispatch_count(); - crate::reset_ecc_dispatch_count(); - crate::reset_mldsa_dispatch_count(); -} diff --git a/wolfcrypt-dpe-hw/tests/link_probe.rs b/wolfcrypt-dpe-hw/tests/link_probe.rs deleted file mode 100644 index 824017c..0000000 --- a/wolfcrypt-dpe-hw/tests/link_probe.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Step 2 link probe: calls wolfcrypt_dpe_hw::init() and nothing else. -// Compiled with rustc --edition 2021 --crate-type bin (no -I headers). -extern crate wolfcrypt_dpe_hw; - -fn main() { - let _ = wolfcrypt_dpe_hw::init(); -} diff --git a/wolfcrypt-dpe-hw/tests/link_probe_aes.rs b/wolfcrypt-dpe-hw/tests/link_probe_aes.rs deleted file mode 100644 index d7ab46f..0000000 --- a/wolfcrypt-dpe-hw/tests/link_probe_aes.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Phase 3 Step 2 validation: verify wc_AesGcmEncrypt links without -//! macro-expansion headers or extra -I flags. If this file compiles and -//! links, the wolfcrypt-sys AES-GCM bindings are present and complete. - -fn main() { - let init_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!(init_rc == 0 || init_rc == 1, "wolfCrypt_Init failed: {init_rc}"); - - // Call wc_AesGcmEncrypt with zero-length input to verify the symbol links. - let mut aes: wolfcrypt_sys::Aes = unsafe { core::mem::zeroed() }; - let key = [0u8; 32]; - let iv = [0u8; 12]; - let mut tag = [0u8; 16]; - let rc = unsafe { - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), wolfcrypt_sys::INVALID_DEVID); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), key.len() as u32); - wolfcrypt_sys::wc_AesGcmEncrypt( - &mut aes, - core::ptr::null_mut(), - core::ptr::null(), - 0, - iv.as_ptr(), - iv.len() as u32, - tag.as_mut_ptr(), - tag.len() as u32, - core::ptr::null(), - 0, - ) - }; - unsafe { wolfcrypt_sys::wc_AesFree(&mut aes) }; - assert_eq!(rc, 0, "wc_AesGcmEncrypt(empty) failed with rc={rc}"); - - // Write result to audit file (best-effort; ignore fs errors in test env). - let _ = std::fs::create_dir_all("./audit"); - let _ = std::fs::write("./audit/phase3_link_probe.txt", "LINK OK\n"); - println!("link_probe_aes: PASS (rc={rc}, tag[0]={:#04x})", tag[0]); -} diff --git a/wolfcrypt-dpe-hw/tests/link_probe_hash.rs b/wolfcrypt-dpe-hw/tests/link_probe_hash.rs deleted file mode 100644 index 2420df4..0000000 --- a/wolfcrypt-dpe-hw/tests/link_probe_hash.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Phase 1 Step 2 validation: verify wc_Hash() links without macro-expansion -//! headers or extra -I flags. If this file compiles and links, the wolfcrypt-sys -//! CryptoCb bindings are present and complete. - -fn main() { - // wolfCrypt_Init is required before any hash operation (idempotent; FIPS POST). - let init_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!(init_rc == 0 || init_rc == 1, "wolfCrypt_Init failed: {init_rc}"); - - // wc_Hash is available unconditionally (no devId variant needed for this probe). - let data = b"abc"; - let mut digest = [0u8; 32]; - let rc = unsafe { - wolfcrypt_sys::wc_Hash( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA256, - data.as_ptr(), - data.len() as u32, - digest.as_mut_ptr(), - digest.len() as u32, - ) - }; - assert_eq!(rc, 0, "wc_Hash(SHA256, 'abc') failed with rc={rc}"); - // Digest correctness is validated by CryptoCb integration tests (phase1_hash.rs). - // This probe only verifies that wc_Hash links and returns 0. - println!("link_probe_hash: PASS (rc={rc}, digest[0]={:#04x})", digest[0]); -} diff --git a/wolfcrypt-dpe-hw/tests/link_probe_integration.rs b/wolfcrypt-dpe-hw/tests/link_probe_integration.rs deleted file mode 100644 index ea7b6a2..0000000 --- a/wolfcrypt-dpe-hw/tests/link_probe_integration.rs +++ /dev/null @@ -1,123 +0,0 @@ -//! Phase 5 link probe integration test. -//! -//! Calls one function from each dispatch module via wolfcrypt-sys directly. -//! No -I flags. Must link without any macro-expansion headers. -//! -//! Each function called here is a symbol from a different dispatch module: -//! dispatch_hash โ†’ wc_Hash_ex (SHA-256) -//! dispatch_hmac โ†’ wc_HmacInit -//! dispatch_rng โ†’ wc_InitRng_ex -//! dispatch_cipher โ†’ wc_AesGcmEncrypt (after wc_AesInit + wc_AesGcmSetKey) -//! dispatch_pk โ†’ wc_ecc_init_ex -//! -//! This test uses harness = false so it has its own main(). - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -fn main() { - // wolfCrypt must be initialised before any API calls. - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!(rc == 0 || rc == 1, "wolfCrypt_Init failed: {rc}"); - - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - - unsafe { - // --- dispatch_hash: wc_Hash_ex (SHA-256, 3 bytes) -------------------- - let data = [0x61u8, 0x62, 0x63]; // "abc" - let mut digest = [0u8; 32]; - let rc = wolfcrypt_sys::wc_Hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA256, - data.as_ptr(), - data.len() as u32, - digest.as_mut_ptr(), - digest.len() as u32, - core::ptr::null_mut(), - wolfcrypt_dpe_hw::HW_DEVICE_ID, - ); - // Link probe: verify the symbol links and the call succeeds. - // Output correctness is verified by the phase1_hash tests (run with --test-threads=1). - // The link probe runs concurrently with other tests so exact output is not asserted. - assert_eq!(rc, 0, "wc_Hash_ex(SHA256) failed: {rc}"); - assert_ne!(digest, [0u8; 32], "SHA-256 output must not be all-zero"); - - // --- dispatch_hmac: wc_HmacInit + key + update + final + free -------- - let mut hmac: wolfcrypt_sys::Hmac = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_HmacInit( - &mut hmac, - core::ptr::null_mut(), - wolfcrypt_dpe_hw::HW_DEVICE_ID, - ); - assert_eq!(rc, 0, "wc_HmacInit failed: {rc}"); - let key = [0x0bu8; 20]; - let rc = wolfcrypt_sys::wc_HmacSetKey( - &mut hmac, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384 as i32, - key.as_ptr(), - key.len() as u32, - ); - assert_eq!(rc, 0, "wc_HmacSetKey failed: {rc}"); - let msg = b"Hi There"; - let rc = wolfcrypt_sys::wc_HmacUpdate(&mut hmac, msg.as_ptr(), msg.len() as u32); - assert_eq!(rc, 0, "wc_HmacUpdate failed: {rc}"); - let mut mac_out = [0u8; 48]; - let rc = wolfcrypt_sys::wc_HmacFinal(&mut hmac, mac_out.as_mut_ptr()); - assert_eq!(rc, 0, "wc_HmacFinal failed: {rc}"); - wolfcrypt_sys::wc_HmacFree(&mut hmac); - - // --- dispatch_rng: wc_InitRng_ex + wc_RNG_GenerateBlock + free ------ - let mut rng: wolfcrypt_sys::WC_RNG = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_InitRng_ex( - &mut rng, - core::ptr::null_mut(), - wolfcrypt_dpe_hw::HW_DEVICE_ID, - ); - assert_eq!(rc, 0, "wc_InitRng_ex failed: {rc}"); - let mut buf = [0u8; 16]; - let rc = wolfcrypt_sys::wc_RNG_GenerateBlock(&mut rng, buf.as_mut_ptr(), 16); - assert_eq!(rc, 0, "wc_RNG_GenerateBlock failed: {rc}"); - wolfcrypt_sys::wc_FreeRng(&mut rng); - - // --- dispatch_cipher: wc_AesInit + wc_AesGcmSetKey + encrypt + free - - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), wolfcrypt_dpe_hw::HW_DEVICE_ID); - let aes_key = [0x00u8; 32]; - let rc = wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, aes_key.as_ptr(), 32); - assert_eq!(rc, 0, "wc_AesGcmSetKey failed: {rc}"); - let iv = [0u8; 12]; - let pt = [0u8; 16]; - let mut ct = [0u8; 16]; - let mut tag = [0u8; 16]; - let rc = wolfcrypt_sys::wc_AesGcmEncrypt( - &mut aes, - ct.as_mut_ptr(), pt.as_ptr(), 16, - iv.as_ptr(), 12, - tag.as_mut_ptr(), 16, - core::ptr::null(), 0, - ); - assert_eq!(rc, 0, "wc_AesGcmEncrypt failed: {rc}"); - wolfcrypt_sys::wc_AesFree(&mut aes); - - // --- dispatch_pk: wc_ecc_init_ex ----------------------------------- - let mut key: wolfcrypt_sys::ecc_key = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_ecc_init_ex( - &mut key, - core::ptr::null_mut(), - wolfcrypt_dpe_hw::HW_DEVICE_ID, - ); - assert_eq!(rc, 0, "wc_ecc_init_ex failed: {rc}"); - wolfcrypt_sys::wc_ecc_free(&mut key); - } - - println!("link_probe_integration PASSED โ€” all dispatch module symbols link and execute"); - std::fs::write( - concat!(env!("CARGO_MANIFEST_DIR"), "/../audit/phase5_link_probe.txt"), - "PASS: all dispatch module symbols link without macro-expansion headers\n\ - Verified: wc_Hash_ex, wc_HmacInit, wc_InitRng_ex, wc_AesGcmEncrypt, wc_ecc_init_ex\n", - ) - .ok(); -} - -#[cfg(not(all(feature = "caliptra-2x", not(target_arch = "riscv32"))))] -fn main() { - eprintln!("link_probe_integration: requires caliptra-2x on non-riscv32"); - std::process::exit(1); -} diff --git a/wolfcrypt-dpe-hw/tests/link_probe_pk.rs b/wolfcrypt-dpe-hw/tests/link_probe_pk.rs deleted file mode 100644 index 39fbda8..0000000 --- a/wolfcrypt-dpe-hw/tests/link_probe_pk.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! Phase 4 link probe: verify wc_ecc_sign_hash / wc_ecc_verify_hash link -//! without macro-expansion headers or extra -I flags. If this file compiles -//! and links, the wolfcrypt-sys ECC bindings are present and complete. -//! -//! This probe runs WITHOUT wolfcrypt_dpe_hw::init() to avoid hardware -//! registration. It uses INVALID_DEVID (software path) so the ECC -//! operations are pure wolfCrypt and require no CryptoCb callback. - -fn main() { - let init_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!(init_rc == 0 || init_rc == 1, "wolfCrypt_Init failed: {init_rc}"); - - // --- RNG --- - let mut rng: wolfcrypt_sys::WC_RNG = unsafe { core::mem::zeroed() }; - let rc = unsafe { wolfcrypt_sys::wc_InitRng(&mut rng) }; - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - // --- Key generation --- - let mut key: wolfcrypt_sys::ecc_key = unsafe { core::mem::zeroed() }; - let rc = unsafe { - wolfcrypt_sys::wc_ecc_init_ex( - &mut key, - core::ptr::null_mut(), - wolfcrypt_sys::INVALID_DEVID, - ) - }; - assert_eq!(rc, 0, "wc_ecc_init_ex failed: {rc}"); - - let rc = unsafe { - wolfcrypt_sys::wc_ecc_make_key_ex( - &mut rng, - 48, - &mut key, - wolfcrypt_sys::ecc_curve_ids_ECC_SECP384R1 as core::ffi::c_int, - ) - }; - assert_eq!(rc, 0, "wc_ecc_make_key_ex failed: {rc}"); - - // --- Sign --- - let hash = [0u8; 48]; - let mut sig = vec![0u8; 128]; - let mut sig_len: wolfcrypt_sys::word32 = 128; - let rc = unsafe { - wolfcrypt_sys::wc_ecc_sign_hash( - hash.as_ptr(), - 48, - sig.as_mut_ptr(), - &mut sig_len, - &mut rng, - &mut key, - ) - }; - assert_eq!(rc, 0, "wc_ecc_sign_hash failed: {rc}"); - assert!(sig_len > 0 && sig_len <= 128, "unexpected sig_len={sig_len}"); - - // --- Verify --- - let mut result: core::ffi::c_int = 0; - let rc = unsafe { - wolfcrypt_sys::wc_ecc_verify_hash( - sig.as_ptr(), - sig_len, - hash.as_ptr(), - 48, - &mut result, - &mut key, - ) - }; - assert_eq!(rc, 0, "wc_ecc_verify_hash failed: {rc}"); - assert_eq!(result, 1, "signature verification failed"); - - // --- wc_ecc_shared_secret symbol probe --- - // Just verify it links; don't call it (would need a second key pair). - let _fn_ptr: unsafe extern "C" fn( - *mut wolfcrypt_sys::ecc_key, - *mut wolfcrypt_sys::ecc_key, - *mut wolfcrypt_sys::byte, - *mut wolfcrypt_sys::word32, - ) -> core::ffi::c_int = wolfcrypt_sys::wc_ecc_shared_secret; - let _ = _fn_ptr; - - // --- Cleanup --- - unsafe { - wolfcrypt_sys::wc_ecc_free(&mut key); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - - // Write result to audit file (best-effort; ignore fs errors in test env). - let _ = std::fs::create_dir_all("./audit"); - let _ = std::fs::write("./audit/phase4_link_probe.txt", "LINK OK\n"); - println!("link_probe_pk: PASS (sig_len={sig_len}, result={result})"); -} diff --git a/wolfcrypt-dpe-hw/tests/link_probe_rng.rs b/wolfcrypt-dpe-hw/tests/link_probe_rng.rs deleted file mode 100644 index 18d33e7..0000000 --- a/wolfcrypt-dpe-hw/tests/link_probe_rng.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! Phase 2 Step 2 validation: verify wc_RNG_GenerateBlock links without -//! macro-expansion headers or extra -I flags. If this file compiles and -//! links, the wolfcrypt-sys RNG bindings are present and the wolfSSL library -//! supplies the wc_InitRng_ex / wc_RNG_GenerateBlock / wc_FreeRng symbols. - -use std::fs; -use std::path::Path; - -fn main() { - let init_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - init_rc == 0 || init_rc == 1, - "wolfCrypt_Init failed: {init_rc}" - ); - - let mut output = [0u8; 32]; - let rc = unsafe { - let mut rng: wolfcrypt_sys::WC_RNG = core::mem::zeroed(); - - // Initialise with INVALID_DEVID (software path) so the probe does not - // depend on the CryptoCb device being registered. - let init_rc = wolfcrypt_sys::wc_InitRng(&mut rng); - assert_eq!(init_rc, 0, "wc_InitRng failed: {init_rc}"); - - let gen_rc = wolfcrypt_sys::wc_RNG_GenerateBlock( - &mut rng, - output.as_mut_ptr(), - output.len() as u32, - ); - - wolfcrypt_sys::wc_FreeRng(&mut rng); - gen_rc - }; - assert_eq!(rc, 0, "wc_RNG_GenerateBlock failed with rc={rc}"); - - // Write result to audit file as required by PROMPT-agentic.md. - let audit_path = Path::new("./audit/phase2_link_probe.txt"); - if let Some(parent) = audit_path.parent() { - let _ = fs::create_dir_all(parent); - } - let result = format!( - "link_probe_rng: PASS\nrc={rc}\noutput[0]={:#04x}\n", - output[0] - ); - fs::write(audit_path, &result) - .unwrap_or_else(|e| eprintln!("warning: could not write audit file: {e}")); - println!("link_probe_rng: PASS (rc={rc}, output[0]={:#04x})", output[0]); -} diff --git a/wolfcrypt-dpe-hw/tests/phase0_scaffold.rs b/wolfcrypt-dpe-hw/tests/phase0_scaffold.rs deleted file mode 100644 index 6f3f09e..0000000 --- a/wolfcrypt-dpe-hw/tests/phase0_scaffold.rs +++ /dev/null @@ -1,200 +0,0 @@ -// Phase 0 test scaffold for wolfcrypt-dpe-hw. -// -// Integration tests run on the HOST with std available even though the -// library itself is no_std. -// -// Test 1: init() is a no-op without caliptra-2x; no CryptoCb device registered. -// Test 2: init() registers a stub device; callback returns CRYPTOCB_UNAVAILABLE. -// (compiled only when feature=caliptra-2x AND not riscv32 target) -// Test 3: feature gate is real at linker level; probe symbol absent without feature. - -// --------------------------------------------------------------------------- -// Test 1 โ€” init() no-op without caliptra-2x feature -// --------------------------------------------------------------------------- - -// Test 1 is explicitly a "no caliptra-2x" test: it asserts that init() is a -// no-op and that has_caliptra_hw_backend() is false. When caliptra-2x IS -// active, init() legitimately registers a device, so this test must be -// skipped in that configuration. -#[cfg(not(feature = "caliptra-2x"))] -#[test] -fn test_init_noop_without_feature() { - // init() must succeed and register NOTHING. - let result = wolfcrypt_dpe_hw::init(); - assert!(result.is_ok(), "init() must return Ok(()) without caliptra-2x"); - - // Verify the library reports no hardware backend active. - // has_caliptra_hw_backend() reflects whether init() actually performs - // CryptoCb registration; it is false iff the caliptra-2x feature is absent - // or the target is riscv32 (no wolfSSL linkage). - // - // This assertion WILL fail if someone accidentally adds CryptoCb - // registration code to init() outside the caliptra-2x cfg block. - assert!( - !wolfcrypt_dpe_hw::has_caliptra_hw_backend(), - "has_caliptra_hw_backend() must be false without caliptra-2x; \ - init() must not register any CryptoCb device in this configuration" - ); - - // Also verify wc_CryptoCb_RegisterDevice is callable (CryptoCb bindings exist). - // Initialize wolfCrypt first (required before any CryptoCb calls), then - // register a no-op probe callback at HW_DEVICE_ID, assert success, and - // unregister. If init() had already registered at HW_DEVICE_ID this would - // silently overwrite it โ€” which is why we also check has_caliptra_hw_backend(). - let wc_init_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!(wc_init_rc == 0 || wc_init_rc == 1, - "wolfCrypt_Init must succeed (0) or be already initialized (1); got {wc_init_rc}"); - - unsafe extern "C" fn probe_cb( - _: core::ffi::c_int, - _: *mut wolfcrypt_sys::wc_CryptoInfo, - _: *mut core::ffi::c_void, - ) -> core::ffi::c_int { - -1 - } - let rc = unsafe { - wolfcrypt_sys::wc_CryptoCb_RegisterDevice( - wolfcrypt_dpe_hw::HW_DEVICE_ID, - Some(probe_cb), - core::ptr::null_mut(), - ) - }; - assert_eq!(rc, 0, "wc_CryptoCb_RegisterDevice sanity probe failed with rc={rc}"); - unsafe { wolfcrypt_sys::wc_CryptoCb_UnRegisterDevice(wolfcrypt_dpe_hw::HW_DEVICE_ID) }; -} - -// --------------------------------------------------------------------------- -// Test 2 โ€” stub callback returns CRYPTOCB_UNAVAILABLE -// --------------------------------------------------------------------------- - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -#[test] -fn test_stub_callback_returns_unavailable() { - // wolfCrypt must be initialized before CryptoCb registration. - let wc_rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!(wc_rc == 0 || wc_rc == 1, - "wolfCrypt_Init must succeed (0=fresh, 1=already-init); got {wc_rc}"); - - // Register the hardware device. - wolfcrypt_dpe_hw::init().expect("init() must succeed under caliptra-2x"); - - // Construct a wc_CryptoInfo with algo_type = WC_ALGO_TYPE_HASH. - // Zero the whole struct first so the anonymous union is valid. - let mut info: wolfcrypt_sys::wc_CryptoInfo = unsafe { core::mem::zeroed() }; - // algo_type is a c_int in the struct; WC_ALGO_TYPE_HASH = 1. - info.algo_type = wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_HASH as _; - - // Call the stub callback directly via function pointer retrieval. - // stub_hw_callback is exported as pub extern "C" so we can take its address. - let callback_fn: unsafe extern "C" fn( - core::ffi::c_int, - *mut wolfcrypt_sys::wc_CryptoInfo, - *mut core::ffi::c_void, - ) -> core::ffi::c_int = wolfcrypt_dpe_hw::stub_hw_callback; - - let result = unsafe { - callback_fn( - wolfcrypt_dpe_hw::HW_DEVICE_ID, - &mut info, - core::ptr::null_mut(), - ) - }; - - assert_eq!( - result, - wolfcrypt_dpe_hw::CRYPTOCB_UNAVAILABLE, - "stub callback must return CRYPTOCB_UNAVAILABLE (-1); got {result}" - ); - - // Clean up: unregister the device so test_init_noop_without_feature is not - // polluted if tests run in the same process. - unsafe { - wolfcrypt_sys::wc_CryptoCb_UnRegisterDevice(wolfcrypt_dpe_hw::HW_DEVICE_ID); - } -} - -// --------------------------------------------------------------------------- -// Test 3 โ€” feature gate is real at linker level -// --------------------------------------------------------------------------- - -// Only valid without caliptra-2x: with the feature active the probe symbol IS -// present in the library, so the "must be absent" assertion would correctly -// fail โ€” but that failure would be spurious when a caller intentionally enables -// the feature. -#[cfg(not(feature = "caliptra-2x"))] -#[test] -fn test_feature_flag_compile_guard() { - use std::path::PathBuf; - use std::process::Command; - - // Locate the compiled library (no caliptra-2x; default features only). - // cargo stores rlibs in target/debug/deps/ with a hash suffix. - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let target_dir = std::env::var("CARGO_TARGET_DIR") - .map(PathBuf::from) - .unwrap_or_else(|_| manifest_dir.join("../target")); - let deps_dir = target_dir.join("debug/deps"); - - let rlib_entry = std::fs::read_dir(&deps_dir) - .expect("target/debug/deps must exist") - .filter_map(|e| e.ok()) - .find(|e| { - let name = e.file_name().to_string_lossy().to_string(); - name.starts_with("libwolfcrypt_dpe_hw-") && name.ends_with(".rlib") - }); - - let rlib_path = match rlib_entry { - Some(e) => e.path(), - None => { - // rlib might not be present if the test itself IS the only build - // artifact. Use nm on the test binary to check symbol absence. - let test_bin = std::env::current_exe().unwrap(); - let nm = Command::new("nm").arg(&test_bin).output(); - if let Ok(out) = nm { - let syms = String::from_utf8_lossy(&out.stdout); - assert!( - !syms.contains("wolfcrypt_dpe_hw_caliptra2x_probe"), - "caliptra-2x probe symbol must NOT be present in test binary \ - without feature; feature gate is broken" - ); - } - // Write result and return. - let result_path = manifest_dir.join("../audit/phase0_feature_guard.txt"); - let _ = std::fs::write( - &result_path, - "PASS: probe symbol absent from test binary without caliptra-2x\n", - ); - return; - } - }; - - // Use nm to verify the probe symbol is absent from the rlib. - // GNU nm handles archives (rlibs) directly. - let nm_out = Command::new("nm") - .arg(&rlib_path) - .output() - .expect("nm must be available"); - let symbols = String::from_utf8_lossy(&nm_out.stdout); - - assert!( - !symbols.contains("wolfcrypt_dpe_hw_caliptra2x_probe"), - "caliptra-2x probe symbol MUST NOT be present in library without the feature.\n\ - Feature gate is broken.\nrlib: {}\nSymbol table excerpt:\n{}", - rlib_path.display(), - symbols - .lines() - .filter(|l| l.contains("wolfcrypt_dpe_hw")) - .collect::>() - .join("\n"), - ); - - // Write result to audit. - let result_path = manifest_dir.join("../audit/phase0_feature_guard.txt"); - let _ = std::fs::write( - &result_path, - format!( - "PASS: wolfcrypt_dpe_hw_caliptra2x_probe absent in {}\n", - rlib_path.display() - ), - ); -} diff --git a/wolfcrypt-dpe-hw/tests/phase1_hash.rs b/wolfcrypt-dpe-hw/tests/phase1_hash.rs deleted file mode 100644 index 638839f..0000000 --- a/wolfcrypt-dpe-hw/tests/phase1_hash.rs +++ /dev/null @@ -1,498 +0,0 @@ -//! Phase 1 integration tests: SHA-256/384/512 and HMAC-384 via CryptoCb. -//! -//! All tests: -//! - Run on host (target_arch != "riscv32"), feature = "caliptra-2x". -//! - Instantiate the caliptra sw-emulator (CaliptraRootBus) as per the -//! pattern in audit/recon_swemulator.md. On the host path the actual SHA -//! computation uses the sha2/hmac crates (same as the caliptra emulator -//! uses internally); CaliptraRootBus is instantiated to exercise the -//! emulator infrastructure. -//! - Verify HW_DISPATCH_COUNT increments to confirm the hardware path fires. -//! -//! IMPORTANT: run with `-- --test-threads=1` because HW_HASH_STATE and -//! HW_HMAC_STATE are global singletons. Concurrent tests would corrupt -//! streaming state. - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod tests { - use wolfcrypt_dpe_hw::{hw_dispatch_count, reset_hw_dispatch_count, HW_DEVICE_ID}; - - // ----------------------------------------------------------------------- - // Shared setup - // ----------------------------------------------------------------------- - - /// One-time wolfCrypt + hardware backend initialisation (idempotent). - fn setup() { - static ONCE: std::sync::Once = std::sync::Once::new(); - ONCE.call_once(|| { - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - rc == 0 || rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - }); - } - - /// Minimal sw-emulator instantiation (Pattern 2 from recon_swemulator.md). - fn make_emulator() -> caliptra_emu_periph::CaliptraRootBus { - caliptra_emu_periph::CaliptraRootBus::new( - caliptra_emu_periph::CaliptraRootBusArgs::default(), - ) - } - - // ----------------------------------------------------------------------- - // Helper: one-shot hash via wolfSSL CryptoCb - // ----------------------------------------------------------------------- - - fn wc_hash_ex( - hash_type: wolfcrypt_sys::wc_HashType, - data: &[u8], - out: &mut [u8], - ) -> i32 { - unsafe { - wolfcrypt_sys::wc_Hash_ex( - hash_type, - data.as_ptr(), - data.len() as u32, - out.as_mut_ptr(), - out.len() as u32, - core::ptr::null_mut(), - HW_DEVICE_ID, - ) - } - } - - // ----------------------------------------------------------------------- - // assert_hw_was_used! macro - // ----------------------------------------------------------------------- - - /// Asserts that `hw_dispatch_count()` equals `before + expected_increment`. - /// - /// Panics with a descriptive message if the hardware path was not taken. - macro_rules! assert_hw_was_used { - ($before:expr, $expected_increment:expr) => {{ - let before: usize = $before; - let expected_increment: usize = $expected_increment; - let actual = hw_dispatch_count(); - assert_eq!( - actual, - before + expected_increment, - "hardware path was not taken โ€” test is invalid. \ - before={before}, after={actual}, \ - expected increment={expected_increment}" - ); - }}; - } - - // ----------------------------------------------------------------------- - // NIST FIPS 180-4 test vectors (embedded constants) - // ----------------------------------------------------------------------- - - // SHA-256 - const SHA256_EMPTY: [u8; 32] = [ - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, - 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, - 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, - 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, - ]; - const SHA256_ABC: [u8; 32] = [ - 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad, - ]; - const SHA256_1M_A: [u8; 32] = [ - 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, - 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, - 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, - 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0, - ]; - - // SHA-384 - const SHA384_EMPTY: [u8; 48] = [ - 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, - 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, - 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, - 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, - 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, - 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b, - ]; - const SHA384_ABC: [u8; 48] = [ - 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, - 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, - 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, - 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, - 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, - 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7, - ]; - const SHA384_1M_A: [u8; 48] = [ - 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb, - 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c, - 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52, - 0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b, - 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb, - 0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85, - ]; - - // SHA-512 - const SHA512_EMPTY: [u8; 64] = [ - 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, - 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, - 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, - 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, - 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, - 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, - 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, - 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e, - ]; - const SHA512_ABC: [u8; 64] = [ - 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, - 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, - 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, - 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, - 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, - 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, - 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, - 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f, - ]; - const SHA512_1M_A: [u8; 64] = [ - 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, - 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63, - 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28, - 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb, - 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, - 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b, - 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e, - 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b, - ]; - - // ----------------------------------------------------------------------- - // Test 1 โ€” SHA-256 NIST FIPS 180-4 byte vectors - // ----------------------------------------------------------------------- - - #[test] - fn test_sha256_nist_byte_vector() { - setup(); - let _emu = make_emulator(); - - reset_hw_dispatch_count(); - assert_eq!(hw_dispatch_count(), 0, "counter leak from previous test"); - - let cases: &[(&[u8], &[u8])] = &[ - (b"", &SHA256_EMPTY), - (b"abc", &SHA256_ABC), - ]; - - for (data, expected) in cases { - let before = hw_dispatch_count(); - let mut digest = [0u8; 32]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA256, - data, - &mut digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA256) failed: {rc}"); - assert_eq!(&digest[..], *expected, "SHA-256 digest mismatch for input len={}", data.len()); - assert_hw_was_used!(before, 1); - } - - // 1,000,000 ร— 'a' - { - let data = vec![b'a'; 1_000_000]; - let before = hw_dispatch_count(); - let mut digest = [0u8; 32]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA256, - &data, - &mut digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA256, 1Mร—a) failed: {rc}"); - assert_eq!(&digest[..], SHA256_1M_A, "SHA-256(1Mร—'a') mismatch"); - assert_hw_was_used!(before, 1); - } - } - - // ----------------------------------------------------------------------- - // Test 2 โ€” SHA-384 NIST FIPS 180-4 byte vectors - // ----------------------------------------------------------------------- - - #[test] - fn test_sha384_nist_byte_vector() { - setup(); - let _emu = make_emulator(); - - reset_hw_dispatch_count(); - assert_eq!(hw_dispatch_count(), 0, "counter leak from previous test"); - - let cases: &[(&[u8], &[u8])] = &[ - (b"", &SHA384_EMPTY), - (b"abc", &SHA384_ABC), - ]; - - for (data, expected) in cases { - let before = hw_dispatch_count(); - let mut digest = [0u8; 48]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - data, - &mut digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA384) failed: {rc}"); - assert_eq!(&digest[..], *expected, "SHA-384 digest mismatch for input len={}", data.len()); - assert_hw_was_used!(before, 1); - } - - { - let data = vec![b'a'; 1_000_000]; - let before = hw_dispatch_count(); - let mut digest = [0u8; 48]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - &data, - &mut digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA384, 1Mร—a) failed: {rc}"); - assert_eq!(&digest[..], SHA384_1M_A, "SHA-384(1Mร—'a') mismatch"); - assert_hw_was_used!(before, 1); - } - } - - // ----------------------------------------------------------------------- - // Test 3 โ€” SHA-512 NIST FIPS 180-4 byte vectors - // ----------------------------------------------------------------------- - - #[test] - fn test_sha512_nist_byte_vector() { - setup(); - let _emu = make_emulator(); - - reset_hw_dispatch_count(); - assert_eq!(hw_dispatch_count(), 0, "counter leak from previous test"); - - let cases: &[(&[u8], &[u8])] = &[ - (b"", &SHA512_EMPTY), - (b"abc", &SHA512_ABC), - ]; - - for (data, expected) in cases { - let before = hw_dispatch_count(); - let mut digest = [0u8; 64]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA512, - data, - &mut digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA512) failed: {rc}"); - assert_eq!(&digest[..], *expected, "SHA-512 digest mismatch for input len={}", data.len()); - assert_hw_was_used!(before, 1); - } - - { - let data = vec![b'a'; 1_000_000]; - let before = hw_dispatch_count(); - let mut digest = [0u8; 64]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA512, - &data, - &mut digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA512, 1Mร—a) failed: {rc}"); - assert_eq!(&digest[..], SHA512_1M_A, "SHA-512(1Mร—'a') mismatch"); - assert_hw_was_used!(before, 1); - } - } - - // ----------------------------------------------------------------------- - // Test 4 โ€” HMAC-SHA-384 NIST vector (RFC 4231 Test Case 1) - // ----------------------------------------------------------------------- - - #[test] - fn test_hmac384_nist_vector() { - setup(); - let _emu = make_emulator(); - - reset_hw_dispatch_count(); - assert_eq!(hw_dispatch_count(), 0, "counter leak from previous test"); - - // RFC 4231 Test Case 1 - // Key = 0x0b ร— 20 bytes - // Data = "Hi There" - // Source: RFC 4231 ยง2, confirmed against NIST CAVP HMAC test vectors. - const HMAC384_KEY: [u8; 20] = [0x0b; 20]; - const HMAC384_DATA: &[u8] = b"Hi There"; - const HMAC384_RFC4231_TC1: [u8; 48] = [ - 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, - 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, - 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, - 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, - 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, - 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6, - ]; - - // Compute via CryptoCb (our hw_callback โ†’ dispatch_hmac). - let before = hw_dispatch_count(); - let mut output = [0u8; 48]; - unsafe { - let mut hmac_ctx: wolfcrypt_sys::Hmac = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_HmacInit( - &mut hmac_ctx, - core::ptr::null_mut(), - HW_DEVICE_ID, - ); - assert_eq!(rc, 0, "wc_HmacInit failed: {rc}"); - - let rc = wolfcrypt_sys::wc_HmacSetKey( - &mut hmac_ctx, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384 as i32, - HMAC384_KEY.as_ptr(), - HMAC384_KEY.len() as u32, - ); - assert_eq!(rc, 0, "wc_HmacSetKey failed: {rc}"); - - let rc = wolfcrypt_sys::wc_HmacUpdate( - &mut hmac_ctx, - HMAC384_DATA.as_ptr(), - HMAC384_DATA.len() as u32, - ); - assert_eq!(rc, 0, "wc_HmacUpdate failed: {rc}"); - - let rc = wolfcrypt_sys::wc_HmacFinal(&mut hmac_ctx, output.as_mut_ptr()); - assert_eq!(rc, 0, "wc_HmacFinal failed: {rc}"); - - wolfcrypt_sys::wc_HmacFree(&mut hmac_ctx); - } - - assert_eq!(&output[..], &HMAC384_RFC4231_TC1[..], "HMAC-SHA-384 output mismatch (RFC 4231 TC1)"); - assert_hw_was_used!(before, 1); - } - - // ----------------------------------------------------------------------- - // Test 5 โ€” SHA-384 hardware path matches software (endian bug catcher) - // ----------------------------------------------------------------------- - - #[test] - fn test_sha384_matches_software() { - setup(); - let _emu = make_emulator(); - - reset_hw_dispatch_count(); - assert_eq!(hw_dispatch_count(), 0, "counter leak from previous test"); - - // 10 deterministic inputs of varying sizes (fixed LCG seed). - let sizes: [usize; 10] = [1, 13, 64, 127, 256, 512, 1000, 2048, 4096, 8192]; - let mut seed: u64 = 0xdeadbeef_cafef00d; - - let before = hw_dispatch_count(); - for size in sizes { - // Fill input deterministically. - let mut data = vec![0u8; size]; - for b in data.iter_mut() { - seed = seed.wrapping_mul(6364136223846793005) - .wrapping_add(1442695040888963407); - *b = (seed >> 33) as u8; - } - - // Hardware path (via CryptoCb). - let mut hw_digest = [0u8; 48]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - &data, - &mut hw_digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex(SHA384, size={size}) failed: {rc}"); - - // Software reference (sha2 crate). - let sw_digest: [u8; 48] = { - use sha2::Digest as _; - sha2::Sha384::digest(&data).into() - }; - - assert_eq!( - hw_digest, sw_digest, - "SHA-384 hardware/software mismatch at input size={size}" - ); - } - assert_hw_was_used!(before, 10); - } - - // ----------------------------------------------------------------------- - // Test 6 โ€” streaming matches one-shot - // ----------------------------------------------------------------------- - - #[test] - fn test_streaming_matches_oneshot() { - setup(); - let _emu = make_emulator(); - - reset_hw_dispatch_count(); - assert_eq!(hw_dispatch_count(), 0, "counter leak from previous test"); - - // 4096-byte input, split into 7 unequal chunks. - let data: Vec = (0u16..4096).map(|i| (i as u8) ^ (i >> 8) as u8).collect(); - let _splits: [usize; 7] = [1, 100, 333, 512, 1000, 1500, 4096]; - // chunks[i] = data[splits[i-1]..splits[i]] (splits[0]=1 is first chunk end) - // We build the actual chunk boundaries: - let boundaries: [usize; 8] = [0, 1, 101, 434, 946, 1946, 3446, 4096]; - - // --- One-shot via wc_Hash_ex --- - let before_oneshot = hw_dispatch_count(); - let mut oneshot_digest = [0u8; 48]; - let rc = wc_hash_ex( - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - &data, - &mut oneshot_digest, - ); - assert_eq!(rc, 0, "wc_Hash_ex one-shot failed: {rc}"); - assert_hw_was_used!(before_oneshot, 1); - - // --- Streaming via wc_HashInit_ex / wc_HashUpdate / wc_HashFinal --- - let before_stream = hw_dispatch_count(); - let mut stream_digest = [0u8; 48]; - unsafe { - let mut hash_alg: wolfcrypt_sys::wc_HashAlg = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_HashInit_ex( - &mut hash_alg, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - core::ptr::null_mut(), - HW_DEVICE_ID, - ); - assert_eq!(rc, 0, "wc_HashInit_ex failed: {rc}"); - - for i in 0..7 { - let chunk = &data[boundaries[i]..boundaries[i + 1]]; - if chunk.is_empty() { - continue; - } - let rc = wolfcrypt_sys::wc_HashUpdate( - &mut hash_alg, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - chunk.as_ptr(), - chunk.len() as u32, - ); - assert_eq!(rc, 0, "wc_HashUpdate(chunk {i}) failed: {rc}"); - } - - let rc = wolfcrypt_sys::wc_HashFinal( - &mut hash_alg, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - stream_digest.as_mut_ptr(), - ); - assert_eq!(rc, 0, "wc_HashFinal failed: {rc}"); - - wolfcrypt_sys::wc_HashFree( - &mut hash_alg, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384, - ); - } - assert_hw_was_used!(before_stream, 1); - - assert_eq!( - oneshot_digest, stream_digest, - "streaming and one-shot SHA-384 digests must be identical" - ); - - // Total dispatch count for both operations combined. - assert_hw_was_used!(before_oneshot, 2); - } -} diff --git a/wolfcrypt-dpe-hw/tests/phase2_rng.rs b/wolfcrypt-dpe-hw/tests/phase2_rng.rs deleted file mode 100644 index a5dd2a5..0000000 --- a/wolfcrypt-dpe-hw/tests/phase2_rng.rs +++ /dev/null @@ -1,245 +0,0 @@ -//! Phase 2 integration tests: ITRNG via CryptoCb WC_ALGO_TYPE_RNG dispatch. -//! -//! All tests: -//! - Run on host (target_arch != "riscv32"), feature = "caliptra-2x". -//! - Instantiate the caliptra sw-emulator (CaliptraRootBus) following the -//! pattern established in phase1_hash.rs. -//! - Reset TRNG_DISPATCH_COUNT at the start of each test to prevent leaks. -//! -//! The INJECT_TRNG_ERROR hook is an AtomicBool (not thread_local!+Cell) -//! because the library is #![no_std]. Tests use -//! `wolfcrypt_dpe_hw::INJECT_TRNG_ERROR.store(true, Ordering::Relaxed)` -//! in place of `INJECT_TRNG_ERROR.with(|f| f.set(true))`. -//! -//! IMPORTANT: run with `-- --test-threads=1` because TRNG_DISPATCH_COUNT and -//! INJECT_TRNG_ERROR are global singletons. - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod tests { - use core::sync::atomic::Ordering; - - use wolfcrypt_dpe_hw::{ - trng_dispatch_count, reset_trng_dispatch_count, HW_DEVICE_ID, INJECT_TRNG_ERROR, - }; - - // ----------------------------------------------------------------------- - // Shared setup - // ----------------------------------------------------------------------- - - fn setup() { - static ONCE: std::sync::Once = std::sync::Once::new(); - ONCE.call_once(|| { - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - rc == 0 || rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - }); - } - - /// Minimal sw-emulator instantiation (Pattern 2 from recon_swemulator.md). - fn make_emulator() -> caliptra_emu_periph::CaliptraRootBus { - caliptra_emu_periph::CaliptraRootBus::new( - caliptra_emu_periph::CaliptraRootBusArgs::default(), - ) - } - - // ----------------------------------------------------------------------- - // Helpers - // ----------------------------------------------------------------------- - - /// Initialize a WC_RNG with the given devId and generate `sz` bytes. - /// Returns (rc, output_buffer). - unsafe fn rng_generate(dev_id: core::ffi::c_int, sz: usize) -> (i32, Vec) { - let mut rng: wolfcrypt_sys::WC_RNG = core::mem::zeroed(); - let init_rc = wolfcrypt_sys::wc_InitRng_ex(&mut rng, core::ptr::null_mut(), dev_id); - if init_rc != 0 { - wolfcrypt_sys::wc_FreeRng(&mut rng); - return (init_rc, vec![]); - } - let mut output = vec![0u8; sz]; - let gen_rc = wolfcrypt_sys::wc_RNG_GenerateBlock( - &mut rng, - output.as_mut_ptr(), - output.len() as u32, - ); - wolfcrypt_sys::wc_FreeRng(&mut rng); - (gen_rc, output) - } - - // ----------------------------------------------------------------------- - // Test 1 โ€” test_trng_basic_output - // ----------------------------------------------------------------------- - - #[test] - fn test_trng_basic_output() { - setup(); - let _emu = make_emulator(); - - reset_trng_dispatch_count(); - assert_eq!(trng_dispatch_count(), 0, "counter leak from previous test"); - - let before = trng_dispatch_count(); - let (rc, output) = unsafe { rng_generate(HW_DEVICE_ID, 32) }; - assert_eq!(rc, 0, "wc_RNG_GenerateBlock(CALIPTRA_DEV_ID) failed: {rc}"); - assert_eq!( - trng_dispatch_count(), - before + 1, - "TRNG dispatch count must increment by exactly 1" - ); - assert_ne!(output, vec![0u8; 32], "output must not be all-zeros"); - assert_ne!(output, vec![0xffu8; 32], "output must not be all-0xFF"); - } - - // ----------------------------------------------------------------------- - // Test 2 โ€” test_trng_multiple_block_sizes - // ----------------------------------------------------------------------- - - #[test] - fn test_trng_multiple_block_sizes() { - setup(); - let _emu = make_emulator(); - - reset_trng_dispatch_count(); - assert_eq!(trng_dispatch_count(), 0, "counter leak from previous test"); - - let sizes: [usize; 8] = [1, 7, 16, 32, 48, 64, 128, 256]; - let before = trng_dispatch_count(); - - let mut last_output: Vec = vec![]; - for &sz in &sizes { - let (rc, output) = unsafe { rng_generate(HW_DEVICE_ID, sz) }; - assert_eq!( - rc, 0, - "wc_RNG_GenerateBlock(CALIPTRA_DEV_ID, sz={sz}) failed: {rc}" - ); - assert_eq!(output.len(), sz, "output length must equal requested size"); - - if !last_output.is_empty() && sz == last_output.len() { - // Only compare buffers of the same size โ€” statistical check. - assert_ne!( - output, last_output, - "consecutive same-size outputs must differ (size={sz})" - ); - } - last_output = output; - } - - assert_eq!( - trng_dispatch_count(), - before + 8, - "TRNG dispatch count must increment by 1 per generate call (8 total)" - ); - } - - // ----------------------------------------------------------------------- - // Test 3 โ€” test_software_fallback_does_not_use_trng - // ----------------------------------------------------------------------- - - #[test] - fn test_software_fallback_does_not_use_trng() { - setup(); - let _emu = make_emulator(); - - reset_trng_dispatch_count(); - assert_eq!(trng_dispatch_count(), 0, "counter leak from previous test"); - - let before = trng_dispatch_count(); - - // Use INVALID_DEVID (-2) so wolfSSL takes the software DRBG path. - // Our CryptoCb callback is NOT invoked on this path. - let (rc, _output) = - unsafe { rng_generate(wolfcrypt_sys::INVALID_DEVID, 32) }; - assert_eq!(rc, 0, "wc_RNG_GenerateBlock(INVALID_DEVID) must succeed: {rc}"); - - assert_eq!( - trng_dispatch_count(), - before, - "TRNG was called on software path โ€” CryptoCb callback must not fire for INVALID_DEVID" - ); - } - - // ----------------------------------------------------------------------- - // Test 4 โ€” test_drbg_crate_uses_hw_entropy - // - // Verifies that WolfRng::new_with_dev_id (wolfcrypt crate) routes - // wc_RNG_GenerateBlock through CryptoCb so TRNG_DISPATCH_COUNT increments. - // - // Uses wolfcrypt_sys::wc_InitRng_ex directly to mirror what - // WolfRng::new_with_dev_id does internally (avoids adding wolfcrypt as a - // dev-dependency, which would cause wolfcrypt-sys to be re-compiled from - // source in the test binary). - // ----------------------------------------------------------------------- - - #[test] - fn test_drbg_crate_uses_hw_entropy() { - setup(); - let _emu = make_emulator(); - - reset_trng_dispatch_count(); - assert_eq!(trng_dispatch_count(), 0, "counter leak from previous test"); - - // Use wc_InitRng_ex with HW_DEVICE_ID to mirror WolfRng::new_with_dev_id. - // This routes wc_RNG_GenerateBlock through CryptoCb โ†’ dispatch_rng. - let before = trng_dispatch_count(); - let (rc, _buf) = unsafe { rng_generate(HW_DEVICE_ID, 64) }; - assert_eq!(rc, 0, "wc_RNG_GenerateBlock (HW_DEVICE_ID path) failed: {rc}"); - - assert_eq!( - trng_dispatch_count(), - before + 1, - "TRNG dispatch count must increment by exactly 1 โ€” CryptoCb callback did not fire or incremented by wrong amount" - ); - } - - // ----------------------------------------------------------------------- - // Test 5 โ€” test_no_software_prng_fallback (anti-cheat) - // ----------------------------------------------------------------------- - - #[test] - fn test_no_software_prng_fallback() { - setup(); - let _emu = make_emulator(); - - reset_trng_dispatch_count(); - assert_eq!(trng_dispatch_count(), 0, "counter leak from previous test"); - - // Simulate ITRNG hardware fault. - // INJECT_TRNG_ERROR is an AtomicBool (no_std adaptation of thread_local!+Cell). - // Use Release/Acquire ordering so the store is visible to the load in - // dispatch_rng on weakly-ordered architectures. - // - // ClearOnDrop ensures the flag is always cleared even if rng_generate or - // any subsequent assertion panics and unwinds the test thread. - struct ClearOnDrop; - impl Drop for ClearOnDrop { - fn drop(&mut self) { - INJECT_TRNG_ERROR.store(false, Ordering::Release); - } - } - INJECT_TRNG_ERROR.store(true, Ordering::Release); - let _clear_guard = ClearOnDrop; - - let before = trng_dispatch_count(); - let (rc, _output) = unsafe { rng_generate(HW_DEVICE_ID, 32) }; - // _clear_guard clears the flag on drop (including on unwind). - - // The generate attempt MUST fail (non-zero rc). - // A zero rc here means the implementation silently fell back to the - // software PRNG, which is forbidden. - assert_ne!( - rc, 0, - "TRNG error was injected but wc_RNG_GenerateBlock returned success โ€” \ - silent software PRNG fallback is forbidden" - ); - - // TRNG_DISPATCH_COUNT must NOT have incremented โ€” the counter only - // increases on successful ITRNG calls. - assert_eq!( - trng_dispatch_count(), - before, - "TRNG dispatch count must not increment on ITRNG error" - ); - } -} diff --git a/wolfcrypt-dpe-hw/tests/phase3_aes.rs b/wolfcrypt-dpe-hw/tests/phase3_aes.rs deleted file mode 100644 index cb80661..0000000 --- a/wolfcrypt-dpe-hw/tests/phase3_aes.rs +++ /dev/null @@ -1,462 +0,0 @@ -//! Phase 3 integration tests: AES-256-GCM/CBC via CryptoCb WC_ALGO_TYPE_CIPHER dispatch. -//! -//! All tests: -//! - Run on host (target_arch != "riscv32"), feature = "caliptra-2x". -//! - Use the same sw-emulator harness established in phase1_hash.rs / phase2_rng.rs. -//! - Reset AES_DISPATCH_COUNT at the start of each test to prevent counter leaks. -//! -//! IMPORTANT: run with `-- --test-threads=1` because AES_DISPATCH_COUNT is a -//! global singleton. - -// Hex literal macro: hex!("deadbeef") โ†’ [0xde, 0xad, 0xbe, 0xef]. -// Defined before mod tests so it is in scope inside the module. -// All nibble conversion logic is inlined so no external function call is needed -// at the expansion site (macro_rules! uses call-site scope for name resolution). -macro_rules! hex { - ($s:expr) => {{ - const N: usize = $s.len() / 2; - let mut out = [0u8; N]; - let bytes = $s.as_bytes(); - let mut i = 0; - while i < N { - let hi = match bytes[i * 2] { - b @ b'0'..=b'9' => b - b'0', - b @ b'a'..=b'f' => b - b'a' + 10, - b @ b'A'..=b'F' => b - b'A' + 10, - _ => panic!("invalid hex digit"), - }; - let lo = match bytes[i * 2 + 1] { - b @ b'0'..=b'9' => b - b'0', - b @ b'a'..=b'f' => b - b'a' + 10, - b @ b'A'..=b'F' => b - b'A' + 10, - _ => panic!("invalid hex digit"), - }; - out[i] = (hi << 4) | lo; - i += 1; - } - out - }}; -} - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod tests { - use wolfcrypt_dpe_hw::{aes_dispatch_count, reset_aes_dispatch_count, HW_DEVICE_ID}; - - // ----------------------------------------------------------------------- - // Shared setup - // ----------------------------------------------------------------------- - - fn setup() { - static ONCE: std::sync::Once = std::sync::Once::new(); - ONCE.call_once(|| { - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - rc == 0 || rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - }); - } - - fn make_emulator() -> caliptra_emu_periph::CaliptraRootBus { - caliptra_emu_periph::CaliptraRootBus::new( - caliptra_emu_periph::CaliptraRootBusArgs::default(), - ) - } - - // ----------------------------------------------------------------------- - // AES-GCM helpers - // ----------------------------------------------------------------------- - - /// Encrypt using wc_AesGcmEncrypt. Returns (rc, ciphertext, tag). - unsafe fn gcm_encrypt( - dev_id: core::ffi::c_int, - key: &[u8; 32], - iv: &[u8; 12], - aad: &[u8], - plaintext: &[u8], - ) -> (i32, Vec, [u8; 16]) { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), 32); - - let mut ct = vec![0u8; plaintext.len()]; - let mut tag = [0u8; 16]; - let rc = wolfcrypt_sys::wc_AesGcmEncrypt( - &mut aes, - if plaintext.is_empty() { core::ptr::null_mut() } else { ct.as_mut_ptr() }, - if plaintext.is_empty() { core::ptr::null() } else { plaintext.as_ptr() }, - plaintext.len() as u32, - iv.as_ptr(), - 12, - tag.as_mut_ptr(), - 16, - if aad.is_empty() { core::ptr::null() } else { aad.as_ptr() }, - aad.len() as u32, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - (rc, ct, tag) - } - - /// Decrypt using wc_AesGcmDecrypt. Returns (rc, plaintext). - unsafe fn gcm_decrypt( - dev_id: core::ffi::c_int, - key: &[u8; 32], - iv: &[u8; 12], - aad: &[u8], - ciphertext: &[u8], - tag: &[u8; 16], - ) -> (i32, Vec) { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), 32); - - let mut pt = vec![0u8; ciphertext.len()]; - let rc = wolfcrypt_sys::wc_AesGcmDecrypt( - &mut aes, - if ciphertext.is_empty() { core::ptr::null_mut() } else { pt.as_mut_ptr() }, - if ciphertext.is_empty() { core::ptr::null() } else { ciphertext.as_ptr() }, - ciphertext.len() as u32, - iv.as_ptr(), - 12, - tag.as_ptr(), - 16, - if aad.is_empty() { core::ptr::null() } else { aad.as_ptr() }, - aad.len() as u32, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - (rc, pt) - } - - // ----------------------------------------------------------------------- - // AES-CBC helper - // ----------------------------------------------------------------------- - - /// Encrypt a single block using wc_AesCbcEncrypt. Returns (rc, ciphertext). - unsafe fn cbc_encrypt( - dev_id: core::ffi::c_int, - key: &[u8; 32], - iv: &[u8; 16], - plaintext: &[u8], - ) -> (i32, Vec) { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesSetKey( - &mut aes, - key.as_ptr(), - 32, - iv.as_ptr(), - wolfcrypt_sys::AES_ENCRYPTION as i32, - ); - let mut ct = vec![0u8; plaintext.len()]; - let rc = wolfcrypt_sys::wc_AesCbcEncrypt( - &mut aes, - ct.as_mut_ptr(), - plaintext.as_ptr(), - plaintext.len() as u32, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - (rc, ct) - } - - // ----------------------------------------------------------------------- - // Test 1 โ€” test_aes256gcm_nist_encrypt - // - // NIST SP 800-38D Test Case 15: AES-256-GCM, 64-byte plaintext, empty AAD. - // Vectors from NIST SP 800-38D Appendix B. - // ----------------------------------------------------------------------- - - #[test] - fn test_aes256gcm_nist_encrypt() { - setup(); - let _emu = make_emulator(); - reset_aes_dispatch_count(); - assert_eq!(aes_dispatch_count(), 0, "counter leak from previous test"); - - // NIST SP 800-38D TC15 (AES-256-GCM, 64-byte PT, no AAD). - const KEY: [u8; 32] = hex!("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"); - const IV: [u8; 12] = hex!("cafebabefacedbaddecaf888"); - const PT: [u8; 64] = hex!("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"); - const EXPECTED_CT: [u8; 64] = hex!("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad"); - const EXPECTED_TAG: [u8; 16] = hex!("b094dac5d93471bdec1a502270e3cc6c"); - - let before = aes_dispatch_count(); - let (rc, ct, tag) = unsafe { gcm_encrypt(HW_DEVICE_ID, &KEY, &IV, &[], &PT) }; - assert_eq!(rc, 0, "wc_AesGcmEncrypt(NIST TC15) failed: {rc}"); - assert_eq!(ct.as_slice(), EXPECTED_CT.as_slice(), "ciphertext mismatch"); - assert_eq!(tag, EXPECTED_TAG, "auth tag mismatch"); - assert_eq!(aes_dispatch_count(), before + 1, "AES_DISPATCH_COUNT must increment by 1"); - } - - // ----------------------------------------------------------------------- - // Test 2 โ€” test_aes256gcm_nist_decrypt - // ----------------------------------------------------------------------- - - #[test] - fn test_aes256gcm_nist_decrypt() { - setup(); - let _emu = make_emulator(); - reset_aes_dispatch_count(); - assert_eq!(aes_dispatch_count(), 0, "counter leak from previous test"); - - const KEY: [u8; 32] = hex!("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"); - const IV: [u8; 12] = hex!("cafebabefacedbaddecaf888"); - const CT: [u8; 64] = hex!("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad"); - const TAG: [u8; 16] = hex!("b094dac5d93471bdec1a502270e3cc6c"); - const EXPECTED_PT: [u8; 64] = hex!("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"); - - let before = aes_dispatch_count(); - let (rc, pt) = unsafe { gcm_decrypt(HW_DEVICE_ID, &KEY, &IV, &[], &CT, &TAG) }; - assert_eq!(rc, 0, "wc_AesGcmDecrypt(NIST TC15) failed: {rc}"); - assert_eq!(pt.as_slice(), EXPECTED_PT.as_slice(), "plaintext mismatch"); - assert_eq!(aes_dispatch_count(), before + 1, "AES_DISPATCH_COUNT must increment by 1"); - } - - // ----------------------------------------------------------------------- - // Test 3 โ€” test_aes256gcm_tag_rejection - // ----------------------------------------------------------------------- - - #[test] - fn test_aes256gcm_tag_rejection() { - setup(); - let _emu = make_emulator(); - reset_aes_dispatch_count(); - assert_eq!(aes_dispatch_count(), 0, "counter leak from previous test"); - - const KEY: [u8; 32] = hex!("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"); - const IV: [u8; 12] = hex!("cafebabefacedbaddecaf888"); - const CT: [u8; 64] = hex!("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad"); - // Flip the first bit of the correct tag. - let mut bad_tag: [u8; 16] = hex!("b094dac5d93471bdec1a502270e3cc6c"); - bad_tag[0] ^= 0x01; - - let before = aes_dispatch_count(); - let (rc, _pt) = unsafe { gcm_decrypt(HW_DEVICE_ID, &KEY, &IV, &[], &CT, &bad_tag) }; - - // The implementation must reach hardware (compute GHASH) before rejecting โ€” - // short-circuiting before hardware is forbidden. - assert_eq!( - aes_dispatch_count(), - before + 1, - "AES_DISPATCH_COUNT did not increment โ€” implementation short-circuited \ - before calling hardware on tag-rejection path (wrong)" - ); - - assert_ne!( - rc, 0, - "wc_AesGcmDecrypt must fail when tag is invalid (flipped bit in tag[0])" - ); - } - - // ----------------------------------------------------------------------- - // Test 4 โ€” test_aes256gcm_matches_software - // - // For 5 deterministic test vectors (fixed values, no RNG): - // hw encrypt + sw decrypt โ†’ plaintext matches - // sw encrypt + hw decrypt โ†’ plaintext matches - // AES_DISPATCH_COUNT must increment exactly 10 (2 hw calls per vector ร— 5). - // Catches endianness and key marshaling bugs. - // ----------------------------------------------------------------------- - - #[test] - fn test_aes256gcm_matches_software() { - setup(); - let _emu = make_emulator(); - reset_aes_dispatch_count(); - assert_eq!(aes_dispatch_count(), 0, "counter leak from previous test"); - - // 5 deterministic (key, iv, aad, pt) tuples. - // Values chosen to exercise different data patterns, not truly random. - let vectors: [([u8; 32], [u8; 12], [u8; 8], [u8; 32]); 5] = [ - ( - hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), - hex!("aabbccddeeff00112233445566778899")[..12].try_into().unwrap(), - *b"aad_vec1", - hex!("deadbeefcafebabe0102030405060708090a0b0c0d0e0f101112131415161718"), - ), - ( - hex!("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0"), - hex!("000102030405060708090a0b"), - *b"aad_vec2", - hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60"), - ), - ( - hex!("0000000000000000000000000000000000000000000000000000000000000000"), - hex!("000000000000000000000000"), - *b"aad_vec3", - hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - ), - ( - hex!("6162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80"), - hex!("112233445566778899aabbcc"), - *b"aad_vec4", - hex!("0f0e0d0c0b0a09080706050403020100fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0"), - ), - ( - hex!("a0b0c0d0e0f0a1b1c1d1e1f1a2b2c2d2e2f2a3b3c3d3e3f3a4b4c4d4e4f4a5b5"), - hex!("010203040506070809101112"), - *b"aad_vec5", - hex!("55aaff0055aaff0055aaff0055aaff0055aaff0055aaff0055aaff0055aaff00"), - ), - ]; - - let before = aes_dispatch_count(); - - for (i, (key, iv, aad, pt)) in vectors.iter().enumerate() { - // hw encrypt โ†’ sw decrypt - let (enc_rc, ct, tag) = - unsafe { gcm_encrypt(HW_DEVICE_ID, key, iv, aad, pt) }; - assert_eq!(enc_rc, 0, "hw encrypt failed for vector {i}: {enc_rc}"); - - let (dec_rc, recovered) = unsafe { - gcm_decrypt(wolfcrypt_sys::INVALID_DEVID, key, iv, aad, &ct, &tag) - }; - assert_eq!(dec_rc, 0, "sw decrypt failed for vector {i}: {dec_rc}"); - assert_eq!( - recovered.as_slice(), - pt.as_slice(), - "hw-encryptโ†’sw-decrypt plaintext mismatch for vector {i}" - ); - - // sw encrypt โ†’ hw decrypt - let (sw_enc_rc, sw_ct, sw_tag) = - unsafe { gcm_encrypt(wolfcrypt_sys::INVALID_DEVID, key, iv, aad, pt) }; - assert_eq!(sw_enc_rc, 0, "sw encrypt failed for vector {i}: {sw_enc_rc}"); - - let (hw_dec_rc, hw_recovered) = - unsafe { gcm_decrypt(HW_DEVICE_ID, key, iv, aad, &sw_ct, &sw_tag) }; - assert_eq!(hw_dec_rc, 0, "hw decrypt failed for vector {i}: {hw_dec_rc}"); - assert_eq!( - hw_recovered.as_slice(), - pt.as_slice(), - "sw-encryptโ†’hw-decrypt plaintext mismatch for vector {i}" - ); - } - - // 5 vectors ร— 2 hw operations each = 10 hw dispatches. - assert_eq!( - aes_dispatch_count(), - before + 10, - "AES_DISPATCH_COUNT must increment by 10 (2 hw calls ร— 5 vectors)" - ); - } - - // ----------------------------------------------------------------------- - // Test 5 โ€” test_aes256cbc_behavior - // - // CBC IS available per recon_caliptra_drivers.md ยง11. - // Uses NIST SP 800-38A AES-256-CBC AESAVS test vector (Block 1). - // ----------------------------------------------------------------------- - - #[test] - fn test_aes256cbc_behavior() { - setup(); - let _emu = make_emulator(); - reset_aes_dispatch_count(); - assert_eq!(aes_dispatch_count(), 0, "counter leak from previous test"); - - // NIST SP 800-38A AES-256-CBC AESAVS test vector (first encrypt block). - const KEY: [u8; 32] = - hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"); - const IV: [u8; 16] = hex!("000102030405060708090a0b0c0d0e0f"); - const PT: [u8; 16] = hex!("6bc1bee22e409f96e93d7e117393172a"); - const EXPECTED_CT: [u8; 16] = hex!("f58c4c04d6e5f1ba779eabfb5f7bfbd6"); - - let before = aes_dispatch_count(); - let (rc, ct) = unsafe { cbc_encrypt(HW_DEVICE_ID, &KEY, &IV, &PT) }; - assert_eq!(rc, 0, "wc_AesCbcEncrypt(NIST AESAVS, AES-256-CBC) failed: {rc}"); - assert_eq!(ct.as_slice(), EXPECTED_CT.as_slice(), "CBC ciphertext mismatch"); - assert_eq!( - aes_dispatch_count(), - before + 1, - "AES_DISPATCH_COUNT must increment by 1 for CBC hw dispatch" - ); - } - - // ----------------------------------------------------------------------- - // Test 6 โ€” test_key_material_zeroized - // - // Verifies that dispatch_aesgcm_encrypt calls zeroize::Zeroize on its - // local key copy after use. Uses a heuristic stack scan: if the test key - // pattern appears in the stack region occupied by the dispatch function's - // frame immediately after it returns, zeroize was NOT called. - // - // Uses a key of sequential bytes (0x80..=0x9F repeated) for easy - // detection. If zeroize::Zeroize (volatile writes) ran, those bytes are - // guaranteed to be zero at their former locations. - // ----------------------------------------------------------------------- - - #[test] - fn test_key_material_zeroized() { - setup(); - let _emu = make_emulator(); - reset_aes_dispatch_count(); - assert_eq!(aes_dispatch_count(), 0, "counter leak from previous test"); - - // Distinctive key pattern: sequential bytes 0x80..=0x9F stored as a - // const in .rodata โ€” using a const for comparison ensures the reference - // bytes are never on the stack themselves. - const SCAN_KEY: [u8; 32] = { - let mut k = [0u8; 32]; - let mut i = 0usize; - while i < 32 { - k[i] = 0x80u8 | (i as u8 & 0x1f); - i += 1; - } - k - }; - - let iv = [0x55u8; 12]; - let pt = [0xffu8; 16]; - - // Create a mutable local copy for the GCM call. - let mut test_key = SCAN_KEY; - - // Run AES-256-GCM through the HW dispatch path. - // Inside dispatch_aesgcm_encrypt: - // 1. key copy is made from aes->devKey onto the dispatch stack frame - // 2. key copy is used for the AES-GCM operation - // 3. key.zeroize() is called โ€” zeroes the dispatch stack frame's copy - let (rc, _ct, _tag) = - unsafe { gcm_encrypt(HW_DEVICE_ID, &test_key, &iv, &[], &pt) }; - assert_eq!(rc, 0, "GCM encrypt failed: {rc}"); - assert_eq!(aes_dispatch_count(), 1, "AES_DISPATCH_COUNT must be 1 after one dispatch"); - - // Zero OUR local test_key before scanning so it doesn't cause a false - // positive when we scan our own stack frame. - // volatile_write prevents dead-store elimination. - unsafe { core::ptr::write_volatile(&mut test_key as *mut [u8; 32], [0u8; 32]) }; - // Note: gcm_encrypt โ†’ wc_AesFree already called ForceZero on aes->devKey. - - // Take the approximate stack pointer AFTER zeroing test_key and AFTER - // gcm_encrypt returned so that the scan region covers the freed dispatch - // frames but not our live variables. - let sp_marker: u8 = 0; - let scan_end = &sp_marker as *const u8 as usize; - - // Heuristic scan: read 8 KiB below our current frame. - // After cleanup: - // - test_key: zeroed above โœ“ - // - aes->devKey (inside gcm_encrypt's frame): ForceZero'd by wc_AesFree โœ“ - // - dispatch's key copy: zeroed by key.zeroize() โœ“ - // If zeroize DID run, none of these contain SCAN_KEY anymore. - // If zeroize was REMOVED, dispatch's copy would still have SCAN_KEY bytes. - let found = unsafe { - let scan_start = scan_end.saturating_sub(8192); - let len = scan_end - scan_start; - if len >= 32 { - let region = core::slice::from_raw_parts(scan_start as *const u8, len); - region.windows(32).any(|w| w == SCAN_KEY) - } else { - false - } - }; - - assert!( - !found, - "Key pattern found in stack region โ€” dispatch_aesgcm_encrypt may \ - not be calling zeroize::Zeroize on the local key copy" - ); - } -} - diff --git a/wolfcrypt-dpe-hw/tests/phase4_ecc.rs b/wolfcrypt-dpe-hw/tests/phase4_ecc.rs deleted file mode 100644 index 687056f..0000000 --- a/wolfcrypt-dpe-hw/tests/phase4_ecc.rs +++ /dev/null @@ -1,552 +0,0 @@ -//! Phase 4 integration tests: ECC-384 sign/verify/ECDH via CryptoCb WC_ALGO_TYPE_PK. -//! -//! All tests: -//! - Run on host (target_arch != "riscv32"), feature = "caliptra-2x". -//! - Use the same sw-emulator harness established in phase1_hash.rs. -//! - Reset ECC_DISPATCH_COUNT at the start of each test to prevent counter leaks. -//! -//! IMPORTANT: run with `-- --test-threads=1` because ECC_DISPATCH_COUNT is a -//! global singleton. - -// Hex literal macro: hex!("deadbeef") โ†’ [0xde, 0xad, 0xbe, 0xef]. -macro_rules! hex { - ($s:expr) => {{ - const N: usize = $s.len() / 2; - let mut out = [0u8; N]; - let bytes = $s.as_bytes(); - let mut i = 0; - while i < N { - let hi = match bytes[i * 2] { - b @ b'0'..=b'9' => b - b'0', - b @ b'a'..=b'f' => b - b'a' + 10, - b @ b'A'..=b'F' => b - b'A' + 10, - _ => panic!("invalid hex digit"), - }; - let lo = match bytes[i * 2 + 1] { - b @ b'0'..=b'9' => b - b'0', - b @ b'a'..=b'f' => b - b'a' + 10, - b @ b'A'..=b'F' => b - b'A' + 10, - _ => panic!("invalid hex digit"), - }; - out[i] = (hi << 4) | lo; - i += 1; - } - out - }}; -} - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod tests { - use wolfcrypt_dpe_hw::{ecc_dispatch_count, reset_ecc_dispatch_count, HW_DEVICE_ID}; - - // ----------------------------------------------------------------------- - // Shared setup - // ----------------------------------------------------------------------- - - fn setup() { - static ONCE: std::sync::Once = std::sync::Once::new(); - ONCE.call_once(|| { - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - rc == 0 || rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - }); - } - - fn make_emulator() -> caliptra_emu_periph::CaliptraRootBus { - caliptra_emu_periph::CaliptraRootBus::new( - caliptra_emu_periph::CaliptraRootBusArgs::default(), - ) - } - - // ----------------------------------------------------------------------- - // ECC helpers - // ----------------------------------------------------------------------- - - /// Generate a fresh P-384 key pair with the given devId. - unsafe fn make_ecc384_key( - dev_id: core::ffi::c_int, - rng: *mut wolfcrypt_sys::WC_RNG, - ) -> wolfcrypt_sys::ecc_key { - let mut key: wolfcrypt_sys::ecc_key = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_ecc_init_ex(&mut key, core::ptr::null_mut(), dev_id); - assert_eq!(rc, 0, "wc_ecc_init_ex failed: {rc}"); - let rc = wolfcrypt_sys::wc_ecc_make_key_ex( - rng, - 48, - &mut key, - wolfcrypt_sys::ecc_curve_ids_ECC_SECP384R1 as core::ffi::c_int, - ); - assert_eq!(rc, 0, "wc_ecc_make_key_ex failed: {rc}"); - key - } - - /// Sign a 48-byte hash with the given key. Returns the DER-encoded signature. - unsafe fn ecc384_sign( - key: &mut wolfcrypt_sys::ecc_key, - rng: *mut wolfcrypt_sys::WC_RNG, - hash: &[u8; 48], - ) -> Vec { - let mut sig = vec![0u8; 128]; - let mut sig_len: wolfcrypt_sys::word32 = 128; - let rc = wolfcrypt_sys::wc_ecc_sign_hash( - hash.as_ptr(), - 48, - sig.as_mut_ptr(), - &mut sig_len, - rng, - key, - ); - assert_eq!(rc, 0, "wc_ecc_sign_hash failed: {rc}"); - sig.truncate(sig_len as usize); - sig - } - - /// Verify a DER signature against a 48-byte hash. Returns (rc, result). - unsafe fn ecc384_verify( - key: &mut wolfcrypt_sys::ecc_key, - sig: &[u8], - hash: &[u8; 48], - ) -> (core::ffi::c_int, core::ffi::c_int) { - let mut result: core::ffi::c_int = 0; - let rc = wolfcrypt_sys::wc_ecc_verify_hash( - sig.as_ptr(), - sig.len() as wolfcrypt_sys::word32, - hash.as_ptr(), - 48, - &mut result, - key, - ); - (rc, result) - } - - /// Export the public key from `src_key` as an uncompressed SEC1 blob - /// (0x04 || Qx || Qy, 97 bytes), then import it into a new key with `dev_id`. - unsafe fn import_public_from( - src_key: &mut wolfcrypt_sys::ecc_key, - dev_id: core::ffi::c_int, - ) -> wolfcrypt_sys::ecc_key { - let mut qx = [0u8; 48]; - let mut qy = [0u8; 48]; - let mut qx_len: wolfcrypt_sys::word32 = 48; - let mut qy_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_export_public_raw( - src_key, - qx.as_mut_ptr(), - &mut qx_len, - qy.as_mut_ptr(), - &mut qy_len, - ); - assert_eq!(rc, 0, "wc_ecc_export_public_raw failed: {rc}"); - assert_eq!(qx_len, 48, "unexpected qx_len={qx_len}"); - assert_eq!(qy_len, 48, "unexpected qy_len={qy_len}"); - - // SEC1 uncompressed: 0x04 || Qx || Qy - let mut pub_bytes = [0u8; 97]; - pub_bytes[0] = 0x04; - pub_bytes[1..49].copy_from_slice(&qx); - pub_bytes[49..97].copy_from_slice(&qy); - - // Import into a new key (INVALID_DEVID first to allow clean import). - let mut key: wolfcrypt_sys::ecc_key = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_ecc_init_ex( - &mut key, - core::ptr::null_mut(), - wolfcrypt_sys::INVALID_DEVID, - ); - assert_eq!(rc, 0, "wc_ecc_init_ex (import dst) failed: {rc}"); - let rc = wolfcrypt_sys::wc_ecc_import_x963_ex( - pub_bytes.as_ptr(), - 97, - &mut key, - wolfcrypt_sys::ecc_curve_ids_ECC_SECP384R1 as core::ffi::c_int, - ); - assert_eq!(rc, 0, "wc_ecc_import_x963_ex failed: {rc}"); - - // Set devId explicitly after import (import may not preserve it). - key.devId = dev_id; - key - } - - // ----------------------------------------------------------------------- - // Test 1 โ€” test_ecdsa384_sign_verify_roundtrip - // - // Generate a P-384 key pair, sign a hash via the HW CryptoCb path, - // verify via the HW CryptoCb path. Confirm both operations dispatched. - // ----------------------------------------------------------------------- - - #[test] - fn test_ecdsa384_sign_verify_roundtrip() { - setup(); - let _emu = make_emulator(); - reset_ecc_dispatch_count(); - let before = ecc_dispatch_count(); - assert_eq!(before, 0, "counter leak from previous test"); - - let mut rng: wolfcrypt_sys::WC_RNG = unsafe { core::mem::zeroed() }; - let rc = unsafe { wolfcrypt_sys::wc_InitRng(&mut rng) }; - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - unsafe { - let mut key = make_ecc384_key(HW_DEVICE_ID, &mut rng); - - // Sign a synthetic SHA-384 digest. - let hash = [0x42u8; 48]; - let sig = ecc384_sign(&mut key, &mut rng, &hash); - assert_eq!( - ecc_dispatch_count(), - before + 1, - "sign did not increment dispatch count" - ); - - // Verify the signature. - let (rc, result) = ecc384_verify(&mut key, &sig, &hash); - assert_eq!(rc, 0, "wc_ecc_verify_hash failed: {rc}"); - assert_eq!(result, 1, "signature verification returned result={result}"); - assert_eq!( - ecc_dispatch_count(), - before + 2, - "verify did not increment dispatch count" - ); - - wolfcrypt_sys::wc_ecc_free(&mut key); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - } - - // ----------------------------------------------------------------------- - // Test 2 โ€” test_ecdsa384_nist_verify_vector - // - // Verify a known-good RFC 6979 P-384/SHA-384 signature for message "sample". - // Vectors from NIST FIPS 186-4 test vectors / RFC 6979 ยงA.2.6. - // - // This test does not sign; it only verifies. Expected dispatch count: +1. - // ----------------------------------------------------------------------- - - #[test] - fn test_ecdsa384_nist_verify_vector() { - setup(); - let _emu = make_emulator(); - reset_ecc_dispatch_count(); - let before = ecc_dispatch_count(); - assert_eq!(before, 0, "counter leak from previous test"); - - // RFC 6979 P-384/SHA-384 "sample" test vector. - // Source: wolfssl/wolfcrypt/test/test.c (lines ~33395-33435). - const QX: [u8; 48] = hex!( - "EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64\ - DEF8F0EA9055866064A254515480BC13" - ); - const QY: [u8; 48] = hex!( - "8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1\ - 288B231C3AE0D4FE7344FD2533264720" - ); - const R: [u8; 48] = hex!( - "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C\ - 81A648152E44ACF96E36DD1E80FABE46" - ); - const S: [u8; 48] = hex!( - "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F\ - A329C145786E679E7B82C71A38628AC8" - ); - - unsafe { - // Compute SHA-384("sample"). - let msg = b"sample"; - let mut digest = [0u8; 48]; - let rc = wolfcrypt_sys::wc_Sha384Hash( - msg.as_ptr(), - msg.len() as wolfcrypt_sys::word32, - digest.as_mut_ptr(), - ); - assert_eq!(rc, 0, "wc_Sha384Hash failed: {rc}"); - - // DER-encode the (R, S) signature. - let mut sig = [0u8; 128]; - let mut sig_len: wolfcrypt_sys::word32 = 128; - let rc = wolfcrypt_sys::wc_ecc_rs_raw_to_sig( - R.as_ptr(), - 48, - S.as_ptr(), - 48, - sig.as_mut_ptr(), - &mut sig_len, - ); - assert_eq!(rc, 0, "wc_ecc_rs_raw_to_sig failed: {rc}"); - assert!(sig_len > 0 && sig_len <= 128, "unexpected sig_len={sig_len}"); - - // Build SEC1 uncompressed public key: 0x04 || Qx || Qy. - let mut pub_bytes = [0u8; 97]; - pub_bytes[0] = 0x04; - pub_bytes[1..49].copy_from_slice(&QX); - pub_bytes[49..97].copy_from_slice(&QY); - - // Import the public key with INVALID_DEVID first, then set HW_DEVICE_ID. - let mut key: wolfcrypt_sys::ecc_key = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_ecc_init_ex( - &mut key, - core::ptr::null_mut(), - wolfcrypt_sys::INVALID_DEVID, - ); - assert_eq!(rc, 0, "wc_ecc_init_ex failed: {rc}"); - let rc = wolfcrypt_sys::wc_ecc_import_x963_ex( - pub_bytes.as_ptr(), - 97, - &mut key, - wolfcrypt_sys::ecc_curve_ids_ECC_SECP384R1 as core::ffi::c_int, - ); - assert_eq!(rc, 0, "wc_ecc_import_x963_ex failed: {rc}"); - key.devId = HW_DEVICE_ID; - - // Verify using the HW CryptoCb path. - let (rc, result) = ecc384_verify(&mut key, &sig[..sig_len as usize], &digest); - assert_eq!(rc, 0, "wc_ecc_verify_hash failed: {rc}"); - assert_eq!(result, 1, "NIST vector verification failed (result={result})"); - assert_eq!( - ecc_dispatch_count(), - before + 1, - "verify did not increment dispatch count" - ); - - wolfcrypt_sys::wc_ecc_free(&mut key); - } - } - - // ----------------------------------------------------------------------- - // Test 3 โ€” test_ecdsa384_reject_bad_signature - // - // Sign a hash, then corrupt the signature by flipping a bit in the r - // component. Verify must fail with VERIFY_SIGN_ERROR (-330). - // - // The dispatch count: - // - sign: before โ†’ before + 1 - // - verify: VERIFY_SIGN_ERROR is NOT counted (hardware ran but sig invalid) - // Final count: before + 1 (only from sign). - // ----------------------------------------------------------------------- - - #[test] - fn test_ecdsa384_reject_bad_signature() { - setup(); - let _emu = make_emulator(); - reset_ecc_dispatch_count(); - let before = ecc_dispatch_count(); - assert_eq!(before, 0, "counter leak from previous test"); - - let mut rng: wolfcrypt_sys::WC_RNG = unsafe { core::mem::zeroed() }; - let rc = unsafe { wolfcrypt_sys::wc_InitRng(&mut rng) }; - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - unsafe { - let mut key = make_ecc384_key(HW_DEVICE_ID, &mut rng); - let hash = [0xABu8; 48]; - - // Sign โ€” count becomes before + 1. - let sig = ecc384_sign(&mut key, &mut rng, &hash); - - // Decode (r, s) from DER to corrupt r cleanly. - let mut r_bytes = [0u8; 48]; - let mut s_bytes = [0u8; 48]; - let mut r_len: wolfcrypt_sys::word32 = 48; - let mut s_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_sig_to_rs( - sig.as_ptr(), - sig.len() as wolfcrypt_sys::word32, - r_bytes.as_mut_ptr(), - &mut r_len, - s_bytes.as_mut_ptr(), - &mut s_len, - ); - assert_eq!(rc, 0, "wc_ecc_sig_to_rs failed: {rc}"); - - // Flip a bit in the middle of r โ€” the DER re-encoding will remain valid. - r_bytes[r_len as usize / 2] ^= 0x01; - - // Re-encode as DER. - let mut bad_sig = [0u8; 128]; - let mut bad_sig_len: wolfcrypt_sys::word32 = 128; - let rc = wolfcrypt_sys::wc_ecc_rs_raw_to_sig( - r_bytes.as_ptr(), - r_len, - s_bytes.as_ptr(), - s_len, - bad_sig.as_mut_ptr(), - &mut bad_sig_len, - ); - assert_eq!(rc, 0, "wc_ecc_rs_raw_to_sig (bad sig) failed: {rc}"); - - // Verify the corrupted signature โ€” must return VERIFY_SIGN_ERROR. - const VERIFY_SIGN_ERROR: core::ffi::c_int = -330; - let (rc, result) = - ecc384_verify(&mut key, &bad_sig[..bad_sig_len as usize], &hash); - assert_eq!( - rc, VERIFY_SIGN_ERROR, - "expected VERIFY_SIGN_ERROR ({VERIFY_SIGN_ERROR}), got rc={rc}" - ); - assert_eq!(result, 0, "result should be 0 on verify failure, got {result}"); - - // Dispatch count: only the sign incremented; failed verify did not. - assert_eq!( - ecc_dispatch_count(), - before + 1, - "failed verify must NOT increment dispatch count" - ); - - wolfcrypt_sys::wc_ecc_free(&mut key); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - } - - // ----------------------------------------------------------------------- - // Test 4 โ€” test_ecdh384_shared_secret - // - // Generate two P-384 key pairs, compute ECDH(A_priv, B_pub) and - // ECDH(B_priv, A_pub). Shared secrets must be equal and non-zero. - // Each ECDH call dispatches once; count increments by 2. - // ----------------------------------------------------------------------- - - #[test] - fn test_ecdh384_shared_secret() { - setup(); - let _emu = make_emulator(); - reset_ecc_dispatch_count(); - let before = ecc_dispatch_count(); - assert_eq!(before, 0, "counter leak from previous test"); - - let mut rng: wolfcrypt_sys::WC_RNG = unsafe { core::mem::zeroed() }; - let rc = unsafe { wolfcrypt_sys::wc_InitRng(&mut rng) }; - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - unsafe { - let mut key_a = make_ecc384_key(HW_DEVICE_ID, &mut rng); - let mut key_b = make_ecc384_key(HW_DEVICE_ID, &mut rng); - - // ECDH: A computes shared secret using A's private key and B's public key. - let mut shared_a = [0u8; 48]; - let mut shared_a_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_shared_secret( - &mut key_a, - &mut key_b, - shared_a.as_mut_ptr(), - &mut shared_a_len, - ); - assert_eq!(rc, 0, "wc_ecc_shared_secret (Aโ†’B) failed: {rc}"); - assert_eq!(shared_a_len, 48, "unexpected shared_a_len={shared_a_len}"); - assert_eq!( - ecc_dispatch_count(), - before + 1, - "ECDH Aโ†’B did not increment dispatch count" - ); - - // ECDH: B computes shared secret using B's private key and A's public key. - let mut shared_b = [0u8; 48]; - let mut shared_b_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_shared_secret( - &mut key_b, - &mut key_a, - shared_b.as_mut_ptr(), - &mut shared_b_len, - ); - assert_eq!(rc, 0, "wc_ecc_shared_secret (Bโ†’A) failed: {rc}"); - assert_eq!(shared_b_len, 48, "unexpected shared_b_len={shared_b_len}"); - assert_eq!( - ecc_dispatch_count(), - before + 2, - "ECDH Bโ†’A did not increment dispatch count" - ); - - // The two shared secrets must be identical. - assert_eq!(shared_a, shared_b, "ECDH shared secrets do not match"); - - // The shared secret must not be all zeros (catastrophic failure check). - assert_ne!(shared_a, [0u8; 48], "ECDH produced an all-zeros shared secret"); - - wolfcrypt_sys::wc_ecc_free(&mut key_a); - wolfcrypt_sys::wc_ecc_free(&mut key_b); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - } - - // ----------------------------------------------------------------------- - // Test 5 โ€” test_ecdsa384_cross_validate_with_software - // - // Verify that the HW and software paths produce compatible signatures: - // (a) HW sign โ†’ SW verify: wolfcrypt_dpe_hw signs; plain wolfCrypt verifies. - // (b) SW sign โ†’ HW verify: plain wolfCrypt signs; wolfcrypt_dpe_hw verifies. - // - // Dispatch count after (a): before + 1 (only the HW sign) - // Dispatch count after (b): before + 2 (HW sign from (a) + HW verify from (b)) - // ----------------------------------------------------------------------- - - #[test] - fn test_ecdsa384_cross_validate_with_software() { - setup(); - let _emu = make_emulator(); - reset_ecc_dispatch_count(); - let before = ecc_dispatch_count(); - assert_eq!(before, 0, "counter leak from previous test"); - - let mut rng: wolfcrypt_sys::WC_RNG = unsafe { core::mem::zeroed() }; - let rc = unsafe { wolfcrypt_sys::wc_InitRng(&mut rng) }; - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - let hash = [0x7Eu8; 48]; - - unsafe { - // --- (a) HW sign โ†’ SW verify --- - - // HW key pair. - let mut key_hw = make_ecc384_key(HW_DEVICE_ID, &mut rng); - - // Sign with HW path. - let sig_hw = ecc384_sign(&mut key_hw, &mut rng, &hash); - assert_eq!(ecc_dispatch_count(), before + 1, "HW sign did not dispatch"); - - // Export HW public key; import into a software (INVALID_DEVID) key. - let mut key_sw_pub = import_public_from(&mut key_hw, wolfcrypt_sys::INVALID_DEVID); - - // Verify with software path (no dispatch expected). - let (rc, result) = ecc384_verify(&mut key_sw_pub, &sig_hw, &hash); - assert_eq!(rc, 0, "SW verify of HW sig failed: rc={rc}"); - assert_eq!(result, 1, "SW verify of HW sig: result={result}"); - assert_eq!( - ecc_dispatch_count(), - before + 1, - "SW verify must not increment HW dispatch count" - ); - - // --- (b) SW sign โ†’ HW verify --- - - // Software key pair (INVALID_DEVID). - let mut key_sw = make_ecc384_key(wolfcrypt_sys::INVALID_DEVID, &mut rng); - - // Sign with software path (no dispatch expected). - let sig_sw = ecc384_sign(&mut key_sw, &mut rng, &hash); - assert_eq!( - ecc_dispatch_count(), - before + 1, - "SW sign must not increment HW dispatch count" - ); - - // Export SW public key; import into a hardware (HW_DEVICE_ID) key. - let mut key_hw_pub = import_public_from(&mut key_sw, HW_DEVICE_ID); - - // Verify with HW path. - let (rc, result) = ecc384_verify(&mut key_hw_pub, &sig_sw, &hash); - assert_eq!(rc, 0, "HW verify of SW sig failed: rc={rc}"); - assert_eq!(result, 1, "HW verify of SW sig: result={result}"); - assert_eq!( - ecc_dispatch_count(), - before + 2, - "HW verify did not increment dispatch count" - ); - - wolfcrypt_sys::wc_ecc_free(&mut key_hw); - wolfcrypt_sys::wc_ecc_free(&mut key_sw_pub); - wolfcrypt_sys::wc_ecc_free(&mut key_sw); - wolfcrypt_sys::wc_ecc_free(&mut key_hw_pub); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - } -} diff --git a/wolfcrypt-dpe-hw/tests/phase4_mldsa.rs b/wolfcrypt-dpe-hw/tests/phase4_mldsa.rs deleted file mode 100644 index da871cb..0000000 --- a/wolfcrypt-dpe-hw/tests/phase4_mldsa.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Phase 4 ML-DSA-87 integration tests. -//! -//! All tests in this file are gated on `feature = "mldsa87-hw"`. -//! -//! # Current status: ML-DSA dispatch is BLOCKED โ€” wire-format unverified -//! -//! wolfSSL at `/usr/local` has been rebuilt with `WOLFSSL_DILITHIUM=yes`. -//! The `pqc_sign` and `pqc_verify` sub-structs ARE present in the wolfcrypt-sys -//! bindings, and `WC_PK_TYPE_PQC_SIG_SIGN = 22` / `WC_PK_TYPE_PQC_SIG_VERIFY = 23` -//! ARE imported from wolfcrypt_sys in hw_pk.rs. -//! -//! The remaining blocker is wire-format compatibility verification between -//! wolfCrypt ML-DSA-87 and Adams Bridge (caliptra-drivers). Specifically: -//! - wolfCrypt's sign variant (pure ML-DSA vs. HashML-DSA) vs. Adams Bridge's -//! SHA-512 pre-hash `sign()` variant is unconfirmed. -//! - wolfCrypt's ML-DSA key and signature byte order vs. Adams Bridge's `LEArray4x*` -//! little-endian representation has not been cross-validated. -//! -//! These tests document the stub behavior and verify the dispatch counter stays zero -//! until wire-format is confirmed and dispatch is implemented. -//! -//! To unblock: -//! 1. Audit `info.pk.pqc_sign` fields vs. Adams Bridge sign() interface. -//! 2. Run cross-validation: wolfCrypt sign โ†’ Adams Bridge verify (or vice versa). -//! 3. Implement dispatch_mldsa87_sign/verify in hw_pk.rs once round-trip passes. -//! 4. Update or replace these stub tests. - -#[cfg(all(feature = "mldsa87-hw", not(target_arch = "riscv32")))] -mod tests { - use wolfcrypt_dpe_hw::{ - mldsa_dispatch_count, reset_mldsa_dispatch_count, HW_DEVICE_ID, CRYPTOCB_UNAVAILABLE, - }; - - fn setup() { - static ONCE: std::sync::Once = std::sync::Once::new(); - ONCE.call_once(|| { - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - rc == 0 || rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - }); - } - - // ----------------------------------------------------------------------- - // Test 1 โ€” test_mldsa87_dispatch_count_stays_zero - // - // Verify that MLDSA_DISPATCH_COUNT starts at zero and is not affected by - // ECC operations. (The counter is only incremented when ML-DSA dispatch - // is actually implemented and succeeds, which is currently blocked.) - // ----------------------------------------------------------------------- - - #[test] - fn test_mldsa87_dispatch_count_stays_zero() { - setup(); - reset_mldsa_dispatch_count(); - assert_eq!( - mldsa_dispatch_count(), - 0, - "MLDSA_DISPATCH_COUNT should be zero before any ML-DSA dispatch" - ); - // No ML-DSA operations are possible with the current system wolfSSL. - // Counter must stay zero. - assert_eq!( - mldsa_dispatch_count(), - 0, - "MLDSA_DISPATCH_COUNT must remain zero while dispatch is blocked" - ); - } - - // ----------------------------------------------------------------------- - // Test 2 โ€” test_mldsa87_hw_feature_compiles - // - // Verify that the `mldsa87-hw` feature gate compiles without errors and - // the counter accessor functions are accessible. This is a compile-only - // test; if this file compiles and links, the feature gate is correct. - // ----------------------------------------------------------------------- - - #[test] - fn test_mldsa87_hw_feature_compiles() { - setup(); - // These accessor functions are only exported when mldsa87-hw is active. - // If this test compiles, the feature gate and pub use are correct. - reset_mldsa_dispatch_count(); - let count = mldsa_dispatch_count(); - assert_eq!(count, 0, "unexpected initial count: {count}"); - } - - // ----------------------------------------------------------------------- - // Test 3 โ€” test_mldsa87_pqc_type_constants_documented - // - // Verify the expected values of WC_PK_TYPE_PQC_SIG_SIGN (22) and - // WC_PK_TYPE_PQC_SIG_VERIFY (23). wolfSSL was rebuilt with - // WOLFSSL_DILITHIUM=yes; both constants are imported from wolfcrypt_sys - // in hw_pk.rs. These local constants assert the expected numeric values - // remain stable. - // - // Also documents that the HW CryptoCb device is registered (devId = 1) - // and that CRYPTOCB_UNAVAILABLE = -271 (confirmed from error-crypt.h). - // ----------------------------------------------------------------------- - - #[test] - fn test_mldsa87_pqc_type_constants_documented() { - setup(); - // Per audit/phase4_reconciliation.md ยง6: - // WC_PK_TYPE_PQC_SIG_SIGN (22) and WC_PK_TYPE_PQC_SIG_VERIFY (23) are - // absent from wolfcrypt-sys bindings until HAVE_DILITHIUM is enabled. - // Hardcoded in hw_pk.rs; both dispatch stubs return CRYPTOCB_UNAVAILABLE. - const WC_PK_TYPE_PQC_SIG_SIGN: u32 = 22; - const WC_PK_TYPE_PQC_SIG_VERIFY: u32 = 23; - assert_eq!(WC_PK_TYPE_PQC_SIG_SIGN, 22, "PQC sign type constant"); - assert_eq!(WC_PK_TYPE_PQC_SIG_VERIFY, 23, "PQC verify type constant"); - - // CRYPTOCB_UNAVAILABLE must be -271 (from wolfssl/wolfcrypt/error-crypt.h). - assert_eq!( - CRYPTOCB_UNAVAILABLE, - -271, - "CRYPTOCB_UNAVAILABLE value mismatch" - ); - - // HW_DEVICE_ID must be 1 (registered in init()). - assert_eq!(HW_DEVICE_ID, 1, "HW_DEVICE_ID value mismatch"); - - // ML-DSA dispatch count must be zero (all stubs return CRYPTOCB_UNAVAILABLE). - reset_mldsa_dispatch_count(); - assert_eq!(mldsa_dispatch_count(), 0); - } -} diff --git a/wolfcrypt-dpe-hw/tests/phase5_integration.rs b/wolfcrypt-dpe-hw/tests/phase5_integration.rs deleted file mode 100644 index 6a51d3c..0000000 --- a/wolfcrypt-dpe-hw/tests/phase5_integration.rs +++ /dev/null @@ -1,477 +0,0 @@ -//! Phase 5 integration tests: full TLS simulation, no-software-crypto proof, -//! and counter-not-gameable verification. -//! -//! All tests: -//! - Run on host (target_arch != "riscv32"), feature = "caliptra-2x". -//! - Use reset_all_counters() at the start of each test. -//! - Assert exact counter increments for every dispatched operation. -//! -//! IMPORTANT: run with `-- --test-threads=1` because all dispatch counters -//! are global singletons. - -#[cfg(all(feature = "caliptra-2x", not(target_arch = "riscv32")))] -mod tests { - use wolfcrypt_dpe_hw::{ - aes_dispatch_count, ecc_dispatch_count, hw_dispatch_count, - test_support::reset_all_counters, - HW_DEVICE_ID, - }; - - // ----------------------------------------------------------------------- - // Shared setup - // ----------------------------------------------------------------------- - - fn setup() { - static ONCE: std::sync::Once = std::sync::Once::new(); - ONCE.call_once(|| { - let rc = unsafe { wolfcrypt_sys::wolfCrypt_Init() }; - assert!( - rc == 0 || rc == 1, - "wolfCrypt_Init failed (expected 0 or 1, got {rc})" - ); - wolfcrypt_dpe_hw::init().expect("wolfcrypt_dpe_hw::init failed"); - }); - } - - fn make_emulator() -> caliptra_emu_periph::CaliptraRootBus { - caliptra_emu_periph::CaliptraRootBus::new( - caliptra_emu_periph::CaliptraRootBusArgs::default(), - ) - } - - // ----------------------------------------------------------------------- - // HMAC-384 helper โ€” manual HKDF steps - // ----------------------------------------------------------------------- - - /// One HMAC-SHA-384 computation with HW_DEVICE_ID. - /// Increments hw_dispatch_count by 1. - unsafe fn hmac384(key: &[u8], data: &[u8], out: &mut [u8; 48], dev_id: core::ffi::c_int) { - let mut hmac: wolfcrypt_sys::Hmac = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_HmacInit(&mut hmac, core::ptr::null_mut(), dev_id); - assert_eq!(rc, 0, "hmac384: wc_HmacInit failed: {rc}"); - let rc = wolfcrypt_sys::wc_HmacSetKey( - &mut hmac, - wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA384 as i32, - key.as_ptr(), - key.len() as u32, - ); - assert_eq!(rc, 0, "hmac384: wc_HmacSetKey failed: {rc}"); - let rc = wolfcrypt_sys::wc_HmacUpdate(&mut hmac, data.as_ptr(), data.len() as u32); - assert_eq!(rc, 0, "hmac384: wc_HmacUpdate failed: {rc}"); - let rc = wolfcrypt_sys::wc_HmacFinal(&mut hmac, out.as_mut_ptr()); - assert_eq!(rc, 0, "hmac384: wc_HmacFinal failed: {rc}"); - wolfcrypt_sys::wc_HmacFree(&mut hmac); - } - - // ----------------------------------------------------------------------- - // AES-256-GCM helpers (same pattern as phase3_aes.rs) - // ----------------------------------------------------------------------- - - unsafe fn gcm_encrypt( - dev_id: core::ffi::c_int, - key: &[u8; 32], - iv: &[u8; 12], - plaintext: &[u8], - ) -> (i32, Vec, [u8; 16]) { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), 32); - let mut ct = vec![0u8; plaintext.len()]; - let mut tag = [0u8; 16]; - let rc = wolfcrypt_sys::wc_AesGcmEncrypt( - &mut aes, - if plaintext.is_empty() { core::ptr::null_mut() } else { ct.as_mut_ptr() }, - if plaintext.is_empty() { core::ptr::null() } else { plaintext.as_ptr() }, - plaintext.len() as u32, - iv.as_ptr(), 12, - tag.as_mut_ptr(), 16, - core::ptr::null(), 0, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - (rc, ct, tag) - } - - unsafe fn gcm_decrypt( - dev_id: core::ffi::c_int, - key: &[u8; 32], - iv: &[u8; 12], - ciphertext: &[u8], - tag: &[u8; 16], - ) -> (i32, Vec) { - let mut aes: wolfcrypt_sys::Aes = core::mem::zeroed(); - wolfcrypt_sys::wc_AesInit(&mut aes, core::ptr::null_mut(), dev_id); - wolfcrypt_sys::wc_AesGcmSetKey(&mut aes, key.as_ptr(), 32); - let mut pt = vec![0u8; ciphertext.len()]; - let rc = wolfcrypt_sys::wc_AesGcmDecrypt( - &mut aes, - if ciphertext.is_empty() { core::ptr::null_mut() } else { pt.as_mut_ptr() }, - if ciphertext.is_empty() { core::ptr::null() } else { ciphertext.as_ptr() }, - ciphertext.len() as u32, - iv.as_ptr(), 12, - tag.as_ptr(), 16, - core::ptr::null(), 0, - ); - wolfcrypt_sys::wc_AesFree(&mut aes); - (rc, pt) - } - - // ----------------------------------------------------------------------- - // ECC helpers (same pattern as phase4_ecc.rs) - // ----------------------------------------------------------------------- - - unsafe fn make_ecc384_key( - dev_id: core::ffi::c_int, - rng: *mut wolfcrypt_sys::WC_RNG, - ) -> wolfcrypt_sys::ecc_key { - let mut key: wolfcrypt_sys::ecc_key = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_ecc_init_ex(&mut key, core::ptr::null_mut(), dev_id); - assert_eq!(rc, 0, "wc_ecc_init_ex failed: {rc}"); - let rc = wolfcrypt_sys::wc_ecc_make_key_ex( - rng, 48, &mut key, - wolfcrypt_sys::ecc_curve_ids_ECC_SECP384R1 as core::ffi::c_int, - ); - assert_eq!(rc, 0, "wc_ecc_make_key_ex failed: {rc}"); - key - } - - // ----------------------------------------------------------------------- - // Test 1 โ€” test_full_tls_handshake_simulation - // - // TLS 1.3 handshake simulation with CALIPTRA_DEV_ID active: - // a) ECDH key exchange (two keypairs, shared secret from each side) - // b) HKDF-Extract + HKDF-Expand via HMAC-384 - // c) AES-256-GCM encrypt 1024-byte record - // d) AES-256-GCM decrypt and verify - // e) ECDSA-384 sign transcript hash - // f) ECDSA-384 verify signature - // - // Expected counter increments: - // ecc_dispatch: +4 (ECDH Aโ†’B, ECDH Bโ†’A, sign, verify) - // hw_dispatch: +2 (HKDF-Extract HMAC, HKDF-Expand HMAC) - // aes_dispatch: +2 (encrypt, decrypt) - // ----------------------------------------------------------------------- - - #[test] - fn test_full_tls_handshake_simulation() { - setup(); - let _emu = make_emulator(); - reset_all_counters(); - - let before_ecc = ecc_dispatch_count(); - let before_hw = hw_dispatch_count(); - let before_aes = aes_dispatch_count(); - - let plaintext: Vec = (0u8..=255).cycle().take(1024).collect(); - - unsafe { - // ---- a) ECDH key exchange ---------------------------------------- - let mut rng: wolfcrypt_sys::WC_RNG = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_InitRng(&mut rng); - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - let mut key_a = make_ecc384_key(HW_DEVICE_ID, &mut rng); - let mut key_b = make_ecc384_key(HW_DEVICE_ID, &mut rng); - - let mut shared_a = [0u8; 48]; - let mut shared_a_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_shared_secret( - &mut key_a, &mut key_b, - shared_a.as_mut_ptr(), &mut shared_a_len, - ); - assert_eq!(rc, 0, "ECDH Aโ†’B failed: {rc}"); - assert_eq!(shared_a_len, 48); - - let mut shared_b = [0u8; 48]; - let mut shared_b_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_shared_secret( - &mut key_b, &mut key_a, - shared_b.as_mut_ptr(), &mut shared_b_len, - ); - assert_eq!(rc, 0, "ECDH Bโ†’A failed: {rc}"); - assert_eq!(shared_b_len, 48); - assert_eq!(shared_a, shared_b, "ECDH shared secrets must match"); - - assert_eq!(ecc_dispatch_count(), before_ecc + 2, "after ECDH: ecc_dispatch must be +2"); - - // ---- b) HKDF-Extract + HKDF-Expand via HMAC-384 ------------------ - // HKDF-Extract: PRK = HMAC-384(salt=zeros, IKM=shared_secret) - let salt = [0u8; 48]; - let mut prk = [0u8; 48]; - hmac384(&salt, &shared_a, &mut prk, HW_DEVICE_ID); - assert_eq!(hw_dispatch_count(), before_hw + 1, "after HKDF-Extract: hw_dispatch must be +1"); - - // HKDF-Expand: OKM = HMAC-384(PRK, info || 0x01) - let mut info_block = [0u8; 49]; - info_block[..48].copy_from_slice(b"wolfssl-rs caliptra-hw conformance label 384\x00\x00\x00\x00"); - info_block[48] = 0x01; - let mut okm = [0u8; 48]; - hmac384(&prk, &info_block, &mut okm, HW_DEVICE_ID); - assert_eq!(hw_dispatch_count(), before_hw + 2, "after HKDF-Expand: hw_dispatch must be +2"); - - // Derive AES key (first 32 bytes) and IV (next 12 bytes) from OKM. - let mut aes_key = [0u8; 32]; - aes_key.copy_from_slice(&okm[..32]); - let mut aes_iv = [0u8; 12]; - aes_iv.copy_from_slice(&okm[32..44]); - - // ---- c) AES-256-GCM encrypt 1024-byte record --------------------- - let (rc, ct, tag) = gcm_encrypt(HW_DEVICE_ID, &aes_key, &aes_iv, &plaintext); - assert_eq!(rc, 0, "AES-GCM encrypt failed: {rc}"); - assert_eq!(aes_dispatch_count(), before_aes + 1, "after encrypt: aes_dispatch must be +1"); - - // ---- d) AES-256-GCM decrypt and verify --------------------------- - let (rc, pt_dec) = gcm_decrypt(HW_DEVICE_ID, &aes_key, &aes_iv, &ct, &tag); - assert_eq!(rc, 0, "AES-GCM decrypt failed: {rc}"); - assert_eq!(pt_dec, plaintext, "round-trip plaintext mismatch"); - assert_eq!(aes_dispatch_count(), before_aes + 2, "after decrypt: aes_dispatch must be +2"); - - // ---- e) ECDSA-384 sign transcript hash --------------------------- - let mut signing_key = make_ecc384_key(HW_DEVICE_ID, &mut rng); - let transcript_hash = [0xABu8; 48]; // synthetic 48-byte hash - let mut sig = vec![0u8; 128]; - let mut sig_len: wolfcrypt_sys::word32 = 128; - let rc = wolfcrypt_sys::wc_ecc_sign_hash( - transcript_hash.as_ptr(), 48, - sig.as_mut_ptr(), &mut sig_len, - &mut rng, &mut signing_key, - ); - assert_eq!(rc, 0, "ECDSA sign failed: {rc}"); - sig.truncate(sig_len as usize); - assert_eq!(ecc_dispatch_count(), before_ecc + 3, "after sign: ecc_dispatch must be +3"); - - // ---- f) ECDSA-384 verify signature -------------------------------- - let mut verify_result: core::ffi::c_int = 0; - let rc = wolfcrypt_sys::wc_ecc_verify_hash( - sig.as_ptr(), sig.len() as wolfcrypt_sys::word32, - transcript_hash.as_ptr(), 48, - &mut verify_result, &mut signing_key, - ); - assert_eq!(rc, 0, "ECDSA verify failed: {rc}"); - assert_eq!(verify_result, 1, "ECDSA signature did not verify"); - assert_eq!(ecc_dispatch_count(), before_ecc + 4, "after verify: ecc_dispatch must be +4"); - - // ---- Final counter assertions ------------------------------------ - assert_eq!( - ecc_dispatch_count(), before_ecc + 4, - "ecc_dispatch final check: expected 4 dispatches (2 ECDH + sign + verify)" - ); - assert_eq!( - hw_dispatch_count(), before_hw + 2, - "hw_dispatch final check: expected 2 dispatches (HKDF Extract + Expand via HMAC)" - ); - assert_eq!( - aes_dispatch_count(), before_aes + 2, - "aes_dispatch final check: expected 2 dispatches (encrypt + decrypt)" - ); - - // Cleanup - wolfcrypt_sys::wc_ecc_free(&mut key_a); - wolfcrypt_sys::wc_ecc_free(&mut key_b); - wolfcrypt_sys::wc_ecc_free(&mut signing_key); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - } - - // ----------------------------------------------------------------------- - // Test 2 โ€” test_no_software_crypto_used_in_full_flow - // - // Register a sentinel CryptoCb (SOFTWARE_SENTINEL_ID=2) that panics if - // invoked. Run the full TLS simulation from Test 1. All operations must - // route through HW_DEVICE_ID (ID=1). If any operation uses - // SOFTWARE_SENTINEL_ID (ID=2), the test panics, proving that ID escaped - // from HW_DEVICE_ID. - // - // Counter assertions are identical to Test 1, providing a second - // independent proof that the hardware path was taken. - // ----------------------------------------------------------------------- - - const SOFTWARE_SENTINEL_ID: core::ffi::c_int = 2; - - unsafe extern "C" fn sentinel_callback( - _dev_id: core::ffi::c_int, - info: *mut wolfcrypt_sys::wc_CryptoInfo, - _ctx: *mut core::ffi::c_void, - ) -> core::ffi::c_int { - let algo_type = if info.is_null() { -1 } else { (*info).algo_type }; - panic!("software crypto called unexpectedly: algo_type={algo_type}"); - } - - #[test] - fn test_no_software_crypto_used_in_full_flow() { - setup(); - let _emu = make_emulator(); - reset_all_counters(); - - // Register the sentinel callback. - let rc = unsafe { - wolfcrypt_sys::wc_CryptoCb_RegisterDevice( - SOFTWARE_SENTINEL_ID, - Some(sentinel_callback), - core::ptr::null_mut(), - ) - }; - assert_eq!(rc, 0, "failed to register sentinel callback: {rc}"); - - // Run the full TLS flow. All operations MUST use HW_DEVICE_ID (1). - // If anything accidentally uses SOFTWARE_SENTINEL_ID (2), sentinel_callback - // panics and this test fails with a clear error. - let before_ecc = ecc_dispatch_count(); - let before_hw = hw_dispatch_count(); - let before_aes = aes_dispatch_count(); - - let plaintext: Vec = (0u8..=255).cycle().take(1024).collect(); - - unsafe { - let mut rng: wolfcrypt_sys::WC_RNG = core::mem::zeroed(); - let rc = wolfcrypt_sys::wc_InitRng(&mut rng); - assert_eq!(rc, 0, "wc_InitRng failed: {rc}"); - - let mut key_a = make_ecc384_key(HW_DEVICE_ID, &mut rng); - let mut key_b = make_ecc384_key(HW_DEVICE_ID, &mut rng); - - // ECDH - let mut shared_a = [0u8; 48]; - let mut shared_a_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_shared_secret( - &mut key_a, &mut key_b, shared_a.as_mut_ptr(), &mut shared_a_len, - ); - assert_eq!(rc, 0, "ECDH Aโ†’B failed: {rc}"); - - let mut shared_b = [0u8; 48]; - let mut shared_b_len: wolfcrypt_sys::word32 = 48; - let rc = wolfcrypt_sys::wc_ecc_shared_secret( - &mut key_b, &mut key_a, shared_b.as_mut_ptr(), &mut shared_b_len, - ); - assert_eq!(rc, 0, "ECDH Bโ†’A failed: {rc}"); - assert_eq!(shared_a, shared_b, "ECDH mismatch"); - - // HKDF - let salt = [0u8; 48]; - let mut prk = [0u8; 48]; - hmac384(&salt, &shared_a, &mut prk, HW_DEVICE_ID); - - let mut info_block = [0u8; 49]; - info_block[..48].copy_from_slice(b"wolfssl-rs caliptra-hw conformance label 384\x00\x00\x00\x00"); - info_block[48] = 0x01; - let mut okm = [0u8; 48]; - hmac384(&prk, &info_block, &mut okm, HW_DEVICE_ID); - - let mut aes_key = [0u8; 32]; - aes_key.copy_from_slice(&okm[..32]); - let mut aes_iv = [0u8; 12]; - aes_iv.copy_from_slice(&okm[32..44]); - - // AES-256-GCM encrypt/decrypt - let (rc, ct, tag) = gcm_encrypt(HW_DEVICE_ID, &aes_key, &aes_iv, &plaintext); - assert_eq!(rc, 0, "encrypt failed: {rc}"); - let (rc, pt_dec) = gcm_decrypt(HW_DEVICE_ID, &aes_key, &aes_iv, &ct, &tag); - assert_eq!(rc, 0, "decrypt failed: {rc}"); - assert_eq!(pt_dec, plaintext, "round-trip mismatch"); - - // ECDSA sign/verify - let mut signing_key = make_ecc384_key(HW_DEVICE_ID, &mut rng); - let transcript_hash = [0xABu8; 48]; - let mut sig = vec![0u8; 128]; - let mut sig_len: wolfcrypt_sys::word32 = 128; - let rc = wolfcrypt_sys::wc_ecc_sign_hash( - transcript_hash.as_ptr(), 48, - sig.as_mut_ptr(), &mut sig_len, &mut rng, &mut signing_key, - ); - assert_eq!(rc, 0, "sign failed: {rc}"); - sig.truncate(sig_len as usize); - - let mut verify_result: core::ffi::c_int = 0; - let rc = wolfcrypt_sys::wc_ecc_verify_hash( - sig.as_ptr(), sig.len() as wolfcrypt_sys::word32, - transcript_hash.as_ptr(), 48, &mut verify_result, &mut signing_key, - ); - assert_eq!(rc, 0, "verify failed: {rc}"); - assert_eq!(verify_result, 1, "signature did not verify"); - - // Counter assertions (same as Test 1) - assert_eq!(ecc_dispatch_count(), before_ecc + 4, "ecc_dispatch mismatch"); - assert_eq!(hw_dispatch_count(), before_hw + 2, "hw_dispatch mismatch"); - assert_eq!(aes_dispatch_count(), before_aes + 2, "aes_dispatch mismatch"); - - wolfcrypt_sys::wc_ecc_free(&mut key_a); - wolfcrypt_sys::wc_ecc_free(&mut key_b); - wolfcrypt_sys::wc_ecc_free(&mut signing_key); - wolfcrypt_sys::wc_FreeRng(&mut rng); - } - // Sentinel was never called โ€” all operations used HW_DEVICE_ID. - } - - // ----------------------------------------------------------------------- - // Test 3 โ€” test_dispatch_counters_are_not_gameable - // - // Call hw_callback directly with malformed / unsupported inputs. - // For each call: assert the relevant counter did NOT increase. - // Closes the loophole where a counter increments before input validation. - // ----------------------------------------------------------------------- - - #[test] - fn test_dispatch_counters_are_not_gameable() { - setup(); - let _emu = make_emulator(); - reset_all_counters(); - - let before_hw = hw_dispatch_count(); - let before_aes = aes_dispatch_count(); - let before_ecc = ecc_dispatch_count(); - - unsafe { - // ---- 1. Null info pointer โ†’ hw_callback must return UNAVAILABLE ----- - let rc = wolfcrypt_dpe_hw::hw_callback( - HW_DEVICE_ID, - core::ptr::null_mut(), - core::ptr::null_mut(), - ); - assert_eq!(rc, wolfcrypt_dpe_hw::CRYPTOCB_UNAVAILABLE, "null info must return UNAVAILABLE"); - assert_eq!(hw_dispatch_count(), before_hw, "null info must not increment hw counter"); - assert_eq!(aes_dispatch_count(), before_aes, "null info must not increment aes counter"); - assert_eq!(ecc_dispatch_count(), before_ecc, "null info must not increment ecc counter"); - - // ---- 2. Unsupported algo_type value (9999) ------------------------- - let mut info: wolfcrypt_sys::wc_CryptoInfo = core::mem::zeroed(); - info.algo_type = 9999; - let rc = wolfcrypt_dpe_hw::hw_callback( - HW_DEVICE_ID, - &mut info as *mut _, - core::ptr::null_mut(), - ); - assert_eq!(rc, wolfcrypt_dpe_hw::CRYPTOCB_UNAVAILABLE, "algo_type=9999 must return UNAVAILABLE"); - assert_eq!(hw_dispatch_count(), before_hw, "algo_type=9999 must not increment hw counter"); - assert_eq!(aes_dispatch_count(), before_aes, "algo_type=9999 must not increment aes counter"); - assert_eq!(ecc_dispatch_count(), before_ecc, "algo_type=9999 must not increment ecc counter"); - - // ---- 3. WC_ALGO_TYPE_HASH with unsupported hash type (SHA-1) ------- - // dispatch_hash returns CRYPTOCB_UNAVAILABLE for non-SHA256/384/512 types. - let mut info: wolfcrypt_sys::wc_CryptoInfo = core::mem::zeroed(); - info.algo_type = wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_HASH as i32; - // SHA-1 (wc_HashType_WC_HASH_TYPE_SHA = 4): not handled by dispatch_hash. - info.__bindgen_anon_1.hash.type_ = wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA as i32; - let rc = wolfcrypt_dpe_hw::hw_callback( - HW_DEVICE_ID, - &mut info as *mut _, - core::ptr::null_mut(), - ); - assert_eq!(rc, wolfcrypt_dpe_hw::CRYPTOCB_UNAVAILABLE, "SHA-1 must return UNAVAILABLE"); - assert_eq!(hw_dispatch_count(), before_hw, "SHA-1 must not increment hw counter"); - - // ---- 4. WC_ALGO_TYPE_HASH with SHA-256 but digest=null (update call) - // Counter only increments on Final (digest != null), not on Update. - let mut info: wolfcrypt_sys::wc_CryptoInfo = core::mem::zeroed(); - info.algo_type = wolfcrypt_sys::wc_AlgoType_WC_ALGO_TYPE_HASH as i32; - info.__bindgen_anon_1.hash.type_ = wolfcrypt_sys::wc_HashType_WC_HASH_TYPE_SHA256 as i32; - // digest is null โ†’ this is an Update call, not Final. - // in_ is null and inSz is 0 โ†’ no-op update with empty data. - // Counter must NOT increment (only Final increments it). - let _rc = wolfcrypt_dpe_hw::hw_callback( - HW_DEVICE_ID, - &mut info as *mut _, - core::ptr::null_mut(), - ); - assert_eq!(hw_dispatch_count(), before_hw, "SHA256 Update (digest=null) must not increment hw counter"); - } - } -} diff --git a/wolfcrypt-dpe/Cargo.toml b/wolfcrypt-dpe/Cargo.toml index 32110ff..ced9227 100644 --- a/wolfcrypt-dpe/Cargo.toml +++ b/wolfcrypt-dpe/Cargo.toml @@ -21,12 +21,6 @@ name = "wolfcrypt_dpe" [features] riscv-bare-metal = ["wolfcrypt/riscv-bare-metal"] -cryptocb-only = ["wolfcrypt/cryptocb-only"] -cryptocb-pure = ["wolfcrypt/cryptocb-pure"] -# Propagates wolfcrypt/require-dev-id: removes WolfRng::new() (software DRBG path) -# so only WolfRng::new_with_dev_id is callable. When enabled, construct -# WolfCryptDpeImpl via new_with_rng_dev_id() to supply the CryptoCb device ID. -require-dev-id = ["wolfcrypt/require-dev-id"] [dependencies] # wolfcrypt from the local workspace -- the ONLY crypto dependency diff --git a/wolfcrypt-dpe/src/lib.rs b/wolfcrypt-dpe/src/lib.rs index 58bea86..bfecb4d 100644 --- a/wolfcrypt-dpe/src/lib.rs +++ b/wolfcrypt-dpe/src/lib.rs @@ -51,11 +51,6 @@ impl Drop for WolfCryptPrivKey { /// Maximum number of exported CDI handles stored simultaneously. const MAX_CDI_HANDLES: usize = 1; -/// Device ID passed to `wc_InitRng_ex` that selects the software DRBG path. -/// Mirrors wolfSSL's `INVALID_DEVID (-2)`. Used as the default in -/// `WolfCryptDpeImpl::new()` for backward compatibility. -const SOFTWARE_DRBG_DEV_ID: i32 = -2; - /// wolfSSL-backed implementation of the caliptra-dpe Crypto trait, /// parameterized by signature curve and digest algorithm. /// @@ -72,13 +67,8 @@ pub struct WolfCryptDpeImpl { /// Alias public key (set externally; used by sign_with_alias). alias_pub_key: Option, /// Cached wolfCrypt RNG, lazily initialized on first use. - /// Avoids wc_InitRng_ex (DRBG init + entropy reseed) on every call. + /// Avoids wc_InitRng (DRBG init + OS entropy reseed) on every call. rng: Option, - /// Device ID passed to `wc_InitRng_ex` on first RNG use. - /// `SOFTWARE_DRBG_DEV_ID` (-2) selects the software DRBG path. - /// Set a registered CryptoCb device ID (e.g. from wolfcrypt_dpe_hw) - /// via `new_with_rng_dev_id` to route all RNG calls through the ITRNG. - rng_dev_id: i32, _marker: PhantomData<(S, D)>, } @@ -92,44 +82,13 @@ pub type WolfCryptDpe256 = WolfCryptDpeImpl; pub type WolfCryptDpe = WolfCryptDpe384; impl WolfCryptDpeImpl { - /// Create a new instance using the software DRBG path. - /// - /// The RNG is initialised with `INVALID_DEVID` so wolfSSL's software - /// DRBG provides randomness. For hardware ITRNG enforcement, use - /// [`WolfCryptDpeImpl::new_with_rng_dev_id`]. - /// - /// When the `require-dev-id` feature is active on the `wolfcrypt` crate, - /// this constructor compiles but the underlying `WolfRng::new_with_dev_id` - /// call passes `SOFTWARE_DRBG_DEV_ID` โ€” a known-safe value. Code that - /// must enforce ITRNG usage should activate that feature and use - /// `new_with_rng_dev_id` instead. + /// Create a new instance. pub fn new() -> Self { Self { export_cdi_slots: Vec::new(), alias_signing_key: None, alias_pub_key: None, rng: None, - rng_dev_id: SOFTWARE_DRBG_DEV_ID, - _marker: PhantomData, - } - } - - /// Create a new instance that routes all RNG calls through the CryptoCb - /// device registered under `rng_dev_id`. - /// - /// Use this when `wolfcrypt_dpe_hw` (or another hardware backend) has - /// registered a CryptoCb device and you want every `wc_RNG_GenerateBlock` - /// call to go through the ITRNG rather than the software DRBG. - /// - /// When the `require-dev-id` feature is active, this is the only valid - /// constructor that provides hardware entropy. - pub fn new_with_rng_dev_id(rng_dev_id: i32) -> Self { - Self { - export_cdi_slots: Vec::new(), - alias_signing_key: None, - alias_pub_key: None, - rng: None, - rng_dev_id, _marker: PhantomData, } } @@ -196,7 +155,7 @@ impl Crypto for WolfCryptDpeImpl { type PrivKey = WolfCryptPrivKey; fn rand_bytes(&mut self, dst: &mut [u8]) -> Result<(), CryptoError> { - rng::rand_bytes(&mut self.rng, self.rng_dev_id, dst) + rng::rand_bytes(&mut self.rng, dst) } fn hash_initialize(&mut self) -> Result, CryptoError> { diff --git a/wolfcrypt-dpe/src/rng.rs b/wolfcrypt-dpe/src/rng.rs index f7085ab..8bc27ed 100644 --- a/wolfcrypt-dpe/src/rng.rs +++ b/wolfcrypt-dpe/src/rng.rs @@ -9,23 +9,17 @@ use crate::error::ERR_RNG_FAILURE; /// cached RNG instance. /// /// The RNG is lazily initialized on first use and reused for subsequent -/// calls, avoiding the cost of `wc_InitRng_ex` (DRBG init + entropy +/// calls, avoiding the cost of `wc_InitRng` (DRBG init + OS entropy /// reseed) on every call. -/// -/// `rng_dev_id` is passed to `wc_InitRng_ex` on first use. Pass -/// `wolfcrypt_rs::INVALID_DEVID` for the software DRBG path, or a -/// registered CryptoCb device ID (e.g. `wolfcrypt_dpe_hw::HW_DEVICE_ID`) -/// to route every `wc_RNG_GenerateBlock` call through the hardware ITRNG. pub(crate) fn rand_bytes( rng: &mut Option, - rng_dev_id: i32, dst: &mut [u8], ) -> Result<(), CryptoError> { let rng = match rng.as_mut() { Some(r) => r, None => { *rng = Some( - wolfcrypt::WolfRng::new_with_dev_id(rng_dev_id) + wolfcrypt::WolfRng::new() .map_err(|_| CryptoError::CryptoLibError(ERR_RNG_FAILURE))?, ); rng.as_mut().unwrap() diff --git a/wolfcrypt-ring-compat/Cargo.toml b/wolfcrypt-ring-compat/Cargo.toml index 8bf177a..b99c876 100644 --- a/wolfcrypt-ring-compat/Cargo.toml +++ b/wolfcrypt-ring-compat/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wolfcrypt-ring-compat" authors = ["WolfSSL Inc", "AWS-LibCrypto"] -version = "1.16.3" +version = "1.16.2" links = "wolfcrypt_ring_compat_sys" edition = "2021" rust-version = "1.71.0" @@ -56,7 +56,7 @@ fips = ["wolfcrypt-rs", "wolfcrypt-rs/fips"] [dependencies] spin.workspace = true untrusted = { workspace = true, optional = true } -wolfcrypt-rs = { version = "0.1.2", path = "../wolfcrypt-rs", default-features = false, optional = true } +wolfcrypt-rs = { version = "0.1.1", path = "../wolfcrypt-rs", default-features = false, optional = true } zeroize.workspace = true [dev-dependencies] diff --git a/wolfcrypt-rs/Cargo.toml b/wolfcrypt-rs/Cargo.toml index eaeb670..90ef1cd 100644 --- a/wolfcrypt-rs/Cargo.toml +++ b/wolfcrypt-rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wolfcrypt-rs" description = "Low-level FFI bindings for wolfSSL/wolfCrypt cryptographic library." -version = "0.1.2" +version = "0.1.1" authors = ["WolfSSL Inc"] edition = "2021" license = "MIT" @@ -15,14 +15,12 @@ build = "build.rs" links = "wolfssl" [dependencies] -wolfcrypt-sys = { version = "0.1.2", path = "../wolfcrypt-sys", default-features = false, features = ["vendored"] } +wolfcrypt-sys = { version = "0.1.1", path = "../wolfcrypt-sys", default-features = false, features = ["vendored"] } [features] default = [] fips = ["wolfcrypt-sys/fips"] riscv-bare-metal = ["wolfcrypt-sys/riscv-bare-metal"] -cryptocb-only = ["wolfcrypt-sys/cryptocb-only"] -cryptocb-pure = ["wolfcrypt-sys/cryptocb-pure"] [build-dependencies] cc = { workspace = true, features = ["parallel"] } diff --git a/wolfcrypt-rs/build.rs b/wolfcrypt-rs/build.rs index b9facdb..1a5230a 100644 --- a/wolfcrypt-rs/build.rs +++ b/wolfcrypt-rs/build.rs @@ -43,34 +43,19 @@ fn main() { let mut shim_build = cc::Build::new(); shim_build.include(&wolfssl_include); - // For bare-metal features, put our OUT_DIR first so the minimal - // user_settings.h shadows the default one, and add bare-metal stub headers - // (stdio.h etc.) when WOLFSSL_BARE_METAL_STUBS is set. - if cfg!(any( - feature = "riscv-bare-metal", - feature = "cryptocb-only", - feature = "cryptocb-pure", - )) { + // For riscv-bare-metal, put OUT_DIR first so the RISC-V user_settings.h + // shadows the default one, and add bare-metal stub headers. + if cfg!(feature = "riscv-bare-metal") { let out_dir = env::var("OUT_DIR").unwrap(); shim_build.include(&out_dir); if let Ok(stubs) = env::var("WOLFSSL_BARE_METAL_STUBS") { shim_build.include(&stubs); } - // Copy the feature-appropriate user_settings.h to our OUT_DIR so it - // shadows wolfssl-src/user_settings.h in the include search order. - let settings_name = if cfg!(feature = "cryptocb-pure") { - "user_settings_cryptocb_pure.h" - } else if cfg!(feature = "cryptocb-only") { - "user_settings_cryptocb_only.h" - } else { - "user_settings_riscv.h" - }; - let src_settings = std::path::Path::new(&settings_include).join(settings_name); + // Copy RISC-V settings to our OUT_DIR too + let src_settings = std::path::Path::new(&settings_include).join("user_settings_riscv.h"); let dst = std::path::Path::new(&out_dir).join("user_settings.h"); - if src_settings.exists() { - std::fs::copy(&src_settings, &dst) - .unwrap_or_else(|e| panic!("failed to copy {settings_name}: {e}")); - println!("cargo:rerun-if-changed={}", src_settings.display()); + if src_settings.exists() && !dst.exists() { + std::fs::copy(&src_settings, &dst).ok(); } } shim_build.include(&settings_include); diff --git a/wolfcrypt-rs/src/compat_shim.c b/wolfcrypt-rs/src/compat_shim.c index ab19385..2eb90b6 100644 --- a/wolfcrypt-rs/src/compat_shim.c +++ b/wolfcrypt-rs/src/compat_shim.c @@ -25,7 +25,6 @@ */ #include -#include /* Only pull in OpenSSL compat headers when OPENSSL_EXTRA is active */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) @@ -96,8 +95,8 @@ /* These sizes and alignments must match the Rust struct definitions in lib.rs. * If a _Static_assert fires, update the corresponding constant or alignment. */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) -_Static_assert(sizeof(WOLFSSL_AES_KEY) <= 512, - "WOLFSSL_AES_KEY exceeds AES_KEY_ALLOC_SIZE (512) in lib.rs"); +_Static_assert(sizeof(WOLFSSL_AES_KEY) <= 352, + "WOLFSSL_AES_KEY exceeds AES_KEY_ALLOC_SIZE (352) in lib.rs"); #endif _Static_assert(sizeof(Aes) <= 512, @@ -721,11 +720,7 @@ static int wolfcrypt_AES_unwrap_key_padded_multiblock( #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_HMAC) #include -/* STRING_USER means wolfSSL's XSTRCMP/XSTRLEN macros are user-defined - * (via user_settings.h) โ€” no need to pull in string.h for them. */ -#ifndef STRING_USER #include -#endif /* Map EVP_MD name to wc_MACAlgorithm value for wc_PRF_TLS */ static int evp_md_to_mac_type(const WOLFSSL_EVP_MD *md) { @@ -1097,1254 +1092,4 @@ int wolfcrypt_cryptocb_info_pk_type(const wc_CryptoInfo *info) { return info->pk.type; } -/* -- PK eccsign fields -- */ -#ifdef HAVE_ECC -const unsigned char* wolfcrypt_cryptocb_info_pk_eccsign_in(const wc_CryptoInfo *info) { - return info->pk.eccsign.in; -} -unsigned int wolfcrypt_cryptocb_info_pk_eccsign_inlen(const wc_CryptoInfo *info) { - return info->pk.eccsign.inlen; -} -unsigned char* wolfcrypt_cryptocb_info_pk_eccsign_out(wc_CryptoInfo *info) { - return info->pk.eccsign.out; -} -unsigned int* wolfcrypt_cryptocb_info_pk_eccsign_outlen(wc_CryptoInfo *info) { - return info->pk.eccsign.outlen; -} -void* wolfcrypt_cryptocb_info_pk_eccsign_key(const wc_CryptoInfo *info) { - return info->pk.eccsign.key; -} -void* wolfcrypt_cryptocb_info_pk_eccsign_rng(const wc_CryptoInfo *info) { - return info->pk.eccsign.rng; -} - -/* -- PK eccverify fields -- */ -const unsigned char* wolfcrypt_cryptocb_info_pk_eccverify_sig(const wc_CryptoInfo *info) { - return info->pk.eccverify.sig; -} -unsigned int wolfcrypt_cryptocb_info_pk_eccverify_siglen(const wc_CryptoInfo *info) { - return info->pk.eccverify.siglen; -} -const unsigned char* wolfcrypt_cryptocb_info_pk_eccverify_hash(const wc_CryptoInfo *info) { - return info->pk.eccverify.hash; -} -unsigned int wolfcrypt_cryptocb_info_pk_eccverify_hashlen(const wc_CryptoInfo *info) { - return info->pk.eccverify.hashlen; -} -int* wolfcrypt_cryptocb_info_pk_eccverify_res(wc_CryptoInfo *info) { - return info->pk.eccverify.res; -} -void* wolfcrypt_cryptocb_info_pk_eccverify_key(const wc_CryptoInfo *info) { - return info->pk.eccverify.key; -} - -/* -- PK ecdh and eckg fields -- */ -void* wolfcrypt_cryptocb_info_pk_ecdh_private_key(const wc_CryptoInfo *info) { - return info->pk.ecdh.private_key; -} -void* wolfcrypt_cryptocb_info_pk_ecdh_public_key(const wc_CryptoInfo *info) { - return info->pk.ecdh.public_key; -} -unsigned char* wolfcrypt_cryptocb_info_pk_ecdh_out(wc_CryptoInfo *info) { - return info->pk.ecdh.out; -} -unsigned int* wolfcrypt_cryptocb_info_pk_ecdh_outlen(wc_CryptoInfo *info) { - return info->pk.ecdh.outlen; -} -void* wolfcrypt_cryptocb_info_pk_eckg_key(const wc_CryptoInfo *info) { - return info->pk.eckg.key; -} -int wolfcrypt_cryptocb_info_pk_eckg_size(const wc_CryptoInfo *info) { - return info->pk.eckg.size; -} -int wolfcrypt_cryptocb_info_pk_eckg_curve_id(const wc_CryptoInfo *info) { - return info->pk.eckg.curveId; -} -void* wolfcrypt_cryptocb_info_pk_eckg_rng(const wc_CryptoInfo *info) { - return info->pk.eckg.rng; -} -#endif /* HAVE_ECC */ - -/* -- Cipher AES-GCM enc/dec fields -- */ -#ifdef HAVE_AESGCM -void* wolfcrypt_cryptocb_info_cipher_aesgcm_enc_aes(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.aes; -} -unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_enc_out(wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.out; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_enc_in(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.in; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_enc_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.sz; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_enc_iv(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.iv; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_enc_iv_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.ivSz; -} -unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_tag(wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.authTag; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_tag_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.authTagSz; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_in(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.authIn; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_in_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_enc.authInSz; -} - -void* wolfcrypt_cryptocb_info_cipher_aesgcm_dec_aes(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.aes; -} -unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_dec_out(wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.out; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_dec_in(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.in; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_dec_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.sz; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_dec_iv(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.iv; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_dec_iv_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.ivSz; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_tag(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.authTag; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_tag_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.authTagSz; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_in(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.authIn; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_in_sz(const wc_CryptoInfo *info) { - return info->cipher.aesgcm_dec.authInSz; -} -#endif /* HAVE_AESGCM */ - -/* -- Cipher AES-CBC fields -- */ -#ifdef HAVE_AES_CBC -void* wolfcrypt_cryptocb_info_cipher_aescbc_aes(const wc_CryptoInfo *info) { - return info->cipher.aescbc.aes; -} -unsigned char* wolfcrypt_cryptocb_info_cipher_aescbc_out(wc_CryptoInfo *info) { - return info->cipher.aescbc.out; -} -const unsigned char* wolfcrypt_cryptocb_info_cipher_aescbc_in(const wc_CryptoInfo *info) { - return info->cipher.aescbc.in; -} -unsigned int wolfcrypt_cryptocb_info_cipher_aescbc_sz(const wc_CryptoInfo *info) { - return info->cipher.aescbc.sz; -} -#endif /* HAVE_AES_CBC */ - -/* -- Aes struct field accessors (for CryptoCb hardware implementations) -- - * devKey requires WOLF_CRYPTO_CB (already guaranteed by outer #ifdef). - * reg and keylen are always present in the Aes struct. */ -#ifndef NO_AES -unsigned int wolfcrypt_aes_keylen(const void *aes_ptr) { - return ((const Aes*)aes_ptr)->keylen; -} -const unsigned char* wolfcrypt_aes_devkey(const void *aes_ptr) { - return (const unsigned char*)((const Aes*)aes_ptr)->devKey; -} -const unsigned char* wolfcrypt_aes_reg(const void *aes_ptr) { - return (const unsigned char*)((const Aes*)aes_ptr)->reg; -} -unsigned char* wolfcrypt_aes_reg_mut(void *aes_ptr) { - return (unsigned char*)((Aes*)aes_ptr)->reg; -} -#endif /* !NO_AES */ - #endif /* WOLF_CRYPTO_CB */ - -/* ============================================================ - * Native SHA-256 / SHA-384 heap-allocated context shims. - * - * These wrappers let Rust code manage SHA state without knowing - * the layout of wc_Sha256 or wc_Sha512 (which changes between - * wolfSSL builds and target architectures). The context is - * heap-allocated via XMALLOC so the Rust side only ever holds - * an opaque *mut c_void. - * - * Used by wolfcrypt/src/digest.rs when OPENSSL_EXTRA is absent - * (i.e. the cryptocb-only firmware build). - * ============================================================ */ - -#ifndef NO_SHA256 -#include - -void* wolfcrypt_sha256_ctx_new(void) { - wc_Sha256 *ctx = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha256(ctx) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha256_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha256Update((wc_Sha256*)ctx, data, len); -} - -int wolfcrypt_sha256_final(void *ctx, unsigned char *hash) { - return wc_Sha256Final((wc_Sha256*)ctx, hash); -} - -void wolfcrypt_sha256_free(void *ctx) { - wc_Sha256Free((wc_Sha256*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha256_copy(const void *src, void **dst_out) { - wc_Sha256 *dst = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha256Copy((wc_Sha256*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} -#endif /* !NO_SHA256 */ - -#ifdef WOLFSSL_SHA384 -#include - -void* wolfcrypt_sha384_ctx_new(void) { - wc_Sha384 *ctx = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha384(ctx) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha384_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha384Update((wc_Sha384*)ctx, data, len); -} - -int wolfcrypt_sha384_final(void *ctx, unsigned char *hash) { - return wc_Sha384Final((wc_Sha384*)ctx, hash); -} - -void wolfcrypt_sha384_free(void *ctx) { - wc_Sha384Free((wc_Sha384*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha384_copy(const void *src, void **dst_out) { - wc_Sha384 *dst = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha384Copy((wc_Sha384*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} -#endif /* WOLFSSL_SHA384 */ - -/* ================================================================ - * Native HMAC shims (wc_Hmac* API, no OPENSSL_EXTRA required). - * ================================================================ */ -#if !defined(NO_HMAC) - -#include - -static void* wolfcrypt_hmac_new_impl(int type, const unsigned char* key, unsigned int keylen) { - Hmac *ctx = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ctx == NULL) return NULL; - if (wc_HmacInit(ctx, NULL, INVALID_DEVID) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - if (wc_HmacSetKey(ctx, type, key, keylen) != 0) { - wc_HmacFree(ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -void* wolfcrypt_hmac_sha1_new(const unsigned char* key, unsigned int keylen) { - return wolfcrypt_hmac_new_impl(WC_SHA, key, keylen); -} - -void* wolfcrypt_hmac_sha256_new(const unsigned char* key, unsigned int keylen) { - return wolfcrypt_hmac_new_impl(WC_SHA256, key, keylen); -} - -#ifdef WOLFSSL_SHA384 -void* wolfcrypt_hmac_sha384_new(const unsigned char* key, unsigned int keylen) { - return wolfcrypt_hmac_new_impl(WC_SHA384, key, keylen); -} -#endif - -#ifdef WOLFSSL_SHA512 -void* wolfcrypt_hmac_sha512_new(const unsigned char* key, unsigned int keylen) { - return wolfcrypt_hmac_new_impl(WC_SHA512, key, keylen); -} -#endif - -int wolfcrypt_hmac_update(void* ctx, const unsigned char* data, unsigned int len) { - return wc_HmacUpdate((Hmac*)ctx, data, len); -} - -int wolfcrypt_hmac_final(void* ctx, unsigned char* out) { - return wc_HmacFinal((Hmac*)ctx, out); -} - -void wolfcrypt_hmac_free(void* ctx) { - wc_HmacFree((Hmac*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -#endif /* !NO_HMAC */ - -#ifndef NO_SHA -#include - -void* wolfcrypt_sha1_ctx_new(void) { - wc_Sha *ctx = (wc_Sha*)XMALLOC(sizeof(wc_Sha), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha(ctx) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha1_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_ShaUpdate((wc_Sha*)ctx, data, len); -} - -int wolfcrypt_sha1_final(void *ctx, unsigned char *hash) { - return wc_ShaFinal((wc_Sha*)ctx, hash); -} - -void wolfcrypt_sha1_free(void *ctx) { - wc_ShaFree((wc_Sha*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha1_copy(const void *src, void **dst_out) { - wc_Sha *dst = (wc_Sha*)XMALLOC(sizeof(wc_Sha), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_ShaCopy((wc_Sha*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} -#endif /* !NO_SHA */ - -#ifdef WOLFSSL_SHA224 -/* wc_Sha224 is defined in sha256.h in wolfSSL */ -#include - -void* wolfcrypt_sha224_ctx_new(void) { - wc_Sha224 *ctx = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha224(ctx) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha224_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha224Update((wc_Sha224*)ctx, data, len); -} - -int wolfcrypt_sha224_final(void *ctx, unsigned char *hash) { - return wc_Sha224Final((wc_Sha224*)ctx, hash); -} - -void wolfcrypt_sha224_free(void *ctx) { - wc_Sha224Free((wc_Sha224*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha224_copy(const void *src, void **dst_out) { - wc_Sha224 *dst = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha224Copy((wc_Sha224*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} -#endif /* WOLFSSL_SHA224 */ - -#ifdef WOLFSSL_SHA512 -#include - -void* wolfcrypt_sha512_ctx_new(void) { - wc_Sha512 *ctx = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha512(ctx) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha512_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha512Update((wc_Sha512*)ctx, data, len); -} - -int wolfcrypt_sha512_final(void *ctx, unsigned char *hash) { - return wc_Sha512Final((wc_Sha512*)ctx, hash); -} - -void wolfcrypt_sha512_free(void *ctx) { - wc_Sha512Free((wc_Sha512*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha512_copy(const void *src, void **dst_out) { - wc_Sha512 *dst = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha512Copy((wc_Sha512*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} - -#if !defined(WOLFSSL_NOSHA512_256) -void* wolfcrypt_sha512_256_ctx_new(void) { - wc_Sha512 *ctx = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha512_256(ctx) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha512_256_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha512_256Update((wc_Sha512*)ctx, data, len); -} - -int wolfcrypt_sha512_256_final(void *ctx, unsigned char *hash) { - return wc_Sha512_256Final((wc_Sha512*)ctx, hash); -} - -void wolfcrypt_sha512_256_free(void *ctx) { - wc_Sha512_256Free((wc_Sha512*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha512_256_copy(const void *src, void **dst_out) { - wc_Sha512 *dst = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha512_256Copy((wc_Sha512*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} -#endif /* !WOLFSSL_NOSHA512_256 */ - -#endif /* WOLFSSL_SHA512 */ - -#ifdef WOLFSSL_SHA3 -#include - -void* wolfcrypt_sha3_256_ctx_new(void) { - wc_Sha3 *ctx = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha3_256(ctx, NULL, INVALID_DEVID) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha3_256_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha3_256_Update((wc_Sha3*)ctx, data, len); -} - -int wolfcrypt_sha3_256_final(void *ctx, unsigned char *hash) { - return wc_Sha3_256_Final((wc_Sha3*)ctx, hash); -} - -void wolfcrypt_sha3_256_free(void *ctx) { - wc_Sha3_256_Free((wc_Sha3*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha3_256_copy(const void *src, void **dst_out) { - wc_Sha3 *dst = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha3_256_Copy((wc_Sha3*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} - -void* wolfcrypt_sha3_384_ctx_new(void) { - wc_Sha3 *ctx = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha3_384(ctx, NULL, INVALID_DEVID) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha3_384_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha3_384_Update((wc_Sha3*)ctx, data, len); -} - -int wolfcrypt_sha3_384_final(void *ctx, unsigned char *hash) { - return wc_Sha3_384_Final((wc_Sha3*)ctx, hash); -} - -void wolfcrypt_sha3_384_free(void *ctx) { - wc_Sha3_384_Free((wc_Sha3*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha3_384_copy(const void *src, void **dst_out) { - wc_Sha3 *dst = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha3_384_Copy((wc_Sha3*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} - -void* wolfcrypt_sha3_512_ctx_new(void) { - wc_Sha3 *ctx = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - if (wc_InitSha3_512(ctx, NULL, INVALID_DEVID) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_sha3_512_update(void *ctx, const unsigned char *data, unsigned int len) { - return wc_Sha3_512_Update((wc_Sha3*)ctx, data, len); -} - -int wolfcrypt_sha3_512_final(void *ctx, unsigned char *hash) { - return wc_Sha3_512_Final((wc_Sha3*)ctx, hash); -} - -void wolfcrypt_sha3_512_free(void *ctx) { - wc_Sha3_512_Free((wc_Sha3*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -int wolfcrypt_sha3_512_copy(const void *src, void **dst_out) { - wc_Sha3 *dst = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!dst) return MEMORY_E; - int rc = wc_Sha3_512_Copy((wc_Sha3*)src, dst); - if (rc != 0) { - XFREE(dst, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return rc; - } - *dst_out = dst; - return 0; -} -#endif /* WOLFSSL_SHA3 */ - -/* ================================================================ - * Native CMAC shims (wc_Cmac* API, no OPENSSL_EXTRA required). - * ================================================================ */ -#ifdef WOLFSSL_CMAC - -#include - -static void* wolfcrypt_cmac_new_impl(const unsigned char* key, unsigned int key_sz) { - Cmac *ctx = (Cmac*)XMALLOC(sizeof(Cmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ctx == NULL) return NULL; - if (wc_InitCmac(ctx, key, key_sz, WC_CMAC_AES, NULL) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -void* wolfcrypt_cmac_aes128_new(const unsigned char* key) { - return wolfcrypt_cmac_new_impl(key, 16); -} - -void* wolfcrypt_cmac_aes256_new(const unsigned char* key) { - return wolfcrypt_cmac_new_impl(key, 32); -} - -int wolfcrypt_cmac_update(void* ctx, const unsigned char* data, unsigned int len) { - return wc_CmacUpdate((Cmac*)ctx, data, len); -} - -int wolfcrypt_cmac_final(void* ctx, unsigned char* out, unsigned int* out_len) { - word32 sz = *out_len; - int rc = wc_CmacFinal((Cmac*)ctx, out, &sz); - *out_len = (unsigned int)sz; - return rc; -} - -void wolfcrypt_cmac_free(void* ctx) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -#endif /* WOLFSSL_CMAC */ - -/* ================================================================ - * Native 3DES shims (wc_Des3* API, no OPENSSL_EXTRA required). - * ================================================================ */ -#ifndef NO_DES3 - -#include - -void* wolfcrypt_des3_enc_new(const unsigned char* key, const unsigned char* iv) { - Des3 *ctx = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ctx == NULL) return NULL; - if (wc_Des3Init(ctx, NULL, INVALID_DEVID) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - if (wc_Des3_SetKey(ctx, key, iv, DES_ENCRYPTION) != 0) { - wc_Des3Free(ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -void* wolfcrypt_des3_dec_new(const unsigned char* key, const unsigned char* iv) { - Des3 *ctx = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ctx == NULL) return NULL; - if (wc_Des3Init(ctx, NULL, INVALID_DEVID) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - if (wc_Des3_SetKey(ctx, key, iv, DES_DECRYPTION) != 0) { - wc_Des3Free(ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - return ctx; -} - -int wolfcrypt_des3_cbc_encrypt(void* ctx, const unsigned char* in, unsigned char* out, unsigned int sz) { - return wc_Des3_CbcEncrypt((Des3*)ctx, out, in, sz); -} - -int wolfcrypt_des3_cbc_decrypt(void* ctx, const unsigned char* in, unsigned char* out, unsigned int sz) { - return wc_Des3_CbcDecrypt((Des3*)ctx, out, in, sz); -} - -void wolfcrypt_des3_free(void* ctx) { - wc_Des3Free((Des3*)ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -#endif /* !NO_DES3 */ - -/* ================================================================ - * Native DH shims (wc_Dh* API, no OPENSSL_EXTRA required). - * - * WC_FFDHE_2048 = 256, WC_FFDHE_3072 = 257, WC_FFDHE_4096 = 258 - * (values from wolfssl/wolfcrypt/dh.h) - * ================================================================ */ -#ifndef NO_DH - -#include - -typedef struct { - DhKey key; - WC_RNG rng; - byte priv[512]; - word32 privSz; - byte pub[512]; - word32 pubSz; - word32 groupSz; -} wolfcrypt_dh_ctx; - -void* wolfcrypt_dh_new(int name, unsigned int group_sz) { - wolfcrypt_dh_ctx *ctx = (wolfcrypt_dh_ctx*)XMALLOC(sizeof(*ctx), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - XMEMSET(ctx, 0, sizeof(*ctx)); - - if (wc_InitRng(&ctx->rng) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - if (wc_InitDhKey(&ctx->key) != 0) { - wc_FreeRng(&ctx->rng); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - if (wc_DhSetNamedKey(&ctx->key, name) != 0) { - wc_FreeDhKey(&ctx->key); - wc_FreeRng(&ctx->rng); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - ctx->groupSz = group_sz; - return ctx; -} - -int wolfcrypt_dh_generate_keypair(void* handle) { - wolfcrypt_dh_ctx *ctx = (wolfcrypt_dh_ctx*)handle; - ctx->privSz = (word32)sizeof(ctx->priv); - ctx->pubSz = (word32)sizeof(ctx->pub); - return wc_DhGenerateKeyPair(&ctx->key, &ctx->rng, - ctx->priv, &ctx->privSz, - ctx->pub, &ctx->pubSz); -} - -int wolfcrypt_dh_public_key(void* handle, unsigned char* out, unsigned int* out_len) { - wolfcrypt_dh_ctx *ctx = (wolfcrypt_dh_ctx*)handle; - if (*out_len < ctx->groupSz) { - *out_len = ctx->groupSz; - return BUFFER_E; - } - /* Left-pad with zeros to reach a fixed groupSz-byte output. */ - if (ctx->pubSz < ctx->groupSz) { - word32 pad = ctx->groupSz - ctx->pubSz; - XMEMSET(out, 0, pad); - XMEMCPY(out + pad, ctx->pub, ctx->pubSz); - } else { - XMEMCPY(out, ctx->pub, ctx->pubSz); - } - *out_len = ctx->groupSz; - return 0; -} - -int wolfcrypt_dh_agree(void* handle, const unsigned char* peer_pub, - unsigned int peer_pub_sz, unsigned char* secret, - unsigned int* secret_sz) { - wolfcrypt_dh_ctx *ctx = (wolfcrypt_dh_ctx*)handle; - byte tmp[512]; - word32 sz = (word32)sizeof(tmp); - - int rc = wc_DhAgree(&ctx->key, tmp, &sz, - ctx->priv, ctx->privSz, - peer_pub, peer_pub_sz); - if (rc != 0) { - wc_ForceZero(tmp, sizeof(tmp)); - return rc; - } - - if (*secret_sz < ctx->groupSz) { - wc_ForceZero(tmp, sizeof(tmp)); - *secret_sz = ctx->groupSz; - return BUFFER_E; - } - - /* Left-pad with zeros to groupSz bytes (matches DH_compute_key_padded). */ - if (sz < ctx->groupSz) { - word32 pad = ctx->groupSz - sz; - XMEMSET(secret, 0, pad); - XMEMCPY(secret + pad, tmp, sz); - } else { - XMEMCPY(secret, tmp, sz); - } - *secret_sz = ctx->groupSz; - wc_ForceZero(tmp, sizeof(tmp)); - return 0; -} - -void wolfcrypt_dh_free(void* handle) { - wolfcrypt_dh_ctx *ctx = (wolfcrypt_dh_ctx*)handle; - wc_ForceZero(ctx->priv, sizeof(ctx->priv)); - wc_FreeDhKey(&ctx->key); - wc_FreeRng(&ctx->rng); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -#endif /* !NO_DH */ - -/* ----------------------------------------------------------------- */ -/* RSA key lifecycle shims โ€” no OPENSSL_EXTRA required */ -/* ----------------------------------------------------------------- */ -#ifndef NO_RSA - -#include -#include -#include - -/* Maximum DigestInfo DER size: SEQUENCE { SEQUENCE{OID,NULL} OCTET-STRING{hash} } - * SHA-512 (64 bytes) + ~20 bytes ASN.1 overhead = 83 bytes; 128 is safe. */ -#define WOLFCRYPT_MAX_DIGEST_INFO_SZ 128 - -/* Map our stable hash-bit-width codes (256/384/512) to wolfSSL enum values. - * Using enum names avoids coupling Rust to wolfSSL's internal integer values, - * which differ between FIPS and non-FIPS builds. */ -static enum wc_HashType wolfcrypt_rsa_hash_wc_type(int hash_bits) -{ - switch (hash_bits) { -#ifndef NO_SHA - case 160: return WC_HASH_TYPE_SHA; -#endif - case 256: return WC_HASH_TYPE_SHA256; - case 384: return WC_HASH_TYPE_SHA384; - case 512: return WC_HASH_TYPE_SHA512; - default: return WC_HASH_TYPE_NONE; - } -} - -/* Map hash_bits to the corresponding MGF1 constant (WC_MGF1SHA*). - * Returns -1 for unsupported hash sizes. */ -static int wolfcrypt_rsa_hash_mgf(int hash_bits) -{ - switch (hash_bits) { - case 256: return WC_MGF1SHA256; - case 384: return WC_MGF1SHA384; - case 512: return WC_MGF1SHA512; - default: return -1; - } -} - -typedef struct { - RsaKey key; - WC_RNG rng; -} wolfcrypt_rsa_ctx; - -void* wolfcrypt_rsa_new(void) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)XMALLOC(sizeof(*ctx), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!ctx) return NULL; - XMEMSET(ctx, 0, sizeof(*ctx)); - - if (wc_InitRsaKey(&ctx->key, NULL) != 0) { - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - if (wc_InitRng(&ctx->rng) != 0) { - wc_FreeRsaKey(&ctx->key); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } -#ifndef WC_NO_RNG - /* Associate the RNG so that wolfCrypt internal RNG calls work. */ - wc_RsaSetRNG(&ctx->key, &ctx->rng); -#endif - return ctx; -} - -void wolfcrypt_rsa_free(void* handle) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - if (!ctx) return; - wc_FreeRsaKey(&ctx->key); - wc_FreeRng(&ctx->rng); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); -} - -#ifdef WOLFSSL_KEY_GEN -int wolfcrypt_rsa_generate(void* handle, int bits) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - return wc_MakeRsaKey(&ctx->key, bits, WC_RSA_EXPONENT, &ctx->rng); -} -#else -int wolfcrypt_rsa_generate(void* handle, int bits) { - (void)handle; (void)bits; - return NOT_COMPILED_IN; -} -#endif /* WOLFSSL_KEY_GEN */ - -int wolfcrypt_rsa_import_private_pkcs1(void* handle, const byte* der, word32 der_len) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - word32 idx = 0; - int rc = wc_RsaPrivateKeyDecode(der, &idx, &ctx->key, der_len); - if (rc != 0) return rc; -#ifndef WC_NO_RNG - /* Re-attach RNG after import so randomised operations (PSS, OAEP) work. */ - wc_RsaSetRNG(&ctx->key, &ctx->rng); -#endif - return 0; -} - -int wolfcrypt_rsa_import_public_spki(void* handle, const byte* der, word32 der_len) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - word32 idx = 0; - /* wc_RsaPublicKeyDecode accepts SubjectPublicKeyInfo (SPKI) DER. */ - return wc_RsaPublicKeyDecode(der, &idx, &ctx->key, der_len); -} - -/* wolfcrypt_rsa_export_* require WOLFSSL_KEY_TO_DER in user_settings.h. */ -#ifdef WOLFSSL_KEY_TO_DER - -int wolfcrypt_rsa_export_private_pkcs1(void* handle, byte* out, word32* out_len) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - /* wc_RsaKeyToDer: pass out=NULL to query required size. - * Returns bytes written (>0) on success, negative error code on failure. */ - int rc = wc_RsaKeyToDer(&ctx->key, out, out ? *out_len : 0); - if (rc < 0) return rc; - *out_len = (word32)rc; - return 0; -} - -int wolfcrypt_rsa_export_public_spki(void* handle, byte* out, word32* out_len) { - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - /* wc_RsaKeyToPublicDer outputs SubjectPublicKeyInfo (SPKI) DER - * (with_header implicitly = 1). */ - int rc = wc_RsaKeyToPublicDer(&ctx->key, out, out ? *out_len : 0); - if (rc < 0) return rc; - *out_len = (word32)rc; - return 0; -} - -#else /* !WOLFSSL_KEY_TO_DER */ - -int wolfcrypt_rsa_export_private_pkcs1(void* handle, byte* out, word32* out_len) { - (void)handle; (void)out; (void)out_len; - return NOT_COMPILED_IN; -} - -int wolfcrypt_rsa_export_public_spki(void* handle, byte* out, word32* out_len) { - (void)handle; (void)out; (void)out_len; - return NOT_COMPILED_IN; -} - -#endif /* WOLFSSL_KEY_TO_DER */ - -int wolfcrypt_rsa_key_size_bytes(void* handle) { - const wolfcrypt_rsa_ctx *ctx = (const wolfcrypt_rsa_ctx*)handle; - return wc_RsaEncryptSize(&ctx->key); -} - -/* Encrypt `pt_len` bytes from `pt` using OAEP with SHA-256/MGF1-SHA256. - * `out` must point to a buffer of at least wolfcrypt_rsa_key_size_bytes(handle) - * bytes. On success returns the ciphertext length (== key size in bytes). */ -int wolfcrypt_rsa_oaep_encrypt_sha256(void* handle, - const byte* pt, word32 pt_len, - byte* out, word32 out_buf_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - return wc_RsaPublicEncrypt_ex(pt, pt_len, out, out_buf_len, &ctx->key, - &ctx->rng, WC_RSA_OAEP_PAD, - WC_HASH_TYPE_SHA256, WC_MGF1SHA256, - NULL, 0); -} - -/* Decrypt `ct_len` bytes from `ct` using OAEP with SHA-256/MGF1-SHA256. - * `out` must point to a buffer of at least wolfcrypt_rsa_key_size_bytes(handle) - * bytes. On success returns the plaintext length (>0). */ -int wolfcrypt_rsa_oaep_decrypt_sha256(void* handle, - const byte* ct, word32 ct_len, - byte* out, word32 out_buf_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - return wc_RsaPrivateDecrypt_ex(ct, ct_len, out, out_buf_len, &ctx->key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, - WC_MGF1SHA256, NULL, 0); -} - -/* Encrypt `in_len` bytes from `in` using PKCS#1v1.5 padding (RSA public-key op). - * `out` must be at least wolfcrypt_rsa_key_size_bytes(handle) bytes. - * Returns ciphertext length (== key modulus size) on success, negative on error. - * Follows the same convention as wolfcrypt_rsa_oaep_encrypt_sha256. */ -int wolfcrypt_rsa_pkcs1v15_encrypt(void* handle, - const byte* in, word32 in_len, - byte* out, word32 out_buf_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - return wc_RsaPublicEncrypt(in, in_len, out, out_buf_len, - &ctx->key, &ctx->rng); -} - -/* Decrypt `in_len` bytes from `in` using PKCS#1v1.5 padding (RSA private-key op). - * `out` must be at least wolfcrypt_rsa_key_size_bytes(handle) bytes. - * Returns plaintext length (> 0) on success, 0 or negative on error. - * Callers must check rc <= 0 for failure (matches EVP_PKEY_decrypt semantics). - * NOTE: wolfSSL built with WOLFSSL_RSA_DECRYPT_TO_0_LEN returns 0 for both - * invalid padding and valid empty plaintext; callers treat 0 as failure. */ -int wolfcrypt_rsa_pkcs1v15_decrypt(void* handle, - const byte* in, word32 in_len, - byte* out, word32 out_buf_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - return wc_RsaPrivateDecrypt(in, in_len, out, out_buf_len, &ctx->key); -} - -/* Encrypt `in_len` bytes from `in` using OAEP padding with explicit hash. - * hash_bits selects the OAEP hash and MGF1 hash: 256, 384, or 512. - * `out` must be at least wolfcrypt_rsa_key_size_bytes(handle) bytes. - * Returns ciphertext length on success, negative on error. */ -int wolfcrypt_rsa_oaep_encrypt(void* handle, int hash_bits, - const byte* in, word32 in_len, - byte* out, word32 out_buf_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - enum wc_HashType hash_type = wolfcrypt_rsa_hash_wc_type(hash_bits); - int mgf = wolfcrypt_rsa_hash_mgf(hash_bits); - if (hash_type == WC_HASH_TYPE_NONE || mgf < 0) return BAD_FUNC_ARG; - return wc_RsaPublicEncrypt_ex(in, in_len, out, out_buf_len, &ctx->key, - &ctx->rng, WC_RSA_OAEP_PAD, - hash_type, mgf, NULL, 0); -} - -/* Decrypt `in_len` bytes from `in` using OAEP padding with explicit hash. - * hash_bits selects the OAEP hash and MGF1 hash: 256, 384, or 512. - * `out` must be at least wolfcrypt_rsa_key_size_bytes(handle) bytes. - * Returns plaintext length (>= 0) on success, negative on error. - * Callers must check rc <= 0 for failure. */ -int wolfcrypt_rsa_oaep_decrypt(void* handle, int hash_bits, - const byte* in, word32 in_len, - byte* out, word32 out_buf_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - enum wc_HashType hash_type = wolfcrypt_rsa_hash_wc_type(hash_bits); - int mgf = wolfcrypt_rsa_hash_mgf(hash_bits); - if (hash_type == WC_HASH_TYPE_NONE || mgf < 0) return BAD_FUNC_ARG; - return wc_RsaPrivateDecrypt_ex(in, in_len, out, out_buf_len, &ctx->key, - WC_RSA_OAEP_PAD, hash_type, mgf, NULL, 0); -} - -/* Sign `msg_len` bytes from `msg` using RSA-PKCS#1v1.5. - * - * hash_bits: 256, 384, or 512 โ€” selects SHA-256/384/512 as the hash. - * sig must point to a buffer of at least wolfcrypt_rsa_key_size_bytes() bytes. - * On success, *sig_len is set to the signature length and returns 0. - * On error returns a negative wolfCrypt error code. */ -int wolfcrypt_rsa_pkcs1v15_sign(void* handle, - int hash_bits, - const byte* msg, word32 msg_len, - byte* sig, word32* sig_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - enum wc_HashType hash_type; - byte hash[WC_MAX_DIGEST_SIZE]; - byte digest_info[WOLFCRYPT_MAX_DIGEST_INFO_SZ]; - word32 hash_len; - word32 encoded_len; - int oid; - int rc; - - hash_type = wolfcrypt_rsa_hash_wc_type(hash_bits); - if (hash_type == WC_HASH_TYPE_NONE) - return BAD_FUNC_ARG; - - rc = wc_HashGetDigestSize(hash_type); - if (rc <= 0) return BAD_FUNC_ARG; - hash_len = (word32)rc; - - oid = wc_HashGetOID(hash_type); - if (oid < 0) return oid; - - /* Hash the message. */ - rc = wc_Hash(hash_type, msg, msg_len, hash, hash_len); - if (rc != 0) return rc; - - /* Build DigestInfo DER: SEQUENCE { AlgorithmIdentifier OCTET-STRING{hash} } - * wc_EncodeSignature(out, digest, digest_len, hashOID) writes the full - * DER to `out`, which must be at least WOLFCRYPT_MAX_DIGEST_INFO_SZ bytes. */ - encoded_len = wc_EncodeSignature(digest_info, hash, hash_len, oid); - if (encoded_len == 0) return BAD_FUNC_ARG; - - /* RSA-sign the DigestInfo with PKCS#1v1.5 padding. */ - rc = wc_RsaSSL_Sign(digest_info, encoded_len, sig, *sig_len, - &ctx->key, &ctx->rng); - if (rc < 0) return rc; - *sig_len = (word32)rc; - return 0; -} - -/* Verify an RSA-PKCS#1v1.5 signature. - * - * hash_bits: 256, 384, or 512. - * Returns 0 if signature is valid, SIG_VERIFY_E if invalid, - * or another negative wolfCrypt error code on failure. - * - * wc_RsaSSL_VerifyInline modifies the signature buffer in-place, so - * a local copy of sig is made to avoid clobbering the caller's buffer. */ -int wolfcrypt_rsa_pkcs1v15_verify(void* handle, - int hash_bits, - const byte* msg, word32 msg_len, - const byte* sig, word32 sig_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - enum wc_HashType hash_type; - byte hash[WC_MAX_DIGEST_SIZE]; - byte expected_di[WOLFCRYPT_MAX_DIGEST_INFO_SZ]; - /* SP math max key = 4096 bits = 512 bytes. */ - byte sig_copy[512]; - byte *decrypted; - word32 hash_len; - word32 expected_len; - int oid; - int rc; - - if (sig_len > sizeof(sig_copy)) return BAD_FUNC_ARG; - - hash_type = wolfcrypt_rsa_hash_wc_type(hash_bits); - if (hash_type == WC_HASH_TYPE_NONE) return BAD_FUNC_ARG; - - rc = wc_HashGetDigestSize(hash_type); - if (rc <= 0) return BAD_FUNC_ARG; - hash_len = (word32)rc; - - oid = wc_HashGetOID(hash_type); - if (oid < 0) return oid; - - /* Hash the message to build the expected DigestInfo. */ - rc = wc_Hash(hash_type, msg, msg_len, hash, hash_len); - if (rc != 0) return rc; - - expected_len = wc_EncodeSignature(expected_di, hash, hash_len, oid); - if (expected_len == 0) return BAD_FUNC_ARG; - - /* RSA-decrypt the signature inline (modifies sig_copy in-place, - * sets decrypted to point into sig_copy at the decrypted DigestInfo). */ - XMEMCPY(sig_copy, sig, sig_len); - rc = wc_RsaSSL_VerifyInline(sig_copy, sig_len, &decrypted, &ctx->key); - if (rc < 0) return rc; - - /* Constant-time comparison of decrypted DigestInfo with expected. */ - if ((word32)rc != expected_len || - XMEMCMP(decrypted, expected_di, expected_len) != 0) { - return SIG_VERIFY_E; - } - return 0; -} - -#ifdef WC_RSA_PSS - -/* Sign `msg_len` bytes from `msg` using RSA-PSS. - * - * hash_bits: 256, 384, or 512. - * Salt length is set to WC_RSA_PSS_SALTLEN_DIGEST (-1), meaning the salt - * equals the hash output length. This matches OpenSSL RSA_PSS_SALTLEN_DIGEST. - * sig must point to a buffer of at least wolfcrypt_rsa_key_size_bytes() bytes. - * On success, *sig_len is set to the signature length and returns 0. - * PSS signing is randomised: each call produces a different signature. */ -int wolfcrypt_rsa_pss_sign(void* handle, - int hash_bits, - const byte* msg, word32 msg_len, - byte* sig, word32* sig_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - enum wc_HashType hash_type; - byte hash[WC_MAX_DIGEST_SIZE]; - word32 hash_len; - int mgf; - int rc; - - hash_type = wolfcrypt_rsa_hash_wc_type(hash_bits); - if (hash_type == WC_HASH_TYPE_NONE) return BAD_FUNC_ARG; - - rc = wc_HashGetDigestSize(hash_type); - if (rc <= 0) return BAD_FUNC_ARG; - hash_len = (word32)rc; - - mgf = wolfcrypt_rsa_hash_mgf(hash_bits); - if (mgf < 0) return BAD_FUNC_ARG; - - /* Hash the message. */ - rc = wc_Hash(hash_type, msg, msg_len, hash, hash_len); - if (rc != 0) return rc; - - /* Sign the hash with PSS padding. wc_RsaPSS_Sign_ex expects the - * pre-hashed message as `in`. Salt = WC_RSA_PSS_SALTLEN_DIGEST = hash_len. */ - rc = wc_RsaPSS_Sign_ex(hash, hash_len, sig, *sig_len, - hash_type, mgf, WC_RSA_PSS_SALTLEN_DIGEST, - &ctx->key, &ctx->rng); - if (rc < 0) return rc; - *sig_len = (word32)rc; - return 0; -} - -/* Verify an RSA-PSS signature. - * - * hash_bits: 256, 384, or 512. - * Returns 0 if signature is valid, negative wolfCrypt error code otherwise. - * - * wc_RsaPSS_VerifyCheck computes the PSS decryption internally and checks - * the padding against the provided message digest. It assumes salt length - * equals the hash length, matching our signing convention. */ -int wolfcrypt_rsa_pss_verify(void* handle, - int hash_bits, - const byte* msg, word32 msg_len, - const byte* sig, word32 sig_len) -{ - wolfcrypt_rsa_ctx *ctx = (wolfcrypt_rsa_ctx*)handle; - enum wc_HashType hash_type; - byte hash[WC_MAX_DIGEST_SIZE]; - /* wc_RsaPSS_VerifyCheck needs a writable output buffer for the PSS block. */ - byte decrypted[512]; - word32 hash_len; - int mgf; - int rc; - - if (sig_len > sizeof(decrypted)) return BAD_FUNC_ARG; - - hash_type = wolfcrypt_rsa_hash_wc_type(hash_bits); - if (hash_type == WC_HASH_TYPE_NONE) return BAD_FUNC_ARG; - - rc = wc_HashGetDigestSize(hash_type); - if (rc <= 0) return BAD_FUNC_ARG; - hash_len = (word32)rc; - - mgf = wolfcrypt_rsa_hash_mgf(hash_bits); - if (mgf < 0) return BAD_FUNC_ARG; - - /* Hash the message to obtain the digest for comparison. */ - rc = wc_Hash(hash_type, msg, msg_len, hash, hash_len); - if (rc != 0) return rc; - - /* wc_RsaPSS_VerifyCheck: RSA-decrypt the signature, strip PSS padding, - * and compare the embedded hash against `hash`. - * NOTE: on success this returns the decrypted block size (positive), NOT 0. - * Normalize to 0 = success, negative = error. */ - rc = wc_RsaPSS_VerifyCheck(sig, sig_len, decrypted, sizeof(decrypted), - hash, hash_len, hash_type, mgf, &ctx->key); - if (rc < 0) return rc; - return 0; -} - -#endif /* WC_RSA_PSS */ - -#endif /* !NO_RSA */ diff --git a/wolfcrypt-rs/src/lib.rs b/wolfcrypt-rs/src/lib.rs index fe48df4..eb77fc7 100644 --- a/wolfcrypt-rs/src/lib.rs +++ b/wolfcrypt-rs/src/lib.rs @@ -32,10 +32,8 @@ use core::ffi::{c_uint, c_long, c_ulong}; // All allocation sizes are defined here as named constants. /// Allocation size for wolfSSL's `WOLFSSL_AES_KEY` (OpenSSL compat). -/// Sized to accommodate the struct with WOLF_CRYPTO_CB enabled (adds devId, -/// devCtx, devKey fields): โ‰ˆ452 bytes on riscv32, โ‰ˆ400 bytes on x86_64. #[cfg(wolfssl_openssl_extra)] -pub const AES_KEY_ALLOC_SIZE: usize = 512; +pub const AES_KEY_ALLOC_SIZE: usize = 352; /// Allocation size for wolfCrypt's `Aes` struct. pub const WC_AES_ALLOC_SIZE: usize = 512; /// Allocation size for wolfCrypt's `WC_RNG` struct. @@ -607,7 +605,6 @@ pub enum point_conversion_form_t { extern "C" { // wolfCrypt RNG pub fn wc_InitRng(rng: *mut WC_RNG) -> c_int; - pub fn wc_InitRng_ex(rng: *mut WC_RNG, heap: *mut c_void, devId: c_int) -> c_int; pub fn wc_RNG_GenerateBlock(rng: *mut WC_RNG, output: *mut u8, sz: u32) -> c_int; pub fn wc_FreeRng(rng: *mut WC_RNG) -> c_int; @@ -625,12 +622,6 @@ extern "C" { dir: c_int, ) -> c_int; - // AES block modes (native) - pub fn wc_AesCbcEncrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; - pub fn wc_AesCbcDecrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; - pub fn wc_AesEcbEncrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; - pub fn wc_AesEcbDecrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; - // Error strings pub fn wc_GetErrorString(error: c_int) -> *const c_char; @@ -672,250 +663,6 @@ extern "C" { pub fn SHA512(data: *const u8, len: usize, md: *mut u8) -> *mut u8; } -// ============================================================ -// Native wolfCrypt SHA functions (no OPENSSL_EXTRA required). -// -// wc_Sha256Hash / wc_Sha384Hash are one-shot convenience wrappers -// in sha256.c / sha512.c. The wolfcrypt_sha256_* / wolfcrypt_sha384_* -// shims are heap-allocated streaming contexts defined in compat_shim.c. -// Both sets are available in any build that includes sha256.c/sha512.c -// (controlled by NO_SHA256 / WOLFSSL_SHA384 in user_settings.h). -// ============================================================ - -#[cfg(wolfssl_sha256)] -extern "C" { - /// Hash `len` bytes of `data` into the 32-byte buffer `hash`. - #[link_name = "wc_Sha256Hash"] - pub fn wc_Sha256Hash(data: *const u8, len: u32, hash: *mut u8) -> c_int; - - /// Allocate and init a heap-managed SHA-256 context. Returns null on OOM. - pub fn wolfcrypt_sha256_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha256_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha256_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha256_free(ctx: *mut c_void); - pub fn wolfcrypt_sha256_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; -} - -#[cfg(wolfssl_sha384)] -extern "C" { - /// Hash `len` bytes of `data` into the 48-byte buffer `hash`. - #[link_name = "wc_Sha384Hash"] - pub fn wc_Sha384Hash(data: *const u8, len: u32, hash: *mut u8) -> c_int; - - /// Allocate and init a heap-managed SHA-384 context. Returns null on OOM. - pub fn wolfcrypt_sha384_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha384_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha384_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha384_free(ctx: *mut c_void); - pub fn wolfcrypt_sha384_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; -} - -#[cfg(wolfssl_des3)] -extern "C" { - pub fn wolfcrypt_des3_enc_new(key: *const u8, iv: *const u8) -> *mut c_void; - pub fn wolfcrypt_des3_dec_new(key: *const u8, iv: *const u8) -> *mut c_void; - pub fn wolfcrypt_des3_cbc_encrypt(ctx: *mut c_void, in_: *const u8, out: *mut u8, sz: u32) -> c_int; - pub fn wolfcrypt_des3_cbc_decrypt(ctx: *mut c_void, in_: *const u8, out: *mut u8, sz: u32) -> c_int; - pub fn wolfcrypt_des3_free(ctx: *mut c_void); -} - -#[cfg(wolfssl_dh)] -extern "C" { - pub fn wolfcrypt_dh_new(name: c_int, group_sz: u32) -> *mut c_void; - pub fn wolfcrypt_dh_generate_keypair(handle: *mut c_void) -> c_int; - pub fn wolfcrypt_dh_public_key(handle: *mut c_void, out: *mut u8, out_len: *mut u32) -> c_int; - pub fn wolfcrypt_dh_agree(handle: *mut c_void, peer_pub: *const u8, peer_pub_sz: u32, secret: *mut u8, secret_sz: *mut u32) -> c_int; - pub fn wolfcrypt_dh_free(handle: *mut c_void); -} - -#[cfg(wolfssl_rsa)] -extern "C" { - /// Allocate and initialise a wolfcrypt_rsa_ctx (RsaKey + WC_RNG). - /// Returns NULL on allocation or initialisation failure. - pub fn wolfcrypt_rsa_new() -> *mut c_void; - /// Free a context returned by wolfcrypt_rsa_new. - pub fn wolfcrypt_rsa_free(ctx: *mut c_void); - /// Generate an RSA key pair of `bits` bits (e.g. 2048, 3072, 4096). - /// Requires WOLFSSL_KEY_GEN; returns NOT_COMPILED_IN otherwise. - pub fn wolfcrypt_rsa_generate(ctx: *mut c_void, bits: c_int) -> c_int; - /// Import a private key from PKCS#1 RSAPrivateKey DER. - pub fn wolfcrypt_rsa_import_private_pkcs1(ctx: *mut c_void, der: *const u8, der_len: u32) -> c_int; - /// Import a public key from SubjectPublicKeyInfo (SPKI) DER. - pub fn wolfcrypt_rsa_import_public_spki(ctx: *mut c_void, der: *const u8, der_len: u32) -> c_int; - /// Export private key as PKCS#1 RSAPrivateKey DER. - /// Pass out=NULL to query the required buffer size (written to *out_len). - pub fn wolfcrypt_rsa_export_private_pkcs1(ctx: *mut c_void, out: *mut u8, out_len: *mut u32) -> c_int; - /// Export public key as SubjectPublicKeyInfo (SPKI) DER. - /// Pass out=NULL to query the required buffer size (written to *out_len). - pub fn wolfcrypt_rsa_export_public_spki(ctx: *mut c_void, out: *mut u8, out_len: *mut u32) -> c_int; - /// Return RSA modulus size in bytes (e.g. 256 for a 2048-bit key). - pub fn wolfcrypt_rsa_key_size_bytes(ctx: *const c_void) -> c_int; - /// OAEP-SHA256/MGF1-SHA256 encrypt. `out` must be at least key-size bytes. - /// Returns ciphertext length (== key size) on success, negative on error. - pub fn wolfcrypt_rsa_oaep_encrypt_sha256( - ctx: *mut c_void, - pt: *const u8, pt_len: u32, - out: *mut u8, out_buf_len: u32, - ) -> c_int; - /// OAEP-SHA256/MGF1-SHA256 decrypt. - /// Returns plaintext length (>0) on success, negative on error. - pub fn wolfcrypt_rsa_oaep_decrypt_sha256( - ctx: *mut c_void, - ct: *const u8, ct_len: u32, - out: *mut u8, out_buf_len: u32, - ) -> c_int; - /// PKCS#1v1.5 sign. `hash_bits` is 256, 384, or 512. - /// On success sets `*sig_len` to the signature length and returns 0. - pub fn wolfcrypt_rsa_pkcs1v15_sign( - ctx: *mut c_void, - hash_bits: c_int, - msg: *const u8, msg_len: u32, - sig: *mut u8, sig_len: *mut u32, - ) -> c_int; - /// PKCS#1v1.5 verify. `hash_bits` is 256, 384, or 512. - /// Returns 0 if valid, negative (SIG_VERIFY_E = -228) if invalid. - pub fn wolfcrypt_rsa_pkcs1v15_verify( - ctx: *mut c_void, - hash_bits: c_int, - msg: *const u8, msg_len: u32, - sig: *const u8, sig_len: u32, - ) -> c_int; - /// PSS sign. `hash_bits` is 256, 384, or 512. Salt = hash length. - /// On success sets `*sig_len` to the signature length and returns 0. - pub fn wolfcrypt_rsa_pss_sign( - ctx: *mut c_void, - hash_bits: c_int, - msg: *const u8, msg_len: u32, - sig: *mut u8, sig_len: *mut u32, - ) -> c_int; - /// PSS verify. `hash_bits` is 256, 384, or 512. - /// Returns 0 if valid, negative on error or invalid signature. - pub fn wolfcrypt_rsa_pss_verify( - ctx: *mut c_void, - hash_bits: c_int, - msg: *const u8, msg_len: u32, - sig: *const u8, sig_len: u32, - ) -> c_int; - /// PKCS#1v1.5 encrypt (public-key op). `out` must be at least key-size bytes. - /// Returns ciphertext length (== key size) on success, negative on error. - pub fn wolfcrypt_rsa_pkcs1v15_encrypt( - ctx: *mut c_void, - in_: *const u8, in_len: u32, - out: *mut u8, out_buf_len: u32, - ) -> c_int; - /// PKCS#1v1.5 decrypt (private-key op). `out` must be at least key-size bytes. - /// Returns plaintext length on success, 0 or negative on error. - /// Callers MUST check `rc <= 0` as failure (0 = constant-time padding error). - pub fn wolfcrypt_rsa_pkcs1v15_decrypt( - ctx: *mut c_void, - in_: *const u8, in_len: u32, - out: *mut u8, out_buf_len: u32, - ) -> c_int; - /// OAEP encrypt with explicit hash. `hash_bits` is 256, 384, or 512. - /// Returns ciphertext length on success, negative on error. - pub fn wolfcrypt_rsa_oaep_encrypt( - ctx: *mut c_void, - hash_bits: c_int, - in_: *const u8, in_len: u32, - out: *mut u8, out_buf_len: u32, - ) -> c_int; - /// OAEP decrypt with explicit hash. `hash_bits` is 256, 384, or 512. - /// Returns plaintext length on success, 0 or negative on error. - /// Callers MUST check `rc <= 0` as failure. - pub fn wolfcrypt_rsa_oaep_decrypt( - ctx: *mut c_void, - hash_bits: c_int, - in_: *const u8, in_len: u32, - out: *mut u8, out_buf_len: u32, - ) -> c_int; -} - -#[cfg(wolfssl_cmac)] -extern "C" { - pub fn wolfcrypt_cmac_aes128_new(key: *const u8) -> *mut c_void; - pub fn wolfcrypt_cmac_aes256_new(key: *const u8) -> *mut c_void; - pub fn wolfcrypt_cmac_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_cmac_final(ctx: *mut c_void, out: *mut u8, out_len: *mut u32) -> c_int; - pub fn wolfcrypt_cmac_free(ctx: *mut c_void); -} - -#[cfg(wolfssl_hmac)] -extern "C" { - pub fn wolfcrypt_hmac_sha1_new(key: *const u8, keylen: u32) -> *mut c_void; - pub fn wolfcrypt_hmac_sha256_new(key: *const u8, keylen: u32) -> *mut c_void; - pub fn wolfcrypt_hmac_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_hmac_final(ctx: *mut c_void, out: *mut u8) -> c_int; - pub fn wolfcrypt_hmac_free(ctx: *mut c_void); -} - -#[cfg(all(wolfssl_hmac, wolfssl_sha384))] -extern "C" { - pub fn wolfcrypt_hmac_sha384_new(key: *const u8, keylen: u32) -> *mut c_void; -} - -#[cfg(all(wolfssl_hmac, wolfssl_sha512))] -extern "C" { - pub fn wolfcrypt_hmac_sha512_new(key: *const u8, keylen: u32) -> *mut c_void; -} - -#[cfg(wolfssl_sha1)] -extern "C" { - pub fn wolfcrypt_sha1_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha1_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha1_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha1_free(ctx: *mut c_void); - pub fn wolfcrypt_sha1_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; -} - -#[cfg(wolfssl_sha224)] -extern "C" { - pub fn wolfcrypt_sha224_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha224_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha224_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha224_free(ctx: *mut c_void); - pub fn wolfcrypt_sha224_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; -} - -#[cfg(wolfssl_sha512)] -extern "C" { - /// Hash `len` bytes of `data` into the 64-byte buffer `hash`. - #[link_name = "wc_Sha512Hash"] - pub fn wc_Sha512Hash(data: *const u8, len: u32, hash: *mut u8) -> c_int; - - pub fn wolfcrypt_sha512_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha512_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha512_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha512_free(ctx: *mut c_void); - pub fn wolfcrypt_sha512_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; - - pub fn wolfcrypt_sha512_256_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha512_256_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha512_256_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha512_256_free(ctx: *mut c_void); - pub fn wolfcrypt_sha512_256_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; -} - -#[cfg(wolfssl_sha3)] -extern "C" { - pub fn wolfcrypt_sha3_256_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha3_256_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha3_256_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha3_256_free(ctx: *mut c_void); - pub fn wolfcrypt_sha3_256_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; - - pub fn wolfcrypt_sha3_384_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha3_384_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha3_384_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha3_384_free(ctx: *mut c_void); - pub fn wolfcrypt_sha3_384_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; - - pub fn wolfcrypt_sha3_512_ctx_new() -> *mut c_void; - pub fn wolfcrypt_sha3_512_update(ctx: *mut c_void, data: *const u8, len: u32) -> c_int; - pub fn wolfcrypt_sha3_512_final(ctx: *mut c_void, hash: *mut u8) -> c_int; - pub fn wolfcrypt_sha3_512_free(ctx: *mut c_void); - pub fn wolfcrypt_sha3_512_copy(src: *const c_void, dst: *mut *mut c_void) -> c_int; -} - // ============================================================ // OpenSSL compat layer: EVP, BN, ERR, CRYPTO, RAND, etc. // ============================================================ @@ -1462,39 +1209,6 @@ extern "C" { ) -> c_int; } -// Native wc_AesKeyWrap / wc_AesKeyUnWrap (no OPENSSL_EXTRA required). -// Gated on HAVE_AES_KEYWRAP โ†’ wolfssl_aes_keywrap. -// Signatures: (key, keySz, in, inSz, out, outSz, iv) -> c_int -// Returns: positive = bytes written (inSz + 8), negative = error. -// iv = NULL โ†’ default IV (0xA6A6A6A6 A6A6A6A6). - -#[cfg(wolfssl_aes_keywrap)] -extern "C" { - /// Wrap `inSz` bytes of key data under the `keySz`-byte KEK. - /// `iv` may be NULL to use the RFC 3394 default IV. - /// Returns the number of bytes written (`inSz + 8`) on success, - /// or a negative wolfCrypt error code on failure. - #[link_name = "wc_AesKeyWrap"] - pub fn wc_AesKeyWrap( - key: *const u8, keySz: u32, - in_: *const u8, inSz: u32, - out: *mut u8, outSz: u32, - iv: *const u8, - ) -> c_int; - - /// Unwrap `inSz` bytes of wrapped key data under the `keySz`-byte KEK. - /// `iv` may be NULL to use the RFC 3394 default IV. - /// Returns the number of bytes written (`inSz - 8`) on success, - /// or a negative wolfCrypt error code on failure. - #[link_name = "wc_AesKeyUnWrap"] - pub fn wc_AesKeyUnWrap( - key: *const u8, keySz: u32, - in_: *const u8, inSz: u32, - out: *mut u8, outSz: u32, - iv: *const u8, - ) -> c_int; -} - // AES Key Wrap with Padding (RFC 5649) โ€” C shims in compat_shim.c // wolfSSL does not provide the padded variants natively. @@ -1699,6 +1413,11 @@ extern "C" { #[link_name = "wolfSSL_ECDSA_do_verify"] pub fn ECDSA_do_verify(dgst: *const u8, dgst_len: c_int, sig: *const ECDSA_SIG, eckey: *mut EC_KEY) -> c_int; + // ---- ECDH ---- + + #[link_name = "wolfSSL_ECDH_compute_key"] + pub fn ECDH_compute_key(out: *mut c_void, outlen: usize, pub_key: *const EC_POINT, ecdh: *mut EC_KEY, kdf: *mut c_void) -> c_int; + // ---- EVP_PKEY EC integration ---- #[link_name = "wolfSSL_EVP_PKEY_assign_EC_KEY"] @@ -1882,7 +1601,6 @@ extern "C" { out: *mut u8, outLen: *mut u32, ) -> c_int; pub fn wc_ed25519_make_key(rng: *mut WC_RNG, keysize: c_int, key: *mut wc_ed25519_key) -> c_int; - pub fn wc_ed25519_check_key(key: *mut wc_ed25519_key) -> c_int; // Ed25519 DER encode/decode (PKCS#8 / SubjectPublicKeyInfo) // These use wolfCrypt's ASN.1 engine rather than hand-rolled parsing. @@ -2935,28 +2653,6 @@ extern "C" { pub fn wc_AesOfbDecrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; } -// ============================================================ -// AES-CFB (wolfCrypt native, uses existing WcAes struct) -// CFB-128: IV and partial-block counter are managed inside WcAes. -// Encrypt and decrypt are separate because CFB feedback differs -// per direction (unlike OFB/CTR which are symmetric). -// ============================================================ - -#[cfg(wolfssl_aes_cfb)] -extern "C" { - /// Encrypt `sz` bytes of `in_` into `out` using AES-CFB-128. - /// `aes` must be initialised with `wc_AesInit` + `wc_AesSetKey` - /// (direction = `AES_ENCRYPTION`; CFB always uses the encrypt schedule). - #[link_name = "wc_AesCfbEncrypt"] - pub fn wc_AesCfbEncrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; - - /// Decrypt `sz` bytes of `in_` into `out` using AES-CFB-128. - /// `aes` must be initialised with `wc_AesInit` + `wc_AesSetKey` - /// (direction = `AES_ENCRYPTION`; CFB always uses the encrypt schedule). - #[link_name = "wc_AesCfbDecrypt"] - pub fn wc_AesCfbDecrypt(aes: *mut WcAes, out: *mut u8, in_: *const u8, sz: u32) -> c_int; -} - // ============================================================ // AES-CTS (wolfCrypt native) // One-shot API takes raw key+IV; incremental API uses WcAes. @@ -3072,12 +2768,6 @@ extern "C" { ) -> c_int; #[link_name = "wc_ecc_export_x963"] pub fn wc_ecc_export_x963(key: *mut wc_ecc_key, out: *mut u8, outSz: *mut u32) -> c_int; - /// Derive the public key point from the private scalar already loaded into - /// `key`. Pass `pubOut = NULL` to update `key` in place. - /// Required after [`wc_ecc_import_private_key_ex`] with a NULL public key, - /// which leaves the key in `ECC_PRIVATEKEY_ONLY` state. - #[link_name = "wc_ecc_make_pub"] - pub fn wc_ecc_make_pub(key: *mut wc_ecc_key, pubOut: *mut c_void) -> c_int; #[link_name = "wc_ecc_import_x963"] pub fn wc_ecc_import_x963(in_: *const u8, inSz: u32, key: *mut wc_ecc_key) -> c_int; #[link_name = "wc_ecc_import_private_key"] @@ -3097,13 +2787,6 @@ extern "C" { pub fn wc_ecc_export_private_only(key: *mut wc_ecc_key, out: *mut u8, outSz: *mut u32) -> c_int; #[link_name = "wc_ecc_check_key"] pub fn wc_ecc_check_key(key: *mut wc_ecc_key) -> c_int; - /// Attach an RNG to an ECC key for use during scalar-multiplication blinding. - /// - /// Required when `ECC_TIMING_RESISTANT` is defined (the default): calling - /// `wc_ecc_shared_secret` without a prior `wc_ecc_set_rng` returns - /// `MISSING_RNG_E`. - #[link_name = "wc_ecc_set_rng"] - pub fn wc_ecc_set_rng(key: *mut wc_ecc_key, rng: *mut WC_RNG) -> c_int; #[link_name = "wc_ecc_get_curve_size_from_id"] pub fn wc_ecc_get_curve_size_from_id(curveId: c_int) -> c_int; @@ -3530,110 +3213,6 @@ extern "C" { // PK (public key) accessors pub fn wolfcrypt_cryptocb_info_pk_type(info: *const wc_CryptoInfo) -> c_int; - - // PK eccsign accessors - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccsign_in(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccsign_inlen(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccsign_out(info: *mut wc_CryptoInfo) -> *mut u8; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccsign_outlen(info: *mut wc_CryptoInfo) -> *mut u32; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccsign_key(info: *const wc_CryptoInfo) -> *mut c_void; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccsign_rng(info: *const wc_CryptoInfo) -> *mut c_void; - - // PK eccverify accessors - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccverify_sig(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccverify_siglen(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccverify_hash(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccverify_hashlen(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccverify_res(info: *mut wc_CryptoInfo) -> *mut c_int; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eccverify_key(info: *const wc_CryptoInfo) -> *mut c_void; - - // PK ecdh accessors - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_ecdh_private_key(info: *const wc_CryptoInfo) -> *mut c_void; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_ecdh_public_key(info: *const wc_CryptoInfo) -> *mut c_void; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_ecdh_out(info: *mut wc_CryptoInfo) -> *mut u8; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_ecdh_outlen(info: *mut wc_CryptoInfo) -> *mut u32; - - // PK eckg accessors - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eckg_key(info: *const wc_CryptoInfo) -> *mut c_void; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eckg_size(info: *const wc_CryptoInfo) -> c_int; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eckg_curve_id(info: *const wc_CryptoInfo) -> c_int; - #[cfg(wolfssl_ecc)] - pub fn wolfcrypt_cryptocb_info_pk_eckg_rng(info: *const wc_CryptoInfo) -> *mut c_void; - - // Cipher AES-GCM enc accessors - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_aes(info: *const wc_CryptoInfo) -> *mut c_void; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_out(info: *mut wc_CryptoInfo) -> *mut u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_in(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_sz(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_iv(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_iv_sz(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_tag(info: *mut wc_CryptoInfo) -> *mut u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_tag_sz(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_in(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_in_sz(info: *const wc_CryptoInfo) -> u32; - - // Cipher AES-GCM dec accessors - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_aes(info: *const wc_CryptoInfo) -> *mut c_void; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_out(info: *mut wc_CryptoInfo) -> *mut u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_in(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_sz(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_iv(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_iv_sz(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_tag(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_tag_sz(info: *const wc_CryptoInfo) -> u32; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_in(info: *const wc_CryptoInfo) -> *const u8; - #[cfg(wolfssl_aes_gcm)] - pub fn wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_in_sz(info: *const wc_CryptoInfo) -> u32; - - // Cipher AES-CBC accessors - pub fn wolfcrypt_cryptocb_info_cipher_aescbc_aes(info: *const wc_CryptoInfo) -> *mut c_void; - pub fn wolfcrypt_cryptocb_info_cipher_aescbc_out(info: *mut wc_CryptoInfo) -> *mut u8; - pub fn wolfcrypt_cryptocb_info_cipher_aescbc_in(info: *const wc_CryptoInfo) -> *const u8; - pub fn wolfcrypt_cryptocb_info_cipher_aescbc_sz(info: *const wc_CryptoInfo) -> u32; - - // Aes struct field accessors - pub fn wolfcrypt_aes_keylen(aes: *const c_void) -> u32; - pub fn wolfcrypt_aes_devkey(aes: *const c_void) -> *const u8; - pub fn wolfcrypt_aes_reg(aes: *const c_void) -> *const u8; - pub fn wolfcrypt_aes_reg_mut(aes: *mut c_void) -> *mut u8; } // ============================================================ @@ -3881,4 +3460,3 @@ mod tests { assert_eq!(wc_oid_sum(&[]), 0); } } - diff --git a/wolfcrypt-rs/tests/rsa_lifecycle.rs b/wolfcrypt-rs/tests/rsa_lifecycle.rs deleted file mode 100644 index 89fb948..0000000 --- a/wolfcrypt-rs/tests/rsa_lifecycle.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! Integration tests for wolfcrypt_rsa_* key lifecycle shims. -//! -//! These are the first tests that exercise the native wc_* RSA shims directly -//! (bypassing the EVP compat layer). They verify: -//! -//! 1. Key generation works and produces a correctly-sized key. -//! 2. Private key PKCS#1 DER round-trip: generate โ†’ export โ†’ re-import โ†’ export โ†’ bytes identical. -//! 3. Public key SPKI DER round-trip: generate โ†’ export public โ†’ re-import โ†’ export โ†’ bytes identical. -//! 4. Importing garbage DER returns a non-zero error code. -//! 5. wolfcrypt_rsa_free(NULL) does not crash. -//! -//! These tests run against the pre-built wolfSSL library (same as the rest of wolfcrypt-rs). - -#![cfg(wolfssl_rsa)] - -use std::ptr; -use wolfcrypt_rs::{ - wolfcrypt_rsa_export_private_pkcs1, wolfcrypt_rsa_export_public_spki, - wolfcrypt_rsa_free, wolfcrypt_rsa_generate, wolfcrypt_rsa_import_private_pkcs1, - wolfcrypt_rsa_import_public_spki, wolfcrypt_rsa_key_size_bytes, wolfcrypt_rsa_new, -}; - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -/// Export a private key as PKCS#1 DER, panicking on any failure. -unsafe fn export_private(ctx: *mut std::ffi::c_void) -> Vec { - // First call: query needed size. - let mut len = 0u32; - let rc = wolfcrypt_rsa_export_private_pkcs1(ctx, ptr::null_mut(), &mut len); - assert_eq!(rc, 0, "query private DER size failed: {rc}"); - assert!(len > 0, "private DER size query returned 0"); - - // Second call: write bytes. - let mut buf = vec![0u8; len as usize]; - let mut actual = len; - let rc = wolfcrypt_rsa_export_private_pkcs1(ctx, buf.as_mut_ptr(), &mut actual); - assert_eq!(rc, 0, "export private DER failed: {rc}"); - buf.truncate(actual as usize); - buf -} - -/// Export a public key as SPKI DER, panicking on any failure. -unsafe fn export_public_spki(ctx: *mut std::ffi::c_void) -> Vec { - let mut len = 0u32; - let rc = wolfcrypt_rsa_export_public_spki(ctx, ptr::null_mut(), &mut len); - assert_eq!(rc, 0, "query public SPKI size failed: {rc}"); - assert!(len > 0, "public SPKI size query returned 0"); - - let mut buf = vec![0u8; len as usize]; - let mut actual = len; - let rc = wolfcrypt_rsa_export_public_spki(ctx, buf.as_mut_ptr(), &mut actual); - assert_eq!(rc, 0, "export public SPKI failed: {rc}"); - buf.truncate(actual as usize); - buf -} - -// --------------------------------------------------------------------------- -// Tests -// --------------------------------------------------------------------------- - -/// Generate a 2048-bit RSA key and verify the modulus size is 256 bytes. -#[test] -fn rsa_key_size_bytes_2048() { - unsafe { - let ctx = wolfcrypt_rsa_new(); - assert!(!ctx.is_null(), "wolfcrypt_rsa_new returned NULL"); - let rc = wolfcrypt_rsa_generate(ctx, 2048); - assert_eq!(rc, 0, "wolfcrypt_rsa_generate(2048) failed: {rc}"); - let sz = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - assert_eq!(sz, 256, "expected 256 bytes for 2048-bit key; got {sz}"); - wolfcrypt_rsa_free(ctx); - } -} - -/// PKCS#1 private key DER round-trip: generate โ†’ export โ†’ re-import โ†’ export โ†’ bytes equal. -#[test] -fn rsa_private_key_roundtrip() { - unsafe { - let ctx = wolfcrypt_rsa_new(); - assert!(!ctx.is_null(), "wolfcrypt_rsa_new returned NULL"); - let rc = wolfcrypt_rsa_generate(ctx, 2048); - assert_eq!(rc, 0, "wolfcrypt_rsa_generate(2048) failed: {rc}"); - - let der1 = export_private(ctx); - assert!(der1.len() > 100, "private key DER suspiciously short: {} B", der1.len()); - // PKCS#1 RSAPrivateKey starts with SEQUENCE (0x30). - assert_eq!(der1[0], 0x30, "private key DER must start with SEQUENCE tag (0x30)"); - - // Re-import into a fresh context. - let ctx2 = wolfcrypt_rsa_new(); - assert!(!ctx2.is_null()); - let rc = wolfcrypt_rsa_import_private_pkcs1(ctx2, der1.as_ptr(), der1.len() as u32); - assert_eq!(rc, 0, "re-import private key failed: {rc}"); - - // Export again โ€” bytes must be identical. - let der2 = export_private(ctx2); - assert_eq!(der1, der2, "private key DER round-trip produced different bytes"); - - wolfcrypt_rsa_free(ctx2); - wolfcrypt_rsa_free(ctx); - } -} - -/// SPKI public key DER round-trip: generate โ†’ export public โ†’ re-import โ†’ export โ†’ bytes equal. -#[test] -fn rsa_public_key_spki_roundtrip() { - unsafe { - let ctx = wolfcrypt_rsa_new(); - assert!(!ctx.is_null()); - let rc = wolfcrypt_rsa_generate(ctx, 2048); - assert_eq!(rc, 0, "wolfcrypt_rsa_generate(2048) failed: {rc}"); - - let spki1 = export_public_spki(ctx); - assert!(spki1.len() > 20, "public SPKI suspiciously short: {} B", spki1.len()); - assert_eq!(spki1[0], 0x30, "public SPKI must start with SEQUENCE tag (0x30)"); - - // Import public key into a fresh context. - let ctx2 = wolfcrypt_rsa_new(); - assert!(!ctx2.is_null()); - let rc = wolfcrypt_rsa_import_public_spki(ctx2, spki1.as_ptr(), spki1.len() as u32); - assert_eq!(rc, 0, "import public SPKI failed: {rc}"); - - // Export again โ€” bytes must be identical. - let spki2 = export_public_spki(ctx2); - assert_eq!(spki1, spki2, "public SPKI round-trip produced different bytes"); - - wolfcrypt_rsa_free(ctx2); - wolfcrypt_rsa_free(ctx); - } -} - -/// Importing garbage DER must return a non-zero (error) code. -#[test] -fn rsa_import_garbage_private_fails() { - unsafe { - let ctx = wolfcrypt_rsa_new(); - assert!(!ctx.is_null()); - let garbage = [0xffu8; 128]; - let rc = wolfcrypt_rsa_import_private_pkcs1(ctx, garbage.as_ptr(), garbage.len() as u32); - assert_ne!(rc, 0, "import of garbage DER must fail, but returned 0"); - wolfcrypt_rsa_free(ctx); - } -} - -/// Importing garbage as SPKI must return a non-zero error. -#[test] -fn rsa_import_garbage_public_spki_fails() { - unsafe { - let ctx = wolfcrypt_rsa_new(); - assert!(!ctx.is_null()); - let garbage = [0x00u8; 64]; - let rc = wolfcrypt_rsa_import_public_spki(ctx, garbage.as_ptr(), garbage.len() as u32); - assert_ne!(rc, 0, "import of garbage SPKI must fail, but returned 0"); - wolfcrypt_rsa_free(ctx); - } -} - -/// wolfcrypt_rsa_free(NULL) must not crash. -#[test] -fn rsa_free_null_is_safe() { - unsafe { - wolfcrypt_rsa_free(ptr::null_mut()); - } -} - -/// Generating a key twice into the same context overwrites without leaking. -#[test] -fn rsa_generate_overwrites_key() { - unsafe { - let ctx = wolfcrypt_rsa_new(); - assert!(!ctx.is_null()); - - // First key generation - let rc = wolfcrypt_rsa_generate(ctx, 2048); - assert_eq!(rc, 0, "first generate failed: {rc}"); - let sz1 = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - assert_eq!(sz1, 256); - - // Export the first key - let der1 = export_private(ctx); - - // Free context and create a new one (to get a fresh key) - wolfcrypt_rsa_free(ctx); - - let ctx2 = wolfcrypt_rsa_new(); - assert!(!ctx2.is_null()); - let rc = wolfcrypt_rsa_generate(ctx2, 2048); - assert_eq!(rc, 0, "second generate failed: {rc}"); - let der2 = export_private(ctx2); - - // Two different generated keys should (overwhelmingly likely) differ - assert_ne!(der1, der2, "two independently generated keys should differ"); - - wolfcrypt_rsa_free(ctx2); - } -} diff --git a/wolfcrypt-sys/Cargo.toml b/wolfcrypt-sys/Cargo.toml index 2084daa..c63b19c 100644 --- a/wolfcrypt-sys/Cargo.toml +++ b/wolfcrypt-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wolfcrypt-sys" authors = ["WolfSSL Inc"] -version = "0.1.2" +version = "0.1.1" edition = "2021" description = "Auto-generated Rust FFI bindings to wolfSSL via bindgen" license = "MIT" @@ -16,11 +16,9 @@ links = "wolfcrypt_sys" default = [] fips = [] vendored = [] -riscv-bare-metal = ["vendored", "wolfssl-src/riscv-bare-metal"] -cryptocb-only = ["vendored", "wolfssl-src/cryptocb-only"] -cryptocb-pure = ["vendored", "wolfssl-src/cryptocb-pure"] +riscv-bare-metal = ["wolfssl-src/riscv-bare-metal"] [build-dependencies] bindgen = "0.72.0" pkg-config = "0.3" -wolfssl-src = { version = "0.1.2", path = "../wolfssl-src" } +wolfssl-src = { version = "0.1.1", path = "../wolfssl-src" } diff --git a/wolfcrypt-sys/build.rs b/wolfcrypt-sys/build.rs index 31f5127..93e93d1 100644 --- a/wolfcrypt-sys/build.rs +++ b/wolfcrypt-sys/build.rs @@ -207,13 +207,8 @@ fn generate_bindings( builder = builder.clang_arg(format!("-I{}", settings_dir.display())); } builder = builder.clang_arg("-DWOLFSSL_USER_SETTINGS"); - // For bare-metal features, add stub headers (stdio.h, pthread.h, etc.) - // so bindgen can parse wolfSSL headers without host libc headers. - if cfg!(any( - feature = "riscv-bare-metal", - feature = "cryptocb-only", - feature = "cryptocb-pure", - )) { + // For riscv-bare-metal, add stub headers (stdio.h, etc.) + if cfg!(feature = "riscv-bare-metal") { if let Ok(stubs) = env::var("WOLFSSL_BARE_METAL_STUBS") { builder = builder.clang_arg(format!("-I{}", stubs)); } @@ -291,11 +286,6 @@ fn main() { &manifest_dir, is_fips, ); - } else if cfg!(feature = "vendored") { - // vendored (and features that imply it: riscv-bare-metal, cryptocb-only) - // always compile from source via wolfssl-src, bypassing any pre-built - // wolfSSL pointed to by WOLFSSL_DIR. - do_vendored(&manifest_dir, is_fips); } else if let Ok(prefix) = env::var("WOLFSSL_DIR") { let prefix = PathBuf::from(prefix); do_prebuilt( @@ -304,7 +294,7 @@ fn main() { &manifest_dir, is_fips, ); - } else if env::var("WOLFSSL_SRC").is_ok() { + } else if cfg!(feature = "vendored") || env::var("WOLFSSL_SRC").is_ok() { do_vendored(&manifest_dir, is_fips); } else if let Some((include_dir, lib_dirs, defines)) = try_pkg_config() { do_system(&include_dir, &lib_dirs, &manifest_dir, &defines, is_fips); @@ -378,13 +368,9 @@ fn do_vendored(manifest_dir: &Path, is_fips: bool) { let artifacts = builder.build(); let active_cfgs = emit_cfg_flags(&artifacts.defines); - // For bare-metal features, bindgen must see the selected user_settings.h + // For riscv-bare-metal, bindgen must see the RISC-V user_settings.h // (copied to OUT_DIR by wolfssl-src) rather than the default. - let settings_dir = if cfg!(any( - feature = "riscv-bare-metal", - feature = "cryptocb-only", - feature = "cryptocb-pure", - )) { + let settings_dir = if cfg!(feature = "riscv-bare-metal") { PathBuf::from(env::var("OUT_DIR").unwrap()) } else { artifacts.settings_include_dir.clone() diff --git a/wolfcrypt-sys/headers.h b/wolfcrypt-sys/headers.h index 36bbefb..74ac508 100644 --- a/wolfcrypt-sys/headers.h +++ b/wolfcrypt-sys/headers.h @@ -34,4 +34,3 @@ #include "wolfssl/wolfcrypt/cmac.h" #include "wolfssl/wolfcrypt/dilithium.h" #include "wolfssl/wolfcrypt/mlkem.h" -#include "wolfssl/wolfcrypt/cryptocb.h" diff --git a/wolfcrypt-sys/user_settings.h b/wolfcrypt-sys/user_settings.h index 62c740c..ac25ca1 100644 --- a/wolfcrypt-sys/user_settings.h +++ b/wolfcrypt-sys/user_settings.h @@ -157,9 +157,4 @@ #define WOLFSSL_HAVE_MLKEM #define WOLFSSL_WC_MLKEM -/* CryptoCb: hardware crypto callback infrastructure. - * Enables wc_CryptoCb_RegisterDevice / wc_CryptoCb_GetDevIdAtIndex and - * the wc_CryptoInfo dispatch struct. Required for wolfcrypt-dpe-hw. */ -#define WOLF_CRYPTO_CB - #endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/wolfcrypt-tls/Cargo.toml b/wolfcrypt-tls/Cargo.toml index b68b68c..9426f6a 100644 --- a/wolfcrypt-tls/Cargo.toml +++ b/wolfcrypt-tls/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wolfcrypt-tls" authors = ["WolfSSL Inc"] -version = "0.1.2" +version = "0.1.1" edition = "2021" license = "MIT" keywords = ["wolfcrypt", "wolfssl", "tls", "fips", "cryptography"] @@ -26,7 +26,7 @@ vendored = ["wolfcrypt-sys/vendored"] fips = ["wolfcrypt-sys/fips"] [dependencies] -wolfcrypt-sys = { version = "0.1.2", path = "../wolfcrypt-sys" } +wolfcrypt-sys = { version = "0.1.1", path = "../wolfcrypt-sys" } zeroize = { workspace = true } [dev-dependencies] diff --git a/wolfcrypt-wrapper/Cargo.toml b/wolfcrypt-wrapper/Cargo.toml index 9dd8a38..ad4fa51 100644 --- a/wolfcrypt-wrapper/Cargo.toml +++ b/wolfcrypt-wrapper/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wolfcrypt-wrapper" authors = ["WolfSSL Inc"] -version = "1.1.2" +version = "1.1.1" edition = "2021" description = "Rust wrapper for wolfssl C library cryptographic functionality" license = "MIT" @@ -18,7 +18,7 @@ std = [] fips = ["wolfcrypt-sys/fips"] [dependencies] -wolfcrypt-sys = { version = "0.1.2", path = "../wolfcrypt-sys", default-features = false, features = ["vendored"] } +wolfcrypt-sys = { version = "0.1.1", path = "../wolfcrypt-sys", default-features = false, features = ["vendored"] } [build-dependencies] bindgen = { workspace = true } diff --git a/wolfcrypt-wrapper/src/dilithium.rs b/wolfcrypt-wrapper/src/dilithium.rs index 6cdec08..f69a4d6 100644 --- a/wolfcrypt-wrapper/src/dilithium.rs +++ b/wolfcrypt-wrapper/src/dilithium.rs @@ -867,8 +867,7 @@ impl Dilithium { let msg_len = msg.len() as u32; let mut sig_len = sig.len() as u32; let rc = unsafe { - sys::wc_dilithium_sign_ctx_msg( - core::ptr::null(), 0, + sys::wc_dilithium_sign_msg( msg.as_ptr(), msg_len, sig.as_mut_ptr(), &mut sig_len, &mut self.ws_key, @@ -1039,8 +1038,7 @@ impl Dilithium { let msg_len = msg.len() as u32; let mut sig_len = sig.len() as u32; let rc = unsafe { - sys::wc_dilithium_sign_ctx_msg_with_seed( - core::ptr::null(), 0, + sys::wc_dilithium_sign_msg_with_seed( msg.as_ptr(), msg_len, sig.as_mut_ptr(), &mut sig_len, &mut self.ws_key, @@ -1186,9 +1184,8 @@ impl Dilithium { let msg_len = msg.len() as u32; let mut res = 0i32; let rc = unsafe { - sys::wc_dilithium_verify_ctx_msg( + sys::wc_dilithium_verify_msg( sig.as_ptr(), sig_len, - core::ptr::null(), 0, msg.as_ptr(), msg_len, &mut res, &mut self.ws_key, diff --git a/wolfcrypt/Cargo.toml b/wolfcrypt/Cargo.toml index f9d66ee..e511b74 100644 --- a/wolfcrypt/Cargo.toml +++ b/wolfcrypt/Cargo.toml @@ -5,7 +5,7 @@ [package] name = "wolfcrypt" authors = ["WolfSSL Inc"] -version = "0.1.2" +version = "0.1.1" edition = "2021" rust-version = "1.71.0" license = "MIT" @@ -48,16 +48,9 @@ cryptocb = [] hpke = ["rand"] fips = ["wolfcrypt-rs/fips"] riscv-bare-metal = ["wolfcrypt-rs/riscv-bare-metal"] -cryptocb-only = ["wolfcrypt-rs/cryptocb-only"] -cryptocb-pure = ["wolfcrypt-rs/cryptocb-pure"] -# When enabled, `WolfRng::new()` (which uses INVALID_DEVID / software DRBG) is -# removed from the public API. Code must use `WolfRng::new_with_dev_id` and -# supply a hardware CryptoCb device ID. Activating this feature produces a -# compile error at any call site that still uses the software path. -require-dev-id = [] [dependencies] -wolfcrypt-rs = { version = "0.1.2", path = "../wolfcrypt-rs" } +wolfcrypt-rs = { version = "0.1.1", path = "../wolfcrypt-rs" } # RustCrypto trait crates (renamed to avoid module name collision). # diff --git a/wolfcrypt/src/cipher/cbc.rs b/wolfcrypt/src/cipher/cbc.rs index ef3744c..5672b17 100644 --- a/wolfcrypt/src/cipher/cbc.rs +++ b/wolfcrypt/src/cipher/cbc.rs @@ -1,8 +1,15 @@ -//! AES-CBC block cipher (native wolfCrypt wc_Aes* API). +//! AES-CBC block cipher (OpenSSL compat API: AES_cbc_encrypt). use super::*; -struct AesCbcEncBackend<'a>(&'a mut wolfcrypt_rs::WcAes); +// --------------------------------------------------------------------------- +// CBC encrypt backend +// --------------------------------------------------------------------------- + +struct AesCbcEncBackend<'a> { + key: &'a wolfcrypt_rs::AES_KEY, + iv: &'a mut [u8; 16], +} impl<'a> BlockSizeUser for AesCbcEncBackend<'a> { type BlockSize = U16; @@ -16,16 +23,27 @@ impl<'a> BlockBackend for AesCbcEncBackend<'a> { #[inline] fn proc_block(&mut self, block: InOut<'_, '_, Block>) { let (in_ptr, out_ptr) = block.into_raw(); - // SAFETY: in_ptr and out_ptr are valid 16-byte block pointers. - // wc_AesCbcEncrypt updates the IV state inside self.0 after each block. - let rc = unsafe { - wolfcrypt_rs::wc_AesCbcEncrypt(self.0, out_ptr as *mut u8, in_ptr as *const u8, 16) - }; - assert_eq!(rc, 0, "wc_AesCbcEncrypt failed"); + unsafe { + wolfcrypt_rs::AES_cbc_encrypt( + in_ptr as *const u8, + out_ptr as *mut u8, + 16, + self.key as *const wolfcrypt_rs::AES_KEY, + self.iv.as_mut_ptr(), + wolfcrypt_rs::AES_ENCRYPT, + ); + } } } -struct AesCbcDecBackend<'a>(&'a mut wolfcrypt_rs::WcAes); +// --------------------------------------------------------------------------- +// CBC decrypt backend +// --------------------------------------------------------------------------- + +struct AesCbcDecBackend<'a> { + key: &'a wolfcrypt_rs::AES_KEY, + iv: &'a mut [u8; 16], +} impl<'a> BlockSizeUser for AesCbcDecBackend<'a> { type BlockSize = U16; @@ -39,160 +57,142 @@ impl<'a> BlockBackend for AesCbcDecBackend<'a> { #[inline] fn proc_block(&mut self, block: InOut<'_, '_, Block>) { let (in_ptr, out_ptr) = block.into_raw(); - // SAFETY: in_ptr and out_ptr are valid 16-byte block pointers. - // wc_AesCbcDecrypt updates the IV state inside self.0 after each block. - let rc = unsafe { - wolfcrypt_rs::wc_AesCbcDecrypt(self.0, out_ptr as *mut u8, in_ptr as *const u8, 16) - }; - assert_eq!(rc, 0, "wc_AesCbcDecrypt failed"); + unsafe { + wolfcrypt_rs::AES_cbc_encrypt( + in_ptr as *const u8, + out_ptr as *mut u8, + 16, + self.key as *const wolfcrypt_rs::AES_KEY, + self.iv.as_mut_ptr(), + wolfcrypt_rs::AES_DECRYPT, + ); + } } } +// --------------------------------------------------------------------------- +// Macro + concrete types: encrypt +// --------------------------------------------------------------------------- + macro_rules! impl_aes_cbc_enc { - ($name:ident, $key_size:ty, $key_bytes:expr, $doc:expr) => { + ($name:ident, $key_size:ty, $key_bits:expr, $doc:expr) => { #[doc = $doc] pub struct $name { - aes: wolfcrypt_rs::WcAes, + key: wolfcrypt_rs::AES_KEY, + iv: [u8; 16], } unsafe impl Send for $name {} - impl KeySizeUser for $name { - type KeySize = $key_size; - } - - impl IvSizeUser for $name { - type IvSize = U16; - } + impl KeySizeUser for $name { type KeySize = $key_size; } + impl IvSizeUser for $name { type IvSize = U16; } impl KeyIvInit for $name { fn new(key: &GenericArray, iv: &GenericArray) -> Self { - let mut aes = wolfcrypt_rs::WcAes::zeroed(); + let mut aes_key = wolfcrypt_rs::AES_KEY::zeroed(); let rc = unsafe { - wolfcrypt_rs::wc_AesInit( - &mut aes as *mut wolfcrypt_rs::WcAes, - core::ptr::null_mut(), - wolfcrypt_rs::INVALID_DEVID, + wolfcrypt_rs::AES_set_encrypt_key( + key.as_ptr(), $key_bits, + &mut aes_key as *mut wolfcrypt_rs::AES_KEY, ) }; - assert_eq!(rc, 0, "wc_AesInit failed"); - let rc = unsafe { - wolfcrypt_rs::wc_AesSetKey( - &mut aes as *mut wolfcrypt_rs::WcAes, - key.as_ptr(), - $key_bytes, - iv.as_ptr(), - wolfcrypt_rs::AES_ENCRYPT, - ) - }; - assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length)"); - Self { aes } + assert_eq!(rc, 0, "AES_set_encrypt_key failed (invalid key length)"); + let mut iv_buf = [0u8; 16]; + iv_buf.copy_from_slice(iv.as_slice()); + Self { key: aes_key, iv: iv_buf } } } - impl BlockSizeUser for $name { - type BlockSize = U16; - } + impl BlockSizeUser for $name { type BlockSize = U16; } impl BlockEncryptMut for $name { fn encrypt_with_backend_mut( - &mut self, - f: impl BlockClosure, + &mut self, f: impl BlockClosure, ) { - f.call(&mut AesCbcEncBackend(&mut self.aes)); + f.call(&mut AesCbcEncBackend { key: &self.key, iv: &mut self.iv }); } } impl Drop for $name { fn drop(&mut self) { - // SAFETY: self.aes was initialised by wc_AesInit. - unsafe { - wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes); - } + use zeroize::Zeroize; + unsafe { zeroize_aes_key(&mut self.key) }; + self.iv.zeroize(); } } }; } +// --------------------------------------------------------------------------- +// Macro + concrete types: decrypt +// --------------------------------------------------------------------------- + macro_rules! impl_aes_cbc_dec { - ($name:ident, $key_size:ty, $key_bytes:expr, $doc:expr) => { + ($name:ident, $key_size:ty, $key_bits:expr, $doc:expr) => { #[doc = $doc] pub struct $name { - aes: wolfcrypt_rs::WcAes, + key: wolfcrypt_rs::AES_KEY, + iv: [u8; 16], } unsafe impl Send for $name {} - impl KeySizeUser for $name { - type KeySize = $key_size; - } - - impl IvSizeUser for $name { - type IvSize = U16; - } + impl KeySizeUser for $name { type KeySize = $key_size; } + impl IvSizeUser for $name { type IvSize = U16; } impl KeyIvInit for $name { fn new(key: &GenericArray, iv: &GenericArray) -> Self { - let mut aes = wolfcrypt_rs::WcAes::zeroed(); + let mut aes_key = wolfcrypt_rs::AES_KEY::zeroed(); let rc = unsafe { - wolfcrypt_rs::wc_AesInit( - &mut aes as *mut wolfcrypt_rs::WcAes, - core::ptr::null_mut(), - wolfcrypt_rs::INVALID_DEVID, + wolfcrypt_rs::AES_set_decrypt_key( + key.as_ptr(), $key_bits, + &mut aes_key as *mut wolfcrypt_rs::AES_KEY, ) }; - assert_eq!(rc, 0, "wc_AesInit failed"); - let rc = unsafe { - wolfcrypt_rs::wc_AesSetKey( - &mut aes as *mut wolfcrypt_rs::WcAes, - key.as_ptr(), - $key_bytes, - iv.as_ptr(), - wolfcrypt_rs::AES_DECRYPT, - ) - }; - assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length)"); - Self { aes } + assert_eq!(rc, 0, "AES_set_decrypt_key failed (invalid key length)"); + let mut iv_buf = [0u8; 16]; + iv_buf.copy_from_slice(iv.as_slice()); + Self { key: aes_key, iv: iv_buf } } } - impl BlockSizeUser for $name { - type BlockSize = U16; - } + impl BlockSizeUser for $name { type BlockSize = U16; } impl BlockDecryptMut for $name { fn decrypt_with_backend_mut( - &mut self, - f: impl BlockClosure, + &mut self, f: impl BlockClosure, ) { - f.call(&mut AesCbcDecBackend(&mut self.aes)); + f.call(&mut AesCbcDecBackend { key: &self.key, iv: &mut self.iv }); } } impl Drop for $name { fn drop(&mut self) { - // SAFETY: self.aes was initialised by wc_AesInit. - unsafe { - wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes); - } + use zeroize::Zeroize; + unsafe { zeroize_aes_key(&mut self.key) }; + self.iv.zeroize(); } } }; } -impl_aes_cbc_enc!(Aes128CbcEnc, typenum::U16, 16u32, +// --------------------------------------------------------------------------- +// Concrete CBC types +// --------------------------------------------------------------------------- + +impl_aes_cbc_enc!(Aes128CbcEnc, typenum::U16, 128, "AES-128 CBC encryption, implementing `BlockEncryptMut` and `KeyIvInit`."); -impl_aes_cbc_dec!(Aes128CbcDec, typenum::U16, 16u32, +impl_aes_cbc_dec!(Aes128CbcDec, typenum::U16, 128, "AES-128 CBC decryption, implementing `BlockDecryptMut` and `KeyIvInit`."); #[cfg(wolfssl_aes_192)] -impl_aes_cbc_enc!(Aes192CbcEnc, typenum::U24, 24u32, +impl_aes_cbc_enc!(Aes192CbcEnc, typenum::U24, 192, "AES-192 CBC encryption, implementing `BlockEncryptMut` and `KeyIvInit`."); #[cfg(wolfssl_aes_192)] -impl_aes_cbc_dec!(Aes192CbcDec, typenum::U24, 24u32, +impl_aes_cbc_dec!(Aes192CbcDec, typenum::U24, 192, "AES-192 CBC decryption, implementing `BlockDecryptMut` and `KeyIvInit`."); -impl_aes_cbc_enc!(Aes256CbcEnc, typenum::U32, 32u32, +impl_aes_cbc_enc!(Aes256CbcEnc, typenum::U32, 256, "AES-256 CBC encryption, implementing `BlockEncryptMut` and `KeyIvInit`."); -impl_aes_cbc_dec!(Aes256CbcDec, typenum::U32, 32u32, +impl_aes_cbc_dec!(Aes256CbcDec, typenum::U32, 256, "AES-256 CBC decryption, implementing `BlockDecryptMut` and `KeyIvInit`."); diff --git a/wolfcrypt/src/cipher/cfb.rs b/wolfcrypt/src/cipher/cfb.rs index b73fe53..ecd0ca1 100644 --- a/wolfcrypt/src/cipher/cfb.rs +++ b/wolfcrypt/src/cipher/cfb.rs @@ -1,104 +1,72 @@ -//! AES-CFB-128 stream cipher backed by native wolfCrypt `wc_AesCfbEncrypt` / -//! `wc_AesCfbDecrypt`. +//! AES-CFB128 stream cipher (OpenSSL compat API: AES_cfb128_encrypt). //! -//! CFB is a self-synchronizing stream cipher. Unlike OFB or CTR, the feedback -//! path differs between encryption and decryption, so separate `Enc` and `Dec` -//! types are required. Both directions use the **AES encrypt key schedule** -//! (there is no CFB decrypt schedule). +//! CFB128 is a self-synchronizing stream cipher mode. Unlike CTR, encrypt and +//! decrypt are NOT the same operation โ€” the feedback loop differs โ€” so we +//! define separate Enc and Dec types. //! -//! IV state and the partial-block counter are maintained **inside the `WcAes` -//! struct** by wolfCrypt; callers do not need to manage them. +//! We always use `AES_set_encrypt_key` regardless of direction, because CFB +//! mode only uses the AES-encrypt primitive internally. use super::*; -use crate::error::len_as_u32; // --------------------------------------------------------------------------- // CFB encrypt // --------------------------------------------------------------------------- macro_rules! impl_aes_cfb_enc { - ($name:ident, $key_size:ty, $key_bytes:expr, $doc:expr) => { + ($name:ident, $key_size:ty, $key_bits:expr, $doc:expr) => { #[doc = $doc] pub struct $name { - aes: wolfcrypt_rs::WcAes, + key: wolfcrypt_rs::AES_KEY, + iv: [u8; 16], + num: core::ffi::c_int, } unsafe impl Send for $name {} - impl Drop for $name { - fn drop(&mut self) { - // SAFETY: `aes` was successfully initialised in `new`. - unsafe { - wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes); - } - } - } - - impl KeySizeUser for $name { - type KeySize = $key_size; - } - - impl IvSizeUser for $name { - type IvSize = U16; - } + impl KeySizeUser for $name { type KeySize = $key_size; } + impl IvSizeUser for $name { type IvSize = U16; } impl KeyIvInit for $name { fn new(key: &GenericArray, iv: &GenericArray) -> Self { - let mut aes = wolfcrypt_rs::WcAes::zeroed(); - - // SAFETY: `aes` is zero-initialised; INVALID_DEVID selects - // software-only operation. + let mut aes_key = wolfcrypt_rs::AES_KEY::zeroed(); let rc = unsafe { - wolfcrypt_rs::wc_AesInit( - &mut aes as *mut wolfcrypt_rs::WcAes, - core::ptr::null_mut(), - wolfcrypt_rs::INVALID_DEVID, + wolfcrypt_rs::AES_set_encrypt_key( + key.as_ptr(), $key_bits, + &mut aes_key as *mut wolfcrypt_rs::AES_KEY, ) }; - assert_eq!(rc, 0, "wc_AesInit failed (OOM or invalid device)"); - - // CFB always uses the AES encrypt key schedule, even for - // decryption. - // SAFETY: `aes` is initialised; key and IV buffers are valid. - let rc = unsafe { - wolfcrypt_rs::wc_AesSetKey( - &mut aes as *mut wolfcrypt_rs::WcAes, - key.as_ptr(), - $key_bytes, - iv.as_ptr(), - wolfcrypt_rs::AES_ENCRYPT, - ) - }; - assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length or IV)"); - - Self { aes } + assert_eq!(rc, 0, "AES_set_encrypt_key failed (invalid key length)"); + let mut iv_buf = [0u8; 16]; + iv_buf.copy_from_slice(iv.as_slice()); + Self { key: aes_key, iv: iv_buf, num: 0 } } } impl StreamCipher for $name { fn try_apply_keystream_inout( - &mut self, - buf: cipher_trait::inout::InOutBuf<'_, '_, u8>, + &mut self, buf: cipher_trait::inout::InOutBuf<'_, '_, u8>, ) -> Result<(), StreamCipherError> { let len = buf.len(); let (in_ptr, out_ptr) = buf.into_raw(); - - // SAFETY: `aes` is live; in/out pointers are valid for `len` - // bytes; in-place aliasing is safe because CFB processes bytes - // sequentially. - let rc = unsafe { - wolfcrypt_rs::wc_AesCfbEncrypt( - &mut self.aes as *mut wolfcrypt_rs::WcAes, - out_ptr, - in_ptr, - len_as_u32(len), - ) - }; - if rc == 0 { - Ok(()) - } else { - Err(StreamCipherError) + unsafe { + wolfcrypt_rs::AES_cfb128_encrypt( + in_ptr, out_ptr, len, + &self.key as *const wolfcrypt_rs::AES_KEY, + self.iv.as_mut_ptr(), &mut self.num, + wolfcrypt_rs::AES_ENCRYPT, + ); } + Ok(()) + } + } + + impl Drop for $name { + fn drop(&mut self) { + use zeroize::Zeroize; + unsafe { zeroize_aes_key(&mut self.key) }; + self.iv.zeroize(); + self.num = 0; } } }; @@ -109,86 +77,61 @@ macro_rules! impl_aes_cfb_enc { // --------------------------------------------------------------------------- macro_rules! impl_aes_cfb_dec { - ($name:ident, $key_size:ty, $key_bytes:expr, $doc:expr) => { + ($name:ident, $key_size:ty, $key_bits:expr, $doc:expr) => { #[doc = $doc] pub struct $name { - aes: wolfcrypt_rs::WcAes, + key: wolfcrypt_rs::AES_KEY, + iv: [u8; 16], + num: core::ffi::c_int, } unsafe impl Send for $name {} - impl Drop for $name { - fn drop(&mut self) { - // SAFETY: `aes` was successfully initialised in `new`. - unsafe { - wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes); - } - } - } - - impl KeySizeUser for $name { - type KeySize = $key_size; - } - - impl IvSizeUser for $name { - type IvSize = U16; - } + impl KeySizeUser for $name { type KeySize = $key_size; } + impl IvSizeUser for $name { type IvSize = U16; } impl KeyIvInit for $name { fn new(key: &GenericArray, iv: &GenericArray) -> Self { - let mut aes = wolfcrypt_rs::WcAes::zeroed(); - - // SAFETY: `aes` is zero-initialised. - let rc = unsafe { - wolfcrypt_rs::wc_AesInit( - &mut aes as *mut wolfcrypt_rs::WcAes, - core::ptr::null_mut(), - wolfcrypt_rs::INVALID_DEVID, - ) - }; - assert_eq!(rc, 0, "wc_AesInit failed (OOM or invalid device)"); - - // CFB decryption also uses the AES encrypt key schedule. - // SAFETY: `aes` is initialised; key and IV buffers are valid. + let mut aes_key = wolfcrypt_rs::AES_KEY::zeroed(); + // CFB mode always uses the AES-encrypt key schedule, even for + // decryption. let rc = unsafe { - wolfcrypt_rs::wc_AesSetKey( - &mut aes as *mut wolfcrypt_rs::WcAes, - key.as_ptr(), - $key_bytes, - iv.as_ptr(), - wolfcrypt_rs::AES_ENCRYPT, + wolfcrypt_rs::AES_set_encrypt_key( + key.as_ptr(), $key_bits, + &mut aes_key as *mut wolfcrypt_rs::AES_KEY, ) }; - assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length or IV)"); - - Self { aes } + assert_eq!(rc, 0, "AES_set_encrypt_key failed (invalid key length)"); + let mut iv_buf = [0u8; 16]; + iv_buf.copy_from_slice(iv.as_slice()); + Self { key: aes_key, iv: iv_buf, num: 0 } } } impl StreamCipher for $name { fn try_apply_keystream_inout( - &mut self, - buf: cipher_trait::inout::InOutBuf<'_, '_, u8>, + &mut self, buf: cipher_trait::inout::InOutBuf<'_, '_, u8>, ) -> Result<(), StreamCipherError> { let len = buf.len(); let (in_ptr, out_ptr) = buf.into_raw(); - - // SAFETY: `aes` is live; in/out pointers are valid for `len` - // bytes. CFB decrypt uses a different feedback path than - // encrypt but is otherwise identical at the call level. - let rc = unsafe { - wolfcrypt_rs::wc_AesCfbDecrypt( - &mut self.aes as *mut wolfcrypt_rs::WcAes, - out_ptr, - in_ptr, - len_as_u32(len), - ) - }; - if rc == 0 { - Ok(()) - } else { - Err(StreamCipherError) + unsafe { + wolfcrypt_rs::AES_cfb128_encrypt( + in_ptr, out_ptr, len, + &self.key as *const wolfcrypt_rs::AES_KEY, + self.iv.as_mut_ptr(), &mut self.num, + wolfcrypt_rs::AES_DECRYPT, + ); } + Ok(()) + } + } + + impl Drop for $name { + fn drop(&mut self) { + use zeroize::Zeroize; + unsafe { zeroize_aes_key(&mut self.key) }; + self.iv.zeroize(); + self.num = 0; } } }; @@ -198,31 +141,19 @@ macro_rules! impl_aes_cfb_dec { // Concrete types // --------------------------------------------------------------------------- -impl_aes_cfb_enc!( - Aes128CfbEnc, typenum::U16, 16u32, - "AES-128 CFB-128 encryption, implementing `StreamCipher` and `KeyIvInit`." -); -impl_aes_cfb_dec!( - Aes128CfbDec, typenum::U16, 16u32, - "AES-128 CFB-128 decryption, implementing `StreamCipher` and `KeyIvInit`." -); +impl_aes_cfb_enc!(Aes128CfbEnc, typenum::U16, 128, + "AES-128 CFB128 encryption, implementing `StreamCipher` and `KeyIvInit`."); +impl_aes_cfb_dec!(Aes128CfbDec, typenum::U16, 128, + "AES-128 CFB128 decryption, implementing `StreamCipher` and `KeyIvInit`."); #[cfg(wolfssl_aes_192)] -impl_aes_cfb_enc!( - Aes192CfbEnc, typenum::U24, 24u32, - "AES-192 CFB-128 encryption, implementing `StreamCipher` and `KeyIvInit`." -); +impl_aes_cfb_enc!(Aes192CfbEnc, typenum::U24, 192, + "AES-192 CFB128 encryption, implementing `StreamCipher` and `KeyIvInit`."); #[cfg(wolfssl_aes_192)] -impl_aes_cfb_dec!( - Aes192CfbDec, typenum::U24, 24u32, - "AES-192 CFB-128 decryption, implementing `StreamCipher` and `KeyIvInit`." -); - -impl_aes_cfb_enc!( - Aes256CfbEnc, typenum::U32, 32u32, - "AES-256 CFB-128 encryption, implementing `StreamCipher` and `KeyIvInit`." -); -impl_aes_cfb_dec!( - Aes256CfbDec, typenum::U32, 32u32, - "AES-256 CFB-128 decryption, implementing `StreamCipher` and `KeyIvInit`." -); +impl_aes_cfb_dec!(Aes192CfbDec, typenum::U24, 192, + "AES-192 CFB128 decryption, implementing `StreamCipher` and `KeyIvInit`."); + +impl_aes_cfb_enc!(Aes256CfbEnc, typenum::U32, 256, + "AES-256 CFB128 encryption, implementing `StreamCipher` and `KeyIvInit`."); +impl_aes_cfb_dec!(Aes256CfbDec, typenum::U32, 256, + "AES-256 CFB128 decryption, implementing `StreamCipher` and `KeyIvInit`."); diff --git a/wolfcrypt/src/cipher/ecb.rs b/wolfcrypt/src/cipher/ecb.rs index 385dd6c..b1412a1 100644 --- a/wolfcrypt/src/cipher/ecb.rs +++ b/wolfcrypt/src/cipher/ecb.rs @@ -1,8 +1,12 @@ -//! AES-ECB block cipher (native wolfCrypt wc_Aes* API). +//! AES-ECB block cipher (OpenSSL compat API). use super::*; -struct AesEcbEncBackend<'a>(&'a wolfcrypt_rs::WcAes); +// --------------------------------------------------------------------------- +// Shared backends โ€” call AES_ecb_encrypt in the appropriate direction. +// --------------------------------------------------------------------------- + +struct AesEcbEncBackend<'a>(&'a wolfcrypt_rs::AES_KEY); impl<'a> BlockSizeUser for AesEcbEncBackend<'a> { type BlockSize = U16; @@ -16,22 +20,22 @@ impl<'a> BlockBackend for AesEcbEncBackend<'a> { #[inline] fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { let mut tmp = [0u8; 16]; - // SAFETY: wc_AesEcbEncrypt does not modify the key schedule in self.0; - // the *mut cast is required by the C API signature only. - let rc = unsafe { - wolfcrypt_rs::wc_AesEcbEncrypt( - self.0 as *const wolfcrypt_rs::WcAes as *mut wolfcrypt_rs::WcAes, - tmp.as_mut_ptr(), + // SAFETY: `block.get_in()` is a valid 16-byte input, `tmp` is a valid + // 16-byte output, and `self.0` was initialised by `AES_set_encrypt_key`. + // `AES_ENCRYPT` (0) selects the encryption direction. + unsafe { + wolfcrypt_rs::AES_ecb_encrypt( block.get_in().as_ptr(), - 16, - ) - }; - assert_eq!(rc, 0, "wc_AesEcbEncrypt failed"); + tmp.as_mut_ptr(), + self.0 as *const wolfcrypt_rs::AES_KEY, + wolfcrypt_rs::AES_ENCRYPT, + ); + } block.get_out().copy_from_slice(&tmp); } } -struct AesEcbDecBackend<'a>(&'a wolfcrypt_rs::WcAes); +struct AesEcbDecBackend<'a>(&'a wolfcrypt_rs::AES_KEY); impl<'a> BlockSizeUser for AesEcbDecBackend<'a> { type BlockSize = U16; @@ -45,26 +49,30 @@ impl<'a> BlockBackend for AesEcbDecBackend<'a> { #[inline] fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { let mut tmp = [0u8; 16]; - // SAFETY: wc_AesEcbDecrypt does not modify the key schedule in self.0; - // the *mut cast is required by the C API signature only. - let rc = unsafe { - wolfcrypt_rs::wc_AesEcbDecrypt( - self.0 as *const wolfcrypt_rs::WcAes as *mut wolfcrypt_rs::WcAes, - tmp.as_mut_ptr(), + // SAFETY: `block.get_in()` is a valid 16-byte input, `tmp` is a valid + // 16-byte output, and `self.0` was initialised by `AES_set_decrypt_key`. + // `AES_DECRYPT` (1) selects the decryption direction. + unsafe { + wolfcrypt_rs::AES_ecb_encrypt( block.get_in().as_ptr(), - 16, - ) - }; - assert_eq!(rc, 0, "wc_AesEcbDecrypt failed"); + tmp.as_mut_ptr(), + self.0 as *const wolfcrypt_rs::AES_KEY, + wolfcrypt_rs::AES_DECRYPT, + ); + } block.get_out().copy_from_slice(&tmp); } } +// --------------------------------------------------------------------------- +// Macro + concrete types +// --------------------------------------------------------------------------- + macro_rules! impl_aes_ecb_enc { - ($name:ident, $key_size:ty, $key_bytes:expr) => { + ($name:ident, $key_size:ty, $key_bits:expr) => { /// AES-ECB encryption cipher. pub struct $name { - aes: wolfcrypt_rs::WcAes, + key: wolfcrypt_rs::AES_KEY, } unsafe impl Send for $name {} @@ -75,26 +83,16 @@ macro_rules! impl_aes_ecb_enc { impl KeyInit for $name { fn new(key: &GenericArray) -> Self { - let mut aes = wolfcrypt_rs::WcAes::zeroed(); - let rc = unsafe { - wolfcrypt_rs::wc_AesInit( - &mut aes as *mut wolfcrypt_rs::WcAes, - core::ptr::null_mut(), - wolfcrypt_rs::INVALID_DEVID, - ) - }; - assert_eq!(rc, 0, "wc_AesInit failed"); + let mut aes_key = wolfcrypt_rs::AES_KEY::zeroed(); let rc = unsafe { - wolfcrypt_rs::wc_AesSetKey( - &mut aes as *mut wolfcrypt_rs::WcAes, + wolfcrypt_rs::AES_set_encrypt_key( key.as_ptr(), - $key_bytes, - core::ptr::null(), - wolfcrypt_rs::AES_ENCRYPT, + $key_bits, + &mut aes_key as *mut wolfcrypt_rs::AES_KEY, ) }; - assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length)"); - Self { aes } + assert_eq!(rc, 0, "AES_set_encrypt_key failed (invalid key length)"); + Self { key: aes_key } } } @@ -109,26 +107,23 @@ macro_rules! impl_aes_ecb_enc { &self, f: impl BlockClosure, ) { - f.call(&mut AesEcbEncBackend(&self.aes)); + f.call(&mut AesEcbEncBackend(&self.key)); } } impl Drop for $name { fn drop(&mut self) { - // SAFETY: self.aes was initialised by wc_AesInit. - unsafe { - wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes); - } + unsafe { zeroize_aes_key(&mut self.key) }; } } }; } macro_rules! impl_aes_ecb_dec { - ($name:ident, $key_size:ty, $key_bytes:expr) => { + ($name:ident, $key_size:ty, $key_bits:expr) => { /// AES-ECB decryption cipher. pub struct $name { - aes: wolfcrypt_rs::WcAes, + key: wolfcrypt_rs::AES_KEY, } unsafe impl Send for $name {} @@ -139,26 +134,16 @@ macro_rules! impl_aes_ecb_dec { impl KeyInit for $name { fn new(key: &GenericArray) -> Self { - let mut aes = wolfcrypt_rs::WcAes::zeroed(); - let rc = unsafe { - wolfcrypt_rs::wc_AesInit( - &mut aes as *mut wolfcrypt_rs::WcAes, - core::ptr::null_mut(), - wolfcrypt_rs::INVALID_DEVID, - ) - }; - assert_eq!(rc, 0, "wc_AesInit failed"); + let mut aes_key = wolfcrypt_rs::AES_KEY::zeroed(); let rc = unsafe { - wolfcrypt_rs::wc_AesSetKey( - &mut aes as *mut wolfcrypt_rs::WcAes, + wolfcrypt_rs::AES_set_decrypt_key( key.as_ptr(), - $key_bytes, - core::ptr::null(), - wolfcrypt_rs::AES_DECRYPT, + $key_bits, + &mut aes_key as *mut wolfcrypt_rs::AES_KEY, ) }; - assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length)"); - Self { aes } + assert_eq!(rc, 0, "AES_set_decrypt_key failed (invalid key length)"); + Self { key: aes_key } } } @@ -173,28 +158,25 @@ macro_rules! impl_aes_ecb_dec { &self, f: impl BlockClosure, ) { - f.call(&mut AesEcbDecBackend(&self.aes)); + f.call(&mut AesEcbDecBackend(&self.key)); } } impl Drop for $name { fn drop(&mut self) { - // SAFETY: self.aes was initialised by wc_AesInit. - unsafe { - wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes); - } + unsafe { zeroize_aes_key(&mut self.key) }; } } }; } -impl_aes_ecb_enc!(Aes128EcbEnc, typenum::U16, 16u32); -impl_aes_ecb_dec!(Aes128EcbDec, typenum::U16, 16u32); +impl_aes_ecb_enc!(Aes128EcbEnc, typenum::U16, 128); +impl_aes_ecb_dec!(Aes128EcbDec, typenum::U16, 128); #[cfg(wolfssl_aes_192)] -impl_aes_ecb_enc!(Aes192EcbEnc, typenum::U24, 24u32); +impl_aes_ecb_enc!(Aes192EcbEnc, typenum::U24, 192); #[cfg(wolfssl_aes_192)] -impl_aes_ecb_dec!(Aes192EcbDec, typenum::U24, 24u32); +impl_aes_ecb_dec!(Aes192EcbDec, typenum::U24, 192); -impl_aes_ecb_enc!(Aes256EcbEnc, typenum::U32, 32u32); -impl_aes_ecb_dec!(Aes256EcbDec, typenum::U32, 32u32); +impl_aes_ecb_enc!(Aes256EcbEnc, typenum::U32, 256); +impl_aes_ecb_dec!(Aes256EcbDec, typenum::U32, 256); diff --git a/wolfcrypt/src/cipher/mod.rs b/wolfcrypt/src/cipher/mod.rs index 26cdcf0..53e9e1a 100644 --- a/wolfcrypt/src/cipher/mod.rs +++ b/wolfcrypt/src/cipher/mod.rs @@ -23,11 +23,34 @@ pub(crate) use typenum::{U1, U16}; pub use cipher_trait; +/// Zero the bytes of an opaque `AES_KEY` struct for defense-in-depth. +/// +/// `AES_KEY` is a foreign C type that doesn't implement `Zeroize`, so we +/// treat it as a raw byte slice and use `zeroize` (volatile writes) to +/// ensure the compiler cannot elide the clearing. +/// +/// # Safety +/// +/// Caller must have exclusive access (`&mut`). The type must be a plain +/// C struct with no Rust drop glue. +pub(crate) unsafe fn zeroize_aes_key(key: &mut wolfcrypt_rs::AES_KEY) { + use zeroize::Zeroize; + // SAFETY: caller guarantees exclusive access and that AES_KEY is a + // plain C struct with no Rust drop glue. + let bytes = unsafe { + core::slice::from_raw_parts_mut( + key as *mut wolfcrypt_rs::AES_KEY as *mut u8, + core::mem::size_of::(), + ) + }; + bytes.zeroize(); +} + // Submodules โ€” one per cipher mode family. -#[cfg(wolfssl_aes_ecb)] +#[cfg(all(wolfssl_openssl_extra, wolfssl_aes_ecb))] mod ecb; -#[cfg(wolfssl_aes_ecb)] +#[cfg(all(wolfssl_openssl_extra, wolfssl_aes_ecb))] pub use ecb::*; #[cfg(wolfssl_aes_ctr)] @@ -35,7 +58,9 @@ mod ctr; #[cfg(wolfssl_aes_ctr)] pub use ctr::*; +#[cfg(wolfssl_openssl_extra)] mod cbc; +#[cfg(wolfssl_openssl_extra)] pub use cbc::*; #[cfg(wolfssl_chacha)] @@ -43,9 +68,9 @@ mod chacha20; #[cfg(wolfssl_chacha)] pub use chacha20::*; -#[cfg(wolfssl_aes_cfb)] +#[cfg(all(wolfssl_openssl_extra, wolfssl_aes_cfb))] mod cfb; -#[cfg(wolfssl_aes_cfb)] +#[cfg(all(wolfssl_openssl_extra, wolfssl_aes_cfb))] pub use cfb::*; #[cfg(wolfssl_aes_ofb)] diff --git a/wolfcrypt/src/cmac.rs b/wolfcrypt/src/cmac.rs index 931f8ed..0562d05 100644 --- a/wolfcrypt/src/cmac.rs +++ b/wolfcrypt/src/cmac.rs @@ -1,4 +1,4 @@ -//! AES-CMAC algorithms backed by wolfCrypt's native wc_Cmac* API. +//! AES-CMAC algorithms backed by wolfCrypt's CMAC_CTX API. //! //! Each type implements the RustCrypto [`digest`](digest_trait) 0.10 MAC traits //! (`OutputSizeUser`, `KeySizeUser`, `KeyInit`, `Update`, `FixedOutput`, @@ -7,37 +7,55 @@ //! Callers should `use digest_trait::Mac` for the full API: //! `new_from_slice()`, `update()`, `finalize()`, `verify_slice()`. +use core::ffi::c_void; use digest_trait::{FixedOutput, KeyInit, OutputSizeUser, Update}; use generic_array::GenericArray; use typenum::*; /// Internal macro that stamps out a complete AES-CMAC wrapper for one key size. /// -/// The generated struct holds a heap-allocated wolfCrypt `Cmac` context -/// and delegates all operations through `wolfcrypt_cmac_*` C shims. +/// The generated struct holds a heap-allocated `CMAC_CTX` and delegates +/// all operations to wolfCrypt through the OpenSSL-compat CMAC layer. macro_rules! impl_cmac { ( $name:ident, - $new_fn:path, + $cipher_fn:path, $key_size:ty, $cfg_gate:meta ) => { #[$cfg_gate] pub struct $name { - ctx: *mut core::ffi::c_void, + ctx: *mut wolfcrypt_rs::CMAC_CTX, } - // SAFETY: The Cmac context is heap-allocated and only accessed through - // &self / &mut self. Thread-safety is enforced by Rust's ownership rules. + // SAFETY: CMAC_CTX is heap-allocated and only accessed through + // &self / &mut self. wolfCrypt's CMAC layer is thread-safe when a + // context is used from a single thread, which Rust's ownership + // rules enforce. #[$cfg_gate] unsafe impl Send for $name {} + #[$cfg_gate] + impl $name { + /// Return the cipher descriptor pointer for this CMAC's AES variant. + #[inline] + fn evp_cipher() -> *const wolfcrypt_rs::EVP_CIPHER { + // SAFETY: EVP_aes_*_cbc functions return a static const pointer. + unsafe { $cipher_fn() } + } + } + + // ------------------------------------------------------------------ + // core / RustCrypto trait impls + // ------------------------------------------------------------------ + #[$cfg_gate] impl Drop for $name { fn drop(&mut self) { - if !self.ctx.is_null() { - // SAFETY: ctx was allocated by wolfcrypt_cmac_*_new. - unsafe { wolfcrypt_rs::wolfcrypt_cmac_free(self.ctx) }; + // SAFETY: self.ctx was allocated via CMAC_CTX_new and + // is only freed once here. + unsafe { + wolfcrypt_rs::CMAC_CTX_free(self.ctx); } } } @@ -53,65 +71,92 @@ macro_rules! impl_cmac { type KeySize = $key_size; } - #[$cfg_gate] - impl $name { - fn init_with_key(key: &[u8]) -> Option { - use typenum::Unsigned; - if key.len() != <$key_size as Unsigned>::USIZE { - return None; - } - // SAFETY: key pointer is valid; length has been validated above. - let ctx = unsafe { $new_fn(key.as_ptr()) }; - if ctx.is_null() { return None; } - Some(Self { ctx }) - } - } - #[$cfg_gate] impl KeyInit for $name { + /// Create from a fixed-size key (KeySize bytes). fn new(key: &GenericArray::KeySize>) -> Self { Self::init_with_key(key.as_slice()) - .expect("wolfcrypt_cmac_*_new failed with correct key size") + .expect("CMAC_Init failed with correct key size") } + /// Create from a variable-length key. + /// Returns `InvalidLength` if `key.len()` does not match the + /// expected AES key size. fn new_from_slice(key: &[u8]) -> Result { Self::init_with_key(key).ok_or(crypto_common::InvalidLength) } } + #[$cfg_gate] + impl $name { + /// Shared initialisation: allocate a CMAC_CTX and key it. + /// Returns `None` if the key length is wrong or allocation fails. + fn init_with_key(key: &[u8]) -> Option { + use typenum::Unsigned; + let expected_len = <$key_size as Unsigned>::USIZE; + if key.len() != expected_len { + return None; + } + + // SAFETY: CMAC_CTX_new returns a heap-allocated context + // or NULL on OOM. + let ctx = unsafe { wolfcrypt_rs::CMAC_CTX_new() }; + if ctx.is_null() { + return None; + } + + // SAFETY: ctx is non-null and freshly allocated. key pointer + // and length are guaranteed correct by the slice reference. + // CMAC_Init with a non-null key sets the key and cipher. + let rc = unsafe { + wolfcrypt_rs::CMAC_Init( + ctx, + key.as_ptr() as *const c_void, + key.len(), + Self::evp_cipher(), + core::ptr::null_mut(), + ) + }; + if rc != 1 { + unsafe { wolfcrypt_rs::CMAC_CTX_free(ctx) }; + return None; + } + Some(Self { ctx }) + } + } + #[$cfg_gate] impl Update for $name { fn update(&mut self, data: &[u8]) { - // SAFETY: ctx is valid; data pointer and length are correct. - let rc = unsafe { - wolfcrypt_rs::wolfcrypt_cmac_update( + // SAFETY: self.ctx is valid. data pointer and length are + // guaranteed correct by the slice reference. + unsafe { + let rc = wolfcrypt_rs::CMAC_Update( self.ctx, data.as_ptr(), - data.len() as u32, - ) - }; - assert_eq!(rc, 0, concat!(stringify!($name), ": wolfcrypt_cmac_update failed")); + data.len(), + ); + assert_eq!(rc, 1, "CMAC_Update failed (context not initialized)"); + } } } #[$cfg_gate] impl FixedOutput for $name { - fn finalize_into(mut self, out: &mut GenericArray) { - let mut out_len: u32 = 16; - // SAFETY: out is exactly 16 bytes; ctx is valid. - let rc = unsafe { - wolfcrypt_rs::wolfcrypt_cmac_final( + fn finalize_into(self, out: &mut GenericArray) { + let mut len: usize = 0; + // SAFETY: out is exactly OutputSize (16) bytes. self.ctx is + // valid. After this call, Drop will free the context. + unsafe { + let rc = wolfcrypt_rs::CMAC_Final( self.ctx, out.as_mut_ptr(), - &mut out_len, - ) - }; - assert_eq!(rc, 0, concat!(stringify!($name), ": wolfcrypt_cmac_final failed")); - debug_assert_eq!(out_len, 16); - // Prevent Drop from double-freeing. - let ctx = self.ctx; - self.ctx = core::ptr::null_mut(); - unsafe { wolfcrypt_rs::wolfcrypt_cmac_free(ctx) }; + &mut len, + ); + assert_eq!(rc, 1, "CMAC_Final failed (context not initialized)"); + } + debug_assert_eq!(len, 16); + // Drop runs after this and frees self.ctx. } } @@ -120,16 +165,20 @@ macro_rules! impl_cmac { }; } +// ====================================================================== +// Stamp out both AES-CMAC types +// ====================================================================== + impl_cmac!( WolfCmacAes128, - wolfcrypt_rs::wolfcrypt_cmac_aes128_new, + wolfcrypt_rs::EVP_aes_128_cbc, U16, - cfg(wolfssl_cmac) + cfg(all(wolfssl_openssl_extra, wolfssl_cmac)) ); impl_cmac!( WolfCmacAes256, - wolfcrypt_rs::wolfcrypt_cmac_aes256_new, + wolfcrypt_rs::EVP_aes_256_cbc, U32, - cfg(wolfssl_cmac) + cfg(all(wolfssl_openssl_extra, wolfssl_cmac)) ); diff --git a/wolfcrypt/src/cryptocb.rs b/wolfcrypt/src/cryptocb.rs index e3e9487..0dd76e3 100644 --- a/wolfcrypt/src/cryptocb.rs +++ b/wolfcrypt/src/cryptocb.rs @@ -16,14 +16,6 @@ //! 4. wolfCrypt calls your trait methods. Returning //! [`CryptoCallbackResult::NotAvailable`] falls back to software. //! -//! # Opaque pointers -//! -//! Some request fields (e.g. `EcdsaSignRequest::key`, `AesGcmEncRequest::aes`) -//! are raw `*mut c_void` pointers to wolfCrypt C structs. To call wolfCrypt -//! helper functions on them (e.g. `wc_ecc_export_private_only`, reading -//! `aes->keylen`), use the accessor shims in `wolfcrypt_rs` or cast to -//! `wolfcrypt_sys` types. All pointer dereferences require `unsafe`. -//! //! # Example //! //! ```rust,ignore @@ -36,13 +28,15 @@ //! //! impl CryptoCallbacks for MyHsm { //! fn rng(&self, req: RngRequest<'_>) -> CryptoCallbackResult { +//! // Fill buffer from hardware RNG //! my_hw_random_fill(req.out); //! CryptoCallbackResult::Success //! } //! } //! +//! let hsm = MyHsm; //! let dev_id = 42; -//! register_device(dev_id, MyHsm).expect("register"); +//! register_device(dev_id, hsm).expect("register"); //! // ... use dev_id when creating wolfCrypt objects ... //! unregister_device(dev_id); //! ``` @@ -69,6 +63,7 @@ pub enum CryptoCallbackResult { } impl CryptoCallbackResult { + /// Convert to the C return code wolfCrypt expects. fn to_c(self) -> c_int { match self { Self::Success => 0, @@ -79,7 +74,7 @@ impl CryptoCallbackResult { } // --------------------------------------------------------------------------- -// Request types โ€” RNG and hash (data fully exposed as slices) +// Request types โ€” typed views of wc_CryptoInfo fields // --------------------------------------------------------------------------- /// A request to generate random bytes. @@ -108,166 +103,18 @@ pub struct HmacRequest<'a> { pub digest: Option<&'a mut [u8]>, } -// --------------------------------------------------------------------------- -// Request types โ€” cipher -// --------------------------------------------------------------------------- - -/// AES-GCM encrypt request. -/// -/// `aes` is an opaque `Aes*` pointer. Use [`wolfcrypt_rs::wolfcrypt_aes_keylen`] -/// and [`wolfcrypt_rs::wolfcrypt_aes_devkey`] to extract the key length and key -/// bytes for hardware programming. -pub struct AesGcmEncRequest<'a> { - /// Opaque `Aes*` pointer โ€” use wolfcrypt_rs Aes accessors for key/reg. - pub aes: *mut c_void, - /// Plaintext input. - pub input: &'a [u8], - /// Ciphertext output (same length as `input`). - pub out: &'a mut [u8], - /// IV / nonce. - pub iv: &'a [u8], - /// Authentication tag output (written by the callback). - pub auth_tag: &'a mut [u8], - /// Additional authenticated data. - pub auth_in: &'a [u8], -} - -/// AES-GCM decrypt request. -/// -/// On authentication failure return [`CryptoCallbackResult::Error`] with the -/// wolfCrypt `AES_GCM_AUTH_E` error code (`-180`). -pub struct AesGcmDecRequest<'a> { - /// Opaque `Aes*` pointer. - pub aes: *mut c_void, - /// Ciphertext input. - pub input: &'a [u8], - /// Plaintext output (same length as `input`). - pub out: &'a mut [u8], - /// IV / nonce. - pub iv: &'a [u8], - /// Authentication tag to verify (read-only on decrypt). - pub auth_tag: &'a [u8], - /// Additional authenticated data. - pub auth_in: &'a [u8], -} - -/// AES-CBC encrypt or decrypt request. -/// -/// The `encrypting` flag distinguishes the direction. Both share the same -/// struct layout because the underlying `wc_CryptoInfo.cipher.aescbc` struct -/// does not duplicate fields for enc/dec. -/// -/// The IV for CBC is stored in `aes->reg`. Use -/// [`wolfcrypt_rs::wolfcrypt_aes_reg`] to read it and -/// [`wolfcrypt_rs::wolfcrypt_aes_reg_mut`] to update it after the operation -/// (wolfCrypt expects the chaining register to be updated in-place). -pub struct AesCbcRequest<'a> { - /// Opaque `Aes*` pointer. - pub aes: *mut c_void, +/// A cipher operation request (encrypt or decrypt). +pub struct CipherRequest { + /// Cipher type constant (e.g. `WC_CIPHER_AES_GCM`). + pub cipher_type: i32, /// `true` for encryption, `false` for decryption. pub encrypting: bool, - /// Input data (must be a multiple of 16 bytes for CBC). - pub input: &'a [u8], - /// Output buffer (same length as `input`). - pub out: &'a mut [u8], } -/// A symmetric cipher callback request. -pub enum CipherRequest<'a> { - /// AES-GCM encryption. - AesGcmEncrypt(AesGcmEncRequest<'a>), - /// AES-GCM decryption. - AesGcmDecrypt(AesGcmDecRequest<'a>), - /// AES-CBC encryption or decryption (direction in `AesCbcRequest::encrypting`). - AesCbc(AesCbcRequest<'a>), - /// Any cipher type not covered by the variants above. - Unknown { - /// `cipher_type` field of `wc_CryptoInfo.cipher`. - cipher_type: i32, - /// `enc` field of `wc_CryptoInfo.cipher`. - encrypting: bool, - }, -} - -// --------------------------------------------------------------------------- -// Request types โ€” public key -// --------------------------------------------------------------------------- - -/// ECDSA sign request. -/// -/// `key` is an opaque `ecc_key*` pointer. Call wolfCrypt helpers such as -/// `wc_ecc_export_private_only` to extract the key material for hardware. -/// -/// On success: write the DER-encoded signature to `out[..n]` and set -/// `*out_len = n`. `out` is pre-sized to the initial value of `*out_len`. -pub struct EcdsaSignRequest<'a> { - /// Opaque `ecc_key*` pointer. - pub key: *mut c_void, - /// Pre-computed hash (digest) to sign. - pub hash: &'a [u8], - /// Output buffer for the DER-encoded signature. - pub out: &'a mut [u8], - /// Initially the capacity of `out`; callback must set to bytes written. - pub out_len: *mut u32, - /// Opaque `WC_RNG*` pointer. - pub rng: *mut c_void, -} - -/// ECDSA verify request. -/// -/// On success set `*result = 1`. On signature mismatch return -/// [`CryptoCallbackResult::Error`] with `VERIFY_SIGN_ERROR` (-330) and set -/// `*result = 0`. -pub struct EcdsaVerifyRequest<'a> { - /// Opaque `ecc_key*` pointer. - pub key: *mut c_void, - /// DER-encoded signature to verify. - pub sig: &'a [u8], - /// Pre-computed hash (digest) to verify against. - pub hash: &'a [u8], - /// Set to `1` on success, `0` on failure. - pub result: *mut c_int, -} - -/// ECDH shared-secret request. -/// -/// On success: write the 48-byte shared secret to `out[..48]` and set -/// `*out_len = 48`. -pub struct EcdhRequest<'a> { - /// Opaque private `ecc_key*` pointer. - pub private_key: *mut c_void, - /// Opaque public `ecc_key*` pointer (peer's key). - pub public_key: *mut c_void, - /// Output buffer for the shared secret. - pub out: &'a mut [u8], - /// Initially the capacity of `out`; callback must set to bytes written. - pub out_len: *mut u32, -} - -/// EC key generation request. -pub struct EcKeyGenRequest { - /// Opaque `ecc_key*` pointer โ€” the callback must fill this key. - pub key: *mut c_void, - /// Requested key size in bits. - pub size: i32, - /// Curve ID (e.g. `ECC_SECP384R1 = 15`). - pub curve_id: i32, - /// Opaque `WC_RNG*` pointer. - pub rng: *mut c_void, -} - -/// A public-key callback request. -pub enum PkRequest<'a> { - /// ECDSA sign. - EcdsaSign(EcdsaSignRequest<'a>), - /// ECDSA verify. - EcdsaVerify(EcdsaVerifyRequest<'a>), - /// ECDH shared secret. - Ecdh(EcdhRequest<'a>), - /// EC key generation. - EcKeyGen(EcKeyGenRequest), - /// Any PK type not covered by the variants above. - Unknown(i32), +/// A public-key operation request. +pub struct PkRequest { + /// PK type constant (e.g. `WC_PK_TYPE_RSA`, `WC_PK_TYPE_ECDSA_SIGN`). + pub pk_type: i32, } // --------------------------------------------------------------------------- @@ -282,9 +129,8 @@ pub enum PkRequest<'a> { /// /// # Safety /// -/// Callback methods are invoked from within wolfCrypt's C code. -/// Implementations must be `Send + Sync`. Methods receive raw `*mut c_void` -/// pointers for opaque C types; dereferencing them requires `unsafe`. +/// Callback methods are invoked from within wolfCrypt's C code, potentially +/// from any thread. Implementations must be `Send + Sync`. pub trait CryptoCallbacks: Send + Sync { /// Generate random bytes. fn rng(&self, _req: RngRequest<'_>) -> CryptoCallbackResult { @@ -302,12 +148,16 @@ pub trait CryptoCallbacks: Send + Sync { } /// Symmetric cipher operation. - fn cipher(&self, _req: CipherRequest<'_>) -> CryptoCallbackResult { + /// + /// The default returns `NotAvailable`. A real implementation would + /// read the raw `wc_CryptoInfo` via the fields in [`CipherRequest`] + /// and perform the cipher operation in hardware. + fn cipher(&self, _req: CipherRequest) -> CryptoCallbackResult { CryptoCallbackResult::NotAvailable } - /// Public-key operation (ECDSA sign/verify, ECDH, EC key generation, etc.). - fn pk(&self, _req: PkRequest<'_>) -> CryptoCallbackResult { + /// Public-key operation (RSA, ECDSA, ECDH, Ed25519, etc.). + fn pk(&self, _req: PkRequest) -> CryptoCallbackResult { CryptoCallbackResult::NotAvailable } } @@ -316,16 +166,18 @@ pub trait CryptoCallbacks: Send + Sync { // Registration // --------------------------------------------------------------------------- +/// State held behind the `void* ctx` pointer passed to wolfCrypt. +/// Boxed so the pointer is stable across moves. struct DeviceState { callbacks: Box, } -/// The C trampoline called by wolfCrypt. Dispatches to the Rust trait. +/// The C trampoline called by wolfCrypt. It dispatches to the Rust trait. /// /// # Safety /// -/// `ctx` must point to a live `DeviceState`. -/// `info` must be a valid `wc_CryptoInfo` pointer. +/// `ctx` must point to a live `DeviceState` (guaranteed by `register_device`). +/// `info` must be a valid `wc_CryptoInfo` pointer from wolfCrypt. unsafe extern "C" fn trampoline( _dev_id: c_int, info: *mut wolfcrypt_rs::wc_CryptoInfo, @@ -336,261 +188,84 @@ unsafe extern "C" fn trampoline( } let state = unsafe { &*(ctx as *const DeviceState) }; - let info_c = info as *const wolfcrypt_rs::wc_CryptoInfo; - let info_m = info; + let info_ptr = info as *const wolfcrypt_rs::wc_CryptoInfo; - let algo_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_get_algo_type(info_c) }; + let algo_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_get_algo_type(info_ptr) }; let result = match algo_type { wolfcrypt_rs::WC_ALGO_TYPE_RNG => { - let out_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_rng_out(info_c) }; - let sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_rng_sz(info_c) } as usize; + let out_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_rng_out(info_ptr) }; + let sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_rng_sz(info_ptr) } as usize; if out_ptr.is_null() || sz == 0 { - return wolfcrypt_rs::CRYPTOCB_UNAVAILABLE; + CryptoCallbackResult::NotAvailable + } else { + let out = unsafe { core::slice::from_raw_parts_mut(out_ptr, sz) }; + state.callbacks.rng(RngRequest { out }) } - let out = unsafe { core::slice::from_raw_parts_mut(out_ptr, sz) }; - state.callbacks.rng(RngRequest { out }) } - wolfcrypt_rs::WC_ALGO_TYPE_HASH => { - let hash_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_type(info_c) }; - let in_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_in(info_c) }; - let in_sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_in_sz(info_c) } as usize; - let digest_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_digest(info_c) }; + let hash_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_type(info_ptr) }; + let in_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_in(info_ptr) }; + let in_sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_in_sz(info_ptr) } as usize; + let digest_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hash_digest(info_ptr) }; - let input = if !in_ptr.is_null() && in_sz > 0 { - unsafe { core::slice::from_raw_parts(in_ptr, in_sz) } - } else { + let input = if in_ptr.is_null() || in_sz == 0 { &[] + } else { + unsafe { core::slice::from_raw_parts(in_ptr, in_sz) } }; - // Conservative upper bound: 64 bytes covers SHA-512. + + // For finalize, digest is non-null. We need the digest size + // but wc_CryptoInfo doesn't directly carry it. We use a + // conservative upper bound (64 bytes = SHA-512 output). let digest = if digest_ptr.is_null() { None } else { + // The caller is responsible for providing a correctly-sized + // buffer; we pass up to 64 bytes (max digest for SHA-512). Some(unsafe { core::slice::from_raw_parts_mut(digest_ptr, 64) }) }; + state.callbacks.hash(HashRequest { hash_type, input, digest }) } - wolfcrypt_rs::WC_ALGO_TYPE_HMAC => { - let mac_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_mac_type(info_c) }; - let in_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_in(info_c) }; - let in_sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_in_sz(info_c) } as usize; - let digest_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_digest(info_c) }; + let mac_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_mac_type(info_ptr) }; + let in_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_in(info_ptr) }; + let in_sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_in_sz(info_ptr) } as usize; + let digest_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_hmac_digest(info_ptr) }; - let input = if !in_ptr.is_null() && in_sz > 0 { - unsafe { core::slice::from_raw_parts(in_ptr, in_sz) } - } else { + let input = if in_ptr.is_null() || in_sz == 0 { &[] + } else { + unsafe { core::slice::from_raw_parts(in_ptr, in_sz) } }; + let digest = if digest_ptr.is_null() { None } else { Some(unsafe { core::slice::from_raw_parts_mut(digest_ptr, 64) }) }; + state.callbacks.hmac(HmacRequest { mac_type, input, digest }) } - wolfcrypt_rs::WC_ALGO_TYPE_CIPHER => { - let cipher_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_type(info_c) }; - let enc = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_enc(info_c) }; - - #[cfg(wolfssl_aes_gcm)] - if cipher_type == wolfcrypt_rs::WC_CIPHER_AES_GCM { - return build_cipher_aesgcm(state, info_c, info_m, enc != 0); - } - if cipher_type == wolfcrypt_rs::WC_CIPHER_AES_CBC { - return build_cipher_aescbc(state, info_c, info_m, enc != 0); - } - state.callbacks.cipher(CipherRequest::Unknown { + let cipher_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_type(info_ptr) }; + let enc = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_enc(info_ptr) }; + state.callbacks.cipher(CipherRequest { cipher_type, encrypting: enc != 0, }) } - wolfcrypt_rs::WC_ALGO_TYPE_PK => { - let pk_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_type(info_c) }; - - #[cfg(wolfssl_ecc)] - { - if pk_type == wolfcrypt_rs::WC_PK_TYPE_ECDSA_SIGN { - return build_pk_ecdsasign(state, info_c, info_m); - } - if pk_type == wolfcrypt_rs::WC_PK_TYPE_ECDSA_VERIFY { - return build_pk_ecdsaverify(state, info_c, info_m); - } - if pk_type == wolfcrypt_rs::WC_PK_TYPE_ECDH { - return build_pk_ecdh(state, info_c, info_m); - } - if pk_type == wolfcrypt_rs::WC_PK_TYPE_EC_KEYGEN { - return build_pk_eckg(state, info_c); - } - } - state.callbacks.pk(PkRequest::Unknown(pk_type)) + let pk_type = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_type(info_ptr) }; + state.callbacks.pk(PkRequest { pk_type }) } - _ => CryptoCallbackResult::NotAvailable, }; result.to_c() } -// --------------------------------------------------------------------------- -// Trampoline helpers โ€” build typed requests and call the trait -// --------------------------------------------------------------------------- - -#[cfg(wolfssl_aes_gcm)] -unsafe fn build_cipher_aesgcm( - state: &DeviceState, - info_c: *const wolfcrypt_rs::wc_CryptoInfo, - info_m: *mut wolfcrypt_rs::wc_CryptoInfo, - encrypting: bool, -) -> c_int { - if encrypting { - let aes = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_aes(info_c) }; - let out = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_out(info_m) }; - let inp = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_in(info_c) }; - let sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_sz(info_c) } as usize; - let iv = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_iv(info_c) }; - let ivsz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_iv_sz(info_c) } as usize; - let tag = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_tag(info_m) }; - let tagsz= unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_tag_sz(info_c) } as usize; - let ain = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_in(info_c) }; - let ainsz= unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_enc_auth_in_sz(info_c) } as usize; - - let input = if !inp.is_null() && sz > 0 { unsafe { core::slice::from_raw_parts(inp, sz) } } else { &[] }; - let out_sl = if !out.is_null() && sz > 0 { unsafe { core::slice::from_raw_parts_mut(out, sz) } } else { &mut [] }; - let iv_sl = if !iv.is_null() && ivsz > 0 { unsafe { core::slice::from_raw_parts(iv, ivsz) } } else { &[] }; - let tag_sl = if !tag.is_null() && tagsz > 0 { unsafe { core::slice::from_raw_parts_mut(tag, tagsz) } } else { &mut [] }; - let auth_in = if !ain.is_null() && ainsz > 0 { unsafe { core::slice::from_raw_parts(ain, ainsz) } } else { &[] }; - - state.callbacks.cipher(CipherRequest::AesGcmEncrypt(AesGcmEncRequest { - aes, input, out: out_sl, iv: iv_sl, auth_tag: tag_sl, auth_in, - })).to_c() - } else { - let aes = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_aes(info_c) }; - let out = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_out(info_m) }; - let inp = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_in(info_c) }; - let sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_sz(info_c) } as usize; - let iv = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_iv(info_c) }; - let ivsz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_iv_sz(info_c) } as usize; - let tag = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_tag(info_c) }; - let tagsz= unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_tag_sz(info_c) } as usize; - let ain = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_in(info_c) }; - let ainsz= unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aesgcm_dec_auth_in_sz(info_c) } as usize; - - let input = if !inp.is_null() && sz > 0 { unsafe { core::slice::from_raw_parts(inp, sz) } } else { &[] }; - let out_sl = if !out.is_null() && sz > 0 { unsafe { core::slice::from_raw_parts_mut(out, sz) } } else { &mut [] }; - let iv_sl = if !iv.is_null() && ivsz > 0 { unsafe { core::slice::from_raw_parts(iv, ivsz) } } else { &[] }; - let tag_sl = if !tag.is_null() && tagsz > 0 { unsafe { core::slice::from_raw_parts(tag, tagsz) } } else { &[] }; - let auth_in = if !ain.is_null() && ainsz > 0 { unsafe { core::slice::from_raw_parts(ain, ainsz) } } else { &[] }; - - state.callbacks.cipher(CipherRequest::AesGcmDecrypt(AesGcmDecRequest { - aes, input, out: out_sl, iv: iv_sl, auth_tag: tag_sl, auth_in, - })).to_c() - } -} - -unsafe fn build_cipher_aescbc( - state: &DeviceState, - info_c: *const wolfcrypt_rs::wc_CryptoInfo, - info_m: *mut wolfcrypt_rs::wc_CryptoInfo, - encrypting: bool, -) -> c_int { - let aes = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aescbc_aes(info_c) }; - let out = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aescbc_out(info_m) }; - let inp = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aescbc_in(info_c) }; - let sz = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_cipher_aescbc_sz(info_c) } as usize; - - let input = if !inp.is_null() && sz > 0 { unsafe { core::slice::from_raw_parts(inp, sz) } } else { &[] }; - let out_sl = if !out.is_null() && sz > 0 { unsafe { core::slice::from_raw_parts_mut(out, sz) } } else { &mut [] }; - - state.callbacks.cipher(CipherRequest::AesCbc(AesCbcRequest { - aes, encrypting, input, out: out_sl, - })).to_c() -} - -#[cfg(wolfssl_ecc)] -unsafe fn build_pk_ecdsasign( - state: &DeviceState, - info_c: *const wolfcrypt_rs::wc_CryptoInfo, - info_m: *mut wolfcrypt_rs::wc_CryptoInfo, -) -> c_int { - let key = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccsign_key(info_c) }; - let in_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccsign_in(info_c) }; - let inlen = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccsign_inlen(info_c) } as usize; - let out_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccsign_out(info_m) }; - let out_len = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccsign_outlen(info_m) }; - let rng = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccsign_rng(info_c) }; - - let hash = if !in_ptr.is_null() && inlen > 0 { unsafe { core::slice::from_raw_parts(in_ptr, inlen) } } else { &[] }; - let cap = if out_len.is_null() { 0 } else { unsafe { *out_len } as usize }; - let out = if !out_ptr.is_null() && cap > 0 { unsafe { core::slice::from_raw_parts_mut(out_ptr, cap) } } else { &mut [] }; - - state.callbacks.pk(PkRequest::EcdsaSign(EcdsaSignRequest { - key, hash, out, out_len, rng, - })).to_c() -} - -#[cfg(wolfssl_ecc)] -unsafe fn build_pk_ecdsaverify( - state: &DeviceState, - info_c: *const wolfcrypt_rs::wc_CryptoInfo, - info_m: *mut wolfcrypt_rs::wc_CryptoInfo, -) -> c_int { - let key = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccverify_key(info_c) }; - let sig_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccverify_sig(info_c) }; - let siglen = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccverify_siglen(info_c) } as usize; - let hash_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccverify_hash(info_c) }; - let hashlen = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccverify_hashlen(info_c) } as usize; - let result = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eccverify_res(info_m) }; - - let sig = if !sig_ptr.is_null() && siglen > 0 { unsafe { core::slice::from_raw_parts(sig_ptr, siglen) } } else { &[] }; - let hash = if !hash_ptr.is_null() && hashlen > 0 { unsafe { core::slice::from_raw_parts(hash_ptr, hashlen) } } else { &[] }; - - state.callbacks.pk(PkRequest::EcdsaVerify(EcdsaVerifyRequest { - key, sig, hash, result, - })).to_c() -} - -#[cfg(wolfssl_ecc)] -unsafe fn build_pk_ecdh( - state: &DeviceState, - info_c: *const wolfcrypt_rs::wc_CryptoInfo, - info_m: *mut wolfcrypt_rs::wc_CryptoInfo, -) -> c_int { - let private_key = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_ecdh_private_key(info_c) }; - let public_key = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_ecdh_public_key(info_c) }; - let out_ptr = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_ecdh_out(info_m) }; - let out_len = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_ecdh_outlen(info_m) }; - - let cap = if out_len.is_null() { 0 } else { unsafe { *out_len } as usize }; - let out = if !out_ptr.is_null() && cap > 0 { unsafe { core::slice::from_raw_parts_mut(out_ptr, cap) } } else { &mut [] }; - - state.callbacks.pk(PkRequest::Ecdh(EcdhRequest { - private_key, public_key, out, out_len, - })).to_c() -} - -#[cfg(wolfssl_ecc)] -unsafe fn build_pk_eckg( - state: &DeviceState, - info_c: *const wolfcrypt_rs::wc_CryptoInfo, -) -> c_int { - let key = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eckg_key(info_c) }; - let size = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eckg_size(info_c) }; - let curve_id = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eckg_curve_id(info_c) }; - let rng = unsafe { wolfcrypt_rs::wolfcrypt_cryptocb_info_pk_eckg_rng(info_c) }; - - state.callbacks.pk(PkRequest::EcKeyGen(EcKeyGenRequest { - key, size, curve_id, rng, - })).to_c() -} - -// --------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------- - /// Register a crypto callback device. /// /// `dev_id` must be a positive integer (not `INVALID_DEVID`). @@ -624,6 +299,7 @@ pub fn register_device( }; if rc != 0 { + // Registration failed โ€” reclaim the leaked Box. unsafe { drop(Box::from_raw(ctx as *mut DeviceState)); } return Err(WolfCryptError::Ffi { code: rc, func: "wc_CryptoCb_RegisterDevice" }); } @@ -633,24 +309,27 @@ pub fn register_device( /// Unregister a crypto callback device. /// +/// This frees the callback state that was registered with [`register_device`]. +/// /// # Safety /// -/// The caller must ensure no wolfCrypt operations using this `dev_id` are -/// in progress on other threads when this is called. +/// The caller must ensure that no wolfCrypt operations using this `dev_id` +/// are in progress on other threads when this function is called. +/// +/// After this call, any wolfCrypt objects still associated with this +/// `dev_id` will fall through to software or return errors. pub fn unregister_device(dev_id: i32) { - // wolfCrypt doesn't return the ctx pointer on unregister, so we cannot - // reclaim the DeviceState Box here. This leaks the allocation โ€” acceptable - // for long-lived HSM registrations but should be fixed with a side-table - // mapping dev_id -> *mut DeviceState for production use. + // wolfCrypt doesn't return the context pointer on unregister, + // so we can't reclaim the Box here without additional bookkeeping. + // TODO: maintain a side table mapping dev_id -> *mut DeviceState + // so we can drop the Box on unregister. For now, this leaks the + // DeviceState allocation โ€” acceptable for long-lived HSM registrations + // but should be fixed for production use. unsafe { wolfcrypt_rs::wc_CryptoCb_UnRegisterDevice(dev_id); } } -// --------------------------------------------------------------------------- -// Re-exported constants -// --------------------------------------------------------------------------- - /// Re-export the constants callers need for matching operation types. pub mod algo_type { pub use wolfcrypt_rs::WC_ALGO_TYPE_NONE; diff --git a/wolfcrypt/src/des3.rs b/wolfcrypt/src/des3.rs index 2d25baf..42948fc 100644 --- a/wolfcrypt/src/des3.rs +++ b/wolfcrypt/src/des3.rs @@ -3,10 +3,10 @@ //! Provides [`DesEde3CbcEnc`] and [`DesEde3CbcDec`] implementing the //! RustCrypto `BlockEncryptMut`/`BlockDecryptMut` and `KeyIvInit` traits. //! -//! Uses wolfCrypt's native wc_Des3* API with padding disabled, so +//! Uses wolfSSL's EVP API (`EVP_des_ede3_cbc`) with padding disabled, so //! callers must provide data in exact multiples of the 8-byte block size. //! -//! Gated on `cfg(wolfssl_des3)`. +//! Gated on `cfg(wolfssl_openssl_extra)` and `cfg(wolfssl_des3)`. use cipher_trait::generic_array::GenericArray; use cipher_trait::inout::InOut; @@ -14,6 +14,7 @@ use cipher_trait::{ Block, BlockBackend, BlockClosure, BlockDecryptMut, BlockEncryptMut, BlockSizeUser, IvSizeUser, KeyIvInit, KeySizeUser, ParBlocksSizeUser, }; +use core::ffi::c_int; use typenum::{U1, U8, U24}; pub use cipher_trait; @@ -22,90 +23,99 @@ pub use cipher_trait; // 3DES-CBC encrypt // --------------------------------------------------------------------------- -/// Triple-DES CBC encryption using the native wolfCrypt wc_Des3* API. +/// Triple-DES CBC encryption using the EVP API. /// /// Key: 24 bytes (3 x 8-byte DES keys). /// Block size: 8 bytes. /// IV: 8 bytes. -#[cfg(wolfssl_des3)] pub struct DesEde3CbcEnc { - ctx: *mut core::ffi::c_void, + ctx: *mut wolfcrypt_rs::EVP_CIPHER_CTX, } -#[cfg(wolfssl_des3)] -// SAFETY: Des3 context is heap-allocated and self-contained. +// SAFETY: EVP_CIPHER_CTX is heap-allocated, self-contained, and thread-safe. unsafe impl Send for DesEde3CbcEnc {} -#[cfg(wolfssl_des3)] impl Drop for DesEde3CbcEnc { fn drop(&mut self) { if !self.ctx.is_null() { - // SAFETY: ctx was allocated by wolfcrypt_des3_enc_new. - unsafe { wolfcrypt_rs::wolfcrypt_des3_free(self.ctx) }; + // SAFETY: `self.ctx` was allocated by `EVP_CIPHER_CTX_new`. + unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_free(self.ctx) }; } } } -#[cfg(wolfssl_des3)] impl KeySizeUser for DesEde3CbcEnc { - type KeySize = U24; + type KeySize = U24; // 192-bit key (3 x 64-bit DES keys) } -#[cfg(wolfssl_des3)] impl IvSizeUser for DesEde3CbcEnc { - type IvSize = U8; + type IvSize = U8; // 64-bit IV } -#[cfg(wolfssl_des3)] impl BlockSizeUser for DesEde3CbcEnc { - type BlockSize = U8; + type BlockSize = U8; // 64-bit block } -#[cfg(wolfssl_des3)] impl KeyIvInit for DesEde3CbcEnc { fn new(key: &GenericArray, iv: &GenericArray) -> Self { - // SAFETY: key is 24 bytes, iv is 8 bytes. - let ctx = unsafe { - wolfcrypt_rs::wolfcrypt_des3_enc_new(key.as_ptr(), iv.as_ptr()) + // SAFETY: `EVP_CIPHER_CTX_new` allocates a new context. + let ctx = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_new() }; + assert!(!ctx.is_null(), "EVP_CIPHER_CTX_new returned null"); + + // SAFETY: `ctx` is valid. `EVP_des_ede3_cbc()` returns a static + // cipher descriptor. key is 24 bytes, iv is 8 bytes. + let rc = unsafe { + wolfcrypt_rs::EVP_EncryptInit_ex( + ctx, + wolfcrypt_rs::EVP_des_ede3_cbc(), + core::ptr::null_mut(), + key.as_ptr(), + iv.as_ptr(), + ) }; - assert!(!ctx.is_null(), "wolfcrypt_des3_enc_new returned null"); + assert_eq!(rc, 1, "EVP_EncryptInit_ex failed (OOM or invalid cipher)"); + + // Disable padding โ€” we operate at the block level. + // SAFETY: `ctx` is initialized. + let rc = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_set_padding(ctx, 0) }; + assert_eq!(rc, 1, "EVP_CIPHER_CTX_set_padding failed (context not initialized)"); + Self { ctx } } } -#[cfg(wolfssl_des3)] -struct DesEde3CbcEncBackend(*mut core::ffi::c_void); +/// Backend that encrypts one 8-byte block via EVP_EncryptUpdate. +struct DesEde3CbcEncBackend(*mut wolfcrypt_rs::EVP_CIPHER_CTX); -#[cfg(wolfssl_des3)] impl BlockSizeUser for DesEde3CbcEncBackend { type BlockSize = U8; } -#[cfg(wolfssl_des3)] impl ParBlocksSizeUser for DesEde3CbcEncBackend { type ParBlocksSize = U1; } -#[cfg(wolfssl_des3)] impl BlockBackend for DesEde3CbcEncBackend { #[inline] fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { let mut tmp = [0u8; 8]; - // SAFETY: block.get_in() is a valid 8-byte input; tmp is a valid 8-byte output. + let mut outl: c_int = 0; + // SAFETY: `self.0` is a valid EVP_CIPHER_CTX initialized for + // 3DES-CBC encryption. Input and output are 8-byte blocks. let rc = unsafe { - wolfcrypt_rs::wolfcrypt_des3_cbc_encrypt( + wolfcrypt_rs::EVP_EncryptUpdate( self.0, - block.get_in().as_ptr(), tmp.as_mut_ptr(), + &mut outl, + block.get_in().as_ptr(), 8, ) }; - assert_eq!(rc, 0, "wolfcrypt_des3_cbc_encrypt failed"); + assert_eq!(rc, 1, "EVP_EncryptUpdate failed (context not initialized)"); block.get_out().copy_from_slice(&tmp); } } -#[cfg(wolfssl_des3)] impl BlockEncryptMut for DesEde3CbcEnc { fn encrypt_with_backend_mut( &mut self, @@ -119,90 +129,98 @@ impl BlockEncryptMut for DesEde3CbcEnc { // 3DES-CBC decrypt // --------------------------------------------------------------------------- -/// Triple-DES CBC decryption using the native wolfCrypt wc_Des3* API. +/// Triple-DES CBC decryption using the EVP API. /// /// Key: 24 bytes (3 x 8-byte DES keys). /// Block size: 8 bytes. /// IV: 8 bytes. -#[cfg(wolfssl_des3)] pub struct DesEde3CbcDec { - ctx: *mut core::ffi::c_void, + ctx: *mut wolfcrypt_rs::EVP_CIPHER_CTX, } -#[cfg(wolfssl_des3)] -// SAFETY: Des3 context is heap-allocated and self-contained. +// SAFETY: EVP_CIPHER_CTX is heap-allocated, self-contained, and thread-safe. unsafe impl Send for DesEde3CbcDec {} -#[cfg(wolfssl_des3)] impl Drop for DesEde3CbcDec { fn drop(&mut self) { if !self.ctx.is_null() { - // SAFETY: ctx was allocated by wolfcrypt_des3_dec_new. - unsafe { wolfcrypt_rs::wolfcrypt_des3_free(self.ctx) }; + // SAFETY: `self.ctx` was allocated by `EVP_CIPHER_CTX_new`. + unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_free(self.ctx) }; } } } -#[cfg(wolfssl_des3)] impl KeySizeUser for DesEde3CbcDec { - type KeySize = U24; + type KeySize = U24; // 192-bit key } -#[cfg(wolfssl_des3)] impl IvSizeUser for DesEde3CbcDec { - type IvSize = U8; + type IvSize = U8; // 64-bit IV } -#[cfg(wolfssl_des3)] impl BlockSizeUser for DesEde3CbcDec { - type BlockSize = U8; + type BlockSize = U8; // 64-bit block } -#[cfg(wolfssl_des3)] impl KeyIvInit for DesEde3CbcDec { fn new(key: &GenericArray, iv: &GenericArray) -> Self { - // SAFETY: key is 24 bytes, iv is 8 bytes. - let ctx = unsafe { - wolfcrypt_rs::wolfcrypt_des3_dec_new(key.as_ptr(), iv.as_ptr()) + // SAFETY: `EVP_CIPHER_CTX_new` allocates a new context. + let ctx = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_new() }; + assert!(!ctx.is_null(), "EVP_CIPHER_CTX_new returned null"); + + // SAFETY: `ctx` is valid. `EVP_des_ede3_cbc()` returns a static + // cipher descriptor. key is 24 bytes, iv is 8 bytes. + let rc = unsafe { + wolfcrypt_rs::EVP_DecryptInit_ex( + ctx, + wolfcrypt_rs::EVP_des_ede3_cbc(), + core::ptr::null_mut(), + key.as_ptr(), + iv.as_ptr(), + ) }; - assert!(!ctx.is_null(), "wolfcrypt_des3_dec_new returned null"); + assert_eq!(rc, 1, "EVP_DecryptInit_ex failed (OOM or invalid cipher)"); + + // Disable padding โ€” we operate at the block level. + let rc = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_set_padding(ctx, 0) }; + assert_eq!(rc, 1, "EVP_CIPHER_CTX_set_padding failed (context not initialized)"); + Self { ctx } } } -#[cfg(wolfssl_des3)] -struct DesEde3CbcDecBackend(*mut core::ffi::c_void); +/// Backend that decrypts one 8-byte block via EVP_DecryptUpdate. +struct DesEde3CbcDecBackend(*mut wolfcrypt_rs::EVP_CIPHER_CTX); -#[cfg(wolfssl_des3)] impl BlockSizeUser for DesEde3CbcDecBackend { type BlockSize = U8; } -#[cfg(wolfssl_des3)] impl ParBlocksSizeUser for DesEde3CbcDecBackend { type ParBlocksSize = U1; } -#[cfg(wolfssl_des3)] impl BlockBackend for DesEde3CbcDecBackend { #[inline] fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { let mut tmp = [0u8; 8]; - // SAFETY: block.get_in() is a valid 8-byte input; tmp is a valid 8-byte output. + let mut outl: c_int = 0; + // SAFETY: `self.0` is a valid EVP_CIPHER_CTX initialized for + // 3DES-CBC decryption. Input and output are 8-byte blocks. let rc = unsafe { - wolfcrypt_rs::wolfcrypt_des3_cbc_decrypt( + wolfcrypt_rs::EVP_DecryptUpdate( self.0, - block.get_in().as_ptr(), tmp.as_mut_ptr(), + &mut outl, + block.get_in().as_ptr(), 8, ) }; - assert_eq!(rc, 0, "wolfcrypt_des3_cbc_decrypt failed"); + assert_eq!(rc, 1, "EVP_DecryptUpdate failed (context not initialized)"); block.get_out().copy_from_slice(&tmp); } } -#[cfg(wolfssl_des3)] impl BlockDecryptMut for DesEde3CbcDec { fn decrypt_with_backend_mut( &mut self, diff --git a/wolfcrypt/src/dh.rs b/wolfcrypt/src/dh.rs index 0ccd22e..914f53b 100644 --- a/wolfcrypt/src/dh.rs +++ b/wolfcrypt/src/dh.rs @@ -5,20 +5,16 @@ //! FFDHE4096). //! //! There is no standard RustCrypto trait for classic DH, so this module -//! exposes a custom API backed by wolfCrypt's native wc_Dh* functions. +//! exposes a custom API backed by wolfSSL's OpenSSL-compatible DH functions. //! -//! Gated on `cfg(wolfssl_dh)`. +//! Gated on `cfg(wolfssl_openssl_extra)` and `cfg(wolfssl_dh)`. extern crate alloc; use alloc::vec; use alloc::vec::Vec; +use core::ffi::c_int; -use crate::error::WolfCryptError; - -// Named-group constants match wolfssl/wolfcrypt/dh.h WC_FFDHE_* enum. -const WC_FFDHE_2048: i32 = 256; -const WC_FFDHE_3072: i32 = 257; -const WC_FFDHE_4096: i32 = 258; +use crate::error::{len_as_c_int, WolfCryptError}; /// Predefined FFDHE group selection. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -32,65 +28,57 @@ pub enum FfdheGroup { } impl FfdheGroup { - fn wc_name(self) -> i32 { - match self { - FfdheGroup::Ffdhe2048 => WC_FFDHE_2048, - FfdheGroup::Ffdhe3072 => WC_FFDHE_3072, - FfdheGroup::Ffdhe4096 => WC_FFDHE_4096, - } - } - - fn byte_size(self) -> usize { + fn nid(self) -> c_int { match self { - FfdheGroup::Ffdhe2048 => 256, - FfdheGroup::Ffdhe3072 => 384, - FfdheGroup::Ffdhe4096 => 512, + FfdheGroup::Ffdhe2048 => wolfcrypt_rs::NID_ffdhe2048, + FfdheGroup::Ffdhe3072 => wolfcrypt_rs::NID_ffdhe3072, + FfdheGroup::Ffdhe4096 => wolfcrypt_rs::NID_ffdhe4096, } } } /// A DH key pair for classic Diffie-Hellman key exchange. /// -/// Wraps a heap-allocated wolfCrypt `DhKey` context managed by C shims in -/// `compat_shim.c`. The private and public key components are generated -/// inside wolfCrypt and never exposed directly. +/// Wraps a heap-allocated wolfSSL `DH` structure. The private and public +/// key components are generated inside wolfSSL. pub struct DhSecret { - ctx: *mut core::ffi::c_void, - group_sz: usize, + dh: *mut wolfcrypt_rs::DH, } -// SAFETY: The DhKey context is heap-allocated and self-contained. +// SAFETY: The DH struct is heap-allocated and self-contained; it is safe to +// move ownership to another thread. unsafe impl Send for DhSecret {} impl Drop for DhSecret { fn drop(&mut self) { - if !self.ctx.is_null() { - // SAFETY: ctx was allocated by wolfcrypt_dh_new. - unsafe { wolfcrypt_rs::wolfcrypt_dh_free(self.ctx) }; + if !self.dh.is_null() { + // SAFETY: `self.dh` was allocated by `DH_new_by_nid` and is non-null. + unsafe { wolfcrypt_rs::DH_free(self.dh) }; } } } impl DhSecret { /// Generate a new DH key pair using the specified FFDHE group. + /// + /// Calls `DH_new_by_nid` to load the named group parameters, then + /// `DH_generate_key` to produce a fresh private/public key pair. pub fn generate(group: FfdheGroup) -> Result { - // SAFETY: wolfcrypt_dh_new allocates a DhKey, initialises it with the - // named group, and returns NULL on any error. - let ctx = unsafe { - wolfcrypt_rs::wolfcrypt_dh_new(group.wc_name(), group.byte_size() as u32) - }; - if ctx.is_null() { + // SAFETY: `DH_new_by_nid` returns a heap-allocated DH or NULL on error. + let dh = unsafe { wolfcrypt_rs::DH_new_by_nid(group.nid()) }; + if dh.is_null() { return Err(WolfCryptError::ALLOC_FAILED); } - // SAFETY: ctx is a valid, fully-parametrised DhKey context. - let rc = unsafe { wolfcrypt_rs::wolfcrypt_dh_generate_keypair(ctx) }; - if rc != 0 { - unsafe { wolfcrypt_rs::wolfcrypt_dh_free(ctx) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_dh_generate_keypair" }); + // SAFETY: `dh` is a valid, fully-parametrized DH structure. + // `DH_generate_key` returns 1 on success (OpenSSL convention). + let rc = unsafe { wolfcrypt_rs::DH_generate_key(dh) }; + if rc != 1 { + unsafe { wolfcrypt_rs::DH_free(dh) }; + return Err(WolfCryptError::Ffi { code: rc, func: "DH_generate_key" }); } - Ok(Self { ctx, group_sz: group.byte_size() }) + Ok(Self { dh }) } /// Generate a DH key pair using FFDHE2048 (convenience wrapper). @@ -98,22 +86,38 @@ impl DhSecret { Self::generate(FfdheGroup::Ffdhe2048) } - /// Return the public key as big-endian bytes, zero-padded to the group size. + /// Return the public key as big-endian bytes. + /// + /// Allocates a `Vec` because the internal BIGNUM is owned by the DH + /// struct and cannot be borrowed out. The cost is negligible next to + /// the modular exponentiation in `generate`. pub fn public_key_bytes(&self) -> Vec { - let mut buf = vec![0u8; self.group_sz]; - let mut len = self.group_sz as u32; - // SAFETY: buf is group_sz bytes, which is the declared output size. - let rc = unsafe { - wolfcrypt_rs::wolfcrypt_dh_public_key(self.ctx, buf.as_mut_ptr(), &mut len) - }; - assert_eq!(rc, 0, "wolfcrypt_dh_public_key failed"); - buf.truncate(len as usize); + let mut pub_key: *const wolfcrypt_rs::BIGNUM = core::ptr::null(); + // SAFETY: `self.dh` was successfully generated. `DH_get0_key` writes + // internal pointers (not copies) into the out-params. We only read + // `pub_key`; `priv_key` is ignored via NULL. + unsafe { + wolfcrypt_rs::DH_get0_key( + self.dh as *const wolfcrypt_rs::DH, + &mut pub_key, + core::ptr::null_mut(), + ); + } + assert!(!pub_key.is_null(), "DH_get0_key returned null pub_key"); + + // SAFETY: `pub_key` is a valid BIGNUM owned by the DH struct. + let len = unsafe { wolfcrypt_rs::BN_num_bytes(pub_key) } as usize; + let mut buf = vec![0u8; len]; + // SAFETY: `buf` is `len` bytes, which is the correct size for this BIGNUM. + unsafe { wolfcrypt_rs::BN_bn2bin(pub_key, buf.as_mut_ptr()) }; buf } /// Return the DH parameter size in bytes (size of the shared secret). pub fn size(&self) -> usize { - self.group_sz + // SAFETY: `self.dh` is a valid DH structure. + let s = unsafe { wolfcrypt_rs::DH_size(self.dh) }; + s as usize } /// Compute the shared secret given the peer's public key bytes (big-endian). @@ -123,31 +127,46 @@ impl DhSecret { /// after a single exchange. /// /// Returns the shared secret wrapped in `Zeroizing` so the key material - /// is automatically zeroized on drop. The output is always padded to - /// the group size to avoid timing side-channels from variable-length results. - pub fn compute_shared_secret( - &self, - peer_pub_bytes: &[u8], - ) -> Result>, WolfCryptError> { - let mut secret = vec![0u8; self.group_sz]; - let mut sz = self.group_sz as u32; - - // SAFETY: peer_pub_bytes is a valid slice; secret is group_sz bytes. - let rc = unsafe { - wolfcrypt_rs::wolfcrypt_dh_agree( - self.ctx, + /// is automatically zeroized on drop. Uses `DH_compute_key_padded` + /// to produce a fixed-length output (padded to the DH size), which avoids + /// timing side-channels from variable-length results. + pub fn compute_shared_secret(&self, peer_pub_bytes: &[u8]) -> Result>, WolfCryptError> { + // Convert peer public key bytes to BIGNUM. + // SAFETY: `BN_bin2bn` with NULL `ret` allocates a new BIGNUM. + let peer_bn = unsafe { + wolfcrypt_rs::BN_bin2bn( peer_pub_bytes.as_ptr(), - peer_pub_bytes.len() as u32, + len_as_c_int(peer_pub_bytes.len()), + core::ptr::null_mut(), + ) + }; + if peer_bn.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + + let dh_size = self.size(); + let mut secret = vec![0u8; dh_size]; + + // SAFETY: `secret` has `dh_size` bytes, `peer_bn` is a valid BIGNUM, + // and `self.dh` holds a generated key pair. `DH_compute_key_padded` + // returns the number of bytes written (== dh_size) or -1 on error. + let rc = unsafe { + wolfcrypt_rs::DH_compute_key_padded( secret.as_mut_ptr(), - &mut sz, + peer_bn as *const wolfcrypt_rs::BIGNUM, + self.dh, ) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_dh_agree" }); + // Free the temporary BIGNUM regardless of outcome. + unsafe { wolfcrypt_rs::BN_free(peer_bn) }; + + if rc < 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "DH_compute_key_padded" }); } - secret.truncate(sz as usize); + // Truncate to actual length (should equal dh_size for padded variant). + secret.truncate(rc as usize); Ok(zeroize::Zeroizing::new(secret)) } } diff --git a/wolfcrypt/src/digest.rs b/wolfcrypt/src/digest.rs index 950fe8c..67cf065 100644 --- a/wolfcrypt/src/digest.rs +++ b/wolfcrypt/src/digest.rs @@ -1,60 +1,75 @@ -//! Digest (hash) algorithms backed by wolfCrypt. +//! Digest (hash) algorithms backed by wolfCrypt's EVP_MD API. //! //! Each type implements the RustCrypto [`digest`](digest_trait) 0.10 traits //! (`OutputSizeUser`, `BlockSizeUser`, `Update`, `FixedOutput`, //! `FixedOutputReset`, `Reset`, `HashMarker`) so they satisfy the //! blanket `Digest` impl automatically. //! -//! All implementations use the native `wc_Sha*` functions via heap-allocated -//! context shims in `compat_shim.c`. This works in any build that includes -//! the corresponding wolfCrypt SHA source files. -//! //! Callers should `use digest_trait::Digest` (re-exported as //! `wolfcrypt::digest::digest_trait`) for the full API: //! `new()`, `update()`, `finalize()`, `finalize_reset()`, `reset()`. +use core::ffi::c_void; use generic_array::GenericArray; use typenum::*; // Re-export the trait crate types we use in our public API. pub use digest_trait; -// ====================================================================== -// Native wc_Sha* digest types. -// -// The context is heap-allocated by compat_shim.c so Rust never needs -// to know the layout of wc_Sha256 / wc_Sha512 / wc_Sha3 / etc. -// ====================================================================== - -/// Internal macro that stamps out a native wc_Sha* digest wrapper. +/// Internal macro that stamps out a complete digest wrapper for one algorithm. /// -/// The generated struct holds an opaque heap-allocated context pointer -/// and delegates all operations to C shim wrappers in compat_shim.c. -macro_rules! impl_digest_native { +/// The generated struct holds a heap-allocated `EVP_MD_CTX` and delegates +/// all hashing to wolfCrypt through the OpenSSL-compat EVP layer. +macro_rules! impl_digest { ( $name:ident, - $new_fn:path, - $update_fn:path, - $final_fn:path, - $free_fn:path, - $copy_fn:path, + $evp_fn:path, $output_size:ty, $block_size:ty, $cfg_gate:meta ) => { #[$cfg_gate] pub struct $name { - ctx: *mut core::ffi::c_void, + ctx: *mut wolfcrypt_rs::EVP_MD_CTX, } + // SAFETY: EVP_MD_CTX is heap-allocated and only accessed through + // &self / &mut self. wolfCrypt's EVP layer is thread-safe when a + // context is used from a single thread, which Rust's ownership + // rules enforce. #[$cfg_gate] unsafe impl Send for $name {} + #[$cfg_gate] + impl $name { + /// Return the algorithm descriptor pointer for this hash. + #[inline] + fn evp_md() -> *const wolfcrypt_rs::EVP_MD { + // SAFETY: EVP_sha* functions return a static const pointer. + unsafe { $evp_fn() } + } + } + + // ------------------------------------------------------------------ + // core / RustCrypto trait impls + // ------------------------------------------------------------------ + #[$cfg_gate] impl Default for $name { fn default() -> Self { - let ctx = unsafe { $new_fn() }; - assert!(!ctx.is_null(), concat!(stringify!($name), ": context allocation failed")); + // SAFETY: EVP_MD_CTX_new returns a heap-allocated context + // or NULL on OOM. + let ctx = unsafe { wolfcrypt_rs::EVP_MD_CTX_new() }; + assert!(!ctx.is_null(), "EVP_MD_CTX_new returned NULL"); + // SAFETY: ctx is non-null and freshly allocated. + unsafe { + let rc = wolfcrypt_rs::EVP_DigestInit_ex( + ctx, + Self::evp_md(), + core::ptr::null_mut(), + ); + assert_eq!(rc, 1, "EVP_DigestInit_ex failed (OOM or invalid algorithm)"); + } Self { ctx } } } @@ -62,9 +77,14 @@ macro_rules! impl_digest_native { #[$cfg_gate] impl Clone for $name { fn clone(&self) -> Self { - let mut new_ctx: *mut core::ffi::c_void = core::ptr::null_mut(); - let rc = unsafe { $copy_fn(self.ctx, &mut new_ctx) }; - assert_eq!(rc, 0, concat!(stringify!($name), ": clone (copy) failed")); + // SAFETY: Allocate a fresh context and deep-copy state. + let new_ctx = unsafe { wolfcrypt_rs::EVP_MD_CTX_new() }; + assert!(!new_ctx.is_null(), "EVP_MD_CTX_new returned NULL"); + // SAFETY: both contexts are valid, non-overlapping. + unsafe { + let rc = wolfcrypt_rs::EVP_MD_CTX_copy(new_ctx, self.ctx); + assert_eq!(rc, 1, "EVP_MD_CTX_copy failed (OOM)"); + } Self { ctx: new_ctx } } } @@ -72,8 +92,10 @@ macro_rules! impl_digest_native { #[$cfg_gate] impl Drop for $name { fn drop(&mut self) { - if !self.ctx.is_null() { - unsafe { $free_fn(self.ctx) }; + // SAFETY: self.ctx was allocated via EVP_MD_CTX_new and + // is only freed once here. + unsafe { + wolfcrypt_rs::EVP_MD_CTX_free(self.ctx); } } } @@ -91,22 +113,34 @@ macro_rules! impl_digest_native { #[$cfg_gate] impl digest_trait::Update for $name { fn update(&mut self, data: &[u8]) { - let rc = unsafe { - $update_fn(self.ctx, data.as_ptr(), data.len() as u32) - }; - assert_eq!(rc, 0, concat!(stringify!($name), ": update failed")); + // SAFETY: self.ctx is valid. data pointer and length are + // guaranteed correct by the slice reference. + unsafe { + let rc = wolfcrypt_rs::EVP_DigestUpdate( + self.ctx, + data.as_ptr() as *const c_void, + data.len(), + ); + assert_eq!(rc, 1, "EVP_DigestUpdate failed (context not initialized)"); + } } } #[$cfg_gate] impl digest_trait::FixedOutput for $name { - fn finalize_into(mut self, out: &mut GenericArray) { - let rc = unsafe { $final_fn(self.ctx, out.as_mut_ptr()) }; - assert_eq!(rc, 0, concat!(stringify!($name), ": finalize failed")); - // Prevent Drop from double-freeing โ€” free is our responsibility here. - let ctx = self.ctx; - self.ctx = core::ptr::null_mut(); - unsafe { $free_fn(ctx) }; + fn finalize_into(self, out: &mut GenericArray) { + let mut len: u32 = 0; + // SAFETY: out is exactly OutputSize bytes. self.ctx is + // valid. After this call, Drop will free the context. + unsafe { + let rc = wolfcrypt_rs::EVP_DigestFinal( + self.ctx, + out.as_mut_ptr(), + &mut len, + ); + assert_eq!(rc, 1, "EVP_DigestFinal failed (context not initialized)"); + } + // Drop runs after this and frees self.ctx. } } @@ -116,21 +150,43 @@ macro_rules! impl_digest_native { &mut self, out: &mut GenericArray, ) { - let rc = unsafe { $final_fn(self.ctx, out.as_mut_ptr()) }; - assert_eq!(rc, 0, concat!(stringify!($name), ": finalize_into_reset failed")); - // Re-init: free old context, allocate a fresh one. - unsafe { $free_fn(self.ctx) }; - self.ctx = unsafe { $new_fn() }; - assert!(!self.ctx.is_null(), concat!(stringify!($name), ": re-init after reset failed")); + let mut len: u32 = 0; + // SAFETY: ctx is valid, out has correct size. + unsafe { + let rc = wolfcrypt_rs::EVP_DigestFinal( + self.ctx, + out.as_mut_ptr(), + &mut len, + ); + assert_eq!(rc, 1, "EVP_DigestFinal failed (context not initialized)"); + } + // Re-initialise for reuse. + // SAFETY: ctx is still allocated (DigestFinal does not free it). + unsafe { + let rc = wolfcrypt_rs::EVP_DigestInit_ex( + self.ctx, + Self::evp_md(), + core::ptr::null_mut(), + ); + assert_eq!(rc, 1, "EVP_DigestInit_ex failed after finalize_into_reset (OOM or invalid algorithm)"); + } } } #[$cfg_gate] impl digest_trait::Reset for $name { fn reset(&mut self) { - unsafe { $free_fn(self.ctx) }; - self.ctx = unsafe { $new_fn() }; - assert!(!self.ctx.is_null(), concat!(stringify!($name), ": reset failed")); + // SAFETY: ctx is valid. cleanup + re-init is the + // documented way to reset an EVP_MD_CTX. + unsafe { + wolfcrypt_rs::EVP_MD_CTX_cleanup(self.ctx); + let rc = wolfcrypt_rs::EVP_DigestInit_ex( + self.ctx, + Self::evp_md(), + core::ptr::null_mut(), + ); + assert_eq!(rc, 1, "EVP_DigestInit_ex failed in reset (OOM or invalid algorithm)"); + } } } @@ -139,101 +195,16 @@ macro_rules! impl_digest_native { }; } -impl_digest_native!( - Sha256, - wolfcrypt_rs::wolfcrypt_sha256_ctx_new, - wolfcrypt_rs::wolfcrypt_sha256_update, - wolfcrypt_rs::wolfcrypt_sha256_final, - wolfcrypt_rs::wolfcrypt_sha256_free, - wolfcrypt_rs::wolfcrypt_sha256_copy, - U32, U64, - cfg(wolfssl_sha256) -); - -impl_digest_native!( - Sha384, - wolfcrypt_rs::wolfcrypt_sha384_ctx_new, - wolfcrypt_rs::wolfcrypt_sha384_update, - wolfcrypt_rs::wolfcrypt_sha384_final, - wolfcrypt_rs::wolfcrypt_sha384_free, - wolfcrypt_rs::wolfcrypt_sha384_copy, - U48, U128, - cfg(wolfssl_sha384) -); - -impl_digest_native!( - Sha1, - wolfcrypt_rs::wolfcrypt_sha1_ctx_new, - wolfcrypt_rs::wolfcrypt_sha1_update, - wolfcrypt_rs::wolfcrypt_sha1_final, - wolfcrypt_rs::wolfcrypt_sha1_free, - wolfcrypt_rs::wolfcrypt_sha1_copy, - U20, U64, - cfg(wolfssl_sha1) -); - -impl_digest_native!( - Sha224, - wolfcrypt_rs::wolfcrypt_sha224_ctx_new, - wolfcrypt_rs::wolfcrypt_sha224_update, - wolfcrypt_rs::wolfcrypt_sha224_final, - wolfcrypt_rs::wolfcrypt_sha224_free, - wolfcrypt_rs::wolfcrypt_sha224_copy, - U28, U64, - cfg(wolfssl_sha224) -); - -impl_digest_native!( - Sha512, - wolfcrypt_rs::wolfcrypt_sha512_ctx_new, - wolfcrypt_rs::wolfcrypt_sha512_update, - wolfcrypt_rs::wolfcrypt_sha512_final, - wolfcrypt_rs::wolfcrypt_sha512_free, - wolfcrypt_rs::wolfcrypt_sha512_copy, - U64, U128, - cfg(wolfssl_sha512) -); - -impl_digest_native!( - Sha512_256, - wolfcrypt_rs::wolfcrypt_sha512_256_ctx_new, - wolfcrypt_rs::wolfcrypt_sha512_256_update, - wolfcrypt_rs::wolfcrypt_sha512_256_final, - wolfcrypt_rs::wolfcrypt_sha512_256_free, - wolfcrypt_rs::wolfcrypt_sha512_256_copy, - U32, U128, - cfg(wolfssl_sha512) -); - -impl_digest_native!( - Sha3_256, - wolfcrypt_rs::wolfcrypt_sha3_256_ctx_new, - wolfcrypt_rs::wolfcrypt_sha3_256_update, - wolfcrypt_rs::wolfcrypt_sha3_256_final, - wolfcrypt_rs::wolfcrypt_sha3_256_free, - wolfcrypt_rs::wolfcrypt_sha3_256_copy, - U32, U136, - cfg(wolfssl_sha3) -); - -impl_digest_native!( - Sha3_384, - wolfcrypt_rs::wolfcrypt_sha3_384_ctx_new, - wolfcrypt_rs::wolfcrypt_sha3_384_update, - wolfcrypt_rs::wolfcrypt_sha3_384_final, - wolfcrypt_rs::wolfcrypt_sha3_384_free, - wolfcrypt_rs::wolfcrypt_sha3_384_copy, - U48, U104, - cfg(wolfssl_sha3) -); - -impl_digest_native!( - Sha3_512, - wolfcrypt_rs::wolfcrypt_sha3_512_ctx_new, - wolfcrypt_rs::wolfcrypt_sha3_512_update, - wolfcrypt_rs::wolfcrypt_sha3_512_final, - wolfcrypt_rs::wolfcrypt_sha3_512_free, - wolfcrypt_rs::wolfcrypt_sha3_512_copy, - U64, U72, - cfg(wolfssl_sha3) -); +// ====================================================================== +// Stamp out all nine digest types +// ====================================================================== + +impl_digest!(Sha1, wolfcrypt_rs::EVP_sha1, U20, U64, cfg(wolfssl_openssl_extra)); +impl_digest!(Sha224, wolfcrypt_rs::EVP_sha224, U28, U64, cfg(all(wolfssl_openssl_extra, wolfssl_sha224))); +impl_digest!(Sha256, wolfcrypt_rs::EVP_sha256, U32, U64, cfg(wolfssl_openssl_extra)); +impl_digest!(Sha384, wolfcrypt_rs::EVP_sha384, U48, U128, cfg(all(wolfssl_openssl_extra, wolfssl_sha384))); +impl_digest!(Sha512, wolfcrypt_rs::EVP_sha512, U64, U128, cfg(all(wolfssl_openssl_extra, wolfssl_sha512))); +impl_digest!(Sha512_256, wolfcrypt_rs::EVP_sha512_256, U32, U128, cfg(all(wolfssl_openssl_extra, wolfssl_sha512))); +impl_digest!(Sha3_256, wolfcrypt_rs::EVP_sha3_256, U32, U136, cfg(all(wolfssl_openssl_extra, wolfssl_sha3))); +impl_digest!(Sha3_384, wolfcrypt_rs::EVP_sha3_384, U48, U104, cfg(all(wolfssl_openssl_extra, wolfssl_sha3))); +impl_digest!(Sha3_512, wolfcrypt_rs::EVP_sha3_512, U64, U72, cfg(all(wolfssl_openssl_extra, wolfssl_sha3))); diff --git a/wolfcrypt/src/ecdh.rs b/wolfcrypt/src/ecdh.rs index bb9d13c..8c9324f 100644 --- a/wolfcrypt/src/ecdh.rs +++ b/wolfcrypt/src/ecdh.rs @@ -510,44 +510,43 @@ impl X448SharedSecret { &self.0 } } + // =========================================================================== -// NIST curve ECDH โ€” native wc_ecc_* implementation +// NIST curve ECDH (P-256, P-384) via OpenSSL compat layer // =========================================================================== // -// Uses wolfCrypt's native wc_ecc_* API. No OPENSSL_EXTRA required. -// The old EVP-based `nist_ecdh` module is retained below but no longer -// re-exported; it will be deleted in a follow-up cleanup. +// Uses wolfSSL's OpenSSL-compatible EC_KEY / ECDH_compute_key API to perform +// elliptic-curve Diffie-Hellman on NIST prime curves. -#[cfg(wolfssl_ecc)] -pub(crate) mod nist_ecdh_native { - extern crate alloc; - use alloc::vec; - use alloc::vec::Vec; - use core::cell::UnsafeCell; - use core::ffi::c_int; +#[cfg(all(wolfssl_openssl_extra, wolfssl_ecc))] +mod nist_ecdh { + use core::ffi::{c_int, c_void}; use core::marker::PhantomData; use core::ptr; + use alloc::vec; + use alloc::vec::Vec; + use zeroize::ZeroizeOnDrop; use crate::error::WolfCryptError; use wolfcrypt_rs::{ - wc_ecc_key, wc_ecc_key_new, wc_ecc_key_free, - wc_ecc_make_key_ex, - wc_ecc_shared_secret, - wc_ecc_import_x963, wc_ecc_export_x963, - wc_ecc_import_private_key_ex, - wc_ecc_check_key, wc_ecc_set_rng, - wc_InitRng, wc_FreeRng, WC_RNG, - ECC_SECP256R1, + EC_GROUP_free, EC_GROUP_new_by_curve_name, + EC_KEY_free, EC_KEY_generate_key, EC_KEY_get0_public_key, EC_KEY_new, + EC_KEY_set_group, + EC_POINT_free, EC_POINT_new, EC_POINT_oct2point, EC_POINT_point2oct, + ECDH_compute_key, + NID_X9_62_prime256v1, + EC_GROUP, EC_KEY, + point_conversion_form_t, }; #[cfg(wolfssl_ecc_p384)] - use wolfcrypt_rs::ECC_SECP384R1; + use wolfcrypt_rs::NID_secp384r1; #[cfg(wolfssl_ecc_p521)] - use wolfcrypt_rs::ECC_SECP521R1; + use wolfcrypt_rs::NID_secp521r1; // ================================================================ // Sealed trait pattern @@ -557,69 +556,66 @@ pub(crate) mod nist_ecdh_native { pub trait Sealed {} } - /// Parameters for a NIST prime curve ECDH operation. + /// Trait describing a NIST prime curve's ECDH parameters. /// /// Sealed so that only [`NistP256`], [`NistP384`], and [`NistP521`] /// can implement it. + /// + /// This is intentionally separate from [`ecdsa::EcdsaCurve`] โ€” ECDSA + /// needs hash parameters (`evp_md()`, `HASH_LEN`, `SigSize`) that ECDH + /// never uses. Merging would couple the `ecdh` and `ecdsa` feature + /// gates and pollute ECDH with unused hash concerns. pub trait NistCurve: sealed::Sealed + 'static { - /// wolfCrypt curve ID (e.g. `ECC_SECP256R1`). - const CURVE_ID: c_int; + /// The OpenSSL NID for this curve. + const NID: c_int; /// Size of one field element in bytes (= shared secret length). const FIELD_SIZE: usize; - /// Size of an uncompressed public point: `1 + 2 * FIELD_SIZE`. + /// Size of the uncompressed public point: `1 + 2 * FIELD_SIZE`. const POINT_SIZE: usize; } - /// NIST P-256 curve marker. + /// NIST P-256 (secp256r1 / prime256v1) curve marker for ECDH. pub struct NistP256; + impl sealed::Sealed for NistP256 {} + impl NistCurve for NistP256 { - const CURVE_ID: c_int = ECC_SECP256R1; + const NID: c_int = NID_X9_62_prime256v1; const FIELD_SIZE: usize = 32; const POINT_SIZE: usize = 65; // 1 + 2*32 } - /// NIST P-384 curve marker. + /// NIST P-384 (secp384r1) curve marker for ECDH. #[cfg(wolfssl_ecc_p384)] pub struct NistP384; + #[cfg(wolfssl_ecc_p384)] impl sealed::Sealed for NistP384 {} + #[cfg(wolfssl_ecc_p384)] impl NistCurve for NistP384 { - const CURVE_ID: c_int = ECC_SECP384R1; + const NID: c_int = NID_secp384r1; const FIELD_SIZE: usize = 48; const POINT_SIZE: usize = 97; // 1 + 2*48 } - /// NIST P-521 curve marker. - #[cfg(wolfssl_ecc_p521)] - pub struct NistP521; - #[cfg(wolfssl_ecc_p521)] - impl sealed::Sealed for NistP521 {} - #[cfg(wolfssl_ecc_p521)] - impl NistCurve for NistP521 { - const CURVE_ID: c_int = ECC_SECP521R1; - const FIELD_SIZE: usize = 66; - const POINT_SIZE: usize = 133; // 1 + 2*66 - } - // ================================================================ // NistEcdhPublicKey // ================================================================ - /// An uncompressed NIST curve public key: `0x04 || x || y`. + /// An uncompressed public point for NIST curve ECDH. + /// + /// Stored as the standard uncompressed encoding: `0x04 || x || y`. pub struct NistEcdhPublicKey { bytes: Vec, _curve: PhantomData, } impl NistEcdhPublicKey { - /// Import from uncompressed point bytes (`0x04 || x || y`). + /// Import a public key from its uncompressed point encoding. /// - /// Validates that the bytes encode a point that lies on curve `C` - /// by importing into a temporary wolfCrypt key and calling - /// `wc_ecc_check_key`. Returns an error for points that fail - /// curve membership (small subgroup, not on curve, etc.). + /// The first byte must be `0x04` and the total length must be + /// `1 + 2 * FIELD_SIZE`. pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != C::POINT_SIZE { return Err(WolfCryptError::INVALID_INPUT); @@ -627,30 +623,10 @@ pub(crate) mod nist_ecdh_native { if bytes[0] != 0x04 { return Err(WolfCryptError::INVALID_INPUT); } - // Cryptographically validate the point: import into a temporary - // key and check that it lies on the curve. This matches the - // contract of EcdsaVerifyingKey::from_uncompressed_point and - // ensures callers get a type that is already validated, not one - // that can only fail later inside diffie_hellman. - // - // SAFETY: wc_ecc_key_new returns a heap-allocated key or null. - let tmp = unsafe { wc_ecc_key_new(ptr::null_mut()) }; - if tmp.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - let rc = unsafe { - wc_ecc_import_x963(bytes.as_ptr(), bytes.len() as u32, tmp) - }; - if rc != 0 { - unsafe { wc_ecc_key_free(tmp) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_import_x963" }); - } - let rc = unsafe { wc_ecc_check_key(tmp) }; - unsafe { wc_ecc_key_free(tmp) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_check_key" }); - } - Ok(Self { bytes: bytes.to_vec(), _curve: PhantomData }) + Ok(Self { + bytes: bytes.to_vec(), + _curve: PhantomData, + }) } /// Return the raw uncompressed point bytes (`0x04 || x || y`). @@ -667,9 +643,7 @@ pub(crate) mod nist_ecdh_native { // NistEcdhSharedSecret // ================================================================ - /// The shared secret from a NIST curve ECDH exchange. - /// - /// Zeroized on drop. + /// The shared secret resulting from a NIST curve ECDH exchange. #[derive(ZeroizeOnDrop)] pub struct NistEcdhSharedSecret { #[zeroize(drop)] @@ -678,7 +652,9 @@ pub(crate) mod nist_ecdh_native { } impl NistEcdhSharedSecret { - /// Return the raw shared secret bytes (length = `C::FIELD_SIZE`). + /// Return the raw shared secret bytes. + /// + /// Length is [`NistCurve::FIELD_SIZE`] (32 for P-256, 48 for P-384). pub fn as_bytes(&self) -> &[u8] { &self.bytes } @@ -688,205 +664,199 @@ pub(crate) mod nist_ecdh_native { // NistEcdhSecret // ================================================================ - /// A NIST curve ECDH private key backed by native wolfCrypt `wc_ecc_*`. + /// A NIST curve ECDH private key. /// - /// `UnsafeCell` makes this type `!Sync`, which is correct: wolfCrypt - /// contexts are not thread-safe. + /// Wraps a wolfSSL `EC_KEY` with the curve's group set. The key + /// is freed on drop. pub struct NistEcdhSecret { - /// Heap-allocated wc_ecc_key (via wc_ecc_key_new). Non-null while alive. - key: UnsafeCell<*mut wc_ecc_key>, + /// Owned EC_KEY pointer. Non-null while the struct is alive. + ec_key: *mut EC_KEY, + /// Owned EC_GROUP pointer. Non-null while the struct is alive. + group: *mut EC_GROUP, _curve: PhantomData, } - // SAFETY: wc_ecc_key owns independent heap state; safe to move across threads. - unsafe impl Send for NistEcdhSecret {} - - impl Drop for NistEcdhSecret { - fn drop(&mut self) { - let key = *self.key.get_mut(); - if !key.is_null() { - // SAFETY: key was allocated by wc_ecc_key_new in all constructors. - unsafe { wc_ecc_key_free(key); } - } - } - } - impl NistEcdhSecret { /// Generate a random ECDH keypair on this curve. + #[cfg(feature = "rand")] pub fn generate() -> Result { - // SAFETY: wc_ecc_key_new returns a heap-allocated key or null. - let key = unsafe { wc_ecc_key_new(ptr::null_mut()) }; - if key.is_null() { + // SAFETY: EC_GROUP_new_by_curve_name returns a heap-allocated + // group or null on failure. + let group = unsafe { EC_GROUP_new_by_curve_name(C::NID) }; + if group.is_null() { return Err(WolfCryptError::ALLOC_FAILED); } - let mut rng = WC_RNG::zeroed(); - // SAFETY: rng is zero-initialised; wc_InitRng completes setup. - let rc = unsafe { wc_InitRng(&mut rng) }; - if rc != 0 { - unsafe { wc_ecc_key_free(key); } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_InitRng" }); + // SAFETY: EC_KEY_new returns a heap-allocated key or null. + let ec_key = unsafe { EC_KEY_new() }; + if ec_key.is_null() { + unsafe { EC_GROUP_free(group) }; + return Err(WolfCryptError::ALLOC_FAILED); } - // SAFETY: key and rng are both initialised; FIELD_SIZE matches CURVE_ID. - let rc = unsafe { - wc_ecc_make_key_ex(&mut rng, C::FIELD_SIZE as i32, key, C::CURVE_ID) - }; - // Free RNG regardless of outcome. - unsafe { wc_FreeRng(&mut rng); } - if rc != 0 { - unsafe { wc_ecc_key_free(key); } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_make_key_ex" }); + // SAFETY: Both pointers are valid, non-null. + let rc = unsafe { EC_KEY_set_group(ec_key, group) }; + if rc != 1 { + unsafe { + EC_KEY_free(ec_key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_group" }); } - Ok(Self { key: UnsafeCell::new(key), _curve: PhantomData }) - } - - /// Import a private key from its raw scalar bytes (big-endian, - /// exactly `C::FIELD_SIZE` bytes). - /// - /// The public key component is **not** set on the resulting key struct; - /// `public_key()` will return an error if called on this key. Use this - /// constructor when you only need `diffie_hellman()` (e.g. in tests). - pub fn from_private_scalar(scalar: &[u8]) -> Result { - if scalar.len() != C::FIELD_SIZE { - return Err(WolfCryptError::INVALID_INPUT); - } - let key = unsafe { wc_ecc_key_new(ptr::null_mut()) }; - if key.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - // SAFETY: key is initialised; scalar is FIELD_SIZE bytes. - // Passing null public key is valid โ€” wolfCrypt accepts private-only import. - let rc = unsafe { - wc_ecc_import_private_key_ex( - scalar.as_ptr(), scalar.len() as u32, - ptr::null(), 0, - key, C::CURVE_ID, - ) - }; - if rc != 0 { - unsafe { wc_ecc_key_free(key); } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_import_private_key_ex" }); + // SAFETY: ec_key has a group set; generate_key fills in + // private scalar and public point. + let rc = unsafe { EC_KEY_generate_key(ec_key) }; + if rc != 1 { + unsafe { + EC_KEY_free(ec_key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_generate_key" }); } - Ok(Self { key: UnsafeCell::new(key), _curve: PhantomData }) + + Ok(Self { + ec_key, + group, + _curve: PhantomData, + }) } - /// Export the public key as an uncompressed point (`0x04 || x || y`). - /// - /// Returns an error if the key was created with `from_private_scalar` - /// (public component not available without a separate derivation step). - pub fn public_key(&self) -> Result, WolfCryptError> { - let key = unsafe { *self.key.get() }; + /// Export the public key as an uncompressed point. + pub fn public_key(&self) -> NistEcdhPublicKey { + // SAFETY: ec_key is valid and has a generated keypair. + let point = unsafe { EC_KEY_get0_public_key(self.ec_key) }; + assert!(!point.is_null(), "EC_KEY_get0_public_key returned null"); + let mut buf = vec![0u8; C::POINT_SIZE]; - let mut sz = buf.len() as u32; - // SAFETY: key is initialised and has a public component (generate path). - let rc = unsafe { wc_ecc_export_x963(key, buf.as_mut_ptr(), &mut sz) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_export_x963" }); - } - if sz as usize != C::POINT_SIZE { - return Err(WolfCryptError::INVALID_INPUT); + + // SAFETY: group and point are valid. The buffer is large enough + // for the uncompressed encoding. Returns the number of bytes + // written, or 0 on failure. + let n = unsafe { + EC_POINT_point2oct( + self.group, + point, + point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED, + buf.as_mut_ptr(), + buf.len(), + ptr::null_mut(), + ) + }; + assert_eq!( + n, C::POINT_SIZE, + "EC_POINT_point2oct returned unexpected size: {n}" + ); + + NistEcdhPublicKey { + bytes: buf, + _curve: PhantomData, } - NistEcdhPublicKey::from_bytes(&buf) } /// Perform ECDH with the given peer public key. /// - /// Validates the peer point before use (`wc_ecc_check_key`). - /// Attaches a fresh RNG to the private key for ECC_TIMING_RESISTANT - /// scalar-multiplication blinding. + /// Consumes `self` so the private key is freed after use. pub fn diffie_hellman( self, peer_public: &NistEcdhPublicKey, - ) -> Result, WolfCryptError> { - // โ”€โ”€ Import peer public key โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - let peer_key = unsafe { wc_ecc_key_new(ptr::null_mut()) }; - if peer_key.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } + ) -> NistEcdhSharedSecret { + // Parse the peer's uncompressed point into an EC_POINT. + // + // SAFETY: group is valid; EC_POINT_new returns a heap-allocated + // point or null. + let peer_point = unsafe { EC_POINT_new(self.group) }; + assert!(!peer_point.is_null(), "EC_POINT_new failed"); + // SAFETY: group and peer_point are valid, peer bytes encode a + // valid uncompressed point for this curve. let rc = unsafe { - wc_ecc_import_x963( + EC_POINT_oct2point( + self.group, + peer_point, peer_public.bytes.as_ptr(), - peer_public.bytes.len() as u32, - peer_key, + peer_public.bytes.len(), + ptr::null_mut(), ) }; - if rc != 0 { - unsafe { wc_ecc_key_free(peer_key); } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_import_x963" }); - } - - // โ”€โ”€ Paranoid: validate peer point is on the curve โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - let rc = unsafe { wc_ecc_check_key(peer_key) }; - if rc != 0 { - unsafe { wc_ecc_key_free(peer_key); } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_check_key" }); - } + assert_eq!(rc, 1, "EC_POINT_oct2point failed (invalid point encoding)"); - // โ”€โ”€ Attach RNG to private key for blinding โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - // Required when ECC_TIMING_RESISTANT is defined (default). - // wc_ecc_shared_secret returns MISSING_RNG_E without this. - let priv_key = unsafe { *self.key.get() }; - let mut rng = WC_RNG::zeroed(); - let rc = unsafe { wc_InitRng(&mut rng) }; - if rc != 0 { - unsafe { wc_ecc_key_free(peer_key); } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_InitRng" }); - } - let rc = unsafe { wc_ecc_set_rng(priv_key, &mut rng) }; - if rc != 0 { - unsafe { - wc_ecc_key_free(peer_key); - wc_FreeRng(&mut rng); - } - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_set_rng" }); - } - - // โ”€โ”€ Compute shared secret โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + // Compute the shared secret. let mut out = vec![0u8; C::FIELD_SIZE]; - let mut out_len = out.len() as u32; - // SAFETY: priv_key has private scalar + RNG; peer_key has public point. + + // SAFETY: ec_key holds a valid private key, peer_point is a + // valid point on the same curve. `out` is FIELD_SIZE bytes. + // KDF is null โ†’ raw x-coordinate is returned. let rc = unsafe { - wc_ecc_shared_secret(priv_key, peer_key, out.as_mut_ptr(), &mut out_len) + ECDH_compute_key( + out.as_mut_ptr() as *mut c_void, + C::FIELD_SIZE, + peer_point, + self.ec_key, + ptr::null_mut(), + ) }; + assert_eq!( + rc as usize, C::FIELD_SIZE, + "ECDH_compute_key failed (invalid key or point)" + ); - // Always clean up peer key and RNG. - unsafe { - wc_ecc_key_free(peer_key); - wc_FreeRng(&mut rng); - } + // SAFETY: peer_point was allocated above; free it now. + unsafe { EC_POINT_free(peer_point) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_shared_secret" }); - } - if out_len as usize != C::FIELD_SIZE { - return Err(WolfCryptError::INVALID_INPUT); + NistEcdhSharedSecret { + bytes: out, + _curve: PhantomData, } + } + } - Ok(NistEcdhSharedSecret { bytes: out, _curve: PhantomData }) + impl Drop for NistEcdhSecret { + fn drop(&mut self) { + // SAFETY: ec_key and group were allocated in `generate` and + // are non-null. Freed exactly once here. + unsafe { + EC_KEY_free(self.ec_key); + EC_GROUP_free(self.group); + } } } - /// P-256 ECDH secret key. + // SAFETY: EC_KEY / EC_GROUP are self-contained heap objects with no + // shared mutable globals; safe to move between threads. + unsafe impl Send for NistEcdhSecret {} + + /// NIST P-521 (secp521r1) curve marker for ECDH. + #[cfg(wolfssl_ecc_p521)] + pub struct NistP521; + + #[cfg(wolfssl_ecc_p521)] + impl sealed::Sealed for NistP521 {} + + #[cfg(wolfssl_ecc_p521)] + impl NistCurve for NistP521 { + const NID: c_int = NID_secp521r1; + const FIELD_SIZE: usize = 66; + const POINT_SIZE: usize = 133; // 1 + 2*66 + } + + /// Type alias: P-256 ECDH secret key. pub type P256EcdhSecret = NistEcdhSecret; - /// P-384 ECDH secret key. + /// Type alias: P-384 ECDH secret key. #[cfg(wolfssl_ecc_p384)] pub type P384EcdhSecret = NistEcdhSecret; - /// P-521 ECDH secret key. + /// Type alias: P-521 ECDH secret key. #[cfg(wolfssl_ecc_p521)] pub type P521EcdhSecret = NistEcdhSecret; } -// Re-export native NIST ECDH types at module level. -// No wolfssl_openssl_extra required โ€” native wc_ecc_* only. -#[cfg(wolfssl_ecc)] -pub use nist_ecdh_native::{ +// Re-export NIST ECDH types at module level. +#[cfg(all(wolfssl_openssl_extra, wolfssl_ecc))] +pub use nist_ecdh::{ NistCurve, NistEcdhPublicKey, NistEcdhSecret, NistEcdhSharedSecret, NistP256, P256EcdhSecret, }; -#[cfg(all(wolfssl_ecc, wolfssl_ecc_p384))] -pub use nist_ecdh_native::{NistP384, P384EcdhSecret}; -#[cfg(all(wolfssl_ecc, wolfssl_ecc_p521))] -pub use nist_ecdh_native::{NistP521, P521EcdhSecret}; +#[cfg(all(wolfssl_openssl_extra, wolfssl_ecc, wolfssl_sha384))] +pub use nist_ecdh::{NistP384, P384EcdhSecret}; +#[cfg(all(wolfssl_openssl_extra, wolfssl_ecc, wolfssl_sha512))] +pub use nist_ecdh::{NistP521, P521EcdhSecret}; diff --git a/wolfcrypt/src/ecdsa.rs b/wolfcrypt/src/ecdsa.rs new file mode 100644 index 0000000..257c59a --- /dev/null +++ b/wolfcrypt/src/ecdsa.rs @@ -0,0 +1,957 @@ +//! ECDSA signing and verification (P-256, P-384, P-521) backed by wolfCrypt. +//! +//! Provides [`EcdsaSigningKey`] and [`EcdsaVerifyingKey`] parameterized by +//! curve ([`P256`] or [`P384`]), implementing the RustCrypto +//! [`signature::Signer`] and [`signature::Verifier`] traits. +//! +//! Signatures use the fixed-size `r || s` encoding (each component +//! zero-padded to the curve's field size), not DER. + +use core::cell::UnsafeCell; +use core::ffi::{c_int, c_uint, c_void}; +use core::marker::PhantomData; + +use alloc::vec; +use alloc::vec::Vec; + +use generic_array::GenericArray; + +use crate::error::{len_as_c_int, WolfCryptError}; + +use wolfcrypt_rs::{ + BN_bn2bin, BN_bin2bn, BN_free, BN_num_bytes, + EC_GROUP_free, EC_GROUP_new_by_curve_name, + EC_KEY_free, EC_KEY_generate_key, EC_KEY_get0_public_key, EC_KEY_new, + EC_KEY_set_group, EC_KEY_set_private_key, EC_KEY_set_public_key, + EC_POINT_free, EC_POINT_mul, EC_POINT_new, EC_POINT_oct2point, EC_POINT_point2oct, + ECDSA_SIG_free, ECDSA_SIG_get0, ECDSA_SIG_new, ECDSA_SIG_set0, + ECDSA_do_sign, ECDSA_do_verify, + EVP_DigestFinal, EVP_DigestInit_ex, EVP_DigestUpdate, + EVP_MD, EVP_MD_CTX_free, EVP_MD_CTX_new, + EVP_sha256, + NID_X9_62_prime256v1, + BIGNUM, EC_GROUP, EC_KEY, + point_conversion_form_t, +}; + +#[cfg(wolfssl_ecc_p384)] +use wolfcrypt_rs::{EVP_sha384, NID_secp384r1}; + +#[cfg(wolfssl_ecc_p521)] +use wolfcrypt_rs::{EVP_sha512, NID_secp521r1}; + +// ============================================================ +// Sealed trait pattern +// ============================================================ + +mod sealed { + pub trait Sealed {} +} + +/// Trait describing an ECDSA curve's parameters. +/// +/// Sealed so that only [`P256`] and [`P384`] can implement it. +pub trait EcdsaCurve: sealed::Sealed + 'static { + /// The OpenSSL NID for this curve. + const NID: c_int; + /// Size of one field element in bytes (32 for P-256, 48 for P-384). + const FIELD_SIZE: usize; + /// Size of the fixed-size signature (2 * FIELD_SIZE). + const SIG_SIZE: usize; + /// Typenum encoding of [`SIG_SIZE`](Self::SIG_SIZE) for stack-allocated + /// signature storage via `GenericArray`. + type SigSize: generic_array::ArrayLength; + /// Size of the uncompressed public point (1 + 2 * FIELD_SIZE). + const UNCOMPRESSED_POINT_SIZE: usize; + /// Hash length produced by the associated digest (same as FIELD_SIZE). + const HASH_LEN: usize; + /// Return a pointer to the EVP_MD for this curve's canonical hash. + fn evp_md() -> *const EVP_MD; +} + +/// NIST P-256 (secp256r1 / prime256v1) curve marker. +pub struct P256; + +impl sealed::Sealed for P256 {} + +impl EcdsaCurve for P256 { + const NID: c_int = NID_X9_62_prime256v1; + const FIELD_SIZE: usize = 32; + const SIG_SIZE: usize = 64; + type SigSize = typenum::U64; + const UNCOMPRESSED_POINT_SIZE: usize = 65; + const HASH_LEN: usize = 32; + fn evp_md() -> *const EVP_MD { + // SAFETY: EVP_sha256 returns a static pointer; always valid. + unsafe { EVP_sha256() } + } +} + +/// NIST P-384 (secp384r1) curve marker. +#[cfg(wolfssl_ecc_p384)] +pub struct P384; + +#[cfg(wolfssl_ecc_p384)] +impl sealed::Sealed for P384 {} + +#[cfg(wolfssl_ecc_p384)] +impl EcdsaCurve for P384 { + const NID: c_int = NID_secp384r1; + const FIELD_SIZE: usize = 48; + const SIG_SIZE: usize = 96; + type SigSize = typenum::U96; + const UNCOMPRESSED_POINT_SIZE: usize = 97; + const HASH_LEN: usize = 48; + fn evp_md() -> *const EVP_MD { + // SAFETY: EVP_sha384 returns a static pointer; always valid. + unsafe { EVP_sha384() } + } +} + +/// NIST P-521 (secp521r1) curve marker. +#[cfg(wolfssl_ecc_p521)] +pub struct P521; + +#[cfg(wolfssl_ecc_p521)] +impl sealed::Sealed for P521 {} + +#[cfg(wolfssl_ecc_p521)] +impl EcdsaCurve for P521 { + const NID: c_int = NID_secp521r1; + const FIELD_SIZE: usize = 66; // ceil(521/8) = 66 bytes + const SIG_SIZE: usize = 132; // 2 * 66 + type SigSize = typenum::U132; + const UNCOMPRESSED_POINT_SIZE: usize = 133; // 1 + 2*66 + const HASH_LEN: usize = 64; // SHA-512 produces 64 bytes + fn evp_md() -> *const EVP_MD { + // SAFETY: EVP_sha512 returns a static pointer; always valid. + unsafe { EVP_sha512() } + } +} + +// ============================================================ +// EcdsaSignature +// ============================================================ + +/// A fixed-size, stack-allocated ECDSA signature in `r || s` format. +/// +/// Each component is zero-padded on the left to [`EcdsaCurve::FIELD_SIZE`] +/// bytes, giving a total length of `2 * FIELD_SIZE`. The bytes are stored +/// inline in a `GenericArray` (no heap allocation). +pub struct EcdsaSignature { + /// r || s, each FIELD_SIZE bytes. + bytes: GenericArray, + _curve: PhantomData, +} + +impl EcdsaSignature { + /// Create a signature from raw `r || s` bytes. + /// + /// Returns `Err` if the slice length is not `C::SIG_SIZE`. + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != C::SIG_SIZE { + return Err(WolfCryptError::INVALID_INPUT); + } + Ok(Self { + bytes: GenericArray::clone_from_slice(bytes), + _curve: PhantomData, + }) + } + + /// Return the raw `r || s` bytes. + pub fn as_bytes(&self) -> &[u8] { + &self.bytes + } + + /// Return `r` component (big-endian, FIELD_SIZE bytes). + pub fn r_bytes(&self) -> &[u8] { + &self.bytes[..C::FIELD_SIZE] + } + + /// Return `s` component (big-endian, FIELD_SIZE bytes). + pub fn s_bytes(&self) -> &[u8] { + &self.bytes[C::FIELD_SIZE..] + } +} + +impl Clone for EcdsaSignature { + fn clone(&self) -> Self { + Self { + bytes: self.bytes.clone(), + _curve: PhantomData, + } + } +} + +impl PartialEq for EcdsaSignature { + fn eq(&self, other: &Self) -> bool { + self.bytes == other.bytes + } +} +impl Eq for EcdsaSignature {} + +impl core::fmt::Debug for EcdsaSignature { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("EcdsaSignature") + .field("len", &self.bytes.len()) + .finish() + } +} + +impl signature_trait::SignatureEncoding for EcdsaSignature { + // Vec rather than GenericArray: using the GenericArray + // would require `impl TryFrom> for GenericArray<...>`, + // which is an orphan impl on a foreign type with a generic parameter โ€” + // technically allowed today but fragile across crate boundaries. The + // allocation (64โ€“132 bytes, once per sign/verify) is negligible next to + // the EC scalar multiplication. + type Repr = Vec; +} + +impl TryFrom<&[u8]> for EcdsaSignature { + type Error = signature_trait::Error; + + fn try_from(bytes: &[u8]) -> Result { + Self::from_bytes(bytes).map_err(|_| signature_trait::Error::new()) + } +} + +impl From> for Vec { + fn from(sig: EcdsaSignature) -> Vec { + sig.bytes.to_vec() + } +} + +impl AsRef<[u8]> for EcdsaSignature { + fn as_ref(&self) -> &[u8] { + &self.bytes + } +} + +// ============================================================ +// Helpers: hashing and BIGNUM conversion +// ============================================================ + +/// Hash `msg` with the curve's canonical digest, returning the hash bytes. +/// +/// Allocates a fresh `EVP_MD_CTX` per call. This is intentional: caching +/// the context in the key struct would add interior-mutability complexity +/// for no measurable gain โ€” the EC scalar multiplication in sign/verify +/// dwarfs a single `XMALLOC`/`XFREE` pair. +fn hash_message(msg: &[u8]) -> Result, WolfCryptError> { + // SAFETY: EVP_MD_CTX_new returns a heap-allocated context or null. + let ctx = unsafe { EVP_MD_CTX_new() }; + if ctx.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: ctx is valid, evp_md() returns a static pointer, engine is null. + let rc = unsafe { + EVP_DigestInit_ex(ctx, C::evp_md(), core::ptr::null_mut()) + }; + if rc != 1 { + unsafe { EVP_MD_CTX_free(ctx) }; + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestInit_ex" }); + } + + // SAFETY: ctx is initialized, msg pointer and length are valid. + let rc = unsafe { + EVP_DigestUpdate(ctx, msg.as_ptr() as *const c_void, msg.len()) + }; + if rc != 1 { + unsafe { EVP_MD_CTX_free(ctx) }; + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestUpdate" }); + } + + let mut hash = vec![0u8; C::HASH_LEN]; + let mut hash_len: c_uint = 0; + + // SAFETY: ctx is initialized, hash buffer is HASH_LEN bytes. + let rc = unsafe { EVP_DigestFinal(ctx, hash.as_mut_ptr(), &mut hash_len) }; + unsafe { EVP_MD_CTX_free(ctx) }; + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestFinal" }); + } + + Ok(hash) +} + +/// Convert a BIGNUM to a fixed-size big-endian byte array of `field_size` +/// bytes, zero-padded on the left. +/// +/// SAFETY: `bn` must be a valid, non-null BIGNUM pointer. +unsafe fn bn_to_fixed_bytes(bn: *const BIGNUM, field_size: usize) -> Vec { + // SAFETY: caller guarantees `bn` is a valid, non-null BIGNUM pointer. + let num_bytes = unsafe { BN_num_bytes(bn) } as usize; + let mut buf = vec![0u8; field_size]; + if num_bytes > 0 { + // Write to the end of the buffer so leading zeros pad the front. + let offset = field_size.saturating_sub(num_bytes); + // SAFETY: `bn` is valid and `buf[offset..]` has at least `num_bytes` bytes. + unsafe { BN_bn2bin(bn, buf[offset..].as_mut_ptr()) }; + } + buf +} + +// ============================================================ +// EcdsaSigningKey +// ============================================================ + +/// An ECDSA signing key (private key) backed by wolfCrypt's OpenSSL compat +/// layer. +/// +/// Parameterized by curve: use [`P256`] or [`P384`]. +pub struct EcdsaSigningKey { + /// Heap-allocated EC_KEY. + /// + /// Strictly speaking `UnsafeCell` around the raw pointer is not + /// required for soundness โ€” `&self`'s aliasing scope covers the + /// struct's own memory (the pointer value) but not the heap data + /// behind it, so passing `*mut EC_KEY` to FFI is already legal. + /// We keep `UnsafeCell` because it makes the type `!Sync`, which + /// is the correct contract (wolfCrypt contexts are not thread-safe). + key: UnsafeCell<*mut EC_KEY>, + /// Heap-allocated EC_GROUP (owned; freed on drop). + group: *mut EC_GROUP, + _curve: PhantomData, +} + +// SAFETY: EC_KEY and EC_GROUP own independent heap state with no shared +// mutable globals; safe to move between threads. +unsafe impl Send for EcdsaSigningKey {} + +impl EcdsaSigningKey { + /// Generate a random ECDSA keypair on curve `C`. + pub fn generate() -> Result { + // SAFETY: EC_GROUP_new_by_curve_name returns null on failure. + let group = unsafe { EC_GROUP_new_by_curve_name(C::NID) }; + if group.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: EC_KEY_new returns null on failure. + let key = unsafe { EC_KEY_new() }; + if key.is_null() { + unsafe { EC_GROUP_free(group) }; + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: key and group are valid non-null pointers. + let rc = unsafe { EC_KEY_set_group(key, group) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_group" }); + } + + // SAFETY: key is fully configured with a group; generate fills in + // both private scalar and public point. + let rc = unsafe { EC_KEY_generate_key(key) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_generate_key" }); + } + + Ok(Self { + key: UnsafeCell::new(key), + group, + _curve: PhantomData, + }) + } + + /// Return the corresponding verifying (public) key. + /// + /// Exports the public point in uncompressed form and constructs an + /// [`EcdsaVerifyingKey`]. + pub fn verifying_key(&self) -> Result, WolfCryptError> { + let key = unsafe { *self.key.get() }; + + // SAFETY: key is valid; get0_public_key returns an internal pointer. + let point = unsafe { EC_KEY_get0_public_key(key) }; + if point.is_null() { + return Err(WolfCryptError::Ffi { code: 0, func: "EC_KEY_get0_public_key" }); + } + + let mut buf = vec![0u8; C::UNCOMPRESSED_POINT_SIZE]; + + // SAFETY: group and point are valid. The buffer is sized for + // uncompressed output. ctx is null (no BN_CTX needed). + let written = unsafe { + EC_POINT_point2oct( + self.group as *const _, + point, + point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED, + buf.as_mut_ptr(), + buf.len(), + core::ptr::null_mut(), + ) + }; + if written != C::UNCOMPRESSED_POINT_SIZE { + return Err(WolfCryptError::Ffi { code: written as i32, func: "EC_POINT_point2oct" }); + } + + EcdsaVerifyingKey::from_uncompressed_point(&buf) + } + + /// Construct a signing key from raw private-key scalar bytes and an + /// uncompressed public point (0x04 || x || y). + /// + /// `priv_bytes` is the big-endian encoding of the private scalar. + /// `pub_bytes` must be exactly `C::UNCOMPRESSED_POINT_SIZE` bytes and + /// start with `0x04`. + pub fn from_private_key_and_public_point( + priv_bytes: &[u8], + pub_bytes: &[u8], + ) -> Result { + if pub_bytes.len() != C::UNCOMPRESSED_POINT_SIZE { + return Err(WolfCryptError::INVALID_INPUT); + } + if pub_bytes[0] != 0x04 { + return Err(WolfCryptError::INVALID_INPUT); + } + + // SAFETY: EC_GROUP_new_by_curve_name returns null on failure. + let group = unsafe { EC_GROUP_new_by_curve_name(C::NID) }; + if group.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: EC_KEY_new returns null on failure. + let key = unsafe { EC_KEY_new() }; + if key.is_null() { + unsafe { EC_GROUP_free(group) }; + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: key and group are valid non-null pointers. + let rc = unsafe { EC_KEY_set_group(key, group) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_group" }); + } + + // --- Import the private key scalar --- + + // SAFETY: BN_bin2bn creates a new BIGNUM from big-endian bytes. + // Passing null as ret allocates a fresh BIGNUM. + let priv_bn = unsafe { + BN_bin2bn( + priv_bytes.as_ptr(), + len_as_c_int(priv_bytes.len()), + core::ptr::null_mut(), + ) + }; + if priv_bn.is_null() { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: key is valid, priv_bn is a valid BIGNUM. + // EC_KEY_set_private_key copies the BIGNUM, so we free it after. + let rc = unsafe { EC_KEY_set_private_key(key, priv_bn) }; + unsafe { BN_free(priv_bn) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_private_key" }); + } + + // --- Import the public point --- + + // SAFETY: group is valid; EC_POINT_new returns null on failure. + let point = unsafe { EC_POINT_new(group) }; + if point.is_null() { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: group and point are valid. pub_bytes is the correct length. + let rc = unsafe { + EC_POINT_oct2point( + group, + point, + pub_bytes.as_ptr(), + pub_bytes.len(), + core::ptr::null_mut(), + ) + }; + if rc != 1 { + unsafe { + EC_POINT_free(point); + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_POINT_oct2point" }); + } + + // SAFETY: key is valid, point is a valid decoded public point. + // EC_KEY_set_public_key copies the point, so we can free it after. + let rc = unsafe { EC_KEY_set_public_key(key, point) }; + unsafe { EC_POINT_free(point) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_public_key" }); + } + + Ok(Self { + key: UnsafeCell::new(key), + group, + _curve: PhantomData, + }) + } + + /// Construct a signing key from raw private-key scalar bytes only. + /// + /// The public key is computed via EC point multiplication (pub = priv * G). + /// `priv_bytes` is the big-endian encoding of the private scalar. + pub fn from_private_key_bytes(priv_bytes: &[u8]) -> Result { + // SAFETY: EC_GROUP_new_by_curve_name returns null on failure. + let group = unsafe { EC_GROUP_new_by_curve_name(C::NID) }; + if group.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: EC_KEY_new returns null on failure. + let key = unsafe { EC_KEY_new() }; + if key.is_null() { + unsafe { EC_GROUP_free(group) }; + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: key and group are valid non-null pointers. + let rc = unsafe { EC_KEY_set_group(key, group) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_group" }); + } + + // --- Import the private key scalar --- + let priv_bn = unsafe { + BN_bin2bn( + priv_bytes.as_ptr(), + len_as_c_int(priv_bytes.len()), + core::ptr::null_mut(), + ) + }; + if priv_bn.is_null() { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::ALLOC_FAILED); + } + + let rc = unsafe { EC_KEY_set_private_key(key, priv_bn) }; + if rc != 1 { + unsafe { + BN_free(priv_bn); + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_private_key" }); + } + + // --- Compute public key: pub = priv * G --- + let point = unsafe { EC_POINT_new(group) }; + if point.is_null() { + unsafe { + BN_free(priv_bn); + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: EC_POINT_mul(group, result, n, NULL, NULL, NULL) computes result = n * G. + let rc = unsafe { + EC_POINT_mul( + group, + point, + priv_bn, + core::ptr::null(), + core::ptr::null(), + core::ptr::null_mut(), + ) + }; + unsafe { BN_free(priv_bn) }; + if rc != 1 { + unsafe { + EC_POINT_free(point); + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_POINT_mul" }); + } + + // SAFETY: key is valid, point is the computed public point. + let rc = unsafe { EC_KEY_set_public_key(key, point) }; + unsafe { EC_POINT_free(point) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_public_key" }); + } + + Ok(Self { + key: UnsafeCell::new(key), + group, + _curve: PhantomData, + }) + } + + /// Sign pre-hashed data directly, skipping the internal hashing step. + /// + /// `hash` must be exactly `C::HASH_LEN` bytes (the output of the + /// curve's canonical digest). Returns `WolfCryptError::InvalidInput` + /// if the length is wrong. + pub fn sign_prehash( + &self, + hash: &[u8], + ) -> Result, WolfCryptError> { + if hash.len() != C::HASH_LEN { + return Err(WolfCryptError::INVALID_INPUT); + } + + let key = unsafe { *self.key.get() }; + + // SAFETY: hash is HASH_LEN bytes, key is a valid EC_KEY with + // private + public components. ECDSA_do_sign returns null on failure. + let sig = unsafe { + ECDSA_do_sign(hash.as_ptr(), len_as_c_int(hash.len()), key) + }; + if sig.is_null() { + return Err(WolfCryptError::Ffi { code: 0, func: "ECDSA_do_sign" }); + } + + // Extract r and s as BIGNUMs (internal pointers โ€” do NOT free). + let mut r_ptr: *const BIGNUM = core::ptr::null(); + let mut s_ptr: *const BIGNUM = core::ptr::null(); + + // SAFETY: sig is a valid ECDSA_SIG. get0 writes internal pointers + // to r_ptr and s_ptr. These are borrowed and must not be freed. + unsafe { ECDSA_SIG_get0(sig, &mut r_ptr, &mut s_ptr) }; + + // Convert to fixed-size bytes. + let r_bytes = unsafe { bn_to_fixed_bytes(r_ptr, C::FIELD_SIZE) }; + let s_bytes = unsafe { bn_to_fixed_bytes(s_ptr, C::FIELD_SIZE) }; + + // SAFETY: sig was allocated by ECDSA_do_sign; free it now. + unsafe { ECDSA_SIG_free(sig) }; + + let mut combined = GenericArray::::default(); + combined[..C::FIELD_SIZE].copy_from_slice(&r_bytes); + combined[C::FIELD_SIZE..].copy_from_slice(&s_bytes); + + Ok(EcdsaSignature { + bytes: combined, + _curve: PhantomData, + }) + } +} + +impl Drop for EcdsaSigningKey { + fn drop(&mut self) { + // SAFETY: key and group were successfully allocated during + // construction. Free key first (it references the group internally), + // then group. Each is freed exactly once. + unsafe { + EC_KEY_free(*self.key.get_mut()); + EC_GROUP_free(self.group); + } + } +} + +impl signature_trait::Signer> for EcdsaSigningKey { + fn try_sign( + &self, + msg: &[u8], + ) -> Result, signature_trait::Error> { + let hash = hash_message::(msg).map_err(|_| signature_trait::Error::new())?; + let key = unsafe { *self.key.get() }; + + // SAFETY: hash is HASH_LEN bytes, key is a valid EC_KEY with + // private + public components. ECDSA_do_sign returns null on failure. + let sig = unsafe { + ECDSA_do_sign(hash.as_ptr(), len_as_c_int(hash.len()), key) + }; + if sig.is_null() { + return Err(signature_trait::Error::new()); + } + + // Extract r and s as BIGNUMs (internal pointers โ€” do NOT free). + let mut r_ptr: *const BIGNUM = core::ptr::null(); + let mut s_ptr: *const BIGNUM = core::ptr::null(); + + // SAFETY: sig is a valid ECDSA_SIG. get0 writes internal pointers + // to r_ptr and s_ptr. These are borrowed and must not be freed. + unsafe { ECDSA_SIG_get0(sig, &mut r_ptr, &mut s_ptr) }; + + // Convert to fixed-size bytes. + let r_bytes = unsafe { bn_to_fixed_bytes(r_ptr, C::FIELD_SIZE) }; + let s_bytes = unsafe { bn_to_fixed_bytes(s_ptr, C::FIELD_SIZE) }; + + // SAFETY: sig was allocated by ECDSA_do_sign; free it now. + unsafe { ECDSA_SIG_free(sig) }; + + let mut combined = GenericArray::::default(); + combined[..C::FIELD_SIZE].copy_from_slice(&r_bytes); + combined[C::FIELD_SIZE..].copy_from_slice(&s_bytes); + + Ok(EcdsaSignature { + bytes: combined, + _curve: PhantomData, + }) + } +} + +// ============================================================ +// EcdsaVerifyingKey +// ============================================================ + +/// An ECDSA verifying key (public key) backed by wolfCrypt's OpenSSL compat +/// layer. +/// +/// Parameterized by curve: use [`P256`] or [`P384`]. +pub struct EcdsaVerifyingKey { + /// Heap-allocated EC_KEY (public-only). + /// + /// `UnsafeCell` around the pointer: same rationale as + /// [`EcdsaSigningKey::key`] โ€” provides `!Sync`. + key: UnsafeCell<*mut EC_KEY>, + /// Heap-allocated EC_GROUP (owned; freed on drop). + group: *mut EC_GROUP, + /// Cached uncompressed public point bytes for cheap access. + pub_bytes: Vec, + _curve: PhantomData, +} + +// SAFETY: EC_KEY and EC_GROUP own independent heap state; safe to send. +unsafe impl Send for EcdsaVerifyingKey {} + +impl EcdsaVerifyingKey { + /// Construct a verifying key from an uncompressed public point + /// (0x04 || x || y). + /// + /// The `bytes` slice must be exactly `C::UNCOMPRESSED_POINT_SIZE` bytes. + pub fn from_uncompressed_point(bytes: &[u8]) -> Result { + if bytes.len() != C::UNCOMPRESSED_POINT_SIZE { + return Err(WolfCryptError::INVALID_INPUT); + } + if bytes[0] != 0x04 { + return Err(WolfCryptError::INVALID_INPUT); + } + + // SAFETY: EC_GROUP_new_by_curve_name returns null on failure. + let group = unsafe { EC_GROUP_new_by_curve_name(C::NID) }; + if group.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: EC_KEY_new returns null on failure. + let key = unsafe { EC_KEY_new() }; + if key.is_null() { + unsafe { EC_GROUP_free(group) }; + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: key and group are valid. + let rc = unsafe { EC_KEY_set_group(key, group) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_group" }); + } + + // Create a temporary EC_POINT and decode the uncompressed bytes. + // SAFETY: group is valid; EC_POINT_new returns null on failure. + let point = unsafe { EC_POINT_new(group) }; + if point.is_null() { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::ALLOC_FAILED); + } + + // SAFETY: group and point are valid. bytes is the correct length. + let rc = unsafe { + EC_POINT_oct2point( + group, + point, + bytes.as_ptr(), + bytes.len(), + core::ptr::null_mut(), + ) + }; + if rc != 1 { + unsafe { + EC_POINT_free(point); + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_POINT_oct2point" }); + } + + // SAFETY: key is valid, point is a valid decoded public point. + // EC_KEY_set_public_key copies the point, so we can free it after. + let rc = unsafe { EC_KEY_set_public_key(key, point) }; + unsafe { EC_POINT_free(point) }; + if rc != 1 { + unsafe { + EC_KEY_free(key); + EC_GROUP_free(group); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EC_KEY_set_public_key" }); + } + + Ok(Self { + key: UnsafeCell::new(key), + group, + pub_bytes: bytes.to_vec(), + _curve: PhantomData, + }) + } + + /// Return the uncompressed public point bytes (0x04 || x || y). + pub fn as_bytes(&self) -> &[u8] { + &self.pub_bytes + } +} + +impl Drop for EcdsaVerifyingKey { + fn drop(&mut self) { + // SAFETY: key and group were successfully allocated during + // construction. Freed exactly once, key before group. + unsafe { + EC_KEY_free(*self.key.get_mut()); + EC_GROUP_free(self.group); + } + } +} + +impl signature_trait::Verifier> for EcdsaVerifyingKey { + fn verify( + &self, + msg: &[u8], + signature: &EcdsaSignature, + ) -> Result<(), signature_trait::Error> { + let hash = hash_message::(msg).map_err(|_| signature_trait::Error::new())?; + let key = unsafe { *self.key.get() }; + + // Parse r and s from the fixed-size signature. + let r_bytes = signature.r_bytes(); + let s_bytes = signature.s_bytes(); + + // SAFETY: BN_bin2bn creates a new BIGNUM from big-endian bytes. + // Passing null as ret allocates a fresh BIGNUM. + let r_bn = unsafe { + BN_bin2bn(r_bytes.as_ptr(), len_as_c_int(r_bytes.len()), core::ptr::null_mut()) + }; + if r_bn.is_null() { + return Err(signature_trait::Error::new()); + } + + let s_bn = unsafe { + BN_bin2bn(s_bytes.as_ptr(), len_as_c_int(s_bytes.len()), core::ptr::null_mut()) + }; + if s_bn.is_null() { + unsafe { BN_free(r_bn) }; + return Err(signature_trait::Error::new()); + } + + // SAFETY: ECDSA_SIG_new allocates a new ECDSA_SIG. + let sig = unsafe { ECDSA_SIG_new() }; + if sig.is_null() { + unsafe { + BN_free(r_bn); + BN_free(s_bn); + } + return Err(signature_trait::Error::new()); + } + + // SAFETY: ECDSA_SIG_set0 takes ownership of r_bn and s_bn. + // After this call, do NOT free r_bn or s_bn โ€” they belong to sig. + let rc = unsafe { ECDSA_SIG_set0(sig, r_bn, s_bn) }; + if rc != 1 { + // set0 failed; sig did NOT take ownership, so free everything. + unsafe { + BN_free(r_bn); + BN_free(s_bn); + ECDSA_SIG_free(sig); + } + return Err(signature_trait::Error::new()); + } + + // SAFETY: hash is HASH_LEN bytes, sig is valid, key is valid. + // ECDSA_do_verify returns 1 on success, 0 or negative on failure. + let result = unsafe { + ECDSA_do_verify(hash.as_ptr(), len_as_c_int(hash.len()), sig, key) + }; + + // SAFETY: sig was allocated by ECDSA_SIG_new and owns r_bn/s_bn. + unsafe { ECDSA_SIG_free(sig) }; + + if result == 1 { + Ok(()) + } else { + Err(signature_trait::Error::new()) + } + } +} + +// ============================================================ +// Type aliases +// ============================================================ + +/// P-256 ECDSA signing key. +pub type P256SigningKey = EcdsaSigningKey; +/// P-256 ECDSA verifying key. +pub type P256VerifyingKey = EcdsaVerifyingKey; +/// P-256 ECDSA signature. +pub type P256Signature = EcdsaSignature; + +/// P-384 ECDSA signing key. +#[cfg(wolfssl_ecc_p384)] +pub type P384SigningKey = EcdsaSigningKey; +/// P-384 ECDSA verifying key. +#[cfg(wolfssl_ecc_p384)] +pub type P384VerifyingKey = EcdsaVerifyingKey; +/// P-384 ECDSA signature. +#[cfg(wolfssl_ecc_p384)] +pub type P384Signature = EcdsaSignature; + +/// P-521 ECDSA signing key. +#[cfg(wolfssl_ecc_p521)] +pub type P521SigningKey = EcdsaSigningKey; +/// P-521 ECDSA verifying key. +#[cfg(wolfssl_ecc_p521)] +pub type P521VerifyingKey = EcdsaVerifyingKey; +/// P-521 ECDSA signature. +#[cfg(wolfssl_ecc_p521)] +pub type P521Signature = EcdsaSignature; diff --git a/wolfcrypt/src/ecdsa_native.rs b/wolfcrypt/src/ecdsa_native.rs deleted file mode 100644 index 26ce06d..0000000 --- a/wolfcrypt/src/ecdsa_native.rs +++ /dev/null @@ -1,587 +0,0 @@ -//! ECDSA signing and verification (P-256, P-384) backed by native wolfCrypt -//! `wc_ecc_*` functions. -//! -//! This module is active when `OPENSSL_EXTRA` is absent (e.g. the -//! `cryptocb-only` firmware build). It provides the same public API as -//! the `ecdsa` module (EVP-based) so that callers are unaffected by the -//! choice of implementation. -//! -//! Signing uses `wc_ecc_sign_hash` which dispatches to the registered -//! CryptoCb device in `WOLF_CRYPTO_CB_ONLY_ECC` builds. Hashing uses the -//! native `wc_Sha256Hash` / `wc_Sha384Hash` one-shot functions. - -extern crate alloc; - -use alloc::vec; -use alloc::vec::Vec; -use core::cell::UnsafeCell; -use core::ffi::c_int; -use core::marker::PhantomData; - -use generic_array::GenericArray; - -use crate::error::WolfCryptError; - -use wolfcrypt_rs::{ - WC_RNG, wc_InitRng, wc_FreeRng, - wc_ecc_key, - wc_ecc_key_new, wc_ecc_key_free, - wc_ecc_make_key_ex, wc_ecc_set_rng, - wc_ecc_import_private_key_ex, wc_ecc_import_x963, wc_ecc_export_x963, - wc_ecc_sign_hash, wc_ecc_verify_hash, - wc_ecc_sig_to_rs, wc_ecc_rs_raw_to_sig, - ECC_SECP256R1, -}; - -#[cfg(wolfssl_ecc_p384)] -use wolfcrypt_rs::ECC_SECP384R1; - -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -use wolfcrypt_rs::ECC_SECP521R1; - -// ============================================================ -// Sealed trait pattern -// ============================================================ - -mod sealed { - pub trait Sealed {} -} - -/// Trait describing an ECDSA curve's parameters. -/// -/// Sealed so that only [`P256`] and [`P384`] can implement it. -pub trait EcdsaCurve: sealed::Sealed + 'static { - /// wolfCrypt curve ID (e.g. `ECC_SECP256R1`). - const CURVE_ID: c_int; - /// Size of one field element in bytes (32 for P-256, 48 for P-384). - const FIELD_SIZE: usize; - /// Size of the fixed-size signature (2 * FIELD_SIZE). - const SIG_SIZE: usize; - /// Size of the uncompressed public point (1 + 2 * FIELD_SIZE). - const UNCOMPRESSED_POINT_SIZE: usize; - /// Hash output length in bytes for this curve's canonical digest. - /// - /// This is *not* always equal to `FIELD_SIZE`. For example, P-521 uses - /// SHA-512 (64 bytes) while its field size is 66 bytes. - const HASH_LEN: usize; - /// Typenum encoding of [`SIG_SIZE`](Self::SIG_SIZE). - type SigSize: generic_array::ArrayLength; - - /// Hash `msg` using the curve's canonical digest. - fn hash_message(msg: &[u8]) -> Result, WolfCryptError>; -} - -/// NIST P-256 (secp256r1 / prime256v1) curve marker. -pub struct P256; - -impl sealed::Sealed for P256 {} - -impl EcdsaCurve for P256 { - const CURVE_ID: c_int = ECC_SECP256R1; - const FIELD_SIZE: usize = 32; - const SIG_SIZE: usize = 64; - const UNCOMPRESSED_POINT_SIZE: usize = 65; - const HASH_LEN: usize = 32; - type SigSize = typenum::U64; - - fn hash_message(msg: &[u8]) -> Result, WolfCryptError> { - let mut hash = vec![0u8; 32]; - let rc = unsafe { - wolfcrypt_rs::wc_Sha256Hash(msg.as_ptr(), msg.len() as u32, hash.as_mut_ptr()) - }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_Sha256Hash" }); - } - Ok(hash) - } -} - -/// NIST P-384 (secp384r1) curve marker. -#[cfg(wolfssl_ecc_p384)] -pub struct P384; - -#[cfg(wolfssl_ecc_p384)] -impl sealed::Sealed for P384 {} - -#[cfg(wolfssl_ecc_p384)] -impl EcdsaCurve for P384 { - const CURVE_ID: c_int = ECC_SECP384R1; - const FIELD_SIZE: usize = 48; - const SIG_SIZE: usize = 96; - const UNCOMPRESSED_POINT_SIZE: usize = 97; - const HASH_LEN: usize = 48; - type SigSize = typenum::U96; - - fn hash_message(msg: &[u8]) -> Result, WolfCryptError> { - let mut hash = vec![0u8; 48]; - let rc = unsafe { - wolfcrypt_rs::wc_Sha384Hash(msg.as_ptr(), msg.len() as u32, hash.as_mut_ptr()) - }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_Sha384Hash" }); - } - Ok(hash) - } -} - -/// NIST P-521 (secp521r1) curve marker. -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -pub struct P521; - -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -impl sealed::Sealed for P521 {} - -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -impl EcdsaCurve for P521 { - const CURVE_ID: c_int = ECC_SECP521R1; - /// P-521 field element: ceil(521/8) = 66 bytes. - const FIELD_SIZE: usize = 66; - /// Fixed-size r || s signature: 2 * 66 = 132 bytes. - const SIG_SIZE: usize = 132; - /// Uncompressed public point: 1 + 2 * 66 = 133 bytes. - const UNCOMPRESSED_POINT_SIZE: usize = 133; - const HASH_LEN: usize = 64; - type SigSize = typenum::U132; - - fn hash_message(msg: &[u8]) -> Result, WolfCryptError> { - let mut hash = vec![0u8; 64]; - let rc = unsafe { - wolfcrypt_rs::wc_Sha512Hash(msg.as_ptr(), msg.len() as u32, hash.as_mut_ptr()) - }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_Sha512Hash" }); - } - Ok(hash) - } -} - -// ============================================================ -// EcdsaSignature -// ============================================================ - -/// A fixed-size, stack-allocated ECDSA signature in `r || s` format. -pub struct EcdsaSignature { - bytes: GenericArray, - _curve: PhantomData, -} - -impl EcdsaSignature { - /// Create a signature from raw `r || s` bytes. - pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != C::SIG_SIZE { - return Err(WolfCryptError::INVALID_INPUT); - } - Ok(Self { - bytes: GenericArray::clone_from_slice(bytes), - _curve: PhantomData, - }) - } - - /// Return the raw `r || s` bytes. - pub fn as_bytes(&self) -> &[u8] { - &self.bytes - } - - /// Return `r` component (big-endian, zero-padded to FIELD_SIZE bytes). - pub fn r_bytes(&self) -> &[u8] { - &self.bytes[..C::FIELD_SIZE] - } - - /// Return `s` component (big-endian, zero-padded to FIELD_SIZE bytes). - pub fn s_bytes(&self) -> &[u8] { - &self.bytes[C::FIELD_SIZE..] - } -} - -impl Clone for EcdsaSignature { - fn clone(&self) -> Self { - Self { bytes: self.bytes.clone(), _curve: PhantomData } - } -} - -impl PartialEq for EcdsaSignature { - fn eq(&self, other: &Self) -> bool { - self.bytes == other.bytes - } -} -impl Eq for EcdsaSignature {} - -impl core::fmt::Debug for EcdsaSignature { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("EcdsaSignature") - .field("len", &self.bytes.len()) - .finish() - } -} - -impl signature_trait::SignatureEncoding for EcdsaSignature { - type Repr = Vec; -} - -impl TryFrom<&[u8]> for EcdsaSignature { - type Error = signature_trait::Error; - fn try_from(bytes: &[u8]) -> Result { - Self::from_bytes(bytes).map_err(|_| signature_trait::Error::new()) - } -} - -impl From> for Vec { - fn from(sig: EcdsaSignature) -> Vec { - sig.bytes.to_vec() - } -} - -impl AsRef<[u8]> for EcdsaSignature { - fn as_ref(&self) -> &[u8] { - &self.bytes - } -} - -// ============================================================ -// Helper: convert DER signature to fixed r||s -// ============================================================ - -fn der_to_fixed_rs( - der: &[u8], - der_len: u32, -) -> Result, WolfCryptError> { - let mut r = vec![0u8; C::FIELD_SIZE]; - let mut s = vec![0u8; C::FIELD_SIZE]; - let mut r_len = C::FIELD_SIZE as u32; - let mut s_len = C::FIELD_SIZE as u32; - - let rc = unsafe { - wc_ecc_sig_to_rs( - der.as_ptr(), der_len, - r.as_mut_ptr(), &mut r_len, - s.as_mut_ptr(), &mut s_len, - ) - }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_sig_to_rs" }); - } - - // wc_ecc_sig_to_rs returns r and s stripped of leading zeros. - // Zero-pad them to FIELD_SIZE on the left. - // - // Defensive: we passed FIELD_SIZE as the buffer capacity; wolfCrypt must - // never report a length exceeding it. If it does (C bug, memory - // corruption) the subtraction below would wrap in release builds causing - // UB. Return an error instead. - if r_len as usize > C::FIELD_SIZE || s_len as usize > C::FIELD_SIZE { - return Err(WolfCryptError::INVALID_INPUT); - } - let mut combined = GenericArray::::default(); - let r_pad = C::FIELD_SIZE - r_len as usize; - combined[r_pad..C::FIELD_SIZE].copy_from_slice(&r[..r_len as usize]); - let s_pad = C::FIELD_SIZE - s_len as usize; - combined[C::FIELD_SIZE + s_pad..].copy_from_slice(&s[..s_len as usize]); - - Ok(combined) -} - -// ============================================================ -// EcdsaSigningKey -// ============================================================ - -/// An ECDSA signing key (private key) backed by native wolfCrypt `wc_ecc_*`. -pub struct EcdsaSigningKey { - /// Heap-allocated wc_ecc_key (via wc_ecc_key_new). - /// - /// `UnsafeCell` makes this type `!Sync`, which is the correct contract: - /// wolfCrypt contexts are not thread-safe. - key: UnsafeCell<*mut wc_ecc_key>, - _curve: PhantomData, -} - -// SAFETY: wc_ecc_key owns independent heap state; safe to move between threads. -unsafe impl Send for EcdsaSigningKey {} - -impl Drop for EcdsaSigningKey { - fn drop(&mut self) { - let key = *self.key.get_mut(); - if !key.is_null() { - unsafe { wc_ecc_key_free(key) }; - } - } -} - -impl EcdsaSigningKey { - /// Generate a fresh random ECDSA signing key on curve `C`. - pub fn generate() -> Result { - let key = unsafe { wc_ecc_key_new(core::ptr::null_mut()) }; - if key.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - - let mut rng = WC_RNG::zeroed(); - // SAFETY: rng is zero-initialised; wc_InitRng completes setup. - let rc = unsafe { wc_InitRng(&mut rng) }; - if rc != 0 { - unsafe { wc_ecc_key_free(key) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_InitRng" }); - } - - // SAFETY: key and rng are both initialised; FIELD_SIZE matches CURVE_ID. - let rc = unsafe { - wc_ecc_make_key_ex(&mut rng, C::FIELD_SIZE as c_int, key, C::CURVE_ID) - }; - // Always free the RNG, success or failure. - unsafe { wc_FreeRng(&mut rng) }; - if rc != 0 { - unsafe { wc_ecc_key_free(key) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_make_key_ex" }); - } - - Ok(Self { key: UnsafeCell::new(key), _curve: PhantomData }) - } - - /// Construct a signing key from raw private-key scalar bytes and an - /// uncompressed public point (0x04 || x || y). - pub fn from_private_key_and_public_point( - priv_bytes: &[u8], - pub_bytes: &[u8], - ) -> Result { - if pub_bytes.len() != C::UNCOMPRESSED_POINT_SIZE || pub_bytes[0] != 0x04 { - return Err(WolfCryptError::INVALID_INPUT); - } - let key = unsafe { wc_ecc_key_new(core::ptr::null_mut()) }; - if key.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - let rc = unsafe { - wc_ecc_import_private_key_ex( - priv_bytes.as_ptr(), priv_bytes.len() as u32, - pub_bytes.as_ptr(), pub_bytes.len() as u32, - key, C::CURVE_ID, - ) - }; - if rc != 0 { - unsafe { wc_ecc_key_free(key) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_import_private_key_ex" }); - } - Ok(Self { key: UnsafeCell::new(key), _curve: PhantomData }) - } - - /// Construct a signing key from raw private-key scalar bytes only. - /// - /// The public key is computed via EC point multiplication (pub = priv * G). - /// In a `WOLF_CRYPTO_CB_ONLY_ECC` build this computation is dispatched to - /// the registered CryptoCb device. - pub fn from_private_key_bytes(priv_bytes: &[u8]) -> Result { - let key = unsafe { wc_ecc_key_new(core::ptr::null_mut()) }; - if key.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - let rc = unsafe { - wc_ecc_import_private_key_ex( - priv_bytes.as_ptr(), priv_bytes.len() as u32, - core::ptr::null(), 0, - key, C::CURVE_ID, - ) - }; - if rc != 0 { - unsafe { wc_ecc_key_free(key) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_import_private_key_ex" }); - } - Ok(Self { key: UnsafeCell::new(key), _curve: PhantomData }) - } - - /// Return the corresponding verifying (public) key. - pub fn verifying_key(&self) -> Result, WolfCryptError> { - let key = unsafe { *self.key.get() }; - let mut buf = vec![0u8; C::UNCOMPRESSED_POINT_SIZE]; - let mut sz = buf.len() as u32; - let rc = unsafe { wc_ecc_export_x963(key, buf.as_mut_ptr(), &mut sz) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_export_x963" }); - } - buf.truncate(sz as usize); - EcdsaVerifyingKey::from_uncompressed_point(&buf) - } - - /// Sign pre-hashed data directly (no internal hashing). - /// - /// `hash` must be exactly `C::HASH_LEN` bytes. - pub fn sign_prehash(&self, hash: &[u8]) -> Result, WolfCryptError> { - if hash.len() != C::HASH_LEN { - return Err(WolfCryptError::INVALID_INPUT); - } - let key = unsafe { *self.key.get() }; - - // Max DER ECDSA signature: SEQUENCE + 2 * (INTEGER + optional-zero + field). - let mut der = vec![0u8; C::FIELD_SIZE * 2 + 16]; - let mut der_len = der.len() as u32; - - // Initialise a per-call RNG for ECC_TIMING_RESISTANT scalar-multiplication - // blinding. Required on software builds; harmless on CryptoCb builds where - // the dispatch ignores it. - let mut rng = WC_RNG::zeroed(); - let rc = unsafe { wc_InitRng(&mut rng) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_InitRng (sign)" }); - } - - // Attach the RNG to the key so internal timing-resistant code can use it. - let rc = unsafe { wc_ecc_set_rng(key, &mut rng) }; - if rc != 0 { - unsafe { wc_FreeRng(&mut rng) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_set_rng" }); - } - - // SAFETY: hash is HASH_LEN bytes; key holds the private key; rng is live. - // - // Note: the same `rng` is passed both as the key-attached RNG (via - // `wc_ecc_set_rng` above, used for scalar-multiplication blinding) and - // as the explicit RNG argument here (used for nonce generation). - // wolfCrypt accepts the same object for both roles; this is intentional. - let rc = unsafe { - wc_ecc_sign_hash( - hash.as_ptr(), hash.len() as u32, - der.as_mut_ptr(), &mut der_len, - &mut rng, - key, - ) - }; - // Always free the RNG regardless of outcome. - unsafe { wc_FreeRng(&mut rng) }; - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_sign_hash" }); - } - - let combined = der_to_fixed_rs::(&der, der_len)?; - Ok(EcdsaSignature { bytes: combined, _curve: PhantomData }) - } -} - -impl signature_trait::Signer> for EcdsaSigningKey { - fn try_sign(&self, msg: &[u8]) -> Result, signature_trait::Error> { - let hash = C::hash_message(msg).map_err(|_| signature_trait::Error::new())?; - self.sign_prehash(&hash).map_err(|_| signature_trait::Error::new()) - } -} - -// ============================================================ -// EcdsaVerifyingKey -// ============================================================ - -/// An ECDSA verifying key (public key) backed by native wolfCrypt `wc_ecc_*`. -pub struct EcdsaVerifyingKey { - key: UnsafeCell<*mut wc_ecc_key>, - /// Cached uncompressed point bytes (0x04 || x || y). - pub_bytes: Vec, - _curve: PhantomData, -} - -unsafe impl Send for EcdsaVerifyingKey {} - -impl Drop for EcdsaVerifyingKey { - fn drop(&mut self) { - let key = *self.key.get_mut(); - if !key.is_null() { - unsafe { wc_ecc_key_free(key) }; - } - } -} - -impl EcdsaVerifyingKey { - /// Construct a verifying key from an uncompressed public point (0x04 || x || y). - pub fn from_uncompressed_point(bytes: &[u8]) -> Result { - if bytes.len() != C::UNCOMPRESSED_POINT_SIZE || bytes[0] != 0x04 { - return Err(WolfCryptError::INVALID_INPUT); - } - let key = unsafe { wc_ecc_key_new(core::ptr::null_mut()) }; - if key.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - let rc = unsafe { - wc_ecc_import_x963(bytes.as_ptr(), bytes.len() as u32, key) - }; - if rc != 0 { - unsafe { wc_ecc_key_free(key) }; - return Err(WolfCryptError::Ffi { code: rc, func: "wc_ecc_import_x963" }); - } - Ok(Self { - key: UnsafeCell::new(key), - pub_bytes: bytes.to_vec(), - _curve: PhantomData, - }) - } - - /// Return the uncompressed public point bytes (0x04 || x || y). - pub fn as_bytes(&self) -> &[u8] { - &self.pub_bytes - } -} - -impl signature_trait::Verifier> for EcdsaVerifyingKey { - fn verify( - &self, - msg: &[u8], - signature: &EcdsaSignature, - ) -> Result<(), signature_trait::Error> { - let hash = C::hash_message(msg).map_err(|_| signature_trait::Error::new())?; - let key = unsafe { *self.key.get() }; - - // Convert fixed r||s to DER. - let r = signature.r_bytes(); - let s = signature.s_bytes(); - let mut der = vec![0u8; C::FIELD_SIZE * 2 + 16]; - let mut der_len = der.len() as u32; - - let rc = unsafe { - wc_ecc_rs_raw_to_sig( - r.as_ptr(), r.len() as u32, - s.as_ptr(), s.len() as u32, - der.as_mut_ptr(), &mut der_len, - ) - }; - if rc != 0 { - return Err(signature_trait::Error::new()); - } - - let mut res: c_int = 0; - let rc = unsafe { - wc_ecc_verify_hash( - der.as_ptr(), der_len, - hash.as_ptr(), hash.len() as u32, - &mut res, key, - ) - }; - if rc != 0 || res != 1 { - return Err(signature_trait::Error::new()); - } - Ok(()) - } -} - -// ============================================================ -// Type aliases -// ============================================================ - -/// P-256 ECDSA signing key. -pub type P256SigningKey = EcdsaSigningKey; -/// P-256 ECDSA verifying key. -pub type P256VerifyingKey = EcdsaVerifyingKey; -/// P-256 ECDSA signature. -pub type P256Signature = EcdsaSignature; - -/// P-384 ECDSA signing key. -#[cfg(wolfssl_ecc_p384)] -pub type P384SigningKey = EcdsaSigningKey; -/// P-384 ECDSA verifying key. -#[cfg(wolfssl_ecc_p384)] -pub type P384VerifyingKey = EcdsaVerifyingKey; -/// P-384 ECDSA signature. -#[cfg(wolfssl_ecc_p384)] -pub type P384Signature = EcdsaSignature; - -/// P-521 ECDSA signing key. -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -pub type P521SigningKey = EcdsaSigningKey; -/// P-521 ECDSA verifying key. -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -pub type P521VerifyingKey = EcdsaVerifyingKey; -/// P-521 ECDSA signature. -#[cfg(all(wolfssl_ecc_p521, wolfssl_sha512))] -pub type P521Signature = EcdsaSignature; diff --git a/wolfcrypt/src/ed25519.rs b/wolfcrypt/src/ed25519.rs index d90f61f..eba7c56 100644 --- a/wolfcrypt/src/ed25519.rs +++ b/wolfcrypt/src/ed25519.rs @@ -8,7 +8,7 @@ use core::cell::UnsafeCell; use crate::error::{check, len_as_u32, WolfCryptError}; use wolfcrypt_rs::{ - wc_ed25519_check_key, wc_ed25519_export_public, wc_ed25519_free, + wc_ed25519_export_public, wc_ed25519_free, wc_ed25519_import_private_key, wc_ed25519_import_private_only, wc_ed25519_import_public, wc_ed25519_init, wc_ed25519_make_key, wc_ed25519_make_public, wc_ed25519_sign_msg, @@ -238,25 +238,6 @@ impl Ed25519VerifyingKey { pub fn as_bytes(&self) -> &[u8; ED25519_KEY_SIZE] { &self.pub_bytes } - - /// Validate that the imported public key is a valid point on the Ed25519 - /// curve. - /// - /// `from_bytes` imports the raw bytes into wolfCrypt but does not call - /// `wc_ed25519_check_key`. Call this method when the bytes come from an - /// untrusted source (e.g. a hardware device response) to reject invalid or - /// low-order points before using the key for verification. - /// - /// # Errors - /// - /// Returns `Err(WolfCryptError)` if wolfCrypt reports the key is invalid. - pub fn check_key(&mut self) -> Result<(), WolfCryptError> { - // SAFETY: `self.key` is initialised and has a public key set. - // `wc_ed25519_check_key` reads the key but takes `*mut` per the C API - // convention; no mutation occurs in practice. - let rc = unsafe { wc_ed25519_check_key(self.key.get()) }; - check(rc, "wc_ed25519_check_key") - } } impl Drop for Ed25519VerifyingKey { diff --git a/wolfcrypt/src/hmac.rs b/wolfcrypt/src/hmac.rs index 8084b99..76593b8 100644 --- a/wolfcrypt/src/hmac.rs +++ b/wolfcrypt/src/hmac.rs @@ -1,4 +1,4 @@ -//! HMAC algorithms backed by wolfCrypt's native wc_Hmac* API. +//! HMAC algorithms backed by wolfCrypt's HMAC_CTX API. //! //! Each type implements the RustCrypto [`hmac`](hmac_trait) 0.12 traits //! (`OutputSizeUser`, `KeySizeUser`, `KeyInit`, `Update`, `FixedOutput`, @@ -7,39 +7,57 @@ //! Callers should `use hmac_trait::Mac` for the full API: //! `new_from_slice()`, `update()`, `finalize()`, `verify_slice()`. +use core::ffi::c_void; use digest_trait::{FixedOutput, KeyInit, OutputSizeUser, Update}; use generic_array::GenericArray; use typenum::*; +use crate::error::len_as_c_int; /// Internal macro that stamps out a complete HMAC wrapper for one algorithm. /// -/// The generated struct holds a heap-allocated wolfCrypt `Hmac` context -/// and delegates all operations through `wolfcrypt_hmac_*` C shims. +/// The generated struct holds a heap-allocated `HMAC_CTX` and delegates +/// all operations to wolfCrypt through the OpenSSL-compat HMAC layer. macro_rules! impl_hmac { ( $name:ident, - $new_fn:path, + $evp_fn:path, $output_size:ty, $key_size:ty, $cfg_gate:meta ) => { #[$cfg_gate] pub struct $name { - ctx: *mut core::ffi::c_void, + ctx: *mut wolfcrypt_rs::HMAC_CTX, } - // SAFETY: The Hmac context is heap-allocated and only accessed through - // &self / &mut self. wolfCrypt's HMAC API is thread-safe when a - // context is used from a single thread, which Rust's ownership rules enforce. + // SAFETY: HMAC_CTX is heap-allocated and only accessed through + // &self / &mut self. wolfCrypt's HMAC layer is thread-safe when a + // context is used from a single thread, which Rust's ownership + // rules enforce. #[$cfg_gate] unsafe impl Send for $name {} + #[$cfg_gate] + impl $name { + /// Return the algorithm descriptor pointer for this HMAC's hash. + #[inline] + fn evp_md() -> *const wolfcrypt_rs::EVP_MD { + // SAFETY: EVP_sha* functions return a static const pointer. + unsafe { $evp_fn() } + } + } + + // ------------------------------------------------------------------ + // core / RustCrypto trait impls + // ------------------------------------------------------------------ + #[$cfg_gate] impl Drop for $name { fn drop(&mut self) { - if !self.ctx.is_null() { - // SAFETY: ctx was allocated by wolfcrypt_hmac_*_new. - unsafe { wolfcrypt_rs::wolfcrypt_hmac_free(self.ctx) }; + // SAFETY: self.ctx was allocated via HMAC_CTX_new and + // is only freed once here. + unsafe { + wolfcrypt_rs::HMAC_CTX_free(self.ctx); } } } @@ -56,22 +74,39 @@ macro_rules! impl_hmac { #[$cfg_gate] impl $name { + /// Shared initialisation: allocate an HMAC_CTX and key it. fn init_with_key(key: &[u8]) -> Self { - // SAFETY: key pointer and length are correct from the slice reference. - let ctx = unsafe { - $new_fn(key.as_ptr(), key.len() as u32) - }; - assert!(!ctx.is_null(), concat!(stringify!($name), ": wolfcrypt_hmac_*_new returned NULL")); + // SAFETY: HMAC_CTX_new returns a heap-allocated context + // or NULL on OOM. + let ctx = unsafe { wolfcrypt_rs::HMAC_CTX_new() }; + assert!(!ctx.is_null(), "HMAC_CTX_new returned NULL"); + + // SAFETY: ctx is non-null and freshly allocated. key pointer + // and length are guaranteed correct by the slice reference. + // HMAC_Init_ex with a non-null key sets the key and algorithm. + unsafe { + let rc = wolfcrypt_rs::HMAC_Init_ex( + ctx, + key.as_ptr() as *const c_void, + len_as_c_int(key.len()), + Self::evp_md(), + core::ptr::null_mut(), + ); + assert_eq!(rc, 1, "HMAC_Init_ex failed (OOM or invalid algorithm)"); + } Self { ctx } } } #[$cfg_gate] impl KeyInit for $name { + /// Create from a fixed-size key (KeySize bytes). fn new(key: &GenericArray::KeySize>) -> Self { Self::init_with_key(key.as_slice()) } + /// Create from a variable-length key. HMAC accepts any key size + /// per RFC 2104, so this never returns `InvalidLength`. fn new_from_slice(key: &[u8]) -> Result { Ok(Self::init_with_key(key)) } @@ -80,30 +115,34 @@ macro_rules! impl_hmac { #[$cfg_gate] impl Update for $name { fn update(&mut self, data: &[u8]) { - // SAFETY: ctx is valid; data pointer and length are correct. - let rc = unsafe { - wolfcrypt_rs::wolfcrypt_hmac_update( + // SAFETY: self.ctx is valid. data pointer and length are + // guaranteed correct by the slice reference. + unsafe { + let rc = wolfcrypt_rs::HMAC_Update( self.ctx, data.as_ptr(), - data.len() as u32, - ) - }; - assert_eq!(rc, 0, concat!(stringify!($name), ": wolfcrypt_hmac_update failed")); + data.len(), + ); + assert_eq!(rc, 1, "HMAC_Update failed (context not initialized)"); + } } } #[$cfg_gate] impl FixedOutput for $name { - fn finalize_into(mut self, out: &mut GenericArray) { - // SAFETY: out is exactly OutputSize bytes; ctx is valid. - let rc = unsafe { - wolfcrypt_rs::wolfcrypt_hmac_final(self.ctx, out.as_mut_ptr()) - }; - assert_eq!(rc, 0, concat!(stringify!($name), ": wolfcrypt_hmac_final failed")); - // Prevent Drop from double-freeing. - let ctx = self.ctx; - self.ctx = core::ptr::null_mut(); - unsafe { wolfcrypt_rs::wolfcrypt_hmac_free(ctx) }; + fn finalize_into(self, out: &mut GenericArray) { + let mut len: u32 = 0; + // SAFETY: out is exactly OutputSize bytes. self.ctx is + // valid. After this call, Drop will free the context. + unsafe { + let rc = wolfcrypt_rs::HMAC_Final( + self.ctx, + out.as_mut_ptr(), + &mut len, + ); + assert_eq!(rc, 1, "HMAC_Final failed (context not initialized)"); + } + // Drop runs after this and frees self.ctx. } } @@ -112,34 +151,38 @@ macro_rules! impl_hmac { }; } +// ====================================================================== +// Stamp out HMAC types +// ====================================================================== + impl_hmac!( WolfHmacSha1, - wolfcrypt_rs::wolfcrypt_hmac_sha1_new, + wolfcrypt_rs::EVP_sha1, U20, U20, - cfg(wolfssl_hmac) + cfg(all(wolfssl_openssl_extra, wolfssl_hmac)) ); impl_hmac!( WolfHmacSha256, - wolfcrypt_rs::wolfcrypt_hmac_sha256_new, + wolfcrypt_rs::EVP_sha256, U32, U32, - cfg(wolfssl_hmac) + cfg(all(wolfssl_openssl_extra, wolfssl_hmac)) ); impl_hmac!( WolfHmacSha384, - wolfcrypt_rs::wolfcrypt_hmac_sha384_new, + wolfcrypt_rs::EVP_sha384, U48, U48, - cfg(all(wolfssl_hmac, wolfssl_sha384)) + cfg(all(wolfssl_openssl_extra, wolfssl_hmac, wolfssl_sha384)) ); impl_hmac!( WolfHmacSha512, - wolfcrypt_rs::wolfcrypt_hmac_sha512_new, + wolfcrypt_rs::EVP_sha512, U64, U64, - cfg(all(wolfssl_hmac, wolfssl_sha512)) + cfg(all(wolfssl_openssl_extra, wolfssl_hmac, wolfssl_sha512)) ); diff --git a/wolfcrypt/src/keywrap.rs b/wolfcrypt/src/keywrap.rs index ef5216b..a956080 100644 --- a/wolfcrypt/src/keywrap.rs +++ b/wolfcrypt/src/keywrap.rs @@ -1,8 +1,8 @@ //! AES Key Wrap (RFC 3394) backed by wolfCrypt. //! //! Provides [`aes_wrap_key`] and [`aes_unwrap_key`] which implement the -//! AES Key Wrap algorithm per RFC 3394 using wolfCrypt's native -//! `wc_AesKeyWrap` / `wc_AesKeyUnWrap` functions. +//! AES Key Wrap algorithm per RFC 3394 using wolfSSL's OpenSSL-compatible +//! `AES_wrap_key` / `AES_unwrap_key` functions. //! //! The Key Encryption Key (KEK) must be 16, 24, or 32 bytes (AES-128/192/256). //! The plaintext (key data) must be a multiple of 8 bytes and at least 16 bytes. @@ -20,13 +20,35 @@ //! assert_eq!(&key_data[..], &unwrapped[..]); //! ``` +use core::ffi::c_uint; use core::ptr; use alloc::vec; use alloc::vec::Vec; -use crate::error::WolfCryptError; -use wolfcrypt_rs::{wc_AesKeyWrap, wc_AesKeyUnWrap}; +use crate::error::{check, WolfCryptError}; +use wolfcrypt_rs::{AES_KEY, AES_set_encrypt_key, AES_set_decrypt_key, AES_wrap_key, AES_unwrap_key}; + +/// RAII guard that zeroizes the key schedule in an `AES_KEY` on drop. +/// +/// Ensures the key material is cleared on every exit path (success, error, +/// or panic) without requiring manual cleanup at each `return`. +struct AesKeyGuard(AES_KEY); + +impl Drop for AesKeyGuard { + fn drop(&mut self) { + use zeroize::Zeroize; + // SAFETY: We have exclusive access (&mut self). AES_KEY is a plain + // C struct with no Rust drop glue. Zeroing its raw bytes is safe. + let bytes = unsafe { + core::slice::from_raw_parts_mut( + &mut self.0 as *mut AES_KEY as *mut u8, + core::mem::size_of::(), + ) + }; + bytes.zeroize(); + } +} /// Wrap `plaintext` key data under `kek` per RFC 3394. /// @@ -42,27 +64,29 @@ pub fn aes_wrap_key(kek: &[u8], plaintext: &[u8]) -> Result, WolfCryptEr _ => return Err(WolfCryptError::INVALID_INPUT), } - let mut out = vec![0u8; plaintext.len() + 8]; - let rc = unsafe { - wc_AesKeyWrap( - kek.as_ptr(), - kek.len() as u32, - plaintext.as_ptr(), - plaintext.len() as u32, - out.as_mut_ptr(), - out.len() as u32, + unsafe { + let mut guard = AesKeyGuard(AES_KEY::zeroed()); + let rc = AES_set_encrypt_key(kek.as_ptr(), (kek.len() * 8) as c_uint, &mut guard.0); + check(rc, "AES_set_encrypt_key")?; + + let mut out = vec![0u8; plaintext.len() + 8]; + let rc = AES_wrap_key( + &guard.0, ptr::null(), // default IV (A6A6A6A6 A6A6A6A6) - ) - }; - if rc <= 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_AesKeyWrap" }); - } - let out_len = rc as usize; - if out_len > out.len() { - return Err(WolfCryptError::Ffi { code: -1, func: "wc_AesKeyWrap (output length)" }); + out.as_mut_ptr(), + plaintext.as_ptr(), + plaintext.len(), + ); + if rc <= 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "AES_wrap_key" }); + } + let out_len = rc as usize; + if out_len > out.len() { + return Err(WolfCryptError::Ffi { code: -1, func: "AES_wrap_key (output length)" }); + } + out.truncate(out_len); + Ok(out) } - out.truncate(out_len); - Ok(out) } /// Unwrap `ciphertext` under `kek` per RFC 3394. @@ -79,25 +103,27 @@ pub fn aes_unwrap_key(kek: &[u8], ciphertext: &[u8]) -> Result, WolfCryp _ => return Err(WolfCryptError::INVALID_INPUT), } - let mut out = vec![0u8; ciphertext.len()]; - let rc = unsafe { - wc_AesKeyUnWrap( - kek.as_ptr(), - kek.len() as u32, - ciphertext.as_ptr(), - ciphertext.len() as u32, - out.as_mut_ptr(), - out.len() as u32, + unsafe { + let mut guard = AesKeyGuard(AES_KEY::zeroed()); + let rc = AES_set_decrypt_key(kek.as_ptr(), (kek.len() * 8) as c_uint, &mut guard.0); + check(rc, "AES_set_decrypt_key")?; + + let mut out = vec![0u8; ciphertext.len()]; + let rc = AES_unwrap_key( + &guard.0, ptr::null(), // default IV (A6A6A6A6 A6A6A6A6) - ) - }; - if rc <= 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wc_AesKeyUnWrap" }); - } - let out_len = rc as usize; - if out_len > out.len() { - return Err(WolfCryptError::Ffi { code: -1, func: "wc_AesKeyUnWrap (output length)" }); + out.as_mut_ptr(), + ciphertext.as_ptr(), + ciphertext.len(), + ); + if rc <= 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "AES_unwrap_key" }); + } + let out_len = rc as usize; + if out_len > out.len() { + return Err(WolfCryptError::Ffi { code: -1, func: "AES_unwrap_key (output length)" }); + } + out.truncate(out_len); + Ok(out) } - out.truncate(out_len); - Ok(out) } diff --git a/wolfcrypt/src/lib.rs b/wolfcrypt/src/lib.rs index 92c7215..869b91e 100644 --- a/wolfcrypt/src/lib.rs +++ b/wolfcrypt/src/lib.rs @@ -90,9 +90,10 @@ //! doesn't require `ZeroizeOnDrop` or any cleanup guarantee. Each //! implementor must remember to add it manually โ€” an easy thing to miss. //! -//! **Workaround:** We manually implement `Drop` with `wc_AesFree` or -//! `zeroize` calls on every type that holds key material (AES key schedules, -//! ChaCha20Poly1305 keys, HKDF PRKs, keywrap temporaries). +//! **Workaround:** We manually implement `Drop` with `zeroize` calls on +//! every type that holds key material (AES key schedules, ChaCha20Poly1305 +//! keys, HKDF PRKs, keywrap temporaries). The `zeroize_aes_key` helper +//! centralizes the pattern for opaque C structs. //! //! ## 3. `AeadInPlace` is the only AEAD trait //! @@ -162,7 +163,7 @@ //! `&mut self` to the FFI. //! //! **Workaround:** Signing and verifying key types wrap their C key handle -//! in `UnsafeCell` (see `ed25519.rs`, `ed448.rs`, `ecdsa_native.rs`, `rsa.rs`, +//! in `UnsafeCell` (see `ed25519.rs`, `ed448.rs`, `ecdsa.rs`, `rsa.rs`, //! `mldsa.rs`, `lms.rs`, `aead.rs`, `cipher/ccm.rs`). This lets us //! obtain `*mut` from `&self` for FFI calls. `UnsafeCell` also makes the //! type `!Sync`, which is correct โ€” wolfCrypt key handles are not @@ -199,31 +200,31 @@ pub use error::WolfCryptError; pub mod digest; // Re-export digest types at crate root for ergonomic use. -#[cfg(all(feature = "digest", wolfssl_sha1))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra))] pub use digest::Sha1; -#[cfg(all(feature = "digest", wolfssl_sha224))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha224))] pub use digest::Sha224; -#[cfg(all(feature = "digest", wolfssl_sha256))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra))] pub use digest::Sha256; -#[cfg(all(feature = "digest", wolfssl_sha384))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha384))] pub use digest::Sha384; -#[cfg(all(feature = "digest", wolfssl_sha512))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha512))] pub use digest::Sha512; -#[cfg(all(feature = "digest", wolfssl_sha512))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha512))] pub use digest::Sha512_256; -#[cfg(all(feature = "digest", wolfssl_sha3))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha3))] pub use digest::Sha3_256; -#[cfg(all(feature = "digest", wolfssl_sha3))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha3))] pub use digest::Sha3_384; -#[cfg(all(feature = "digest", wolfssl_sha3))] +#[cfg(all(feature = "digest", wolfssl_openssl_extra, wolfssl_sha3))] pub use digest::Sha3_512; #[cfg(feature = "rand")] @@ -234,21 +235,21 @@ pub use rand::WolfRng; #[cfg(feature = "hmac")] pub mod hmac; -#[cfg(all(feature = "hmac", wolfssl_hmac))] +#[cfg(all(feature = "hmac", wolfssl_openssl_extra, wolfssl_hmac))] pub use hmac::WolfHmacSha1; -#[cfg(all(feature = "hmac", wolfssl_hmac))] +#[cfg(all(feature = "hmac", wolfssl_openssl_extra, wolfssl_hmac))] pub use hmac::WolfHmacSha256; -#[cfg(all(feature = "hmac", wolfssl_hmac, wolfssl_sha384))] +#[cfg(all(feature = "hmac", wolfssl_openssl_extra, wolfssl_hmac, wolfssl_sha384))] pub use hmac::WolfHmacSha384; -#[cfg(all(feature = "hmac", wolfssl_hmac, wolfssl_sha512))] +#[cfg(all(feature = "hmac", wolfssl_openssl_extra, wolfssl_hmac, wolfssl_sha512))] pub use hmac::WolfHmacSha512; #[cfg(feature = "cmac")] pub mod cmac; -#[cfg(all(feature = "cmac", wolfssl_cmac))] +#[cfg(all(feature = "cmac", wolfssl_openssl_extra, wolfssl_cmac))] pub use cmac::WolfCmacAes128; -#[cfg(all(feature = "cmac", wolfssl_cmac))] +#[cfg(all(feature = "cmac", wolfssl_openssl_extra, wolfssl_cmac))] pub use cmac::WolfCmacAes256; #[cfg(feature = "hkdf")] @@ -286,10 +287,10 @@ pub use aead::ChaCha20Poly1305; #[cfg(feature = "cipher")] pub mod cipher; -#[cfg(all(feature = "cipher", wolfssl_aes_ecb))] +#[cfg(all(feature = "cipher", wolfssl_openssl_extra, wolfssl_aes_ecb))] pub use cipher::{Aes128EcbDec, Aes128EcbEnc, Aes256EcbDec, Aes256EcbEnc}; -#[cfg(all(feature = "cipher", wolfssl_aes_ecb, wolfssl_aes_192))] +#[cfg(all(feature = "cipher", wolfssl_openssl_extra, wolfssl_aes_ecb, wolfssl_aes_192))] pub use cipher::{Aes192EcbDec, Aes192EcbEnc}; #[cfg(all(feature = "cipher", wolfssl_aes_ctr))] @@ -298,36 +299,36 @@ pub use cipher::{Aes128Ctr, Aes256Ctr}; #[cfg(all(feature = "cipher", wolfssl_aes_ctr, wolfssl_aes_192))] pub use cipher::Aes192Ctr; -#[cfg(feature = "cipher")] +#[cfg(all(feature = "cipher", wolfssl_openssl_extra))] pub use cipher::{Aes128CbcEnc, Aes128CbcDec, Aes256CbcEnc, Aes256CbcDec}; -#[cfg(all(feature = "cipher", wolfssl_aes_192))] +#[cfg(all(feature = "cipher", wolfssl_openssl_extra, wolfssl_aes_192))] pub use cipher::{Aes192CbcEnc, Aes192CbcDec}; #[cfg(all(feature = "cipher", wolfssl_chacha))] pub use cipher::WolfChaCha20; -#[cfg(all(feature = "cipher", wolfssl_aes_cfb))] +#[cfg(all(feature = "cipher", wolfssl_openssl_extra, wolfssl_aes_cfb))] pub use cipher::{ Aes128CfbEnc, Aes128CfbDec, Aes256CfbEnc, Aes256CfbDec, }; -#[cfg(all(feature = "cipher", wolfssl_aes_cfb, wolfssl_aes_192))] +#[cfg(all(feature = "cipher", wolfssl_openssl_extra, wolfssl_aes_cfb, wolfssl_aes_192))] pub use cipher::{ Aes192CfbEnc, Aes192CfbDec, }; -#[cfg(all(feature = "des3", wolfssl_des3))] +#[cfg(all(feature = "des3", wolfssl_openssl_extra, wolfssl_des3))] pub mod des3; -#[cfg(all(feature = "des3", wolfssl_des3))] +#[cfg(all(feature = "des3", wolfssl_openssl_extra, wolfssl_des3))] pub use des3::{DesEde3CbcEnc, DesEde3CbcDec}; -#[cfg(all(feature = "dh", wolfssl_dh))] +#[cfg(all(feature = "dh", wolfssl_openssl_extra, wolfssl_dh))] pub mod dh; -#[cfg(all(feature = "dh", wolfssl_dh))] +#[cfg(all(feature = "dh", wolfssl_openssl_extra, wolfssl_dh))] pub use dh::{DhSecret, FfdheGroup}; #[cfg(feature = "poly1305")] @@ -357,34 +358,32 @@ pub use ecdh::{SharedSecret, X25519PublicKey, X25519StaticSecret}; #[cfg(all(feature = "ecdh", wolfssl_curve448))] pub use ecdh::{X448PublicKey, X448SharedSecret, X448StaticSecret}; -#[cfg(all(feature = "ecdh", wolfssl_ecc))] +#[cfg(all(feature = "ecdh", wolfssl_openssl_extra, wolfssl_ecc))] pub use ecdh::{ NistCurve, NistEcdhPublicKey, NistEcdhSecret, NistEcdhSharedSecret, NistP256, P256EcdhSecret, }; -#[cfg(all(feature = "ecdh", wolfssl_ecc, wolfssl_ecc_p384))] +#[cfg(all(feature = "ecdh", wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p384))] pub use ecdh::{NistP384, P384EcdhSecret}; -#[cfg(all(feature = "ecdh", wolfssl_ecc, wolfssl_ecc_p521))] +#[cfg(all(feature = "ecdh", wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p521))] pub use ecdh::{NistP521, P521EcdhSecret}; -// Native wc_ecc_*-based ECDSA. -#[cfg(all(feature = "ecdsa", wolfssl_ecc))] -#[path = "ecdsa_native.rs"] +#[cfg(all(feature = "ecdsa", wolfssl_openssl_extra, wolfssl_ecc))] pub mod ecdsa; -#[cfg(all(feature = "ecdsa", wolfssl_ecc))] +#[cfg(all(feature = "ecdsa", wolfssl_openssl_extra, wolfssl_ecc))] pub use ecdsa::{ EcdsaCurve, EcdsaSignature, EcdsaSigningKey, EcdsaVerifyingKey, P256, P256SigningKey, P256VerifyingKey, P256Signature, }; -#[cfg(all(feature = "ecdsa", wolfssl_ecc, wolfssl_ecc_p384))] +#[cfg(all(feature = "ecdsa", wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p384))] pub use ecdsa::{ P384, P384SigningKey, P384VerifyingKey, P384Signature, }; -#[cfg(all(feature = "ecdsa", wolfssl_ecc, wolfssl_ecc_p521, wolfssl_sha512))] +#[cfg(all(feature = "ecdsa", wolfssl_openssl_extra, wolfssl_ecc, wolfssl_ecc_p521))] pub use ecdsa::{ P521, P521SigningKey, P521VerifyingKey, P521Signature, }; @@ -392,7 +391,7 @@ pub use ecdsa::{ #[cfg(feature = "rsa")] pub mod rsa; -#[cfg(all(feature = "rsa", wolfssl_rsa))] +#[cfg(all(feature = "rsa", wolfssl_openssl_extra, wolfssl_rsa))] pub use rsa::{ RsaDigest, RsaPkcs1v15Signature, RsaPssSignature, RsaPrivateKey, RsaPublicKey, }; @@ -400,10 +399,10 @@ pub use rsa::{ #[cfg(all(feature = "rsa-direct", wolfssl_rsa))] pub use rsa::{NativeRsaKey, RsaDirectType, RsaRawComponents}; -#[cfg(all(feature = "keywrap", wolfssl_aes_keywrap))] +#[cfg(feature = "keywrap")] pub mod keywrap; -#[cfg(all(feature = "keywrap", wolfssl_aes_keywrap))] +#[cfg(all(feature = "keywrap", wolfssl_openssl_extra, wolfssl_aes_keywrap))] pub use keywrap::{aes_wrap_key, aes_unwrap_key}; #[cfg(all(feature = "mldsa", wolfssl_dilithium))] diff --git a/wolfcrypt/src/rand.rs b/wolfcrypt/src/rand.rs index 1033f81..5711ddf 100644 --- a/wolfcrypt/src/rand.rs +++ b/wolfcrypt/src/rand.rs @@ -1,7 +1,5 @@ use crate::error::{check, len_as_u32, WolfCryptError}; -#[cfg(not(feature = "require-dev-id"))] -use wolfcrypt_rs::wc_InitRng; -use wolfcrypt_rs::{wc_FreeRng, wc_InitRng_ex, wc_RNG_GenerateBlock, WC_RNG}; +use wolfcrypt_rs::{wc_FreeRng, wc_InitRng, wc_RNG_GenerateBlock, WC_RNG}; /// A wolfCrypt-backed random number generator that implements /// [`rand_core::TryRng`] and [`rand_core::TryCryptoRng`] with @@ -13,12 +11,6 @@ pub struct WolfRng { impl WolfRng { /// Create a new `WolfRng`, initialising the underlying wolfCrypt DRBG. - /// - /// Uses `INVALID_DEVID` so wolfSSL's software DRBG provides randomness. - /// When the `require-dev-id` feature is active this function is removed: - /// callers must use [`WolfRng::new_with_dev_id`] and supply a hardware - /// CryptoCb device ID so the ITRNG is always used. - #[cfg(not(feature = "require-dev-id"))] pub fn new() -> Result { let mut rng = WC_RNG::zeroed(); // SAFETY: `rng` is zero-initialised and `wc_InitRng` will fully @@ -28,31 +20,12 @@ impl WolfRng { Ok(Self { rng }) } - /// Create a new `WolfRng` bound to a specific CryptoCb device. - /// - /// Uses `wc_InitRng_ex` so that every `wc_RNG_GenerateBlock` call is - /// routed through the CryptoCb registered for `dev_id`. Required to - /// ensure hardware entropy (e.g. Caliptra ITRNG via `wolfcrypt_dpe_hw`) - /// is used rather than the software DRBG. - /// - /// Pass `wolfcrypt_rs::INVALID_DEVID` to get the same behaviour as - /// [`WolfRng::new`]. - pub fn new_with_dev_id(dev_id: core::ffi::c_int) -> Result { - let mut rng = WC_RNG::zeroed(); - // SAFETY: `rng` is zero-initialised and `wc_InitRng_ex` will fully - // initialise it. `null_mut()` is the documented value for the heap - // parameter when the default allocator is used. - let rc = unsafe { wc_InitRng_ex(&mut rng, core::ptr::null_mut(), dev_id) }; - check(rc, "wc_InitRng_ex")?; - Ok(Self { rng }) - } - } impl Drop for WolfRng { fn drop(&mut self) { - // SAFETY: `self.rng` was successfully initialised by `wc_InitRng` / - // `wc_InitRng_ex` in `new()` / `new_with_dev_id()`. Freed exactly once. + // SAFETY: `self.rng` was successfully initialised by `wc_InitRng` + // in `new()`. We free it exactly once here. unsafe { wc_FreeRng(&mut self.rng); } diff --git a/wolfcrypt/src/rsa.rs b/wolfcrypt/src/rsa.rs index ec273be..7ee6c48 100644 --- a/wolfcrypt/src/rsa.rs +++ b/wolfcrypt/src/rsa.rs @@ -10,9 +10,9 @@ //! padding) because RSA uses the same keypair for both operations: //! the private key signs and decrypts, the public key verifies and encrypts. //! -//! Key generation, signing, and verification use native wolfCrypt `wc_*` shims -//! via the `wolfcrypt_rsa_*` C helpers in `wolfcrypt-rs/src/compat_shim.c`. -//! No OpenSSL-compat EVP layer is required. +//! Key generation uses the EVP_PKEY API with wolfSSL's OpenSSL compatibility +//! layer. Signing and verification use the `EVP_DigestSign*` / +//! `EVP_DigestVerify*` family per RFC 8017 (PKCS#1 v2.2). //! //! # Example //! @@ -34,19 +34,23 @@ use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; -use crate::error::WolfCryptError; -#[cfg(feature = "rsa-direct")] -use crate::error::{len_as_u32, check}; +use crate::error::{check, len_as_u32, WolfCryptError}; use wolfcrypt_rs::{ - wolfcrypt_rsa_new, wolfcrypt_rsa_free, - wolfcrypt_rsa_generate, - wolfcrypt_rsa_import_private_pkcs1, wolfcrypt_rsa_import_public_spki, - wolfcrypt_rsa_export_private_pkcs1, wolfcrypt_rsa_export_public_spki, - wolfcrypt_rsa_key_size_bytes, - wolfcrypt_rsa_oaep_encrypt_sha256, wolfcrypt_rsa_oaep_decrypt_sha256, - wolfcrypt_rsa_pkcs1v15_sign, wolfcrypt_rsa_pkcs1v15_verify, - wolfcrypt_rsa_pss_sign, wolfcrypt_rsa_pss_verify, - wolfcrypt_rsa_pkcs1v15_encrypt, wolfcrypt_rsa_pkcs1v15_decrypt, + EVP_DigestSignFinal, EVP_DigestSignInit, EVP_DigestSignUpdate, + EVP_DigestVerifyFinal, EVP_DigestVerifyInit, EVP_DigestVerifyUpdate, + EVP_MD, EVP_MD_CTX, EVP_MD_CTX_free, EVP_MD_CTX_new, + EVP_PKEY, EVP_PKEY_CTX, EVP_PKEY_CTX_free, EVP_PKEY_CTX_new, + EVP_PKEY_CTX_new_id, + EVP_PKEY_CTX_set_rsa_keygen_bits, EVP_PKEY_CTX_set_rsa_mgf1_md, + EVP_PKEY_CTX_set_rsa_oaep_md, + EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_CTX_set_rsa_pss_saltlen, + EVP_PKEY_encrypt, EVP_PKEY_encrypt_init, + EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, + EVP_PKEY_free, EVP_PKEY_keygen, EVP_PKEY_keygen_init, + EVP_PKEY_RSA, EVP_sha1, EVP_sha256, EVP_sha384, EVP_sha512, + i2d_PUBKEY, i2d_PrivateKey, d2i_PUBKEY, d2i_PrivateKey, + RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING, + RSA_PKCS1_PSS_PADDING, RSA_PSS_SALTLEN_DIGEST, }; // --------------------------------------------------------------------------- @@ -125,11 +129,73 @@ impl From for Box<[u8]> { } } +// --------------------------------------------------------------------------- +// RAII wrapper for EVP_MD_CTX +// --------------------------------------------------------------------------- + +/// Owned EVP_MD_CTX that frees on drop. +struct MdCtx(*mut EVP_MD_CTX); + +impl MdCtx { + fn new() -> Result { + let p = unsafe { EVP_MD_CTX_new() }; + if p.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + Ok(Self(p)) + } + + fn as_mut_ptr(&self) -> *mut EVP_MD_CTX { + self.0 + } +} + +impl Drop for MdCtx { + fn drop(&mut self) { + if !self.0.is_null() { + unsafe { EVP_MD_CTX_free(self.0) }; + } + } +} + +// --------------------------------------------------------------------------- +// RAII wrapper for EVP_PKEY_CTX +// --------------------------------------------------------------------------- + +/// Owned EVP_PKEY_CTX that frees on drop. +struct PkeyCtx(*mut EVP_PKEY_CTX); + +impl PkeyCtx { + /// Create a new EVP_PKEY_CTX from an existing EVP_PKEY. + fn new(pkey: *mut EVP_PKEY) -> Result { + let p = unsafe { EVP_PKEY_CTX_new(pkey, ptr::null_mut()) }; + if p.is_null() { + return Err(WolfCryptError::ALLOC_FAILED); + } + Ok(Self(p)) + } + + fn as_mut_ptr(&self) -> *mut EVP_PKEY_CTX { + self.0 + } +} + +impl Drop for PkeyCtx { + fn drop(&mut self) { + if !self.0.is_null() { + unsafe { EVP_PKEY_CTX_free(self.0) }; + } + } +} + // --------------------------------------------------------------------------- // Internal helpers // --------------------------------------------------------------------------- /// Hash algorithm used for RSA signing/verification. +/// +/// Selects which `EVP_MD` is passed to `EVP_DigestSign*`/`EVP_DigestVerify*` +/// and to the PSS MGF1 configuration. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RsaDigest { /// SHA-1 (20-byte digest). Required for legacy SSH `ssh-rsa` signatures. @@ -143,250 +209,310 @@ pub enum RsaDigest { } impl RsaDigest { - /// Return the hash bit-width code used by the native wolfCrypt shims. - /// - /// SHA-1 โ†’ 160, SHA-256 โ†’ 256, SHA-384 โ†’ 384, SHA-512 โ†’ 512. - /// The C helper `wolfcrypt_rsa_hash_wc_type(hash_bits)` maps these to - /// the appropriate `wc_HashType` enum value. - fn hash_bits(self) -> i32 { - match self { - Self::Sha1 => 160, - Self::Sha256 => 256, - Self::Sha384 => 384, - Self::Sha512 => 512, + /// Return the wolfSSL `EVP_MD` pointer for this digest. + fn evp_md(self) -> *const EVP_MD { + unsafe { + match self { + Self::Sha1 => EVP_sha1(), + Self::Sha256 => EVP_sha256(), + Self::Sha384 => EVP_sha384(), + Self::Sha512 => EVP_sha512(), + } } } } -// --------------------------------------------------------------------------- -// Native OAEP helpers (wc_RsaPublicEncrypt_ex / wc_RsaPrivateDecrypt_ex) -// --------------------------------------------------------------------------- +/// RSA padding mode used by the internal `evp_*` helpers. +/// +/// Converts to the wolfSSL `i32` constant at the FFI boundary via +/// [`as_c_int`](Self::as_c_int). +#[derive(Clone, Copy)] +enum RsaPadding { + /// PKCS#1 v1.5 (RFC 8017 ยง7.2 / ยง8.2). + Pkcs1v15, + /// PSS with SHA-256, salt length = digest length (RFC 8017 ยง8.1). + Pss, + /// OAEP with SHA-256 (RFC 8017 ยง7.1). + Oaep, +} -/// Encrypt `plaintext` using OAEP SHA-256 / MGF1-SHA256. +impl RsaPadding { + fn as_c_int(self) -> i32 { + match self { + Self::Pkcs1v15 => RSA_PKCS1_PADDING, + Self::Pss => RSA_PKCS1_PSS_PADDING, + Self::Oaep => RSA_PKCS1_OAEP_PADDING, + } + } +} + +/// RSA public-key encryption via `EVP_PKEY_encrypt` with the given padding. /// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *` holding a public -/// key (or a private key, which contains both components). -unsafe fn native_oaep_encrypt_sha256( - ctx: *mut c_void, +/// For [`RsaPadding::Oaep`], also sets the OAEP hash to SHA-256. +/// The two-call pattern queries the output length first, then performs the +/// actual encryption. +unsafe fn evp_encrypt( + pkey: *mut EVP_PKEY, plaintext: &[u8], + padding: RsaPadding, ) -> Result, WolfCryptError> { + // SAFETY: caller guarantees `pkey` is a valid, non-null EVP_PKEY. + // All FFI calls below operate on `pkey` or the derived `ctx`. unsafe { - let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - if key_size <= 0 { - return Err(WolfCryptError::Ffi { code: key_size, func: "wolfcrypt_rsa_key_size_bytes" }); + let ctx = PkeyCtx::new(pkey)?; + + let rc = EVP_PKEY_encrypt_init(ctx.as_mut_ptr()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_encrypt_init" }); } - let mut out = vec![0u8; key_size as usize]; - let rc = wolfcrypt_rsa_oaep_encrypt_sha256( - ctx, - plaintext.as_ptr(), plaintext.len() as u32, - out.as_mut_ptr(), key_size as u32, + + let rc = EVP_PKEY_CTX_set_rsa_padding(ctx.as_mut_ptr(), padding.as_c_int()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_padding" }); + } + + if matches!(padding, RsaPadding::Oaep) { + let rc = EVP_PKEY_CTX_set_rsa_oaep_md(ctx.as_mut_ptr(), EVP_sha256()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_oaep_md" }); + } + } + + // First call: determine output size. + let mut out_len: usize = 0; + let rc = EVP_PKEY_encrypt( + ctx.as_mut_ptr(), + ptr::null_mut(), + &mut out_len, + plaintext.as_ptr(), + plaintext.len(), ); - if rc <= 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_oaep_encrypt_sha256" }); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_encrypt" }); } - out.truncate(rc as usize); + if out_len == 0 { + return Err(WolfCryptError::Ffi { code: 0, func: "EVP_PKEY_encrypt (zero output length)" }); + } + + // Second call: perform encryption. + let mut out = vec![0u8; out_len]; + let rc = EVP_PKEY_encrypt( + ctx.as_mut_ptr(), + out.as_mut_ptr(), + &mut out_len, + plaintext.as_ptr(), + plaintext.len(), + ); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_encrypt" }); + } + out.truncate(out_len); Ok(out) } } -/// Decrypt `ciphertext` using OAEP SHA-256 / MGF1-SHA256. +/// RSA private-key decryption via `EVP_PKEY_decrypt` with the given padding. /// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *` holding a private key. -unsafe fn native_oaep_decrypt_sha256( - ctx: *mut c_void, +/// For [`RsaPadding::Oaep`], also sets the OAEP hash to SHA-256. +unsafe fn evp_decrypt( + pkey: *mut EVP_PKEY, ciphertext: &[u8], + padding: RsaPadding, ) -> Result, WolfCryptError> { + // SAFETY: caller guarantees `pkey` is a valid, non-null EVP_PKEY. unsafe { - let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - if key_size <= 0 { - return Err(WolfCryptError::Ffi { code: key_size, func: "wolfcrypt_rsa_key_size_bytes" }); + let ctx = PkeyCtx::new(pkey)?; + + let rc = EVP_PKEY_decrypt_init(ctx.as_mut_ptr()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_decrypt_init" }); } - let mut out = vec![0u8; key_size as usize]; - let rc = wolfcrypt_rsa_oaep_decrypt_sha256( - ctx, - ciphertext.as_ptr(), ciphertext.len() as u32, - out.as_mut_ptr(), key_size as u32, - ); - if rc <= 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_oaep_decrypt_sha256" }); + + let rc = EVP_PKEY_CTX_set_rsa_padding(ctx.as_mut_ptr(), padding.as_c_int()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_padding" }); } - out.truncate(rc as usize); - Ok(out) - } -} -// --------------------------------------------------------------------------- -// Native PKCS#1v1.5 helpers (wc_RsaSSL_Sign / wc_RsaSSL_VerifyInline) -// --------------------------------------------------------------------------- + if matches!(padding, RsaPadding::Oaep) { + let rc = EVP_PKEY_CTX_set_rsa_oaep_md(ctx.as_mut_ptr(), EVP_sha256()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_oaep_md" }); + } + } -/// Sign `msg` using RSA-PKCS#1v1.5 with the given hash via the native shim. -/// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *` holding a private key. -/// `hash_bits` must be 160, 256, 384, or 512. -/// Returns the raw signature bytes (length == key modulus size). -unsafe fn native_pkcs1v15_sign( - ctx: *mut c_void, - msg: &[u8], - hash_bits: i32, -) -> Result, WolfCryptError> { - unsafe { - let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - if key_size <= 0 { - return Err(WolfCryptError::Ffi { code: key_size, func: "wolfcrypt_rsa_key_size_bytes" }); + // First call: determine output size. + let mut out_len: usize = 0; + let rc = EVP_PKEY_decrypt( + ctx.as_mut_ptr(), + ptr::null_mut(), + &mut out_len, + ciphertext.as_ptr(), + ciphertext.len(), + ); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_decrypt" }); + } + if out_len == 0 { + return Err(WolfCryptError::Ffi { code: 0, func: "EVP_PKEY_decrypt (zero output length)" }); } - let mut sig = vec![0u8; key_size as usize]; - let mut sig_len = key_size as u32; - let rc = wolfcrypt_rsa_pkcs1v15_sign( - ctx, hash_bits, - msg.as_ptr(), msg.len() as u32, - sig.as_mut_ptr(), &mut sig_len, + + // Second call: perform decryption. + let mut out = vec![0u8; out_len]; + let rc = EVP_PKEY_decrypt( + ctx.as_mut_ptr(), + out.as_mut_ptr(), + &mut out_len, + ciphertext.as_ptr(), + ciphertext.len(), ); - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_pkcs1v15_sign" }); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_decrypt" }); } - sig.truncate(sig_len as usize); - Ok(sig) + out.truncate(out_len); + Ok(out) } } -/// Verify an RSA-PKCS#1v1.5 signature using the native shim. +/// Perform an RSA signature using EVP_DigestSign with the given padding mode. /// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *`. -/// `hash_bits` must be 160, 256, 384, or 512. -/// Returns `Ok(())` if valid, `Err` if invalid or on error. -unsafe fn native_pkcs1v15_verify( - ctx: *mut c_void, +/// `pkey` must be a valid EVP_PKEY containing an RSA private key. +/// For [`RsaPadding::Pss`], also sets salt length to digest length and +/// MGF1 hash to the same digest. +unsafe fn evp_sign( + pkey: *mut EVP_PKEY, msg: &[u8], - sig: &[u8], - hash_bits: i32, -) -> Result<(), WolfCryptError> { + padding: RsaPadding, + digest: RsaDigest, +) -> Result, WolfCryptError> { + // SAFETY: caller guarantees `pkey` is a valid EVP_PKEY with an RSA + // private key. All FFI calls operate on `pkey` or the derived contexts. unsafe { - let rc = wolfcrypt_rsa_pkcs1v15_verify( - ctx, hash_bits, - msg.as_ptr(), msg.len() as u32, - sig.as_ptr(), sig.len() as u32, + let md_ctx = MdCtx::new()?; + + // EVP_DigestSignInit sets up the context. The returned pkey_ctx is + // owned by md_ctx and must NOT be freed separately. + let mut pkey_ctx: *mut EVP_PKEY_CTX = ptr::null_mut(); + let rc = EVP_DigestSignInit( + md_ctx.as_mut_ptr(), + &mut pkey_ctx, + digest.evp_md(), + ptr::null_mut(), // no ENGINE + pkey, ); - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_pkcs1v15_verify" }); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestSignInit" }); } - Ok(()) - } -} -// --------------------------------------------------------------------------- -// Native PSS helpers (wc_RsaPSS_Sign_ex / wc_RsaPSS_VerifyCheck) -// --------------------------------------------------------------------------- + // Configure padding. + let rc = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding.as_c_int()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_padding" }); + } -/// Sign `msg` using RSA-PSS with the given hash via the native shim. -/// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *` holding a private key. -/// `hash_bits` must be 256, 384, or 512 (SHA-1 PSS is not supported). -/// Salt length equals the hash length. PSS is randomised. -unsafe fn native_pss_sign( - ctx: *mut c_void, - msg: &[u8], - hash_bits: i32, -) -> Result, WolfCryptError> { - unsafe { - let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - if key_size <= 0 { - return Err(WolfCryptError::Ffi { code: key_size, func: "wolfcrypt_rsa_key_size_bytes" }); + if matches!(padding, RsaPadding::Pss) { + // wolfSSL's set_rsa_pss_saltlen and set_rsa_mgf1_md may return 0 + // on success (wolfSSL convention) rather than 1 (OpenSSL convention). + // Check for negative error codes only. + let rc = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, RSA_PSS_SALTLEN_DIGEST); + if rc < 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_pss_saltlen" }); + } + let rc = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, digest.evp_md()); + if rc < 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_mgf1_md" }); + } } - let mut sig = vec![0u8; key_size as usize]; - let mut sig_len = key_size as u32; - let rc = wolfcrypt_rsa_pss_sign( - ctx, hash_bits, - msg.as_ptr(), msg.len() as u32, - sig.as_mut_ptr(), &mut sig_len, + + // Feed message data. + let rc = EVP_DigestSignUpdate( + md_ctx.as_mut_ptr(), + msg.as_ptr() as *const c_void, + len_as_u32(msg.len()), ); - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_pss_sign" }); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestSignUpdate" }); + } + + // First call: determine signature length. + let mut sig_len: usize = 0; + let rc = EVP_DigestSignFinal(md_ctx.as_mut_ptr(), ptr::null_mut(), &mut sig_len); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestSignFinal" }); } - sig.truncate(sig_len as usize); + if sig_len == 0 { + return Err(WolfCryptError::Ffi { code: 0, func: "EVP_DigestSignFinal (zero output length)" }); + } + + // Second call: produce the signature. + let mut sig = vec![0u8; sig_len]; + let rc = EVP_DigestSignFinal(md_ctx.as_mut_ptr(), sig.as_mut_ptr(), &mut sig_len); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestSignFinal" }); + } + sig.truncate(sig_len); + Ok(sig) } } -/// Verify an RSA-PSS signature using the native shim. -/// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *`. -/// `hash_bits` must be 256, 384, or 512. Salt length equals the hash length. -unsafe fn native_pss_verify( - ctx: *mut c_void, +/// Verify an RSA signature using EVP_DigestVerify with the given padding mode. +unsafe fn evp_verify( + pkey: *mut EVP_PKEY, msg: &[u8], sig: &[u8], - hash_bits: i32, + padding: RsaPadding, + digest: RsaDigest, ) -> Result<(), WolfCryptError> { + // SAFETY: caller guarantees `pkey` is a valid EVP_PKEY. unsafe { - let rc = wolfcrypt_rsa_pss_verify( - ctx, hash_bits, - msg.as_ptr(), msg.len() as u32, - sig.as_ptr(), sig.len() as u32, + let md_ctx = MdCtx::new()?; + + let mut pkey_ctx: *mut EVP_PKEY_CTX = ptr::null_mut(); + let rc = EVP_DigestVerifyInit( + md_ctx.as_mut_ptr(), + &mut pkey_ctx, + digest.evp_md(), + ptr::null_mut(), + pkey, ); - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_pss_verify" }); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestVerifyInit" }); } - Ok(()) - } -} -// --------------------------------------------------------------------------- -// Native PKCS#1v1.5 encrypt/decrypt helpers -// --------------------------------------------------------------------------- + let rc = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding.as_c_int()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_padding" }); + } -/// Encrypt `plaintext` using RSA PKCS#1v1.5 padding via the native shim. -/// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *` holding a public key. -unsafe fn native_pkcs1v15_encrypt( - ctx: *mut c_void, - plaintext: &[u8], -) -> Result, WolfCryptError> { - unsafe { - let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - if key_size <= 0 { - return Err(WolfCryptError::Ffi { code: key_size, func: "wolfcrypt_rsa_key_size_bytes" }); + if matches!(padding, RsaPadding::Pss) { + // wolfSSL's set_rsa_pss_saltlen and set_rsa_mgf1_md may return 0 + // on success (wolfSSL convention) rather than 1 (OpenSSL convention). + // Check for negative error codes only. + let rc = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, RSA_PSS_SALTLEN_DIGEST); + if rc < 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_pss_saltlen" }); + } + let rc = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, digest.evp_md()); + if rc < 0 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_mgf1_md" }); + } } - let mut out = vec![0u8; key_size as usize]; - let rc = wolfcrypt_rsa_pkcs1v15_encrypt( - ctx, - plaintext.as_ptr(), plaintext.len() as u32, - out.as_mut_ptr(), key_size as u32, + + let rc = EVP_DigestVerifyUpdate( + md_ctx.as_mut_ptr(), + msg.as_ptr() as *const c_void, + msg.len(), ); - if rc <= 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_pkcs1v15_encrypt" }); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestVerifyUpdate" }); } - out.truncate(rc as usize); - Ok(out) - } -} -/// Decrypt `ciphertext` using RSA PKCS#1v1.5 padding via the native shim. -/// -/// `ctx` must be a valid, non-null `wolfcrypt_rsa_ctx *` holding a private key. -/// -/// Checks `rc <= 0` for failure: wolfSSL returns 0 for invalid PKCS#1v1.5 -/// padding when `WOLFSSL_RSA_DECRYPT_TO_0_LEN` is set (constant-time failure -/// path), and negative for other errors. -unsafe fn native_pkcs1v15_decrypt( - ctx: *mut c_void, - ciphertext: &[u8], -) -> Result, WolfCryptError> { - unsafe { - let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _); - if key_size <= 0 { - return Err(WolfCryptError::Ffi { code: key_size, func: "wolfcrypt_rsa_key_size_bytes" }); - } - let mut out = vec![0u8; key_size as usize]; - let rc = wolfcrypt_rsa_pkcs1v15_decrypt( - ctx, - ciphertext.as_ptr(), ciphertext.len() as u32, - out.as_mut_ptr(), key_size as u32, - ); - if rc <= 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_pkcs1v15_decrypt" }); + let rc = EVP_DigestVerifyFinal(md_ctx.as_mut_ptr(), sig.as_ptr(), sig.len()); + if rc != 1 { + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_DigestVerifyFinal" }); } - out.truncate(rc as usize); - Ok(out) + + Ok(()) } } @@ -394,96 +520,147 @@ unsafe fn native_pkcs1v15_decrypt( // RsaPrivateKey // --------------------------------------------------------------------------- -/// An RSA private key backed by a native `wolfcrypt_rsa_ctx`. +/// An RSA private key backed by wolfCrypt's EVP_PKEY. /// -/// Supports PKCS#1v1.5 and PSS signing/verification, and OAEP / PKCS#1v1.5 -/// encryption/decryption. Uses the native `wc_*` wolfCrypt API directly with -/// no EVP OpenSSL-compat layer. +/// Supports both PKCS#1v1.5 and PSS signing with SHA-256, and OAEP / +/// PKCS#1v1.5 encryption/decryption. The key is generated via +/// `EVP_PKEY_keygen` and freed on drop. pub struct RsaPrivateKey { - /// Opaque heap-allocated `wolfcrypt_rsa_ctx *`. + /// Heap-allocated EVP_PKEY. /// - /// `UnsafeCell` makes the type `!Sync`, which is the correct contract - /// (wolfCrypt contexts are not thread-safe for concurrent access). - ctx: UnsafeCell<*mut c_void>, + /// Strictly speaking `UnsafeCell` around the raw pointer is not + /// required for soundness โ€” `&self`'s aliasing scope covers the + /// struct's own memory (the pointer value) but not the heap data + /// behind it, so passing `*mut EVP_PKEY` to FFI is already legal. + /// We keep `UnsafeCell` because it makes the type `!Sync`, which + /// is the correct contract (wolfCrypt contexts are not thread-safe). + pkey: UnsafeCell<*mut EVP_PKEY>, } -// SAFETY: `wolfcrypt_rsa_ctx` is a self-contained heap object. The struct -// can safely be moved between threads (Send), but not shared (not Sync). +// SAFETY: EVP_PKEY is a self-contained heap object with no shared global +// mutable state. The struct can safely be moved between threads. +// NOTE: NOT Sync โ€” wolfSSL's EVP_PKEY has internal mutable state that is +// not protected against concurrent access from multiple threads. unsafe impl Send for RsaPrivateKey {} impl RsaPrivateKey { /// Import an RSA private key from a PKCS#1 DER-encoded `RSAPrivateKey` /// (RFC 8017 Appendix A.1.2). + /// + /// Uses `d2i_PrivateKey(EVP_PKEY_RSA, ...)` from wolfSSL's OpenSSL + /// compatibility layer. pub fn from_pkcs1_der(der: &[u8]) -> Result { unsafe { - let ctx = wolfcrypt_rsa_new(); - if ctx.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - let rc = wolfcrypt_rsa_import_private_pkcs1(ctx, der.as_ptr(), der.len() as u32); - if rc != 0 { - wolfcrypt_rsa_free(ctx); - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_import_private_pkcs1" }); + let mut in_ptr = der.as_ptr(); + let pkey = d2i_PrivateKey( + EVP_PKEY_RSA, + ptr::null_mut(), + &mut in_ptr as *mut *const u8 as *mut *const u8, + der.len() as core::ffi::c_long, + ); + if pkey.is_null() { + return Err(WolfCryptError::Ffi { code: -1, func: "d2i_PrivateKey" }); } - Ok(Self { ctx: UnsafeCell::new(ctx) }) + Ok(Self { + pkey: UnsafeCell::new(pkey), + }) } } /// Export the private key as a PKCS#1 DER-encoded `RSAPrivateKey`. + /// + /// Uses `i2d_PrivateKey` from wolfSSL's OpenSSL compatibility layer. pub fn to_pkcs1_der(&self) -> Result, WolfCryptError> { unsafe { - let ctx = *self.ctx.get(); - // 4096 bytes is sufficient for any RSA key up to 4096 bits. - let mut buf = vec![0u8; 4096]; - let mut len = buf.len() as u32; - let rc = wolfcrypt_rsa_export_private_pkcs1(ctx, buf.as_mut_ptr(), &mut len); - if rc != 0 { - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_export_private_pkcs1" }); + let pkey = *self.pkey.get(); + + // First call: determine DER output size. + let der_len = i2d_PrivateKey(pkey as *const _, ptr::null_mut()); + if der_len <= 0 { + return Err(WolfCryptError::Ffi { code: der_len, func: "i2d_PrivateKey" }); + } + + // Second call: write DER bytes. + let mut der = vec![0u8; der_len as usize]; + let mut out_ptr = der.as_mut_ptr(); + let written = i2d_PrivateKey(pkey as *const _, &mut out_ptr); + if written != der_len { + return Err(WolfCryptError::Ffi { code: written, func: "i2d_PrivateKey" }); } - buf.truncate(len as usize); - Ok(buf) + Ok(der) } } /// Generate an RSA keypair of the given bit size (e.g. 2048, 3072, 4096). + /// + /// Uses `EVP_PKEY_keygen` from wolfSSL's OpenSSL compatibility layer. pub fn generate(bits: u32) -> Result { unsafe { - let ctx = wolfcrypt_rsa_new(); + let ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, ptr::null_mut()); if ctx.is_null() { return Err(WolfCryptError::ALLOC_FAILED); } - let rc = wolfcrypt_rsa_generate(ctx, bits as i32); - if rc != 0 { - wolfcrypt_rsa_free(ctx); - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_generate" }); + + let rc = EVP_PKEY_keygen_init(ctx); + if rc != 1 { + EVP_PKEY_CTX_free(ctx); + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_keygen_init" }); + } + + let rc = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits as i32); + if rc != 1 { + EVP_PKEY_CTX_free(ctx); + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_CTX_set_rsa_keygen_bits" }); } - Ok(Self { ctx: UnsafeCell::new(ctx) }) + + let mut pkey: *mut EVP_PKEY = ptr::null_mut(); + let rc = EVP_PKEY_keygen(ctx, &mut pkey); + EVP_PKEY_CTX_free(ctx); + + if rc != 1 || pkey.is_null() { + if !pkey.is_null() { + EVP_PKEY_free(pkey); + } + return Err(WolfCryptError::Ffi { code: rc, func: "EVP_PKEY_keygen" }); + } + + Ok(Self { + pkey: UnsafeCell::new(pkey), + }) } } /// Return the corresponding public key. /// - /// Exports the public component as SPKI DER and imports it into a fresh, - /// independent `wolfcrypt_rsa_ctx` with no shared state with this key. - /// Panics if the export/import fails (should not happen for a valid key). + /// Creates a fully independent `EVP_PKEY` by exporting the public key + /// as DER and re-importing it, so the public key shares no mutable + /// state with this private key. This is safe to send to another thread. pub fn public_key(&self) -> RsaPublicKey { unsafe { - let ctx = *self.ctx.get(); - - // Export the public component as SPKI DER. - let mut spki = vec![0u8; 4096]; - let mut spki_len = spki.len() as u32; - let rc = wolfcrypt_rsa_export_public_spki(ctx, spki.as_mut_ptr(), &mut spki_len); - assert!(rc == 0, "wolfcrypt_rsa_export_public_spki failed: {rc}"); - spki.truncate(spki_len as usize); - - // Import into a fresh, independent ctx. - let new_ctx = wolfcrypt_rsa_new(); - assert!(!new_ctx.is_null(), "wolfcrypt_rsa_new returned null"); - let rc = wolfcrypt_rsa_import_public_spki(new_ctx, spki.as_ptr(), spki_len); - assert!(rc == 0, "wolfcrypt_rsa_import_public_spki failed: {rc}"); - - RsaPublicKey { ctx: UnsafeCell::new(new_ctx) } + let pkey = *self.pkey.get(); + + // First call: determine DER output size. + let der_len = i2d_PUBKEY(pkey as *const _, ptr::null_mut()); + assert!(der_len > 0, "i2d_PUBKEY failed (invalid key)"); + + // Second call: write DER bytes. + let mut der = vec![0u8; der_len as usize]; + let mut out_ptr = der.as_mut_ptr(); + let written = i2d_PUBKEY(pkey as *const _, &mut out_ptr); + assert_eq!(written, der_len, "i2d_PUBKEY size mismatch"); + + // Import into a fresh, independent EVP_PKEY. + let mut in_ptr = der.as_ptr(); + let new_pkey = d2i_PUBKEY( + ptr::null_mut(), + &mut in_ptr as *mut *const u8 as *mut *const u8, + der_len as core::ffi::c_long, + ); + assert!(!new_pkey.is_null(), "d2i_PUBKEY failed (invalid DER)"); + + RsaPublicKey { + pkey: UnsafeCell::new(new_pkey), + } } } @@ -498,7 +675,7 @@ impl RsaPrivateKey { msg: &[u8], digest: RsaDigest, ) -> Result { - let sig = unsafe { native_pkcs1v15_sign(*self.ctx.get(), msg, digest.hash_bits())? }; + let sig = unsafe { evp_sign(*self.pkey.get(), msg, RsaPadding::Pkcs1v15, digest)? }; Ok(RsaPkcs1v15Signature(sig)) } @@ -513,27 +690,26 @@ impl RsaPrivateKey { /// Sign `msg` with PSS padding using the specified digest. /// /// Salt length equals the digest length. MGF1 hash matches the digest. - /// SHA-1 PSS is not supported and will return an error. pub fn sign_pss_with_digest( &self, msg: &[u8], digest: RsaDigest, ) -> Result { - let sig = unsafe { native_pss_sign(*self.ctx.get(), msg, digest.hash_bits())? }; + let sig = unsafe { evp_sign(*self.pkey.get(), msg, RsaPadding::Pss, digest)? }; Ok(RsaPssSignature(sig)) } - /// Encrypt `plaintext` with OAEP SHA-256/MGF1-SHA256 (RFC 8017 Section 7.1). + /// Encrypt `plaintext` with OAEP padding and SHA-256 (RFC 8017 Section 7.1). /// /// For a 2048-bit key the maximum plaintext size is 190 bytes /// (256 - 2*32 - 2). pub fn encrypt_oaep(&self, plaintext: &[u8]) -> Result, WolfCryptError> { - unsafe { native_oaep_encrypt_sha256(*self.ctx.get(), plaintext) } + unsafe { evp_encrypt(*self.pkey.get(), plaintext, RsaPadding::Oaep) } } - /// Decrypt `ciphertext` with OAEP SHA-256/MGF1-SHA256 (RFC 8017 Section 7.1). + /// Decrypt `ciphertext` with OAEP padding and SHA-256 (RFC 8017 Section 7.1). pub fn decrypt_oaep(&self, ciphertext: &[u8]) -> Result, WolfCryptError> { - unsafe { native_oaep_decrypt_sha256(*self.ctx.get(), ciphertext) } + unsafe { evp_decrypt(*self.pkey.get(), ciphertext, RsaPadding::Oaep) } } /// Encrypt `plaintext` with PKCS#1 v1.5 padding (RFC 8017 Section 7.2). @@ -541,18 +717,23 @@ impl RsaPrivateKey { /// For a 2048-bit key the maximum plaintext size is 245 bytes /// (256 - 11). pub fn encrypt_pkcs1v15(&self, plaintext: &[u8]) -> Result, WolfCryptError> { - unsafe { native_pkcs1v15_encrypt(*self.ctx.get(), plaintext) } + unsafe { evp_encrypt(*self.pkey.get(), plaintext, RsaPadding::Pkcs1v15) } } /// Decrypt `ciphertext` with PKCS#1 v1.5 padding (RFC 8017 Section 7.2). pub fn decrypt_pkcs1v15(&self, ciphertext: &[u8]) -> Result, WolfCryptError> { - unsafe { native_pkcs1v15_decrypt(*self.ctx.get(), ciphertext) } + unsafe { evp_decrypt(*self.pkey.get(), ciphertext, RsaPadding::Pkcs1v15) } } } impl Drop for RsaPrivateKey { fn drop(&mut self) { - unsafe { wolfcrypt_rsa_free(*self.ctx.get()); } + unsafe { + let pkey = *self.pkey.get(); + if !pkey.is_null() { + EVP_PKEY_free(pkey); + } + } } } @@ -574,16 +755,17 @@ impl signature_trait::Signer for RsaPrivateKey { // RsaPublicKey // --------------------------------------------------------------------------- -/// An RSA public key backed by a native `wolfcrypt_rsa_ctx`. +/// An RSA public key backed by wolfCrypt's EVP_PKEY. /// -/// Obtained from [`RsaPrivateKey::public_key()`] or [`RsaPublicKey::from_der`]. -/// Owns an independent `wolfcrypt_rsa_ctx` with no shared state with the private -/// key, so it is safe to move to another thread. +/// Obtained from [`RsaPrivateKey::public_key()`]. Owns an independent +/// `EVP_PKEY` (no shared state with the private key), so it is safe to +/// move to another thread. pub struct RsaPublicKey { - /// Opaque heap-allocated `wolfcrypt_rsa_ctx *` (public-key component only). + /// Heap-allocated EVP_PKEY (public-only). /// - /// `UnsafeCell` provides `!Sync` โ€” same rationale as `RsaPrivateKey::ctx`. - ctx: UnsafeCell<*mut c_void>, + /// `UnsafeCell` around the pointer: same rationale as + /// [`RsaPrivateKey::pkey`] โ€” provides `!Sync`. + pkey: UnsafeCell<*mut EVP_PKEY>, } // SAFETY: same reasoning as RsaPrivateKey โ€” Send but not Sync. @@ -592,34 +774,37 @@ unsafe impl Send for RsaPublicKey {} impl RsaPublicKey { /// Import a public key from a DER-encoded SubjectPublicKeyInfo (SPKI) blob. /// - /// This is the standard format used by Wycheproof test vectors - /// (`publicKeyDer` field) and produced by `wolfcrypt_rsa_export_public_spki`. + /// This is the standard format produced by `i2d_PUBKEY` / OpenSSL's + /// `PEM_write_bio_PUBKEY` and used by Wycheproof test vectors + /// (`publicKeyDer` field). pub fn from_der(der: &[u8]) -> Result { unsafe { - let ctx = wolfcrypt_rsa_new(); - if ctx.is_null() { - return Err(WolfCryptError::ALLOC_FAILED); - } - let rc = wolfcrypt_rsa_import_public_spki(ctx, der.as_ptr(), der.len() as u32); - if rc != 0 { - wolfcrypt_rsa_free(ctx); - return Err(WolfCryptError::Ffi { code: rc, func: "wolfcrypt_rsa_import_public_spki" }); + let mut in_ptr = der.as_ptr(); + let pkey = d2i_PUBKEY( + ptr::null_mut(), + &mut in_ptr as *mut *const u8 as *mut *const u8, + der.len() as core::ffi::c_long, + ); + if pkey.is_null() { + return Err(WolfCryptError::Ffi { code: -1, func: "d2i_PUBKEY" }); } - Ok(Self { ctx: UnsafeCell::new(ctx) }) + Ok(Self { + pkey: UnsafeCell::new(pkey), + }) } } - /// Encrypt `plaintext` with OAEP SHA-256/MGF1-SHA256 (RFC 8017 Section 7.1). + /// Encrypt `plaintext` with OAEP padding and SHA-256 (RFC 8017 Section 7.1). /// /// RSA encryption only requires the public key. Decryption requires the /// private key held by [`RsaPrivateKey`]. pub fn encrypt_oaep(&self, plaintext: &[u8]) -> Result, WolfCryptError> { - unsafe { native_oaep_encrypt_sha256(*self.ctx.get(), plaintext) } + unsafe { evp_encrypt(*self.pkey.get(), plaintext, RsaPadding::Oaep) } } /// Encrypt `plaintext` with PKCS#1 v1.5 padding (RFC 8017 Section 7.2). pub fn encrypt_pkcs1v15(&self, plaintext: &[u8]) -> Result, WolfCryptError> { - unsafe { native_pkcs1v15_encrypt(*self.ctx.get(), plaintext) } + unsafe { evp_encrypt(*self.pkey.get(), plaintext, RsaPadding::Pkcs1v15) } } /// Verify a PKCS#1v1.5 signature (RFC 8017 Section 8.2) with SHA-256. @@ -638,7 +823,7 @@ impl RsaPublicKey { sig: &RsaPkcs1v15Signature, digest: RsaDigest, ) -> Result<(), WolfCryptError> { - unsafe { native_pkcs1v15_verify(*self.ctx.get(), msg, &sig.0, digest.hash_bits()) } + unsafe { evp_verify(*self.pkey.get(), msg, &sig.0, RsaPadding::Pkcs1v15, digest) } } /// Verify a PSS signature (RFC 8017 Section 8.1) with SHA-256. @@ -649,20 +834,24 @@ impl RsaPublicKey { /// Verify a PSS signature using the specified digest. /// /// Salt length equals the digest length. MGF1 hash matches the digest. - /// SHA-1 PSS is not supported and will return an error. pub fn verify_pss_with_digest( &self, msg: &[u8], sig: &RsaPssSignature, digest: RsaDigest, ) -> Result<(), WolfCryptError> { - unsafe { native_pss_verify(*self.ctx.get(), msg, &sig.0, digest.hash_bits()) } + unsafe { evp_verify(*self.pkey.get(), msg, &sig.0, RsaPadding::Pss, digest) } } } impl Drop for RsaPublicKey { fn drop(&mut self) { - unsafe { wolfcrypt_rsa_free(*self.ctx.get()); } + unsafe { + let pkey = *self.pkey.get(); + if !pkey.is_null() { + EVP_PKEY_free(pkey); + } + } } } @@ -743,7 +932,7 @@ impl RsaDirectType { } /// An RSA key using the **native** wolfCrypt `RsaKey` type (not the -/// native `wolfcrypt_rsa_ctx` wrapper used by [`RsaPrivateKey`]). +/// OpenSSL-compat `EVP_PKEY` wrapper used by [`RsaPrivateKey`]). /// /// This is needed for raw / no-padding RSA operations via /// [`wc_RsaFunction`], which operates directly on the modulus without diff --git a/wolfcrypt/tests/ed25519.rs b/wolfcrypt/tests/ed25519.rs deleted file mode 100644 index 4547bae..0000000 --- a/wolfcrypt/tests/ed25519.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! Ed25519 signing and verification integration tests. -//! -//! Test vectors are taken from RFC 8032 ยง6.1. All verification tests use -//! an external oracle (the RFC) rather than re-using the code under test as -//! the oracle. - -#![cfg(all(feature = "ed25519", wolfssl_ed25519))] - -use wolfcrypt::ed25519::{Ed25519SigningKey, Ed25519VerifyingKey}; -use wolfcrypt::rand::WolfRng; - -// RFC 8032 ยง6.1 Test Vector 1 -// SECRET KEY (seed): 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae3d55 -// PUBLIC KEY: d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a -// MESSAGE: (empty) -// SIGNATURE: e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b -const RFC8032_TV1_SEED: [u8; 32] = [ - 0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, - 0xba, 0x84, 0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, - 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32, 0x69, 0x19, - 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x3d, 0x55, -]; - -const RFC8032_TV1_PUB: [u8; 32] = [ - 0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, - 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, - 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25, - 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a, -]; - -// RFC 8032 ยง6.1 Test Vector 1 signature over the empty message. -const RFC8032_TV1_SIG: [u8; 64] = [ - 0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, - 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a, - 0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, - 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, 0x01, 0x55, - 0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, - 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b, - 0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, - 0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b, -]; - -// ================================================================ -// check_key -// ================================================================ - -#[test] -fn check_key_accepts_rfc8032_tv1() { - let mut vk = Ed25519VerifyingKey::from_bytes(&RFC8032_TV1_PUB) - .expect("RFC 8032 TV1 public key import must succeed"); - vk.check_key() - .expect("RFC 8032 TV1 public key must pass wolfCrypt point validation"); -} - -#[test] -fn check_key_accepts_generated_key() { - let mut rng = WolfRng::new().unwrap(); - let sk = Ed25519SigningKey::generate(&mut rng).expect("key generation must succeed"); - let mut vk = sk.verifying_key(); - vk.check_key() - .expect("a freshly generated key must pass check_key"); -} - -// ================================================================ -// Sign / verify -// ================================================================ - -#[test] -fn verify_rfc8032_tv1_empty_message() { - use ed25519_trait::Signature; - use signature_trait::Verifier; - - let vk = Ed25519VerifyingKey::from_bytes(&RFC8032_TV1_PUB) - .expect("RFC 8032 TV1 public key import must succeed"); - - let sig = Signature::from_bytes(&RFC8032_TV1_SIG); - vk.verify(b"", &sig) - .expect("RFC 8032 TV1 signature over empty message must verify"); -} - -#[test] -fn sign_verify_roundtrip() { - use signature_trait::{Signer, Verifier}; - - let sk = Ed25519SigningKey::from_seed(&RFC8032_TV1_SEED) - .expect("seed import must succeed"); - let vk = sk.verifying_key(); - - let msg = b"onlykey integration test"; - let sig = sk.sign(msg); - vk.verify(msg, &sig).expect("signature produced by sign must verify"); -} - -#[test] -fn wrong_message_does_not_verify() { - use signature_trait::{Signer, Verifier}; - - let sk = Ed25519SigningKey::from_seed(&RFC8032_TV1_SEED) - .expect("seed import must succeed"); - let vk = sk.verifying_key(); - - let sig = sk.sign(b"correct message"); - assert!( - vk.verify(b"tampered message", &sig).is_err(), - "signature over different message must not verify" - ); -} - -#[test] -fn verifying_key_roundtrips_through_bytes() { - let vk1 = Ed25519VerifyingKey::from_bytes(&RFC8032_TV1_PUB) - .expect("import must succeed"); - let vk2 = Ed25519VerifyingKey::from_bytes(vk1.as_bytes()) - .expect("re-import of exported bytes must succeed"); - assert_eq!( - vk1.as_bytes(), - vk2.as_bytes(), - "round-trip through as_bytes must preserve key material" - ); -} diff --git a/wolfcrypt/tests/nist_ecdh.rs b/wolfcrypt/tests/nist_ecdh.rs index 70096db..8b7ca6b 100644 --- a/wolfcrypt/tests/nist_ecdh.rs +++ b/wolfcrypt/tests/nist_ecdh.rs @@ -1,14 +1,16 @@ // NIST curve ECDH round-trip tests (P-256, P-384). // -// Exercises the native wc_ecc_* NIST ECDH implementation. -// Validates DH symmetry, shared-secret length, key export/import, and -// rejection of malformed public keys. - -#![cfg(all(wolfssl_ecc, feature = "ecdh"))] +// These tests exercise the wolfCrypt NIST ECDH implementation via the +// wolfSSL OpenSSL compat layer (EC_KEY / ECDH_compute_key). +// +// Since NIST ECDH test vectors (e.g. from CAVP) require importing +// specific private scalars in DER/raw form, we focus on round-trip +// tests that validate the DH symmetry property and key format +// correctness. use wolfcrypt::{NistEcdhPublicKey, NistP256, P256EcdhSecret}; -#[cfg(wolfssl_ecc_p384)] +#[cfg(wolfssl_sha384)] use wolfcrypt::{NistP384, P384EcdhSecret}; // ================================================================ @@ -19,14 +21,14 @@ use wolfcrypt::{NistP384, P384EcdhSecret}; /// the shared secret from both sides, and verify they are equal. #[test] fn p256_round_trip() { - let alice = P256EcdhSecret::generate().expect("P-256 generate alice"); - let alice_pub = alice.public_key().expect("P-256 export alice pub"); + let alice = P256EcdhSecret::generate().unwrap(); + let alice_pub = alice.public_key(); - let bob = P256EcdhSecret::generate().expect("P-256 generate bob"); - let bob_pub = bob.public_key().expect("P-256 export bob pub"); + let bob = P256EcdhSecret::generate().unwrap(); + let bob_pub = bob.public_key(); - let shared_ab = alice.diffie_hellman(&bob_pub).expect("P-256 DH alice->bob"); - let shared_ba = bob.diffie_hellman(&alice_pub).expect("P-256 DH bob->alice"); + let shared_ab = alice.diffie_hellman(&bob_pub); + let shared_ba = bob.diffie_hellman(&alice_pub); assert_eq!( shared_ab.as_bytes(), @@ -39,11 +41,11 @@ fn p256_round_trip() { /// 32 bytes (the field element size for secp256r1). #[test] fn p256_shared_secret_length() { - let alice = P256EcdhSecret::generate().expect("P-256 generate alice"); - let bob = P256EcdhSecret::generate().expect("P-256 generate bob"); - let bob_pub = bob.public_key().expect("P-256 export bob pub"); + let alice = P256EcdhSecret::generate().unwrap(); + let bob = P256EcdhSecret::generate().unwrap(); + let bob_pub = bob.public_key(); - let shared = alice.diffie_hellman(&bob_pub).expect("P-256 DH"); + let shared = alice.diffie_hellman(&bob_pub); assert_eq!( shared.as_bytes().len(), 32, @@ -55,15 +57,15 @@ fn p256_shared_secret_length() { /// independent pairs (A1,B1) and (A2,B2) and verify DH(A1,B1) != DH(A2,B2). #[test] fn p256_different_keypairs_different_secrets() { - let a1 = P256EcdhSecret::generate().expect("generate a1"); - let b1 = P256EcdhSecret::generate().expect("generate b1"); - let b1_pub = b1.public_key().expect("export b1 pub"); - let shared1 = a1.diffie_hellman(&b1_pub).expect("DH a1*b1"); + let a1 = P256EcdhSecret::generate().unwrap(); + let b1 = P256EcdhSecret::generate().unwrap(); + let b1_pub = b1.public_key(); + let shared1 = a1.diffie_hellman(&b1_pub); - let a2 = P256EcdhSecret::generate().expect("generate a2"); - let b2 = P256EcdhSecret::generate().expect("generate b2"); - let b2_pub = b2.public_key().expect("export b2 pub"); - let shared2 = a2.diffie_hellman(&b2_pub).expect("DH a2*b2"); + let a2 = P256EcdhSecret::generate().unwrap(); + let b2 = P256EcdhSecret::generate().unwrap(); + let b2_pub = b2.public_key(); + let shared2 = a2.diffie_hellman(&b2_pub); // Probability of collision is ~2^{-256}; safe to assert inequality. assert_ne!( @@ -78,8 +80,8 @@ fn p256_different_keypairs_different_secrets() { /// compute ECDH with it to verify correctness. #[test] fn p256_public_key_export_import_round_trip() { - let checker = P256EcdhSecret::generate().expect("generate checker"); - let checker_pub = checker.public_key().expect("export checker pub"); + let checker = P256EcdhSecret::generate().unwrap(); + let checker_pub = checker.public_key(); let exported = checker_pub.as_bytes(); @@ -92,11 +94,11 @@ fn p256_public_key_export_import_round_trip() { NistEcdhPublicKey::from_bytes(exported).expect("valid public key"); // Verify DH works with the reimported key: compute from both sides. - let peer = P256EcdhSecret::generate().expect("generate peer"); - let peer_pub = peer.public_key().expect("export peer pub"); + let peer = P256EcdhSecret::generate().unwrap(); + let peer_pub = peer.public_key(); - let shared_a = checker.diffie_hellman(&peer_pub).expect("DH checker*peer"); - let shared_b = peer.diffie_hellman(&reimported).expect("DH peer*checker(reimported)"); + let shared_a = checker.diffie_hellman(&peer_pub); + let shared_b = peer.diffie_hellman(&reimported); assert_eq!( shared_a.as_bytes(), @@ -132,17 +134,17 @@ fn p256_reject_invalid_pubkey_prefix() { /// NIST SP 800-56Ar3, ECC CDH on P-384: generate two keypairs, compute /// the shared secret from both sides, and verify they are equal. -#[cfg(wolfssl_ecc_p384)] +#[cfg(wolfssl_sha384)] #[test] fn p384_round_trip() { - let alice = P384EcdhSecret::generate().expect("P-384 generate alice"); - let alice_pub = alice.public_key().expect("P-384 export alice pub"); + let alice = P384EcdhSecret::generate().unwrap(); + let alice_pub = alice.public_key(); - let bob = P384EcdhSecret::generate().expect("P-384 generate bob"); - let bob_pub = bob.public_key().expect("P-384 export bob pub"); + let bob = P384EcdhSecret::generate().unwrap(); + let bob_pub = bob.public_key(); - let shared_ab = alice.diffie_hellman(&bob_pub).expect("P-384 DH alice->bob"); - let shared_ba = bob.diffie_hellman(&alice_pub).expect("P-384 DH bob->alice"); + let shared_ab = alice.diffie_hellman(&bob_pub); + let shared_ba = bob.diffie_hellman(&alice_pub); assert_eq!( shared_ab.as_bytes(), @@ -153,14 +155,14 @@ fn p384_round_trip() { /// Shared secret length validation: P-384 ECDH must produce exactly /// 48 bytes (the field element size for secp384r1). -#[cfg(wolfssl_ecc_p384)] +#[cfg(wolfssl_sha384)] #[test] fn p384_shared_secret_length() { - let alice = P384EcdhSecret::generate().expect("P-384 generate alice"); - let bob = P384EcdhSecret::generate().expect("P-384 generate bob"); - let bob_pub = bob.public_key().expect("P-384 export bob pub"); + let alice = P384EcdhSecret::generate().unwrap(); + let bob = P384EcdhSecret::generate().unwrap(); + let bob_pub = bob.public_key(); - let shared = alice.diffie_hellman(&bob_pub).expect("P-384 DH"); + let shared = alice.diffie_hellman(&bob_pub); assert_eq!( shared.as_bytes().len(), 48, @@ -169,18 +171,18 @@ fn p384_shared_secret_length() { } /// Different keypairs produce different shared secrets on P-384. -#[cfg(wolfssl_ecc_p384)] +#[cfg(wolfssl_sha384)] #[test] fn p384_different_keypairs_different_secrets() { - let a1 = P384EcdhSecret::generate().expect("generate a1"); - let b1 = P384EcdhSecret::generate().expect("generate b1"); - let b1_pub = b1.public_key().expect("export b1 pub"); - let shared1 = a1.diffie_hellman(&b1_pub).expect("DH a1*b1"); + let a1 = P384EcdhSecret::generate().unwrap(); + let b1 = P384EcdhSecret::generate().unwrap(); + let b1_pub = b1.public_key(); + let shared1 = a1.diffie_hellman(&b1_pub); - let a2 = P384EcdhSecret::generate().expect("generate a2"); - let b2 = P384EcdhSecret::generate().expect("generate b2"); - let b2_pub = b2.public_key().expect("export b2 pub"); - let shared2 = a2.diffie_hellman(&b2_pub).expect("DH a2*b2"); + let a2 = P384EcdhSecret::generate().unwrap(); + let b2 = P384EcdhSecret::generate().unwrap(); + let b2_pub = b2.public_key(); + let shared2 = a2.diffie_hellman(&b2_pub); assert_ne!( shared1.as_bytes(), @@ -190,11 +192,11 @@ fn p384_different_keypairs_different_secrets() { } /// Public key export/import round-trip on P-384. -#[cfg(wolfssl_ecc_p384)] +#[cfg(wolfssl_sha384)] #[test] fn p384_public_key_export_import_round_trip() { - let checker = P384EcdhSecret::generate().expect("generate checker"); - let checker_pub = checker.public_key().expect("export checker pub"); + let checker = P384EcdhSecret::generate().unwrap(); + let checker_pub = checker.public_key(); let exported = checker_pub.as_bytes(); @@ -207,11 +209,11 @@ fn p384_public_key_export_import_round_trip() { NistEcdhPublicKey::from_bytes(exported).expect("valid public key"); // Verify DH works with the reimported key. - let peer = P384EcdhSecret::generate().expect("generate peer"); - let peer_pub = peer.public_key().expect("export peer pub"); + let peer = P384EcdhSecret::generate().unwrap(); + let peer_pub = peer.public_key(); - let shared_a = checker.diffie_hellman(&peer_pub).expect("DH checker*peer"); - let shared_b = peer.diffie_hellman(&reimported).expect("DH peer*checker(reimported)"); + let shared_a = checker.diffie_hellman(&peer_pub); + let shared_b = peer.diffie_hellman(&reimported); assert_eq!( shared_a.as_bytes(), diff --git a/wolfcrypt/tests/nist_ecdh_p521.rs b/wolfcrypt/tests/nist_ecdh_p521.rs index a83d277..e0bbc67 100644 --- a/wolfcrypt/tests/nist_ecdh_p521.rs +++ b/wolfcrypt/tests/nist_ecdh_p521.rs @@ -1,23 +1,26 @@ //! NIST P-521 ECDH round-trip tests for wolfcrypt. //! -//! Exercises the native wc_ecc_* P-521 ECDH implementation. - -#![cfg(all(wolfssl_ecc, wolfssl_ecc_p521, feature = "ecdh"))] +//! These tests exercise the wolfCrypt NIST ECDH P-521 implementation via the +//! wolfSSL OpenSSL compat layer (EC_KEY / ECDH_compute_key). use wolfcrypt::P521EcdhSecret; +// ================================================================ +// P-521 round-trip DH +// ================================================================ + /// NIST SP 800-56Ar3, ECC CDH on P-521: generate two keypairs, compute /// the shared secret from both sides, and verify they are equal. #[test] fn p521_round_trip() { - let alice = P521EcdhSecret::generate().expect("P-521 generate alice"); - let alice_pub = alice.public_key().expect("P-521 export alice pub"); + let alice = P521EcdhSecret::generate().unwrap(); + let alice_pub = alice.public_key(); - let bob = P521EcdhSecret::generate().expect("P-521 generate bob"); - let bob_pub = bob.public_key().expect("P-521 export bob pub"); + let bob = P521EcdhSecret::generate().unwrap(); + let bob_pub = bob.public_key(); - let shared_ab = alice.diffie_hellman(&bob_pub).expect("P-521 DH alice->bob"); - let shared_ba = bob.diffie_hellman(&alice_pub).expect("P-521 DH bob->alice"); + let shared_ab = alice.diffie_hellman(&bob_pub); + let shared_ba = bob.diffie_hellman(&alice_pub); assert_eq!( shared_ab.as_bytes(), @@ -26,15 +29,19 @@ fn p521_round_trip() { ); } +// ================================================================ +// P-521 shared secret length = 66 bytes +// ================================================================ + /// Shared secret length validation: P-521 ECDH must produce exactly /// 66 bytes (the field element size for secp521r1, ceil(521/8)). #[test] fn p521_shared_secret_length() { - let alice = P521EcdhSecret::generate().expect("P-521 generate alice"); - let bob = P521EcdhSecret::generate().expect("P-521 generate bob"); - let bob_pub = bob.public_key().expect("P-521 export bob pub"); + let alice = P521EcdhSecret::generate().unwrap(); + let bob = P521EcdhSecret::generate().unwrap(); + let bob_pub = bob.public_key(); - let shared = alice.diffie_hellman(&bob_pub).expect("P-521 DH"); + let shared = alice.diffie_hellman(&bob_pub); assert_eq!( shared.as_bytes().len(), 66, diff --git a/wolfssl-c-api-gaps.md b/wolfssl-c-api-gaps.md deleted file mode 100644 index aa574f4..0000000 --- a/wolfssl-c-api-gaps.md +++ /dev/null @@ -1,357 +0,0 @@ -# wolfSSL C API Gaps - -Discovered while wrapping wolfCrypt behind safe Rust in the `wolfcrypt-rs` and -`wolfcrypt` crates. Each gap required either a workaround in Rust or a shim -function in `wolfcrypt-rs/src/compat_shim.c`. - -The gaps are grouped into three categories: confirmed bugs in wolfSSL's C API, -missing API surface (functionality that should be in wolfSSL but isn't), and -API design quirks that are not wrong per se but impose friction on FFI wrappers. - ---- - -## Bugs - -### 1. `d2i_ECPrivateKey` does not derive the public point - -**Affected function:** `wolfSSL_d2i_ECPrivateKey` - -RFC 5915 DER encodings of EC private keys include an optional `publicKey` -field. When that field is absent, OpenSSL derives the public point from the -private scalar automatically. wolfSSL instead sets `type = ECC_PRIVATEKEY_ONLY` -and leaves the public point uninitialized. Any subsequent operation that needs -the public key โ€” ECDSA sign, ECDH, key export โ€” fails or produces garbage. - -**Workaround in `compat_shim.c`:** `wolfcrypt_fix_ec_privatekey_only()` detects -`ECC_PRIVATEKEY_ONLY`, calls `wc_ecc_make_pub()` to derive the public point -from the private scalar, resets `type = ECC_PRIVATEKEY`, then syncs the OpenSSL -compat layer via the internal `SetECKeyExternal()`. Called unconditionally -after every `d2i_ECPrivateKey` import. - -**Fix:** `wolfSSL_d2i_ECPrivateKey` should call `wc_ecc_make_pub` when the -`publicKey` field is absent, matching OpenSSL behavior. - ---- - -### 2. `EVP_CIPHER_iv_length` returns 0 for CFB128 modes - -**Affected function:** `wolfSSL_EVP_CIPHER_iv_length` - -`EVP_CIPHER_iv_length(EVP_aes_128_cfb128())` โ€” and the 192-bit and 256-bit -variants โ€” returns 0. The correct IV length for AES-CFB128 is 16 bytes. -This causes callers that derive IV size from the cipher descriptor to produce -zero-length IVs, silently corrupting every encryption. - -**Workaround in `wolfcrypt-ring-compat`:** A wrapper function -`evp_cipher_iv_length()` (streaming.rs:690) checks for a 0 return and, if the -cipher pointer matches one of the three CFB128 descriptors, substitutes 16. - -```rust -/// EVP_CIPHER_iv_length with wolfSSL CFB128 bug workaround. -/// wolfSSL incorrectly returns 0 for CFB128 cipher IV lengths. -unsafe fn evp_cipher_iv_length(cipher: *const EVP_CIPHER) -> c_int { - let len = EVP_CIPHER_iv_length_raw(cipher); - if len == 0 && (cipher == EVP_aes_128_cfb128() || ...) { - return 16; - } - len -} -``` - -**Fix:** The CFB128 cipher descriptors in wolfSSL should report `iv_len = 16`. - ---- - -### 3. `EVP_DigestSignUpdate` and `EVP_DigestVerifyUpdate` have mismatched `cnt` types - -**Affected functions:** `wolfSSL_EVP_DigestSignUpdate`, `wolfSSL_EVP_DigestVerifyUpdate` - -OpenSSL declares both functions with `size_t cnt`. wolfSSL declares -`DigestSignUpdate` with `unsigned int cnt` and `DigestVerifyUpdate` with -`size_t cnt`. The inconsistency means a Rust binding (or any caller) cannot -use the same type for both and must special-case `DigestSignUpdate`. - -**Workaround in `wolfcrypt-rs/src/lib.rs:975`:** The FFI declarations match -wolfSSL's inconsistency exactly, with a comment noting it is a wolfSSL bug: - -``` -// NOTE: wolfSSL declares SignUpdate with `unsigned int cnt` but -// VerifyUpdate with `size_t cnt`. OpenSSL uses `size_t` for both. -// This is a wolfSSL bug; the mismatch below matches upstream as-is. -``` - -**Fix:** Change `wolfSSL_EVP_DigestSignUpdate`'s `cnt` parameter to `size_t`. - ---- - -### 4. `wolfSSL_ERR_error_string` pulls in the 30k-line TLS state machine - -**Affected function:** `wolfSSL_ERR_error_string` - -This function calls `SetErrorString`, which is defined in `internal.c` โ€” the -TLS handshake state machine, over 30,000 lines. A crypto-only build that does -not compile `internal.c` gets a linker error for this single symbol, even -though `SetErrorString` has no dependency on TLS state. - -**Workaround in `compat_shim.c:392`:** A `__attribute__((weak))` stub converts -the numeric error code to a decimal string without calling any wolfSSL code. -The weak attribute ensures that if a downstream binary links the full wolfSSL -(including `internal.c`), the real implementation wins and the stub is -discarded. - -The comment reads: *"TODO: upstream wolfSSL issue to decouple SetErrorString -from internal.c so crypto-only builds don't need this stub."* - -**Fix:** Move `SetErrorString` (or its error-code-to-string mapping) out of -`internal.c` into a file compiled for all wolfSSL configurations. - ---- - -## Missing APIs - -### 5. RFC 5649 padded AES key wrap is absent - -**Missing function:** no equivalent of `AES_wrap_key_padded` / `AES_unwrap_key_padded` - -wolfSSL provides `AES_wrap_key` / `AES_unwrap_key` for RFC 3394 standard key -wrap. RFC 5649 (padded key wrap, supporting nonโ€“block-multiple plaintext -lengths) is not implemented. - -The RFC 5649 multi-block unwrap path also cannot use wolfSSL's `AES_unwrap_key` -even as a building block, because wolfSSL's implementation validates the -recovered A register against a caller-supplied IV before returning. RFC 5649 -requires recovering the AIV โ€” which encodes the plaintext length โ€” and then -validating it; wolfSSL's validation happens first and rejects the AIV. The -entire RFC 3394 unwrap loop had to be reimplemented from scratch on top of -AES-ECB. - -**Workaround in `compat_shim.c:443`:** Full RFC 5649 wrap and unwrap are -implemented using wolfSSL's `wolfSSL_AES_ecb_encrypt` (single-block case) and -`wolfSSL_AES_wrap_key` with a custom IV (multi-block wrap). Multi-block unwrap -reimplements the RFC 3394 loop using AES-ECB to recover the AIV before -validating it. - -**Fix:** Add native `wolfSSL_AES_wrap_key_padded` / `wolfSSL_AES_unwrap_key_padded` -per RFC 5649. - ---- - -### 6. KBKDF counter mode with HMAC is absent - -**Missing function:** HMAC-based KBKDF per NIST SP 800-108r1 ยง4.1 - -wolfSSL provides `wc_KDA_KDF_PRF_cmac` for CMAC-based key-based key derivation -(SP 800-108) but has no HMAC variant. The HMAC variant is required for -interoperability with systems (TLS, SSH, JOSE) that specify KBKDF-CTR-HMAC -rather than KBKDF-CTR-CMAC. - -**Workaround in `compat_shim.c:792`:** `KBKDF_ctr_hmac()` implements the -NIST SP 800-108r1 ยง4.1 counter-mode KDF using wolfSSL's `WOLFSSL_HMAC_CTX` -primitives directly: per-iteration counter as a 32-bit big-endian prefix, -concatenated with the caller-supplied FixedInfo, hashed with HMAC. - -**Fix:** Add a native `wc_KBKDF_ctr_hmac` function (or extend `wc_KDA_KDF_PRF` -to accept a MAC type selector) matching the existing CMAC variant. - ---- - -## API Design Quirks - -### 7. ChaCha20-Poly1305 state machine rejects empty input without a dummy update - -**Affected function:** `wc_ChaCha20Poly1305_Final` - -wolfCrypt's streaming ChaCha20-Poly1305 API (`Init` / `UpdateAad` / -`UpdateData` / `Final`) tracks a state machine (READY โ†’ AAD โ†’ DATA โ†’ DONE). -`Final` requires the state to be AAD or DATA, not READY. When both AAD and -plaintext are empty โ€” a valid case per RFC 8439 โ€” neither `UpdateAad` nor -`UpdateData` is called, the state remains READY, and `Final` returns -`BAD_STATE_E`. - -**Workaround in `wolfcrypt/src/aead.rs:290`:** `UpdateData` is called -unconditionally with a zero-length buffer (using a stack sentinel pointer -because empty Rust slices may have dangling `as_ptr()` values). This -transitions state to DATA without processing any bytes, which is correct per -RFC 8439. - -```rust -// We always call UpdateData even when buffer is empty because -// wolfCrypt's state machine requires at least one UpdateAad or -// UpdateData call before Final (state must be AAD or DATA, not -// READY). -``` - -**Fix:** `wc_ChaCha20Poly1305_Final` should accept READY state as valid when -both AAD length and data length are zero, or the state machine should advance -to DATA implicitly when `Init` is called. - ---- - -### 8. `wc_curve25519_make_pub` requires the caller to clamp the private scalar - -**Affected function:** `wc_curve25519_make_pub` - -RFC 7748 ยง5 specifies that Curve25519 private keys must be clamped (clear bits -0, 1, 2 of byte 0; clear bit 7 of byte 31; set bit 6 of byte 31) before use. -wolfSSL's `wc_curve25519_make_pub` requires that clamping has already been -applied by the caller. It does not clamp internally. Passing an unclamped -scalar produces a wrong public key without returning an error. - -**Workaround in `wolfcrypt/src/ecdh.rs:64`:** The clamping step is performed -explicitly before calling `wc_curve25519_make_pub`: - -```rust -// Clamp the private scalar per RFC 7748 Section 5. -// wolfSSL requires clamped keys for `wc_curve25519_make_pub`. -let mut clamped = *private; -clamp(&mut clamped); -``` - -**Fix:** `wc_curve25519_make_pub` should clamp internally, matching the -behavior of every other Curve25519 implementation. Alternatively, the -documentation should state this requirement explicitly. - ---- - -### 9. Curve25519 blinding requires attaching an RNG to the key before each scalar multiply - -**Affected function:** `wc_curve25519_shared_secret_ex` - -wolfSSL enables Curve25519 scalar-multiplication blinding by default. Blinding -requires an RNG to be attached to the private-key struct via -`wc_curve25519_set_rng()` before any scalar multiply. The DH API -(`wc_curve25519_shared_secret_ex`) does not accept an RNG parameter inline. - -This forces every DH operation to initialise a throwaway RNG, set it on the -key, perform the multiply, and then free the RNG โ€” four extra steps per -operation, one of which (`wc_InitRng`) may touch the entropy source. - -**Workaround in `wolfcrypt/src/ecdh.rs:157`:** - -```rust -// wolfSSL enables Curve25519 blinding by default, which requires -// an RNG attached to the private key for scalar multiplication. -// Create a temporary RNG for this operation. -let mut rng = WC_RNG::zeroed(); -wc_InitRng(&mut rng); -wc_curve25519_set_rng(&mut self.key, &mut rng); -// ... wc_curve25519_shared_secret_ex ... -wc_FreeRng(&mut rng); -``` - -**Fix:** Accept an optional `WC_RNG *` parameter in `wc_curve25519_shared_secret_ex` -(and the make-public equivalent), so callers can pass their existing RNG rather -than constructing a temporary one. - ---- - -### 10. All sign and verify operations require `*mut` pointers for logically read-only operations - -**Affected functions:** `wc_Ed25519Sign`, `wc_Ed25519Verify`, `wc_Ed448Sign`, -`wc_Ed448Verify`, `wc_ecc_sign_hash`, `wc_ecc_verify_hash`, and their RSA, -ML-DSA, and LMS equivalents. - -wolfCrypt's C API takes `*mut key` for operations that are logically read-only, -including signature verification and public-key access. This is a common -pattern in C ("const-correctness debt") but it breaks straightforwardly in Rust: -the `signature::Verifier` trait takes `&self`, and there is no safe way to -obtain `*mut` from `&self` without interior mutability. - -**Workaround in `wolfcrypt/src/`:** Every key type that backs a sign or verify -operation wraps its C key handle in `UnsafeCell`, which allows obtaining `*mut` -from `&self` for FFI calls. The `UnsafeCell` makes the type `!Sync`, which is -correct โ€” wolfCrypt key handles are not safe to share across threads. - -Affected types: `Ed25519SigningKey`, `Ed25519VerifyingKey`, `Ed448SigningKey`, -`Ed448VerifyingKey`, `EcdsaSigningKey`, `EcdsaVerifyingKey`, `RsaPrivateKey`, -`RsaPublicKey`, `MlDsa*SigningKey`, `MlDsa*VerifyingKey`. - -**Fix:** Mark key parameters `const` in the C signatures of verification and -public-key-export functions where the key is not actually modified. This is -routine C const-correctness work. - ---- - -### 11. Ed448 DER functions take `*mut key` but their Ed25519 counterparts take `const` - -**Affected functions:** `wc_Ed448PrivateKeyDecode`, `wc_Ed448PrivateKeyToDer`, -`wc_Ed448KeyToDer` - -The equivalent Ed25519 functions (`wc_Ed25519PrivateKeyDecode`, -`wc_Ed25519PrivateKeyToDer`, `wc_Ed25519KeyToDer`) take `const *` key -pointers where the operation is read-only. The Ed448 versions take `*mut`. -The asymmetry is unexplained; neither set of operations modifies the key. - -**Workaround in `wolfcrypt-rs/src/lib.rs:1949`:** The FFI declarations match -wolfSSL's inconsistency and a comment explains the discrepancy: - -``` -// NOTE: Ed448 DER functions take non-const key pointers, unlike their -// Ed25519 counterparts which take `const`. This matches the upstream -// wolfSSL API โ€” the inconsistency is in wolfSSL itself. -``` - -**Fix:** Change `wc_Ed448PrivateKeyToDer` and `wc_Ed448KeyToDer` to accept -`const wc_ed448_key *` where the key is not modified. - ---- - -### 12. `wc_curve25519_make_pub` has output parameters before input parameters - -**Affected function:** `wc_curve25519_make_pub` - -The signature is: - -```c -int wc_curve25519_make_pub(int pubSz, byte *pub_, int privSz, const byte *priv_); -``` - -Output parameters (`pubSz`, `pub_`) come before input parameters (`privSz`, -`priv_`). The rest of the wolfCrypt API follows the conventional C ordering -of input before output. This is a readability hazard: callers can silently -swap arguments and get no compile error because both size parameters are `int`. - -**Workaround:** The FFI binding in `wolfcrypt-rs/src/lib.rs:1972` carries an -explicit comment: - -``` -// NOTE: wolfSSL signature has output params before input params -``` - -**Fix:** Swap the parameter order in a future wolfSSL major release, or -introduce a correctly-ordered `wc_curve25519_make_public_key` alias. - ---- - -### 13. Opaque struct sizes must be manually over-approximated and verified at build time - -**Affected structs:** `Aes`, `WC_RNG`, `Poly1305`, `ChaCha`, `ChaChaPoly_Aead`, -`ed25519_key`, `curve25519_key`, `ed448_key`, `curve448_key`, `dilithium_key`, -`LmsKey`, `XtsAes`, `Hpke`, and others. - -Rust cannot know the layout of wolfSSL C structs without running bindgen for -every build configuration. bindgen output is fragile โ€” struct sizes change -with `WOLF_CRYPTO_CB` (adds `devId`, `devCtx`, `devKey` fields to key types), -platform word size, and enabled algorithm sets. - -**Workaround in `wolfcrypt-rs`:** Each struct is stack-allocated as a -`[u8; N]` blob with a hand-chosen `N` that is rounded up to a safe -over-approximation. `compat_shim.c:82โ€“206` contains `_Static_assert` checks -that fire at compile time if the actual struct outgrows the allocation: - -```c -_Static_assert(sizeof(Aes) <= 512, - "Aes exceeds WC_AES_ALLOC_SIZE (512) in lib.rs"); -_Static_assert(_Alignof(Aes) <= 16, - "Aes alignment exceeds repr(C, align(16)) in lib.rs"); -``` - -When a wolfSSL upgrade changes a struct's size or alignment, the build fails -with a diagnostic, and only `compat_shim.c` and the corresponding constant in -`lib.rs` need updating. - -**Fix:** wolfSSL could provide stable C accessor functions and heap-allocate -opaque handle types (returning `Aes *` rather than requiring `Aes` in the -caller's stack frame). Alternatively, exporting a `wc_AesSize()` function -that returns `sizeof(Aes)` at runtime would let the Rust side allocate the -right amount without a compile-time constant. diff --git a/wolfssl-src/Cargo.toml b/wolfssl-src/Cargo.toml index bf443ac..c4bcae1 100644 --- a/wolfssl-src/Cargo.toml +++ b/wolfssl-src/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wolfssl-src" authors = ["WolfSSL Inc"] -version = "0.1.2" +version = "0.1.1" edition = "2021" description = "Compile wolfSSL from source for use by wolfcrypt-sys" license = "MIT" @@ -10,45 +10,12 @@ repository = "https://github.com/wolfSSL/wolfssl-rs" readme = "README.md" keywords = ["wolfcrypt", "wolfssl", "fips", "cryptography"] categories = ["cryptography"] -include = [ - "src/**", - "patches/**", - "user_settings*.h", - "riscv_bare_metal_helpers.c", - "README.md", - "Cargo.toml", -] [features] default = [] # Use the minimal bare-metal user_settings_riscv.h instead of the full # user_settings.h. Intended for riscv32imc-unknown-none-elf targets. riscv-bare-metal = [] -# Build wolfSSL with only the CryptoCb callback infrastructure. -# Uses user_settings_cryptocb_only.h: WOLF_CRYPTO_CB + -# WOLF_CRYPTO_CB_ONLY_ECC + WOLF_CRYPTO_CB_ONLY_RSA (per-algorithm disables -# available in this wolfSSL version), algorithm type definitions for -# wc_CryptoInfo struct layouts, bare-metal platform stubs, but NO SP math. -# sp_int.c / sp_c32.c / sp_c64.c / wolfmath.c excluded from compilation. -# SHA/AES/HMAC software stubs are compiled but never called at runtime when -# CryptoCb handles everything. -# Intended for firmware targets where all crypto is dispatched to hardware. -# Takes precedence over riscv-bare-metal if both are set. -cryptocb-only = [] -# Absolute-minimum wolfSSL build: CryptoCb routing layer only. -# Uses user_settings_cryptocb_pure.h: WOLF_CRYPTO_CB + bare-metal platform -# stubs + algorithm type definitions for wc_CryptoInfo struct layouts. -# Removes everything not needed for pure callback dispatch: -# - No OPENSSL_EXTRA / EVP compat layer (removes evp.c, ssl.c) -# - No HAVE_HKDF / WC_KDF_NIST_SP_800_56C (removes kdf.c) -# - No WOLFSSL_ASN_TEMPLATE (removes asn.c) -# - No SHA-224, no TLS extensions, no SNI -# Source reduction vs cryptocb-only: also removes coding.c, cpuid.c, -# signature.c, wc_encrypt.c. -# Intended for wolfcrypt-dpe-hw and firmware builds where wolfSSL is used -# purely as a CryptoCb routing layer with no higher-level API calls. -# Takes precedence over cryptocb-only and riscv-bare-metal if set. -cryptocb-pure = [] [dependencies] cc = { version = "1.2.26", features = ["parallel"] } diff --git a/wolfssl-src/patches/sp_c32.c b/wolfssl-src/patches/sp_c32.c deleted file mode 100644 index 03de506..0000000 --- a/wolfssl-src/patches/sp_c32.c +++ /dev/null @@ -1,51787 +0,0 @@ -/* sp.c - * - * Copyright (C) 2006-2026 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 3 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 - */ - -/* Implementation by Sean Parkinson. */ - -#include - -#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ - defined(WOLFSSL_HAVE_SP_ECC) - -#include -#ifdef NO_INLINE - #include -#else - #define WOLFSSL_MISC_INCLUDED - #include -#endif - -#ifdef RSA_LOW_MEM -#ifndef SP_RSA_PRIVATE_EXP_D -#define SP_RSA_PRIVATE_EXP_D -#endif - -#ifndef WOLFSSL_SP_SMALL -#define WOLFSSL_SP_SMALL -#endif -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) -#undef WOLFSSL_SP_SMALL_STACK -#define WOLFSSL_SP_SMALL_STACK -#endif - -#include - -#ifdef __IAR_SYSTEMS_ICC__ -#define __asm__ asm -#define __volatile__ volatile -#define WOLFSSL_NO_VAR_ASSIGN_REG -#endif /* __IAR_SYSTEMS_ICC__ */ -#ifdef __KEIL__ -#define __asm__ __asm -#define __volatile__ volatile -#endif - -#ifdef WOLFSSL_SP_SMALL_STACK - #define SP_DECL_VAR(TYPE, NAME, CNT) \ - TYPE* NAME = NULL - #define SP_ALLOC_VAR(TYPE, NAME, CNT, HEAP, DT) \ - if (err == MP_OKAY) { \ - (NAME) = (TYPE*)XMALLOC(sizeof(TYPE) * (CNT), (HEAP), DT); \ - if ((NAME) == NULL) { \ - err = MEMORY_E; \ - } \ - } - - #define SP_VAR_OK(NAME) ((NAME) != NULL) - - #define SP_FREE_VAR(NAME, HEAP, DT) \ - XFREE(NAME, (HEAP), DT) - #define SP_ZEROFREE_VAR(TYPE, NAME, CNT, HEAP, DT) \ - do { \ - if ((NAME) != NULL) { \ - ForceZero(NAME, sizeof(TYPE) * (CNT)); \ - } \ - SP_FREE_VAR(NAME, HEAP, DT); \ - } while (0) - #define SP_ZEROFREE_VAR_ALT(TYPE, NAME, FZ_NAME, CNT, HEAP, DT) \ - do { \ - if ((FZ_NAME) != NULL) { \ - ForceZero(FZ_NAME, sizeof(TYPE) * (CNT)); \ - } \ - SP_FREE_VAR(NAME, HEAP, DT); \ - } while (0) -#else - #define SP_DECL_VAR(TYPE, NAME, CNT) \ - TYPE NAME[CNT] - #define SP_ALLOC_VAR(TYPE, NAME, CNT, HEAP, DT) \ - WC_DO_NOTHING - #define SP_VAR_OK(NAME) (1) - #define SP_FREE_VAR(NAME, HEAP, DT) \ - WC_DO_NOTHING - #define SP_ZEROFREE_VAR(TYPE, NAME, CNT, HEAP, DT) \ - do { \ - if ((NAME) != NULL) { \ - ForceZero(NAME, sizeof(TYPE) * (CNT)); \ - } \ - } while (0) - #define SP_ZEROFREE_VAR_ALT(TYPE, NAME, FZ_NAME, CNT, HEAP, DT) \ - do { \ - if ((FZ_NAME) != NULL) { \ - ForceZero(FZ_NAME, sizeof(TYPE) * (CNT)); \ - } \ - } while (0) -#endif - -#ifndef WOLFSSL_SP_ASM -#if SP_WORD_SIZE == 32 -#ifdef SP_NO_MUL_INSTRUCTION -sp_uint64 __muldi3(sp_uint64 a, sp_uint64 b); -sp_uint64 __muldi3(sp_uint64 a, sp_uint64 b) -{ - sp_uint64 r; - sp_uint64 am[16]; - - /* if b is negative, convert it to positive and negate a. */ - r = 0 - (b >> 63); - a = a ^ r; - b = b ^ r; - a -= r; - b -= r; - -#if defined(WOLFSSL_SP_SMALL) - int i; - - am[0] = 0; - for (i = 1; i < 16; i++) { - am[i] = am[i-1] + a; - } - - r = am[(b >> 28) & 0xf]; - for (i = 24; i >= 0; i -= 4) { - r <<= 4; - r += am[(b >> i) & 0xf]; - } -#else - am[ 0] = 0; - am[ 1] = a; - am[ 2] = a << 1; - am[ 3] = am[ 2] + a; - am[ 4] = a << 2; - am[ 5] = am[ 4] + a; - am[ 6] = am[ 5] + a; - am[ 7] = am[ 6] + a; - am[ 8] = a << 3; - am[ 9] = am[ 8] + a; - am[10] = am[ 9] + a; - am[11] = am[10] + a; - am[12] = am[11] + a; - am[13] = am[12] + a; - am[14] = am[13] + a; - am[15] = am[14] + a; - - r = am[(b >> 28) & 0xf]; - r <<= 4; - r += am[(b >> 24) & 0xf]; - r <<= 4; - r += am[(b >> 20) & 0xf]; - r <<= 4; - r += am[(b >> 16) & 0xf]; - r <<= 4; - r += am[(b >> 12) & 0xf]; - r <<= 4; - r += am[(b >> 8) & 0xf]; - r <<= 4; - r += am[(b >> 4) & 0xf]; - r <<= 4; - r += am[(b >> 0) & 0xf]; -#endif - - return r; -} -#endif /* SP_NO_MUL_INSTRUCTION */ -#define SP_PRINT_NUM(var, name, total, words, bits) \ - do { \ - int ii; \ - byte nb[((bits) + 7) / 8]; \ - sp_digit _s[words]; \ - XMEMCPY(_s, var, sizeof(_s)); \ - sp_##total##_norm_##words(_s); \ - sp_##total##_to_bin_##words(_s, nb); \ - fprintf(stderr, name "=0x"); \ - for (ii=0; ii<((bits) + 7) / 8; ii++) \ - fprintf(stderr, "%02x", nb[ii]); \ - fprintf(stderr, "\n"); \ - } while (0) - -#define SP_PRINT_VAL(var, name) \ - fprintf(stderr, name "=0x" SP_PRINT_FMT "\n", var) - -#define SP_PRINT_INT(var, name) \ - fprintf(stderr, name "=%d\n", var) - -#if defined(WOLFSSL_SP_SMALL) && \ - defined(WOLFSSL_HAVE_SP_ECC) && (!defined(WOLFSSL_SP_NO_256) || \ - defined(WOLFSSL_SP_384) || defined(WOLFSSL_SP_521) || \ - defined(WOLFSSL_SP_1024)) - #define NEED_ADDR_MASK -#endif -#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) - #if !defined(WC_NO_CACHE_RESISTANT) && \ - (defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) - #define NEED_ADDR_MASK - #endif -#endif - -#ifdef NEED_ADDR_MASK -/* Mask for address to obfuscate which of the two address will be used. */ -static const size_t addr_mask[2] = { 0, (size_t)-1 }; -#endif - -#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || \ - !defined(WOLFSSL_SP_SMALL)) - #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC) -#endif - -#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) -#ifndef WOLFSSL_SP_NO_2048 -/* 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_2048_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 >= 21U) { - r[j] &= 0x1fffffff; - s = 29U - 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; - } -} - -/* 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_2048_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 29 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 28); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 28); - } -#elif DIGIT_BIT > 29 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x1fffffff; - s = 29U - 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 + 29U) <= (word32)DIGIT_BIT) { - s += 29U; - r[j] &= 0x1fffffff; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 29) { - r[j] &= 0x1fffffff; - if (j + 1 >= size) { - break; - } - s = 29 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 256 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_2048_to_bin_72(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<71; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - j = 2055 / 8 - 1; - a[j] = 0; - for (i=0; i<71 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 29) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 29); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && (!defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(WOLFSSL_SP_SMALL))) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_36(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 35; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - int i; - for (i = 0; i < 32; i += 8) { - a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff; - a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff; - a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff; - a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff; - a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff; - a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff; - a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff; - a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff; - } - a[33] += a[32] >> 29; a[32] &= 0x1fffffff; - a[34] += a[33] >> 29; a[33] &= 0x1fffffff; - a[35] += a[34] >> 29; a[34] &= 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && (!WOLFSSL_RSA_PUBLIC_ONLY || !WOLFSSL_SP_SMALL)) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_72(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 71; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - int i; - for (i = 0; i < 64; i += 8) { - a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff; - a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff; - a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff; - a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff; - a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff; - a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff; - a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff; - a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff; - } - a[65] += a[64] >> 29; a[64] &= 0x1fffffff; - a[66] += a[65] >> 29; a[65] &= 0x1fffffff; - a[67] += a[66] >> 29; a[66] &= 0x1fffffff; - a[68] += a[67] >> 29; a[67] &= 0x1fffffff; - a[69] += a[68] >> 29; a[68] &= 0x1fffffff; - a[70] += a[69] >> 29; a[69] &= 0x1fffffff; - a[71] += a[70] >> 29; a[70] &= 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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_2048_mul_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_uint64 t0; - sp_uint64 t1; - sp_digit t[12]; - - t0 = ((sp_uint64)a[ 0]) * b[ 0]; - t1 = ((sp_uint64)a[ 0]) * b[ 1] - + ((sp_uint64)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 0]) * b[ 2] - + ((sp_uint64)a[ 1]) * b[ 1] - + ((sp_uint64)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 0]) * b[ 3] - + ((sp_uint64)a[ 1]) * b[ 2] - + ((sp_uint64)a[ 2]) * b[ 1] - + ((sp_uint64)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 0]) * b[ 4] - + ((sp_uint64)a[ 1]) * b[ 3] - + ((sp_uint64)a[ 2]) * b[ 2] - + ((sp_uint64)a[ 3]) * b[ 1] - + ((sp_uint64)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 0]) * b[ 5] - + ((sp_uint64)a[ 1]) * b[ 4] - + ((sp_uint64)a[ 2]) * b[ 3] - + ((sp_uint64)a[ 3]) * b[ 2] - + ((sp_uint64)a[ 4]) * b[ 1] - + ((sp_uint64)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 0]) * b[ 6] - + ((sp_uint64)a[ 1]) * b[ 5] - + ((sp_uint64)a[ 2]) * b[ 4] - + ((sp_uint64)a[ 3]) * b[ 3] - + ((sp_uint64)a[ 4]) * b[ 2] - + ((sp_uint64)a[ 5]) * b[ 1] - + ((sp_uint64)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 0]) * b[ 7] - + ((sp_uint64)a[ 1]) * b[ 6] - + ((sp_uint64)a[ 2]) * b[ 5] - + ((sp_uint64)a[ 3]) * b[ 4] - + ((sp_uint64)a[ 4]) * b[ 3] - + ((sp_uint64)a[ 5]) * b[ 2] - + ((sp_uint64)a[ 6]) * b[ 1] - + ((sp_uint64)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 0]) * b[ 8] - + ((sp_uint64)a[ 1]) * b[ 7] - + ((sp_uint64)a[ 2]) * b[ 6] - + ((sp_uint64)a[ 3]) * b[ 5] - + ((sp_uint64)a[ 4]) * b[ 4] - + ((sp_uint64)a[ 5]) * b[ 3] - + ((sp_uint64)a[ 6]) * b[ 2] - + ((sp_uint64)a[ 7]) * b[ 1] - + ((sp_uint64)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 0]) * b[ 9] - + ((sp_uint64)a[ 1]) * b[ 8] - + ((sp_uint64)a[ 2]) * b[ 7] - + ((sp_uint64)a[ 3]) * b[ 6] - + ((sp_uint64)a[ 4]) * b[ 5] - + ((sp_uint64)a[ 5]) * b[ 4] - + ((sp_uint64)a[ 6]) * b[ 3] - + ((sp_uint64)a[ 7]) * b[ 2] - + ((sp_uint64)a[ 8]) * b[ 1] - + ((sp_uint64)a[ 9]) * b[ 0]; - t[ 8] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 0]) * b[10] - + ((sp_uint64)a[ 1]) * b[ 9] - + ((sp_uint64)a[ 2]) * b[ 8] - + ((sp_uint64)a[ 3]) * b[ 7] - + ((sp_uint64)a[ 4]) * b[ 6] - + ((sp_uint64)a[ 5]) * b[ 5] - + ((sp_uint64)a[ 6]) * b[ 4] - + ((sp_uint64)a[ 7]) * b[ 3] - + ((sp_uint64)a[ 8]) * b[ 2] - + ((sp_uint64)a[ 9]) * b[ 1] - + ((sp_uint64)a[10]) * b[ 0]; - t[ 9] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 0]) * b[11] - + ((sp_uint64)a[ 1]) * b[10] - + ((sp_uint64)a[ 2]) * b[ 9] - + ((sp_uint64)a[ 3]) * b[ 8] - + ((sp_uint64)a[ 4]) * b[ 7] - + ((sp_uint64)a[ 5]) * b[ 6] - + ((sp_uint64)a[ 6]) * b[ 5] - + ((sp_uint64)a[ 7]) * b[ 4] - + ((sp_uint64)a[ 8]) * b[ 3] - + ((sp_uint64)a[ 9]) * b[ 2] - + ((sp_uint64)a[10]) * b[ 1] - + ((sp_uint64)a[11]) * b[ 0]; - t[10] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 1]) * b[11] - + ((sp_uint64)a[ 2]) * b[10] - + ((sp_uint64)a[ 3]) * b[ 9] - + ((sp_uint64)a[ 4]) * b[ 8] - + ((sp_uint64)a[ 5]) * b[ 7] - + ((sp_uint64)a[ 6]) * b[ 6] - + ((sp_uint64)a[ 7]) * b[ 5] - + ((sp_uint64)a[ 8]) * b[ 4] - + ((sp_uint64)a[ 9]) * b[ 3] - + ((sp_uint64)a[10]) * b[ 2] - + ((sp_uint64)a[11]) * b[ 1]; - t[11] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 2]) * b[11] - + ((sp_uint64)a[ 3]) * b[10] - + ((sp_uint64)a[ 4]) * b[ 9] - + ((sp_uint64)a[ 5]) * b[ 8] - + ((sp_uint64)a[ 6]) * b[ 7] - + ((sp_uint64)a[ 7]) * b[ 6] - + ((sp_uint64)a[ 8]) * b[ 5] - + ((sp_uint64)a[ 9]) * b[ 4] - + ((sp_uint64)a[10]) * b[ 3] - + ((sp_uint64)a[11]) * b[ 2]; - r[12] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 3]) * b[11] - + ((sp_uint64)a[ 4]) * b[10] - + ((sp_uint64)a[ 5]) * b[ 9] - + ((sp_uint64)a[ 6]) * b[ 8] - + ((sp_uint64)a[ 7]) * b[ 7] - + ((sp_uint64)a[ 8]) * b[ 6] - + ((sp_uint64)a[ 9]) * b[ 5] - + ((sp_uint64)a[10]) * b[ 4] - + ((sp_uint64)a[11]) * b[ 3]; - r[13] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 4]) * b[11] - + ((sp_uint64)a[ 5]) * b[10] - + ((sp_uint64)a[ 6]) * b[ 9] - + ((sp_uint64)a[ 7]) * b[ 8] - + ((sp_uint64)a[ 8]) * b[ 7] - + ((sp_uint64)a[ 9]) * b[ 6] - + ((sp_uint64)a[10]) * b[ 5] - + ((sp_uint64)a[11]) * b[ 4]; - r[14] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 5]) * b[11] - + ((sp_uint64)a[ 6]) * b[10] - + ((sp_uint64)a[ 7]) * b[ 9] - + ((sp_uint64)a[ 8]) * b[ 8] - + ((sp_uint64)a[ 9]) * b[ 7] - + ((sp_uint64)a[10]) * b[ 6] - + ((sp_uint64)a[11]) * b[ 5]; - r[15] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 6]) * b[11] - + ((sp_uint64)a[ 7]) * b[10] - + ((sp_uint64)a[ 8]) * b[ 9] - + ((sp_uint64)a[ 9]) * b[ 8] - + ((sp_uint64)a[10]) * b[ 7] - + ((sp_uint64)a[11]) * b[ 6]; - r[16] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 7]) * b[11] - + ((sp_uint64)a[ 8]) * b[10] - + ((sp_uint64)a[ 9]) * b[ 9] - + ((sp_uint64)a[10]) * b[ 8] - + ((sp_uint64)a[11]) * b[ 7]; - r[17] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[ 8]) * b[11] - + ((sp_uint64)a[ 9]) * b[10] - + ((sp_uint64)a[10]) * b[ 9] - + ((sp_uint64)a[11]) * b[ 8]; - r[18] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[ 9]) * b[11] - + ((sp_uint64)a[10]) * b[10] - + ((sp_uint64)a[11]) * b[ 9]; - r[19] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_uint64)a[10]) * b[11] - + ((sp_uint64)a[11]) * b[10]; - r[20] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[11]) * b[11]; - r[21] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - r[22] = (sp_digit)(t0 & 0x1fffffff); - r[23] = (sp_digit)(t0 >> 29); - XMEMCPY(r, t, sizeof(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. - */ -SP_NOINLINE static int sp_2048_add_12(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]; - - 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_2048_sub_24(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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]; - } - - 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_2048_add_24(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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]; - } - - return 0; -} - -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_12(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 11; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - a[1] += a[0] >> 29; a[0] &= 0x1fffffff; - a[2] += a[1] >> 29; a[1] &= 0x1fffffff; - a[3] += a[2] >> 29; a[2] &= 0x1fffffff; - a[4] += a[3] >> 29; a[3] &= 0x1fffffff; - a[5] += a[4] >> 29; a[4] &= 0x1fffffff; - a[6] += a[5] >> 29; a[5] &= 0x1fffffff; - a[7] += a[6] >> 29; a[6] &= 0x1fffffff; - a[8] += a[7] >> 29; a[7] &= 0x1fffffff; - a[9] += a[8] >> 29; a[8] &= 0x1fffffff; - a[10] += a[9] >> 29; a[9] &= 0x1fffffff; - a[11] += a[10] >> 29; a[10] &= 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_24(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 23; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - int i; - for (i = 0; i < 16; i += 8) { - a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff; - a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff; - a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff; - a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff; - a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff; - a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff; - a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff; - a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff; - } - a[17] += a[16] >> 29; a[16] &= 0x1fffffff; - a[18] += a[17] >> 29; a[17] &= 0x1fffffff; - a[19] += a[18] >> 29; a[18] &= 0x1fffffff; - a[20] += a[19] >> 29; a[19] &= 0x1fffffff; - a[21] += a[20] >> 29; a[20] &= 0x1fffffff; - a[22] += a[21] >> 29; a[21] &= 0x1fffffff; - a[23] += a[22] >> 29; a[22] &= 0x1fffffff; -#endif /* 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_2048_mul_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit p0[24]; - sp_digit p1[24]; - sp_digit p2[24]; - sp_digit p3[24]; - sp_digit p4[24]; - sp_digit p5[24]; - sp_digit t0[24]; - sp_digit t1[24]; - sp_digit t2[24]; - sp_digit a0[12]; - sp_digit a1[12]; - sp_digit a2[12]; - sp_digit b0[12]; - sp_digit b1[12]; - sp_digit b2[12]; - (void)sp_2048_add_12(a0, a, &a[12]); - sp_2048_norm_12(a0); - (void)sp_2048_add_12(b0, b, &b[12]); - sp_2048_norm_12(b0); - (void)sp_2048_add_12(a1, &a[12], &a[24]); - sp_2048_norm_12(a1); - (void)sp_2048_add_12(b1, &b[12], &b[24]); - sp_2048_norm_12(b1); - (void)sp_2048_add_12(a2, a0, &a[24]); - sp_2048_norm_12(a1); - (void)sp_2048_add_12(b2, b0, &b[24]); - sp_2048_norm_12(b2); - sp_2048_mul_12(p0, a, b); - sp_2048_mul_12(p2, &a[12], &b[12]); - sp_2048_mul_12(p4, &a[24], &b[24]); - sp_2048_mul_12(p1, a0, b0); - sp_2048_mul_12(p3, a1, b1); - sp_2048_mul_12(p5, a2, b2); - XMEMSET(r, 0, sizeof(*r)*2U*36U); - (void)sp_2048_sub_24(t0, p3, p2); - (void)sp_2048_sub_24(t1, p1, p2); - (void)sp_2048_sub_24(t2, p5, t0); - (void)sp_2048_sub_24(t2, t2, t1); - sp_2048_norm_24(t2); - (void)sp_2048_sub_24(t0, t0, p4); - sp_2048_norm_24(t0); - (void)sp_2048_sub_24(t1, t1, p0); - sp_2048_norm_24(t1); - (void)sp_2048_add_24(r, r, p0); - (void)sp_2048_add_24(&r[12], &r[12], t1); - (void)sp_2048_add_24(&r[24], &r[24], t2); - (void)sp_2048_add_24(&r[36], &r[36], t0); - (void)sp_2048_add_24(&r[48], &r[48], p4); - sp_2048_norm_72(r); -} - -/* 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 < 32; 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[32] = a[32] + b[32]; - r[33] = a[33] + b[33]; - r[34] = a[34] + b[34]; - r[35] = a[35] + b[35]; - - 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_2048_add_72(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 72; 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]; - } - - 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_2048_sub_72(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 72; 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]; - } - - return 0; -} - -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_144(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 143; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - int i; - for (i = 0; i < 136; i += 8) { - a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff; - a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff; - a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff; - a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff; - a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff; - a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff; - a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff; - a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff; - } - a[137] += a[136] >> 29; a[136] &= 0x1fffffff; - a[138] += a[137] >> 29; a[137] &= 0x1fffffff; - a[139] += a[138] >> 29; a[138] &= 0x1fffffff; - a[140] += a[139] >> 29; a[139] &= 0x1fffffff; - a[141] += a[140] >> 29; a[140] &= 0x1fffffff; - a[142] += a[141] >> 29; a[141] &= 0x1fffffff; - a[143] += a[142] >> 29; a[142] &= 0x1fffffff; -#endif /* 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_2048_mul_72(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[72]; - sp_digit* a1 = z1; - sp_digit b1[36]; - sp_digit* z2 = r + 72; - (void)sp_2048_add_36(a1, a, &a[36]); - sp_2048_norm_36(a1); - (void)sp_2048_add_36(b1, b, &b[36]); - sp_2048_norm_36(b1); - sp_2048_mul_36(z2, &a[36], &b[36]); - sp_2048_mul_36(z0, a, b); - sp_2048_mul_36(z1, a1, b1); - (void)sp_2048_sub_72(z1, z1, z2); - (void)sp_2048_sub_72(z1, z1, z0); - (void)sp_2048_add_72(r + 36, r + 36, z1); - sp_2048_norm_144(r); -} - -/* 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_2048_sqr_12(sp_digit* r, const sp_digit* a) -{ - sp_uint64 t0; - sp_uint64 t1; - sp_digit t[12]; - - t0 = ((sp_uint64)a[ 0]) * a[ 0]; - t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 0]) * a[ 2]) * 2 - + ((sp_uint64)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 0]) * a[ 3] - + ((sp_uint64)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 0]) * a[ 4] - + ((sp_uint64)a[ 1]) * a[ 3]) * 2 - + ((sp_uint64)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 0]) * a[ 5] - + ((sp_uint64)a[ 1]) * a[ 4] - + ((sp_uint64)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 0]) * a[ 6] - + ((sp_uint64)a[ 1]) * a[ 5] - + ((sp_uint64)a[ 2]) * a[ 4]) * 2 - + ((sp_uint64)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 0]) * a[ 7] - + ((sp_uint64)a[ 1]) * a[ 6] - + ((sp_uint64)a[ 2]) * a[ 5] - + ((sp_uint64)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 0]) * a[ 8] - + ((sp_uint64)a[ 1]) * a[ 7] - + ((sp_uint64)a[ 2]) * a[ 6] - + ((sp_uint64)a[ 3]) * a[ 5]) * 2 - + ((sp_uint64)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 0]) * a[ 9] - + ((sp_uint64)a[ 1]) * a[ 8] - + ((sp_uint64)a[ 2]) * a[ 7] - + ((sp_uint64)a[ 3]) * a[ 6] - + ((sp_uint64)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 0]) * a[10] - + ((sp_uint64)a[ 1]) * a[ 9] - + ((sp_uint64)a[ 2]) * a[ 8] - + ((sp_uint64)a[ 3]) * a[ 7] - + ((sp_uint64)a[ 4]) * a[ 6]) * 2 - + ((sp_uint64)a[ 5]) * a[ 5]; - t[ 9] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 0]) * a[11] - + ((sp_uint64)a[ 1]) * a[10] - + ((sp_uint64)a[ 2]) * a[ 9] - + ((sp_uint64)a[ 3]) * a[ 8] - + ((sp_uint64)a[ 4]) * a[ 7] - + ((sp_uint64)a[ 5]) * a[ 6]) * 2; - t[10] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 1]) * a[11] - + ((sp_uint64)a[ 2]) * a[10] - + ((sp_uint64)a[ 3]) * a[ 9] - + ((sp_uint64)a[ 4]) * a[ 8] - + ((sp_uint64)a[ 5]) * a[ 7]) * 2 - + ((sp_uint64)a[ 6]) * a[ 6]; - t[11] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 2]) * a[11] - + ((sp_uint64)a[ 3]) * a[10] - + ((sp_uint64)a[ 4]) * a[ 9] - + ((sp_uint64)a[ 5]) * a[ 8] - + ((sp_uint64)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 3]) * a[11] - + ((sp_uint64)a[ 4]) * a[10] - + ((sp_uint64)a[ 5]) * a[ 9] - + ((sp_uint64)a[ 6]) * a[ 8]) * 2 - + ((sp_uint64)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 4]) * a[11] - + ((sp_uint64)a[ 5]) * a[10] - + ((sp_uint64)a[ 6]) * a[ 9] - + ((sp_uint64)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 5]) * a[11] - + ((sp_uint64)a[ 6]) * a[10] - + ((sp_uint64)a[ 7]) * a[ 9]) * 2 - + ((sp_uint64)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 6]) * a[11] - + ((sp_uint64)a[ 7]) * a[10] - + ((sp_uint64)a[ 8]) * a[ 9]) * 2; - r[16] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 7]) * a[11] - + ((sp_uint64)a[ 8]) * a[10]) * 2 - + ((sp_uint64)a[ 9]) * a[ 9]; - r[17] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[ 8]) * a[11] - + ((sp_uint64)a[ 9]) * a[10]) * 2; - r[18] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_uint64)a[ 9]) * a[11]) * 2 - + ((sp_uint64)a[10]) * a[10]; - r[19] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_uint64)a[10]) * a[11]) * 2; - r[20] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_uint64)a[11]) * a[11]; - r[21] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - r[22] = (sp_digit)(t0 & 0x1fffffff); - r[23] = (sp_digit)(t0 >> 29); - XMEMCPY(r, t, sizeof(t)); -} - -/* Square a into r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a) -{ - sp_digit p0[24]; - sp_digit p1[24]; - sp_digit p2[24]; - sp_digit p3[24]; - sp_digit p4[24]; - sp_digit p5[24]; - sp_digit t0[24]; - sp_digit t1[24]; - sp_digit t2[24]; - sp_digit a0[12]; - sp_digit a1[12]; - sp_digit a2[12]; - (void)sp_2048_add_12(a0, a, &a[12]); - sp_2048_norm_12(a0); - (void)sp_2048_add_12(a1, &a[12], &a[24]); - sp_2048_norm_12(a1); - (void)sp_2048_add_12(a2, a0, &a[24]); - sp_2048_norm_12(a2); - sp_2048_sqr_12(p0, a); - sp_2048_sqr_12(p2, &a[12]); - sp_2048_sqr_12(p4, &a[24]); - sp_2048_sqr_12(p1, a0); - sp_2048_sqr_12(p3, a1); - sp_2048_sqr_12(p5, a2); - XMEMSET(r, 0, sizeof(*r)*2U*36U); - (void)sp_2048_sub_24(t0, p3, p2); - (void)sp_2048_sub_24(t1, p1, p2); - (void)sp_2048_sub_24(t2, p5, t0); - (void)sp_2048_sub_24(t2, t2, t1); - sp_2048_norm_24(t2); - (void)sp_2048_sub_24(t0, t0, p4); - sp_2048_norm_24(t0); - (void)sp_2048_sub_24(t1, t1, p0); - sp_2048_norm_24(t1); - (void)sp_2048_add_24(r, r, p0); - (void)sp_2048_add_24(&r[12], &r[12], t1); - (void)sp_2048_add_24(&r[24], &r[24], t2); - (void)sp_2048_add_24(&r[36], &r[36], t0); - (void)sp_2048_add_24(&r[48], &r[48], p4); - sp_2048_norm_72(r); -} - -/* 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_2048_sqr_72(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[72]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 72; - (void)sp_2048_add_36(a1, a, &a[36]); - sp_2048_norm_36(a1); - sp_2048_sqr_36(z2, &a[36]); - sp_2048_sqr_36(z0, a); - sp_2048_sqr_36(z1, a1); - (void)sp_2048_sub_72(z1, z1, z2); - (void)sp_2048_sub_72(z1, z1, z0); - (void)sp_2048_add_72(r + 36, r + 36, z1); - sp_2048_norm_144(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. - */ -SP_NOINLINE static int sp_2048_add_72(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 72; i++) { - r[i] = a[i] + b[i]; - } - - 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_2048_sub_72(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 72; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ -#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. - */ -SP_NOINLINE static void sp_2048_mul_72(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[71]) * b[71]; - r[143] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 141; k >= 0; k--) { - if (k >= 72) { - i = k - 71; - imax = 71; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - lo &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - } - r[0] = (sp_digit)c; -} - -/* 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_2048_sqr_72(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[71]) * a[71]; - r[143] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 141; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 71) { - imax = k; - } - else { - imax = 71; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint64 hi; - - hi = c >> 29; - c &= 0x1fffffff; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 29; - c &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(hi >> 29); - r[k + 1] = (sp_digit)(hi & 0x1fffffff); - c <<= 29; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - } - r[0] = (sp_digit)(c >> 29); -} - -#endif /* WOLFSSL_SP_SMALL */ -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#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_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 /* 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_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; -} - -#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_2048_sub_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] - b[32]; - r[33] = a[33] - b[33]; - r[34] = a[34] - b[34]; - r[35] = a[35] - b[35]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ -#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. - */ -SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[35]) * b[35]; - r[71] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 69; k >= 0; k--) { - if (k >= 36) { - i = k - 35; - imax = 35; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - lo &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - } - r[0] = (sp_digit)c; -} - -/* 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_2048_sqr_36(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[35]) * a[35]; - r[71] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 69; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 35) { - imax = k; - } - else { - imax = 35; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint64 hi; - - hi = c >> 29; - c &= 0x1fffffff; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 29; - c &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(hi >> 29); - r[k + 1] = (sp_digit)(hi & 0x1fffffff); - c <<= 29; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - } - r[0] = (sp_digit)(c >> 29); -} - -#endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ - -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x &= 0x1fffffff; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 29) - x; -} - -/* 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_2048_mul_d_72(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 72; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[72] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 72; 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 & 0x1fffffff); - t >>= 29; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 3] = (sp_digit)t2; - } - r[72] = (sp_digit)(t & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_2048_mont_norm_36(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=0; i<35; i++) { - r[i] = 0x1fffffff; - } -#else - int i; - - for (i = 0; i < 32; i += 8) { - r[i + 0] = 0x1fffffff; - r[i + 1] = 0x1fffffff; - r[i + 2] = 0x1fffffff; - r[i + 3] = 0x1fffffff; - r[i + 4] = 0x1fffffff; - r[i + 5] = 0x1fffffff; - r[i + 6] = 0x1fffffff; - r[i + 7] = 0x1fffffff; - } - r[32] = 0x1fffffff; - r[33] = 0x1fffffff; - r[34] = 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ - r[35] = 0x1ffL; - - /* r = (2^n - 1) mod n */ - (void)sp_2048_sub_36(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_2048_cmp_36(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=35; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } -#else - int i; - - r |= (a[35] - b[35]) & (0 - (sp_digit)1); - r |= (a[34] - b[34]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[33] - b[33]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[32] - b[32]) & ~(((sp_digit)0 - r) >> 28); - for (i = 24; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 28); - } -#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_2048_cond_sub_36(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 < 36; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - int i; - - for (i = 0; i < 32; 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[32] = a[32] - (b[32] & m); - r[33] = a[33] - (b[33] & m); - r[34] = a[34] - (b[34] & m); - r[35] = a[35] - (b[35] & 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_2048_mul_add_36(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 36; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[36] += (sp_digit)t; -#else -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 32; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[32]) + r[32]; - t[1] = (tb * a[33]) + r[33]; - t[2] = (tb * a[34]) + r[34]; - t[3] = (tb * a[35]) + r[35]; - r[32] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[33] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[34] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[35] = (sp_digit)(t[3] & 0x1fffffff); - r[36] += (sp_digit)(t[3] >> 29); -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 32; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[4] += t[3] >> 29; - r[i+4] = (sp_digit)(t[4] & 0x1fffffff); - t[5] += t[4] >> 29; - r[i+5] = (sp_digit)(t[5] & 0x1fffffff); - t[6] += t[5] >> 29; - r[i+6] = (sp_digit)(t[6] & 0x1fffffff); - t[7] += t[6] >> 29; - r[i+7] = (sp_digit)(t[7] & 0x1fffffff); - t[0] = t[7] >> 29; - } - t[0] += (tb * a[32]) + r[32]; - t[1] = (tb * a[33]) + r[33]; - t[2] = (tb * a[34]) + r[34]; - t[3] = (tb * a[35]) + r[35]; - r[32] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[33] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[34] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[35] = (sp_digit)(t[3] & 0x1fffffff); - r[36] += (sp_digit)(t[3] >> 29); -#endif /* WOLFSSL_SP_SMALL */ -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* 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_2048_mont_shift_36(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_int64 n = a[35] >> 9; - n += ((sp_int64)a[36]) << 20; - - for (i = 0; i < 35; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[37 + i]) << 20; - } - r[35] = (sp_digit)n; -#else - int i; - sp_int64 n = a[35] >> 9; - n += ((sp_int64)a[36]) << 20; - for (i = 0; i < 32; i += 8) { - r[i + 0] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 37]) << 20; - r[i + 1] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 38]) << 20; - r[i + 2] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 39]) << 20; - r[i + 3] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 40]) << 20; - r[i + 4] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 41]) << 20; - r[i + 5] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 42]) << 20; - r[i + 6] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 43]) << 20; - r[i + 7] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 44]) << 20; - } - r[32] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[69]) << 20; - r[33] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[70]) << 20; - r[34] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[71]) << 20; - r[35] = (sp_digit)n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[36], 0, sizeof(*r) * 36U); -} - -/* 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. - */ -static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_2048_norm_36(a + 36); - - for (i=0; i<35; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1ffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - sp_2048_mont_shift_36(a, a); - over = a[35] - m[35]; - sp_2048_cond_sub_36(a, a, m, ~((over - 1) >> 31)); - sp_2048_norm_36(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_2048_mul_d_36(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 36; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[36] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 36; 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 & 0x1fffffff); - t >>= 29; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 3] = (sp_digit)t2; - } - r[36] = (sp_digit)(t & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ -} - -#ifdef 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_2048_cond_add_36(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 36; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_2048_cond_add_36(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] + (b[32] & m); - r[33] = a[33] + (b[33] & m); - r[34] = a[34] + (b[34] & m); - r[35] = a[35] + (b[35] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_2048_rshift_36(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<35; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } -#else - for (i=0; i<32; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (29 - n)) & 0x1fffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (29 - n)) & 0x1fffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (29 - n)) & 0x1fffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (29 - n)) & 0x1fffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (29 - n)) & 0x1fffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (29 - n)) & 0x1fffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (29 - n)) & 0x1fffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (29 - n)) & 0x1fffffff); - } - r[32] = (a[32] >> n) | (sp_digit)((a[33] << (29 - n)) & 0x1fffffff); - r[33] = (a[33] >> n) | (sp_digit)((a[34] << (29 - n)) & 0x1fffffff); - r[34] = (a[34] >> n) | (sp_digit)((a[35] << (29 - n)) & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[35] = a[35] >> n; -} - -static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 29) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 29); - sp_digit t0 = (sp_digit)(d & 0x1fffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 27; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 28) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 29); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 14) + 1; - - t = (sp_digit)(d >> 28); - t = (t / dv) << 14; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 1); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_2048_word_div_word_36(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_36(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 36 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 36 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 72 + 1; - sd = t2 + 36 + 1; - - sp_2048_mul_d_36(sd, d, (sp_digit)1 << 20); - sp_2048_mul_d_72(t1, a, (sp_digit)1 << 20); - dv = sd[35]; - t1[36 + 36] += t1[36 + 36 - 1] >> 29; - t1[36 + 36 - 1] &= 0x1fffffff; - for (i=36; i>=0; i--) { - r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv); - - sp_2048_mul_d_36(t2, sd, r1); - (void)sp_2048_sub_36(&t1[i], &t1[i], t2); - sp_2048_norm_36(&t1[i]); - t1[36 + i] -= t2[36]; - t1[36 + i] += t1[36 + i - 1] >> 29; - t1[36 + i - 1] &= 0x1fffffff; - r1 = sp_2048_div_word_36(-t1[36 + i], -t1[36 + i - 1], dv); - r1 -= t1[36 + i]; - sp_2048_mul_d_36(t2, sd, r1); - (void)sp_2048_add_36(&t1[i], &t1[i], t2); - t1[36 + i] += t1[36 + i - 1] >> 29; - t1[36 + i - 1] &= 0x1fffffff; - } - t1[36 - 1] += t1[36 - 2] >> 29; - t1[36 - 2] &= 0x1fffffff; - r1 = sp_2048_word_div_word_36(t1[36 - 1], dv); - - sp_2048_mul_d_36(t2, sd, r1); - sp_2048_sub_36(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 72U); - for (i=0; i<35; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - sp_2048_cond_add_36(r, r, sd, r[35] >> 31); - - sp_2048_norm_36(r); - sp_2048_rshift_36(r, r, 20); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_2048_mod_36(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_2048_div_36(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 72); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 72, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 36 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 36U * 2U); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_36(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 36U); - } - } - if (err == MP_OKAY) { - sp_2048_mul_36(t[1], t[1], norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 36 * 2); - sp_2048_mont_sqr_36(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 36 * 2); - } - - sp_2048_mont_reduce_36(t[0], m, mp); - n = sp_2048_cmp_36(t[0], m); - sp_2048_cond_sub_36(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 72); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 72, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 36 * 2); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_36(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_36(t[1], t[1], norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - else { - sp_2048_mul_36(t[1], a, norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 36 * 2); - sp_2048_mont_sqr_36(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 36 * 2); - } - - sp_2048_mont_reduce_36(t[0], m, mp); - n = sp_2048_cmp_36(t[0], m); - sp_2048_cond_sub_36(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 72) + 72); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 72) + 72, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 72; - rt = td + 2304; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_36(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_36(t[1], t[1], norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - else { - sp_2048_mul_36(t[1], a, norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp); - sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp); - sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp); - sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp); - sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp); - sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp); - sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp); - sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp); - sp_2048_mont_sqr_36(t[10], t[ 5], m, mp); - sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp); - sp_2048_mont_sqr_36(t[12], t[ 6], m, mp); - sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp); - sp_2048_mont_sqr_36(t[14], t[ 7], m, mp); - sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp); - sp_2048_mont_sqr_36(t[16], t[ 8], m, mp); - sp_2048_mont_mul_36(t[17], t[ 9], t[ 8], m, mp); - sp_2048_mont_sqr_36(t[18], t[ 9], m, mp); - sp_2048_mont_mul_36(t[19], t[10], t[ 9], m, mp); - sp_2048_mont_sqr_36(t[20], t[10], m, mp); - sp_2048_mont_mul_36(t[21], t[11], t[10], m, mp); - sp_2048_mont_sqr_36(t[22], t[11], m, mp); - sp_2048_mont_mul_36(t[23], t[12], t[11], m, mp); - sp_2048_mont_sqr_36(t[24], t[12], m, mp); - sp_2048_mont_mul_36(t[25], t[13], t[12], m, mp); - sp_2048_mont_sqr_36(t[26], t[13], m, mp); - sp_2048_mont_mul_36(t[27], t[14], t[13], m, mp); - sp_2048_mont_sqr_36(t[28], t[14], m, mp); - sp_2048_mont_mul_36(t[29], t[15], t[14], m, mp); - sp_2048_mont_sqr_36(t[30], t[15], m, mp); - sp_2048_mont_mul_36(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 36) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 72); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c = 24; - } - else { - y = (byte)((n >> 27) & 0x1f); - n = e[i--] << 3; - c = 5 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - - sp_2048_mont_mul_36(rt, rt, t[y], m, mp); - } - - sp_2048_mont_reduce_36(rt, m, mp); - n = sp_2048_cmp_36(rt, m); - sp_2048_cond_sub_36(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 72); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_2048_mont_norm_72(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=0; i<70; i++) { - r[i] = 0x1fffffff; - } -#else - int i; - - for (i = 0; i < 64; i += 8) { - r[i + 0] = 0x1fffffff; - r[i + 1] = 0x1fffffff; - r[i + 2] = 0x1fffffff; - r[i + 3] = 0x1fffffff; - r[i + 4] = 0x1fffffff; - r[i + 5] = 0x1fffffff; - r[i + 6] = 0x1fffffff; - r[i + 7] = 0x1fffffff; - } - r[64] = 0x1fffffff; - r[65] = 0x1fffffff; - r[66] = 0x1fffffff; - r[67] = 0x1fffffff; - r[68] = 0x1fffffff; - r[69] = 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ - r[70] = 0x3ffffL; - r[71] = 0; - - /* r = (2^n - 1) mod n */ - (void)sp_2048_sub_72(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_2048_cmp_72(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=71; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } -#else - int i; - - for (i = 64; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 28); - } -#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_2048_cond_sub_72(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 < 72; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - int i; - - for (i = 0; i < 72; 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); - } -#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_2048_mul_add_72(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 72; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[72] += (sp_digit)t; -#else -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 68; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[68]) + r[68]; - t[1] = (tb * a[69]) + r[69]; - t[2] = (tb * a[70]) + r[70]; - t[3] = (tb * a[71]) + r[71]; - r[68] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[69] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[70] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[71] = (sp_digit)(t[3] & 0x1fffffff); - r[72] += (sp_digit)(t[3] >> 29); -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 64; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[4] += t[3] >> 29; - r[i+4] = (sp_digit)(t[4] & 0x1fffffff); - t[5] += t[4] >> 29; - r[i+5] = (sp_digit)(t[5] & 0x1fffffff); - t[6] += t[5] >> 29; - r[i+6] = (sp_digit)(t[6] & 0x1fffffff); - t[7] += t[6] >> 29; - r[i+7] = (sp_digit)(t[7] & 0x1fffffff); - t[0] = t[7] >> 29; - } - t[0] += (tb * a[64]) + r[64]; - t[1] = (tb * a[65]) + r[65]; - t[2] = (tb * a[66]) + r[66]; - t[3] = (tb * a[67]) + r[67]; - t[4] = (tb * a[68]) + r[68]; - t[5] = (tb * a[69]) + r[69]; - t[6] = (tb * a[70]) + r[70]; - t[7] = (tb * a[71]) + r[71]; - r[64] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[65] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[66] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[67] = (sp_digit)(t[3] & 0x1fffffff); - t[4] += t[3] >> 29; - r[68] = (sp_digit)(t[4] & 0x1fffffff); - t[5] += t[4] >> 29; - r[69] = (sp_digit)(t[5] & 0x1fffffff); - t[6] += t[5] >> 29; - r[70] = (sp_digit)(t[6] & 0x1fffffff); - t[7] += t[6] >> 29; - r[71] = (sp_digit)(t[7] & 0x1fffffff); - r[72] += (sp_digit)(t[7] >> 29); -#endif /* WOLFSSL_SP_SMALL */ -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_2048_mont_shift_72(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_int64 n = a[70] >> 18; - n += ((sp_int64)a[71]) << 11; - - for (i = 0; i < 70; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[72 + i]) << 11; - } - r[70] = (sp_digit)n; -#else - int i; - sp_int64 n = a[70] >> 18; - n += ((sp_int64)a[71]) << 11; - for (i = 0; i < 64; i += 8) { - r[i + 0] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 72]) << 11; - r[i + 1] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 73]) << 11; - r[i + 2] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 74]) << 11; - r[i + 3] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 75]) << 11; - r[i + 4] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 76]) << 11; - r[i + 5] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 77]) << 11; - r[i + 6] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 78]) << 11; - r[i + 7] = (sp_digit)(n & 0x1fffffff); - n >>= 29; n += ((sp_int64)a[i + 79]) << 11; - } - r[64] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[136]) << 11; - r[65] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[137]) << 11; - r[66] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[138]) << 11; - r[67] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[139]) << 11; - r[68] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[140]) << 11; - r[69] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[141]) << 11; - r[70] = (sp_digit)n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[71], 0, sizeof(*r) * 71U); -} - -/* 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. - */ -static void sp_2048_mont_reduce_72(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_2048_norm_72(a + 71); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<70; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_2048_mul_add_72(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL); - sp_2048_mul_add_72(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } - else { - for (i=0; i<70; i++) { - mu = (sp_digit)(a[i] & 0x1fffffff); - sp_2048_mul_add_72(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(a[i] & 0x3ffffL); - sp_2048_mul_add_72(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - for (i=0; i<70; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_2048_mul_add_72(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL); - sp_2048_mul_add_72(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; -#endif - sp_2048_mont_shift_72(a, a); - over = a[70] - m[70]; - sp_2048_cond_sub_72(a, a, m, ~((over - 1) >> 31)); - sp_2048_norm_72(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_2048_mont_mul_72(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_2048_mul_72(r, a, b); - sp_2048_mont_reduce_72(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_2048_mont_sqr_72(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_2048_sqr_72(r, a); - sp_2048_mont_reduce_72(r, m, mp); -} - -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_71(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 70; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - int i; - for (i = 0; i < 64; i += 8) { - a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff; - a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff; - a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff; - a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff; - a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff; - a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff; - a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff; - a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff; - } - a[65] += a[64] >> 29; a[64] &= 0x1fffffff; - a[66] += a[65] >> 29; a[65] &= 0x1fffffff; - a[67] += a[66] >> 29; a[66] &= 0x1fffffff; - a[68] += a[67] >> 29; a[67] &= 0x1fffffff; - a[69] += a[68] >> 29; a[68] &= 0x1fffffff; - a[70] += a[69] >> 29; a[69] &= 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_2048_mul_d_144(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 144; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[144] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 144; 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 & 0x1fffffff); - t >>= 29; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x1fffffff); - t >>= 29; - r[i + 3] = (sp_digit)t2; - } - r[144] = (sp_digit)(t & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ -} - -#ifdef 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_2048_cond_add_72(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 72; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_2048_cond_add_72(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 72; 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); - } -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_2048_rshift_72(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<71; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } -#else - for (i=0; i<64; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (29 - n)) & 0x1fffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (29 - n)) & 0x1fffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (29 - n)) & 0x1fffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (29 - n)) & 0x1fffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (29 - n)) & 0x1fffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (29 - n)) & 0x1fffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (29 - n)) & 0x1fffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (29 - n)) & 0x1fffffff); - } - r[64] = (a[64] >> n) | (sp_digit)((a[65] << (29 - n)) & 0x1fffffff); - r[65] = (a[65] >> n) | (sp_digit)((a[66] << (29 - n)) & 0x1fffffff); - r[66] = (a[66] >> n) | (sp_digit)((a[67] << (29 - n)) & 0x1fffffff); - r[67] = (a[67] >> n) | (sp_digit)((a[68] << (29 - n)) & 0x1fffffff); - r[68] = (a[68] >> n) | (sp_digit)((a[69] << (29 - n)) & 0x1fffffff); - r[69] = (a[69] >> n) | (sp_digit)((a[70] << (29 - n)) & 0x1fffffff); - r[70] = (a[70] >> n) | (sp_digit)((a[71] << (29 - n)) & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[71] = a[71] >> n; -} - -static WC_INLINE sp_digit sp_2048_div_word_72(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 29) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 29); - sp_digit t0 = (sp_digit)(d & 0x1fffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 27; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 28) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 29); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 14) + 1; - - t = (sp_digit)(d >> 28); - t = (t / dv) << 14; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 1); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_2048_word_div_word_72(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_72(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 72 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 72 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 144 + 1; - sd = t2 + 72 + 1; - - sp_2048_mul_d_72(sd, d, (sp_digit)1 << 11); - sp_2048_mul_d_144(t1, a, (sp_digit)1 << 11); - dv = sd[70]; - t1[71 + 71] += t1[71 + 71 - 1] >> 29; - t1[71 + 71 - 1] &= 0x1fffffff; - for (i=71; i>=0; i--) { - r1 = sp_2048_div_word_72(t1[71 + i], t1[71 + i - 1], dv); - - sp_2048_mul_d_72(t2, sd, r1); - (void)sp_2048_sub_72(&t1[i], &t1[i], t2); - sp_2048_norm_71(&t1[i]); - t1[71 + i] += t1[71 + i - 1] >> 29; - t1[71 + i - 1] &= 0x1fffffff; - r1 = sp_2048_div_word_72(-t1[71 + i], -t1[71 + i - 1], dv); - r1 -= t1[71 + i]; - sp_2048_mul_d_72(t2, sd, r1); - (void)sp_2048_add_72(&t1[i], &t1[i], t2); - t1[71 + i] += t1[71 + i - 1] >> 29; - t1[71 + i - 1] &= 0x1fffffff; - } - t1[71 - 1] += t1[71 - 2] >> 29; - t1[71 - 2] &= 0x1fffffff; - r1 = sp_2048_word_div_word_72(t1[71 - 1], dv); - - sp_2048_mul_d_72(t2, sd, r1); - sp_2048_sub_72(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 144U); - for (i=0; i<70; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - sp_2048_cond_add_72(r, r, sd, r[70] >> 31); - - sp_2048_norm_71(r); - sp_2048_rshift_72(r, r, 11); - r[71] = 0; - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_2048_mod_72(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_2048_div_72(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_2048_mod_exp_72(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 144); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 144, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 72 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 72U * 2U); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_72(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_72(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 72U); - } - } - if (err == MP_OKAY) { - sp_2048_mul_72(t[1], t[1], norm); - err = sp_2048_mod_72(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_2048_mont_mul_72(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 72 * 2); - sp_2048_mont_sqr_72(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 72 * 2); - } - - sp_2048_mont_reduce_72(t[0], m, mp); - n = sp_2048_cmp_72(t[0], m); - sp_2048_cond_sub_72(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 72 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 144); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 144, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 72 * 2); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_72(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_72(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_72(t[1], t[1], norm); - err = sp_2048_mod_72(t[1], t[1], m); - } - } - else { - sp_2048_mul_72(t[1], a, norm); - err = sp_2048_mod_72(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_2048_mont_mul_72(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 72 * 2); - sp_2048_mont_sqr_72(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 72 * 2); - } - - sp_2048_mont_reduce_72(t[0], m, mp); - n = sp_2048_cmp_72(t[0], m); - sp_2048_cond_sub_72(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 72 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 144) + 144); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 144) + 144, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 144; - rt = td + 2304; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_72(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_72(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_72(t[1], t[1], norm); - err = sp_2048_mod_72(t[1], t[1], m); - } - } - else { - sp_2048_mul_72(t[1], a, norm); - err = sp_2048_mod_72(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_2048_mont_sqr_72(t[ 2], t[ 1], m, mp); - sp_2048_mont_mul_72(t[ 3], t[ 2], t[ 1], m, mp); - sp_2048_mont_sqr_72(t[ 4], t[ 2], m, mp); - sp_2048_mont_mul_72(t[ 5], t[ 3], t[ 2], m, mp); - sp_2048_mont_sqr_72(t[ 6], t[ 3], m, mp); - sp_2048_mont_mul_72(t[ 7], t[ 4], t[ 3], m, mp); - sp_2048_mont_sqr_72(t[ 8], t[ 4], m, mp); - sp_2048_mont_mul_72(t[ 9], t[ 5], t[ 4], m, mp); - sp_2048_mont_sqr_72(t[10], t[ 5], m, mp); - sp_2048_mont_mul_72(t[11], t[ 6], t[ 5], m, mp); - sp_2048_mont_sqr_72(t[12], t[ 6], m, mp); - sp_2048_mont_mul_72(t[13], t[ 7], t[ 6], m, mp); - sp_2048_mont_sqr_72(t[14], t[ 7], m, mp); - sp_2048_mont_mul_72(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 72) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 144); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 25; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_2048_mont_sqr_72(rt, rt, m, mp); - sp_2048_mont_sqr_72(rt, rt, m, mp); - sp_2048_mont_sqr_72(rt, rt, m, mp); - sp_2048_mont_sqr_72(rt, rt, m, mp); - - sp_2048_mont_mul_72(rt, rt, t[y], m, mp); - } - - sp_2048_mont_reduce_72(rt, m, mp); - n = sp_2048_cmp_72(rt, m); - sp_2048_cond_sub_72(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 144); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 72 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 256U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 72 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 72 * 2; - m = r + 72 * 2; - norm = r; - - sp_2048_from_bin(a, 72, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_2048_from_mp(m, 72, mm); - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_72(norm, m); - } - if (err == MP_OKAY) { - sp_2048_mul_72(a, a, norm); - err = sp_2048_mod_72(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 72 * 2); - for (i--; i>=0; i--) { - sp_2048_mont_sqr_72(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_2048_mont_mul_72(r, r, a, m, mp); - } - } - sp_2048_mont_reduce_72(r, m, mp); - mp = sp_2048_cmp_72(r, m); - sp_2048_cond_sub_72(r, r, m, ~(mp >> 31)); - - sp_2048_to_bin_72(r, out); - *outLen = 256; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 72 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 72 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 72 * 2; - m = r + 72 * 2; - - sp_2048_from_bin(a, 72, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_2048_from_mp(m, 72, mm); - - if (e[0] == 0x3) { - sp_2048_sqr_72(r, a); - err = sp_2048_mod_72(r, r, m); - if (err == MP_OKAY) { - sp_2048_mul_72(r, a, r); - err = sp_2048_mod_72(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_72(norm, m); - - sp_2048_mul_72(a, a, norm); - err = sp_2048_mod_72(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 144U); - for (i--; i>=0; i--) { - sp_2048_mont_sqr_72(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_2048_mont_mul_72(r, r, a, m, mp); - } - } - sp_2048_mont_reduce_72(r, m, mp); - mp = sp_2048_cmp_72(r, m); - sp_2048_cond_sub_72(r, r, m, ~(mp >> 31)); - } - } - } - - if (err == MP_OKAY) { - sp_2048_to_bin_72(r, out); - *outLen = 256; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 72 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 2048) { - err = MP_READ_E; - } - else if (inLen > 256) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 72 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 72; - m = a + 144; - r = a; - - sp_2048_from_bin(a, 72, in, inLen); - sp_2048_from_mp(d, 72, dm); - sp_2048_from_mp(m, 72, mm); - err = sp_2048_mod_exp_72(r, a, d, 2048, m, 0); - } - - if (err == MP_OKAY) { - sp_2048_to_bin_72(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 72, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 72 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 2048) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 72 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 72; - m = a + 144; - r = a; - - sp_2048_from_bin(a, 72, in, inLen); - sp_2048_from_mp(d, 72, dm); - sp_2048_from_mp(m, 72, mm); - err = sp_2048_mod_exp_72(r, a, d, 2048, m, 0); - } - - if (err == MP_OKAY) { - sp_2048_to_bin_72(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 72, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 36 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 256) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 36 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 72; - qi = dq = dp = p + 36; - tmpa = qi + 36; - tmpb = tmpa + 72; - r = a; - - sp_2048_from_bin(a, 72, in, inLen); - sp_2048_from_mp(p, 36, pm); - sp_2048_from_mp(dp, 36, dpm); - err = sp_2048_mod_exp_36(tmpa, a, dp, 1024, p, 1); - } - if (err == MP_OKAY) { - sp_2048_from_mp(p, 36, qm); - sp_2048_from_mp(dq, 36, dqm); - err = sp_2048_mod_exp_36(tmpb, a, dq, 1024, p, 1); - } - if (err == MP_OKAY) { - sp_2048_from_mp(p, 36, pm); - (void)sp_2048_sub_36(tmpa, tmpa, tmpb); - sp_2048_norm_36(tmpa); - sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31)); - sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31)); - sp_2048_norm_36(tmpa); - - sp_2048_from_mp(qi, 36, qim); - sp_2048_mul_36(tmpa, tmpa, qi); - err = sp_2048_mod_36(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_2048_from_mp(p, 36, qm); - sp_2048_mul_36(tmpa, p, tmpa); - (void)sp_2048_add_72(r, tmpb, tmpa); - sp_2048_norm_72(r); - - sp_2048_to_bin_72(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR(sp_digit, a, 36 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 36 * 13); - 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; - (void)mm; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 36 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 72 * 2; - q = p + 36; - dp = q + 36; - dq = dp + 36; - qi = dq + 36; - tmpa = qi + 36; - tmpb = tmpa + 72; - r = a; - - sp_2048_from_bin(a, 72, in, inLen); - sp_2048_from_mp(p, 36, pm); - sp_2048_from_mp(q, 36, qm); - sp_2048_from_mp(dp, 36, dpm); - sp_2048_from_mp(dq, 36, dqm); - sp_2048_from_mp(qi, 36, qim); - - err = sp_2048_mod_exp_36(tmpa, a, dp, 1024, p, 1); - } - if (err == MP_OKAY) { - err = sp_2048_mod_exp_36(tmpb, a, dq, 1024, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_2048_sub_36(tmpa, tmpa, tmpb); - sp_2048_norm_36(tmpa); - sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31)); - sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31)); - sp_2048_norm_36(tmpa); - sp_2048_mul_36(tmpa, tmpa, qi); - err = sp_2048_mod_36(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_2048_mul_36(tmpa, tmpa, q); - (void)sp_2048_add_72(r, tmpb, tmpa); - sp_2048_norm_72(r); - - sp_2048_to_bin_72(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR(sp_digit, a, 36 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_2048_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 29 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 71); - r->used = 71; - mp_clamp(r); -#elif DIGIT_BIT < 29 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 71; 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 <= 29) { - 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 = 29 - s; - } - r->used = (2048 + 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 < 71; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 29 >= 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 = 29 - s; - } - else { - s += 29; - } - } - r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 72 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expBits > 2048) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 72 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 72 * 2; - m = e + 72; - r = b; - - sp_2048_from_mp(b, 72, base); - sp_2048_from_mp(e, 72, exp); - sp_2048_from_mp(m, 72, mod); - - err = sp_2048_mod_exp_72(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 72U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 72 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expBits > 2048) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 72 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 72 * 2; - m = e + 72; - r = b; - - sp_2048_from_mp(b, 72, base); - sp_2048_from_mp(e, 72, exp); - sp_2048_from_mp(m, 72, mod); - - err = sp_2048_mod_exp_72(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 72U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_2048 -SP_NOINLINE static void sp_2048_lshift_72(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[72] = a[71] >> (29 - n); - for (i=71; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[71]; - r[72] = s >> (29U - n); - s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); - r[71] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); - r[70] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); - r[69] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); - r[68] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); - r[67] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); - r[66] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); - r[65] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); - r[64] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); - r[63] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); - r[62] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); - r[61] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); - r[60] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); - r[59] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); - r[58] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); - r[57] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); - r[56] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); - r[55] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); - r[54] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); - r[53] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); - r[52] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); - r[51] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); - r[50] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); - r[49] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); - r[48] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); - r[47] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); - r[46] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); - r[45] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); - r[44] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); - r[43] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); - r[42] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); - r[41] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); - r[40] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); - r[39] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); - r[38] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); - r[37] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); - r[36] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0x1fffffff); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_2048_mod_exp_2_72(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 217); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 217, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 144; - XMEMSET(td, 0, sizeof(sp_digit) * 217); - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_72(norm, m); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 72) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - sp_2048_lshift_72(r, norm, (byte)y); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 25; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_2048_mont_sqr_72(r, r, m, mp); - sp_2048_mont_sqr_72(r, r, m, mp); - sp_2048_mont_sqr_72(r, r, m, mp); - sp_2048_mont_sqr_72(r, r, m, mp); - - sp_2048_lshift_72(r, r, (byte)y); - sp_2048_mul_d_72(tmp, norm, (r[71] << 11) + (r[70] >> 18)); - r[71] = 0; - r[70] &= 0x3ffffL; - (void)sp_2048_add_72(r, r, tmp); - sp_2048_norm_72(r); - o = sp_2048_cmp_72(r, m); - sp_2048_cond_sub_72(r, r, m, ~(o >> 31)); - } - - sp_2048_mont_reduce_72(r, m, mp); - n = sp_2048_cmp_72(r, m); - sp_2048_cond_sub_72(r, r, m, (sp_digit)~(n >> 31)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_2048 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 72 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 72 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 72 * 2; - m = e + 72; - r = b; - - sp_2048_from_mp(b, 72, base); - sp_2048_from_bin(e, 72, exp, expLen); - sp_2048_from_mp(m, 72, mod); - - #ifdef HAVE_FFDHE_2048 - if (base->used == 1 && base->dp[0] == 2U && - (m[70] >> 2) == 0xffffL) { - err = sp_2048_mod_exp_2_72(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_2048_mod_exp_72(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_2048 - } - #endif - } - - if (err == MP_OKAY) { - sp_2048_to_bin_72(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 72U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 36 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1024) { - err = MP_READ_E; - } - else if (expBits > 1024) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1024) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 36 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 36, 0, sizeof(*r) * 36U); - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 72U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 36 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1024) { - err = MP_READ_E; - } - else if (expBits > 1024) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1024) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 36 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 36, 0, sizeof(*r) * 36U); - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 72U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#endif /* !WOLFSSL_SP_NO_2048 */ - -#ifndef WOLFSSL_SP_NO_3072 -#ifdef WOLFSSL_SP_SMALL -/* 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_3072_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 >= 21U) { - r[j] &= 0x1fffffff; - s = 29U - 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; - } -} - -/* 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_3072_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 29 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 28); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 28); - } -#elif DIGIT_BIT > 29 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x1fffffff; - s = 29U - 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 + 29U) <= (word32)DIGIT_BIT) { - s += 29U; - r[j] &= 0x1fffffff; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 29) { - r[j] &= 0x1fffffff; - if (j + 1 >= size) { - break; - } - s = 29 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 384 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_3072_to_bin_106(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<105; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - j = 3079 / 8 - 1; - a[j] = 0; - for (i=0; i<106 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 29) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 29); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_53(sp_digit* a) -{ - int i; - for (i = 0; i < 52; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_106(sp_digit* a) -{ - int i; - for (i = 0; i < 105; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -} - -/* 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_3072_mul_106(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[105]) * b[105]; - r[211] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 209; k >= 0; k--) { - if (k >= 106) { - i = k - 105; - imax = 105; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - lo &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - } - r[0] = (sp_digit)c; -} - -/* 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_3072_sqr_106(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[105]) * a[105]; - r[211] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 209; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 105) { - imax = k; - } - else { - imax = 105; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint64 hi; - - hi = c >> 29; - c &= 0x1fffffff; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 29; - c &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(hi >> 29); - r[k + 1] = (sp_digit)(hi & 0x1fffffff); - c <<= 29; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - } - r[0] = (sp_digit)(c >> 29); -} - -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x &= 0x1fffffff; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 29) - x; -} - -/* 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_3072_mul_d_106(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 106; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[106] = (sp_digit)t; -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* 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_53(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 53; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_53(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<52; i++) { - r[i] = 0x1fffffff; - } - r[52] = 0xfffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_53(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_53(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=52; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } - - 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_3072_cond_sub_53(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 53; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_3072_mul_add_53(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 53; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[53] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 52; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[52]) + r[52]; - r[52] = (sp_digit)(t[0] & 0x1fffffff); - r[53] += (sp_digit)(t[0] >> 29); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 1536 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_53(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[52] >> 28; - n += ((sp_int64)a[53]) << 1; - - for (i = 0; i < 52; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[54 + i]) << 1; - } - r[52] = (sp_digit)n; - XMEMSET(&r[53], 0, sizeof(*r) * 53U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_53(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_53(a + 53); - - for (i=0; i<52; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_3072_mul_add_53(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffffL); - sp_3072_mul_add_53(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - sp_3072_mont_shift_53(a, a); - over = a[52] - m[52]; - sp_3072_cond_sub_53(a, a, m, ~((over - 1) >> 31)); - sp_3072_norm_53(a); -} - -/* 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_3072_mul_53(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[52]) * b[52]; - r[105] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 103; k >= 0; k--) { - if (k >= 53) { - i = k - 52; - imax = 52; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - lo &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - } - r[0] = (sp_digit)c; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_mul_53(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_3072_mul_53(r, a, b); - sp_3072_mont_reduce_53(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_3072_sqr_53(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[52]) * a[52]; - r[105] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 103; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 52) { - imax = k; - } - else { - imax = 52; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint64 hi; - - hi = c >> 29; - c &= 0x1fffffff; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 29; - c &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(hi >> 29); - r[k + 1] = (sp_digit)(hi & 0x1fffffff); - c <<= 29; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - } - r[0] = (sp_digit)(c >> 29); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_sqr_53(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_3072_sqr_53(r, a); - sp_3072_mont_reduce_53(r, m, mp); -} - -/* 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_3072_mul_d_53(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 53; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[53] = (sp_digit)t; -} - -#ifdef 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_3072_cond_add_53(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 53; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_3072_add_53(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 53; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_3072_rshift_53(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<52; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } - r[52] = a[52] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_53(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 29) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 29); - sp_digit t0 = (sp_digit)(d & 0x1fffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 27; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 28) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 29); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 14) + 1; - - t = (sp_digit)(d >> 28); - t = (t / dv) << 14; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 1); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_53(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_53(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 53 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 53 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 106 + 1; - sd = t2 + 53 + 1; - - sp_3072_mul_d_53(sd, d, (sp_digit)1 << 1); - sp_3072_mul_d_106(t1, a, (sp_digit)1 << 1); - dv = sd[52]; - t1[53 + 53] += t1[53 + 53 - 1] >> 29; - t1[53 + 53 - 1] &= 0x1fffffff; - for (i=53; i>=0; i--) { - r1 = sp_3072_div_word_53(t1[53 + i], t1[53 + i - 1], dv); - - sp_3072_mul_d_53(t2, sd, r1); - (void)sp_3072_sub_53(&t1[i], &t1[i], t2); - sp_3072_norm_53(&t1[i]); - t1[53 + i] -= t2[53]; - t1[53 + i] += t1[53 + i - 1] >> 29; - t1[53 + i - 1] &= 0x1fffffff; - r1 = sp_3072_div_word_53(-t1[53 + i], -t1[53 + i - 1], dv); - r1 -= t1[53 + i]; - sp_3072_mul_d_53(t2, sd, r1); - (void)sp_3072_add_53(&t1[i], &t1[i], t2); - t1[53 + i] += t1[53 + i - 1] >> 29; - t1[53 + i - 1] &= 0x1fffffff; - } - t1[53 - 1] += t1[53 - 2] >> 29; - t1[53 - 2] &= 0x1fffffff; - r1 = sp_3072_word_div_word_53(t1[53 - 1], dv); - - sp_3072_mul_d_53(t2, sd, r1); - sp_3072_sub_53(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 106U); - for (i=0; i<52; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - sp_3072_cond_add_53(r, r, sd, r[52] >> 31); - - sp_3072_norm_53(r); - sp_3072_rshift_53(r, r, 1); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_53(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_53(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_53(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 106); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 106, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 53 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 53U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_53(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_53(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 53U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_53(t[1], t[1], norm); - err = sp_3072_mod_53(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_3072_mont_mul_53(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 53 * 2); - sp_3072_mont_sqr_53(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 53 * 2); - } - - sp_3072_mont_reduce_53(t[0], m, mp); - n = sp_3072_cmp_53(t[0], m); - sp_3072_cond_sub_53(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 53 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 106); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 106, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 53 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_53(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_53(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_53(t[1], t[1], norm); - err = sp_3072_mod_53(t[1], t[1], m); - } - } - else { - sp_3072_mul_53(t[1], a, norm); - err = sp_3072_mod_53(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_3072_mont_mul_53(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 53 * 2); - sp_3072_mont_sqr_53(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 53 * 2); - } - - sp_3072_mont_reduce_53(t[0], m, mp); - n = sp_3072_cmp_53(t[0], m); - sp_3072_cond_sub_53(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 53 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 106) + 106); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 106) + 106, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 106; - rt = td + 3392; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_53(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_53(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_53(t[1], t[1], norm); - err = sp_3072_mod_53(t[1], t[1], m); - } - } - else { - sp_3072_mul_53(t[1], a, norm); - err = sp_3072_mod_53(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_53(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_53(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_53(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_53(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_53(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_53(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_53(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_53(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_53(t[10], t[ 5], m, mp); - sp_3072_mont_mul_53(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_53(t[12], t[ 6], m, mp); - sp_3072_mont_mul_53(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_53(t[14], t[ 7], m, mp); - sp_3072_mont_mul_53(t[15], t[ 8], t[ 7], m, mp); - sp_3072_mont_sqr_53(t[16], t[ 8], m, mp); - sp_3072_mont_mul_53(t[17], t[ 9], t[ 8], m, mp); - sp_3072_mont_sqr_53(t[18], t[ 9], m, mp); - sp_3072_mont_mul_53(t[19], t[10], t[ 9], m, mp); - sp_3072_mont_sqr_53(t[20], t[10], m, mp); - sp_3072_mont_mul_53(t[21], t[11], t[10], m, mp); - sp_3072_mont_sqr_53(t[22], t[11], m, mp); - sp_3072_mont_mul_53(t[23], t[12], t[11], m, mp); - sp_3072_mont_sqr_53(t[24], t[12], m, mp); - sp_3072_mont_mul_53(t[25], t[13], t[12], m, mp); - sp_3072_mont_sqr_53(t[26], t[13], m, mp); - sp_3072_mont_mul_53(t[27], t[14], t[13], m, mp); - sp_3072_mont_sqr_53(t[28], t[14], m, mp); - sp_3072_mont_mul_53(t[29], t[15], t[14], m, mp); - sp_3072_mont_sqr_53(t[30], t[15], m, mp); - sp_3072_mont_mul_53(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 53) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 106); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c = 24; - } - else { - y = (byte)((n >> 27) & 0x1f); - n = e[i--] << 3; - c = 5 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_3072_mont_sqr_53(rt, rt, m, mp); - sp_3072_mont_sqr_53(rt, rt, m, mp); - sp_3072_mont_sqr_53(rt, rt, m, mp); - sp_3072_mont_sqr_53(rt, rt, m, mp); - sp_3072_mont_sqr_53(rt, rt, m, mp); - - sp_3072_mont_mul_53(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_53(rt, m, mp); - n = sp_3072_cmp_53(rt, m); - sp_3072_cond_sub_53(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 106); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ - -/* 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_106(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 106; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_106(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<105; i++) { - r[i] = 0x1fffffff; - } - r[105] = 0x7ffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_106(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_106(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=105; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } - - 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_3072_cond_sub_106(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 106; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_3072_mul_add_106(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 106; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[106] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 104; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[104]) + r[104]; - t[1] = (tb * a[105]) + r[105]; - r[104] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[105] = (sp_digit)(t[1] & 0x1fffffff); - r[106] += (sp_digit)(t[1] >> 29); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 3072 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_106(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[105] >> 27; - n += ((sp_int64)a[106]) << 2; - - for (i = 0; i < 105; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[107 + i]) << 2; - } - r[105] = (sp_digit)n; - XMEMSET(&r[106], 0, sizeof(*r) * 106U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_106(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_106(a + 106); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<105; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_3072_mul_add_106(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x7ffffffL); - sp_3072_mul_add_106(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } - else { - for (i=0; i<105; i++) { - mu = (sp_digit)(a[i] & 0x1fffffff); - sp_3072_mul_add_106(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(a[i] & 0x7ffffffL); - sp_3072_mul_add_106(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - for (i=0; i<105; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_3072_mul_add_106(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x7ffffffL); - sp_3072_mul_add_106(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; -#endif - sp_3072_mont_shift_106(a, a); - over = a[105] - m[105]; - sp_3072_cond_sub_106(a, a, m, ~((over - 1) >> 31)); - sp_3072_norm_106(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_mul_106(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_3072_mul_106(r, a, b); - sp_3072_mont_reduce_106(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_sqr_106(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_3072_sqr_106(r, a); - sp_3072_mont_reduce_106(r, m, mp); -} - -/* 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_3072_mul_d_212(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 212; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[212] = (sp_digit)t; -} - -#ifdef 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_3072_cond_add_106(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 106; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_3072_add_106(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 106; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_3072_rshift_106(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<105; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } - r[105] = a[105] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_106(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 29) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 29); - sp_digit t0 = (sp_digit)(d & 0x1fffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 27; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 28) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 29); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 14) + 1; - - t = (sp_digit)(d >> 28); - t = (t / dv) << 14; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 1); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_106(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_106(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 106 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 106 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 212 + 1; - sd = t2 + 106 + 1; - - sp_3072_mul_d_106(sd, d, (sp_digit)1 << 2); - sp_3072_mul_d_212(t1, a, (sp_digit)1 << 2); - dv = sd[105]; - t1[106 + 106] += t1[106 + 106 - 1] >> 29; - t1[106 + 106 - 1] &= 0x1fffffff; - for (i=106; i>=0; i--) { - r1 = sp_3072_div_word_106(t1[106 + i], t1[106 + i - 1], dv); - - sp_3072_mul_d_106(t2, sd, r1); - (void)sp_3072_sub_106(&t1[i], &t1[i], t2); - sp_3072_norm_106(&t1[i]); - t1[106 + i] -= t2[106]; - t1[106 + i] += t1[106 + i - 1] >> 29; - t1[106 + i - 1] &= 0x1fffffff; - r1 = sp_3072_div_word_106(-t1[106 + i], -t1[106 + i - 1], dv); - r1 -= t1[106 + i]; - sp_3072_mul_d_106(t2, sd, r1); - (void)sp_3072_add_106(&t1[i], &t1[i], t2); - t1[106 + i] += t1[106 + i - 1] >> 29; - t1[106 + i - 1] &= 0x1fffffff; - } - t1[106 - 1] += t1[106 - 2] >> 29; - t1[106 - 2] &= 0x1fffffff; - r1 = sp_3072_word_div_word_106(t1[106 - 1], dv); - - sp_3072_mul_d_106(t2, sd, r1); - sp_3072_sub_106(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 212U); - for (i=0; i<105; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - sp_3072_cond_add_106(r, r, sd, r[105] >> 31); - - sp_3072_norm_106(r); - sp_3072_rshift_106(r, r, 2); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_106(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_106(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_106(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 212); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 212, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 106 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 106U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_106(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_106(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 106U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_106(t[1], t[1], norm); - err = sp_3072_mod_106(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_3072_mont_mul_106(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 106 * 2); - sp_3072_mont_sqr_106(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 106 * 2); - } - - sp_3072_mont_reduce_106(t[0], m, mp); - n = sp_3072_cmp_106(t[0], m); - sp_3072_cond_sub_106(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 106 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 212); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 212, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 106 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_106(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_106(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_106(t[1], t[1], norm); - err = sp_3072_mod_106(t[1], t[1], m); - } - } - else { - sp_3072_mul_106(t[1], a, norm); - err = sp_3072_mod_106(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_3072_mont_mul_106(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 106 * 2); - sp_3072_mont_sqr_106(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 106 * 2); - } - - sp_3072_mont_reduce_106(t[0], m, mp); - n = sp_3072_cmp_106(t[0], m); - sp_3072_cond_sub_106(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 106 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 212) + 212); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 212) + 212, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 212; - rt = td + 3392; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_106(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_106(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_106(t[1], t[1], norm); - err = sp_3072_mod_106(t[1], t[1], m); - } - } - else { - sp_3072_mul_106(t[1], a, norm); - err = sp_3072_mod_106(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_106(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_106(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_106(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_106(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_106(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_106(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_106(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_106(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_106(t[10], t[ 5], m, mp); - sp_3072_mont_mul_106(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_106(t[12], t[ 6], m, mp); - sp_3072_mont_mul_106(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_106(t[14], t[ 7], m, mp); - sp_3072_mont_mul_106(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 106) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 212); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 25; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_3072_mont_sqr_106(rt, rt, m, mp); - sp_3072_mont_sqr_106(rt, rt, m, mp); - sp_3072_mont_sqr_106(rt, rt, m, mp); - sp_3072_mont_sqr_106(rt, rt, m, mp); - - sp_3072_mont_mul_106(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_106(rt, m, mp); - n = sp_3072_cmp_106(rt, m); - sp_3072_cond_sub_106(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 212); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 106 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 106 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 106 * 2; - m = r + 106 * 2; - norm = r; - - sp_3072_from_bin(a, 106, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_3072_from_mp(m, 106, mm); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_106(norm, m); - } - if (err == MP_OKAY) { - sp_3072_mul_106(a, a, norm); - err = sp_3072_mod_106(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 106 * 2); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_106(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_106(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_106(r, m, mp); - mp = sp_3072_cmp_106(r, m); - sp_3072_cond_sub_106(r, r, m, ~(mp >> 31)); - - sp_3072_to_bin_106(r, out); - *outLen = 384; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 106 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 106 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 106 * 2; - m = r + 106 * 2; - - sp_3072_from_bin(a, 106, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_3072_from_mp(m, 106, mm); - - if (e[0] == 0x3) { - sp_3072_sqr_106(r, a); - err = sp_3072_mod_106(r, r, m); - if (err == MP_OKAY) { - sp_3072_mul_106(r, a, r); - err = sp_3072_mod_106(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_106(norm, m); - - sp_3072_mul_106(a, a, norm); - err = sp_3072_mod_106(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 212U); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_106(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_106(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_106(r, m, mp); - mp = sp_3072_cmp_106(r, m); - sp_3072_cond_sub_106(r, r, m, ~(mp >> 31)); - } - } - } - - if (err == MP_OKAY) { - sp_3072_to_bin_106(r, out); - *outLen = 384; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 106 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 106 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 106; - m = a + 212; - r = a; - - sp_3072_from_bin(a, 106, in, inLen); - sp_3072_from_mp(d, 106, dm); - sp_3072_from_mp(m, 106, mm); - err = sp_3072_mod_exp_106(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_106(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 106, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 106 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 106 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 106; - m = a + 212; - r = a; - - sp_3072_from_bin(a, 106, in, inLen); - sp_3072_from_mp(d, 106, dm); - sp_3072_from_mp(m, 106, mm); - err = sp_3072_mod_exp_106(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_106(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 106, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 53 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 53 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 106; - qi = dq = dp = p + 53; - tmpa = qi + 53; - tmpb = tmpa + 106; - r = a; - - sp_3072_from_bin(a, 106, in, inLen); - sp_3072_from_mp(p, 53, pm); - sp_3072_from_mp(dp, 53, dpm); - err = sp_3072_mod_exp_53(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 53, qm); - sp_3072_from_mp(dq, 53, dqm); - err = sp_3072_mod_exp_53(tmpb, a, dq, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 53, pm); - (void)sp_3072_sub_53(tmpa, tmpa, tmpb); - sp_3072_norm_53(tmpa); - sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31)); - sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31)); - sp_3072_norm_53(tmpa); - - sp_3072_from_mp(qi, 53, qim); - sp_3072_mul_53(tmpa, tmpa, qi); - err = sp_3072_mod_53(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_from_mp(p, 53, qm); - sp_3072_mul_53(tmpa, p, tmpa); - (void)sp_3072_add_106(r, tmpb, tmpa); - sp_3072_norm_106(r); - - sp_3072_to_bin_106(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 53 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 53 * 13); - 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 53 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 106 * 2; - q = p + 53; - dp = q + 53; - dq = dp + 53; - qi = dq + 53; - tmpa = qi + 53; - tmpb = tmpa + 106; - r = a; - - sp_3072_from_bin(a, 106, in, inLen); - sp_3072_from_mp(p, 53, pm); - sp_3072_from_mp(q, 53, qm); - sp_3072_from_mp(dp, 53, dpm); - sp_3072_from_mp(dq, 53, dqm); - sp_3072_from_mp(qi, 53, qim); - - err = sp_3072_mod_exp_53(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - err = sp_3072_mod_exp_53(tmpb, a, dq, 1536, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_3072_sub_53(tmpa, tmpa, tmpb); - sp_3072_norm_53(tmpa); - sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31)); - sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31)); - sp_3072_norm_53(tmpa); - sp_3072_mul_53(tmpa, tmpa, qi); - err = sp_3072_mod_53(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_mul_53(tmpa, tmpa, q); - (void)sp_3072_add_106(r, tmpb, tmpa); - sp_3072_norm_106(r); - - sp_3072_to_bin_106(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 53 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_3072_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 29 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 106); - r->used = 106; - mp_clamp(r); -#elif DIGIT_BIT < 29 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 106; 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 <= 29) { - 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 = 29 - s; - } - r->used = (3072 + 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 < 106; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 29 >= 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 = 29 - s; - } - else { - s += 29; - } - } - r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 106 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 106 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 106 * 2; - m = e + 106; - r = b; - - sp_3072_from_mp(b, 106, base); - sp_3072_from_mp(e, 106, exp); - sp_3072_from_mp(m, 106, mod); - - err = sp_3072_mod_exp_106(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 106U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 106 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 106 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 106 * 2; - m = e + 106; - r = b; - - sp_3072_from_mp(b, 106, base); - sp_3072_from_mp(e, 106, exp); - sp_3072_from_mp(m, 106, mod); - - err = sp_3072_mod_exp_106(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 106U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_3072 -SP_NOINLINE static void sp_3072_lshift_106(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - r[106] = a[105] >> (29 - n); - for (i=105; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff); - } - r[0] = (sp_digit)((a[0] << n) & 0x1fffffff); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_3072_mod_exp_2_106(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 319); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 319, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 212; - XMEMSET(td, 0, sizeof(sp_digit) * 319); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_106(norm, m); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 106) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - sp_3072_lshift_106(r, norm, (byte)y); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 25; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_3072_mont_sqr_106(r, r, m, mp); - sp_3072_mont_sqr_106(r, r, m, mp); - sp_3072_mont_sqr_106(r, r, m, mp); - sp_3072_mont_sqr_106(r, r, m, mp); - - sp_3072_lshift_106(r, r, (byte)y); - sp_3072_mul_d_106(tmp, norm, (r[106] << 2) + (r[105] >> 27)); - r[106] = 0; - r[105] &= 0x7ffffffL; - (void)sp_3072_add_106(r, r, tmp); - sp_3072_norm_106(r); - o = sp_3072_cmp_106(r, m); - sp_3072_cond_sub_106(r, r, m, ~(o >> 31)); - } - - sp_3072_mont_reduce_106(r, m, mp); - n = sp_3072_cmp_106(r, m); - sp_3072_cond_sub_106(r, r, m, (sp_digit)~(n >> 31)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_3072 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 106 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 106 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 106 * 2; - m = e + 106; - r = b; - - sp_3072_from_mp(b, 106, base); - sp_3072_from_bin(e, 106, exp, expLen); - sp_3072_from_mp(m, 106, mod); - - #ifdef HAVE_FFDHE_3072 - if (base->used == 1 && base->dp[0] == 2U && - (m[105] >> 11) == 0xffffL) { - err = sp_3072_mod_exp_2_106(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_3072_mod_exp_106(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_3072 - } - #endif - } - - if (err == MP_OKAY) { - sp_3072_to_bin_106(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 106U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 53 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 53 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 53 * 2; - m = e + 53; - r = b; - - sp_3072_from_mp(b, 53, base); - sp_3072_from_mp(e, 53, exp); - sp_3072_from_mp(m, 53, mod); - - err = sp_3072_mod_exp_53(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 53, 0, sizeof(*r) * 53U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 106U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 53 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 53 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 53 * 2; - m = e + 53; - r = b; - - sp_3072_from_mp(b, 53, base); - sp_3072_from_mp(e, 53, exp); - sp_3072_from_mp(m, 53, mod); - - err = sp_3072_mod_exp_53(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 53, 0, sizeof(*r) * 53U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 106U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#else -/* 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_3072_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 >= 20U) { - r[j] &= 0xfffffff; - s = 28U - 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; - } -} - -/* 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_3072_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 28 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 27); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 27); - } -#elif DIGIT_BIT > 28 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xfffffff; - s = 28U - 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 + 28U) <= (word32)DIGIT_BIT) { - s += 28U; - r[j] &= 0xfffffff; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 28) { - r[j] &= 0xfffffff; - if (j + 1 >= size) { - break; - } - s = 28 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 384 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_3072_to_bin_112(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<111; i++) { - r[i+1] += r[i] >> 28; - r[i] &= 0xfffffff; - } - j = 3079 / 8 - 1; - a[j] = 0; - for (i=0; i<110 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 28) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 28); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_56(sp_digit* a) -{ - int i; - for (i = 0; i < 48; i += 8) { - a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff; - a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff; - a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff; - a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff; - a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff; - a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff; - a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff; - a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff; - } - a[49] += a[48] >> 28; a[48] &= 0xfffffff; - a[50] += a[49] >> 28; a[49] &= 0xfffffff; - a[51] += a[50] >> 28; a[50] &= 0xfffffff; - a[52] += a[51] >> 28; a[51] &= 0xfffffff; - a[53] += a[52] >> 28; a[52] &= 0xfffffff; - a[54] += a[53] >> 28; a[53] &= 0xfffffff; - a[55] += a[54] >> 28; a[54] &= 0xfffffff; -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_55(sp_digit* a) -{ - int i; - for (i = 0; i < 48; i += 8) { - a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff; - a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff; - a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff; - a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff; - a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff; - a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff; - a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff; - a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff; - } - a[49] += a[48] >> 28; a[48] &= 0xfffffff; - a[50] += a[49] >> 28; a[49] &= 0xfffffff; - a[51] += a[50] >> 28; a[50] &= 0xfffffff; - a[52] += a[51] >> 28; a[51] &= 0xfffffff; - a[53] += a[52] >> 28; a[52] &= 0xfffffff; - a[54] += a[53] >> 28; a[53] &= 0xfffffff; -} - -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_112(sp_digit* a) -{ - int i; - for (i = 0; i < 104; i += 8) { - a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff; - a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff; - a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff; - a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff; - a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff; - a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff; - a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff; - a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff; - } - a[105] += a[104] >> 28; a[104] &= 0xfffffff; - a[106] += a[105] >> 28; a[105] &= 0xfffffff; - a[107] += a[106] >> 28; a[106] &= 0xfffffff; - a[108] += a[107] >> 28; a[107] &= 0xfffffff; - a[109] += a[108] >> 28; a[108] &= 0xfffffff; - a[110] += a[109] >> 28; a[109] &= 0xfffffff; - a[111] += a[110] >> 28; a[110] &= 0xfffffff; -} - -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_110(sp_digit* a) -{ - int i; - for (i = 0; i < 104; i += 8) { - a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff; - a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff; - a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff; - a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff; - a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff; - a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff; - a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff; - a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff; - } - a[105] += a[104] >> 28; a[104] &= 0xfffffff; - a[106] += a[105] >> 28; a[105] &= 0xfffffff; - a[107] += a[106] >> 28; a[106] &= 0xfffffff; - a[108] += a[107] >> 28; a[107] &= 0xfffffff; - a[109] += a[108] >> 28; a[108] &= 0xfffffff; -} - -#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_3072_mul_14(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_uint64 t0; - sp_uint64 t1; - sp_digit t[14]; - - t0 = ((sp_uint64)a[ 0]) * b[ 0]; - t1 = ((sp_uint64)a[ 0]) * b[ 1] - + ((sp_uint64)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 0]) * b[ 2] - + ((sp_uint64)a[ 1]) * b[ 1] - + ((sp_uint64)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 0]) * b[ 3] - + ((sp_uint64)a[ 1]) * b[ 2] - + ((sp_uint64)a[ 2]) * b[ 1] - + ((sp_uint64)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 0]) * b[ 4] - + ((sp_uint64)a[ 1]) * b[ 3] - + ((sp_uint64)a[ 2]) * b[ 2] - + ((sp_uint64)a[ 3]) * b[ 1] - + ((sp_uint64)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 0]) * b[ 5] - + ((sp_uint64)a[ 1]) * b[ 4] - + ((sp_uint64)a[ 2]) * b[ 3] - + ((sp_uint64)a[ 3]) * b[ 2] - + ((sp_uint64)a[ 4]) * b[ 1] - + ((sp_uint64)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 0]) * b[ 6] - + ((sp_uint64)a[ 1]) * b[ 5] - + ((sp_uint64)a[ 2]) * b[ 4] - + ((sp_uint64)a[ 3]) * b[ 3] - + ((sp_uint64)a[ 4]) * b[ 2] - + ((sp_uint64)a[ 5]) * b[ 1] - + ((sp_uint64)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 0]) * b[ 7] - + ((sp_uint64)a[ 1]) * b[ 6] - + ((sp_uint64)a[ 2]) * b[ 5] - + ((sp_uint64)a[ 3]) * b[ 4] - + ((sp_uint64)a[ 4]) * b[ 3] - + ((sp_uint64)a[ 5]) * b[ 2] - + ((sp_uint64)a[ 6]) * b[ 1] - + ((sp_uint64)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 0]) * b[ 8] - + ((sp_uint64)a[ 1]) * b[ 7] - + ((sp_uint64)a[ 2]) * b[ 6] - + ((sp_uint64)a[ 3]) * b[ 5] - + ((sp_uint64)a[ 4]) * b[ 4] - + ((sp_uint64)a[ 5]) * b[ 3] - + ((sp_uint64)a[ 6]) * b[ 2] - + ((sp_uint64)a[ 7]) * b[ 1] - + ((sp_uint64)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 0]) * b[ 9] - + ((sp_uint64)a[ 1]) * b[ 8] - + ((sp_uint64)a[ 2]) * b[ 7] - + ((sp_uint64)a[ 3]) * b[ 6] - + ((sp_uint64)a[ 4]) * b[ 5] - + ((sp_uint64)a[ 5]) * b[ 4] - + ((sp_uint64)a[ 6]) * b[ 3] - + ((sp_uint64)a[ 7]) * b[ 2] - + ((sp_uint64)a[ 8]) * b[ 1] - + ((sp_uint64)a[ 9]) * b[ 0]; - t[ 8] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 0]) * b[10] - + ((sp_uint64)a[ 1]) * b[ 9] - + ((sp_uint64)a[ 2]) * b[ 8] - + ((sp_uint64)a[ 3]) * b[ 7] - + ((sp_uint64)a[ 4]) * b[ 6] - + ((sp_uint64)a[ 5]) * b[ 5] - + ((sp_uint64)a[ 6]) * b[ 4] - + ((sp_uint64)a[ 7]) * b[ 3] - + ((sp_uint64)a[ 8]) * b[ 2] - + ((sp_uint64)a[ 9]) * b[ 1] - + ((sp_uint64)a[10]) * b[ 0]; - t[ 9] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 0]) * b[11] - + ((sp_uint64)a[ 1]) * b[10] - + ((sp_uint64)a[ 2]) * b[ 9] - + ((sp_uint64)a[ 3]) * b[ 8] - + ((sp_uint64)a[ 4]) * b[ 7] - + ((sp_uint64)a[ 5]) * b[ 6] - + ((sp_uint64)a[ 6]) * b[ 5] - + ((sp_uint64)a[ 7]) * b[ 4] - + ((sp_uint64)a[ 8]) * b[ 3] - + ((sp_uint64)a[ 9]) * b[ 2] - + ((sp_uint64)a[10]) * b[ 1] - + ((sp_uint64)a[11]) * b[ 0]; - t[10] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 0]) * b[12] - + ((sp_uint64)a[ 1]) * b[11] - + ((sp_uint64)a[ 2]) * b[10] - + ((sp_uint64)a[ 3]) * b[ 9] - + ((sp_uint64)a[ 4]) * b[ 8] - + ((sp_uint64)a[ 5]) * b[ 7] - + ((sp_uint64)a[ 6]) * b[ 6] - + ((sp_uint64)a[ 7]) * b[ 5] - + ((sp_uint64)a[ 8]) * b[ 4] - + ((sp_uint64)a[ 9]) * b[ 3] - + ((sp_uint64)a[10]) * b[ 2] - + ((sp_uint64)a[11]) * b[ 1] - + ((sp_uint64)a[12]) * b[ 0]; - t[11] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 0]) * b[13] - + ((sp_uint64)a[ 1]) * b[12] - + ((sp_uint64)a[ 2]) * b[11] - + ((sp_uint64)a[ 3]) * b[10] - + ((sp_uint64)a[ 4]) * b[ 9] - + ((sp_uint64)a[ 5]) * b[ 8] - + ((sp_uint64)a[ 6]) * b[ 7] - + ((sp_uint64)a[ 7]) * b[ 6] - + ((sp_uint64)a[ 8]) * b[ 5] - + ((sp_uint64)a[ 9]) * b[ 4] - + ((sp_uint64)a[10]) * b[ 3] - + ((sp_uint64)a[11]) * b[ 2] - + ((sp_uint64)a[12]) * b[ 1] - + ((sp_uint64)a[13]) * b[ 0]; - t[12] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 1]) * b[13] - + ((sp_uint64)a[ 2]) * b[12] - + ((sp_uint64)a[ 3]) * b[11] - + ((sp_uint64)a[ 4]) * b[10] - + ((sp_uint64)a[ 5]) * b[ 9] - + ((sp_uint64)a[ 6]) * b[ 8] - + ((sp_uint64)a[ 7]) * b[ 7] - + ((sp_uint64)a[ 8]) * b[ 6] - + ((sp_uint64)a[ 9]) * b[ 5] - + ((sp_uint64)a[10]) * b[ 4] - + ((sp_uint64)a[11]) * b[ 3] - + ((sp_uint64)a[12]) * b[ 2] - + ((sp_uint64)a[13]) * b[ 1]; - t[13] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 2]) * b[13] - + ((sp_uint64)a[ 3]) * b[12] - + ((sp_uint64)a[ 4]) * b[11] - + ((sp_uint64)a[ 5]) * b[10] - + ((sp_uint64)a[ 6]) * b[ 9] - + ((sp_uint64)a[ 7]) * b[ 8] - + ((sp_uint64)a[ 8]) * b[ 7] - + ((sp_uint64)a[ 9]) * b[ 6] - + ((sp_uint64)a[10]) * b[ 5] - + ((sp_uint64)a[11]) * b[ 4] - + ((sp_uint64)a[12]) * b[ 3] - + ((sp_uint64)a[13]) * b[ 2]; - r[14] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 3]) * b[13] - + ((sp_uint64)a[ 4]) * b[12] - + ((sp_uint64)a[ 5]) * b[11] - + ((sp_uint64)a[ 6]) * b[10] - + ((sp_uint64)a[ 7]) * b[ 9] - + ((sp_uint64)a[ 8]) * b[ 8] - + ((sp_uint64)a[ 9]) * b[ 7] - + ((sp_uint64)a[10]) * b[ 6] - + ((sp_uint64)a[11]) * b[ 5] - + ((sp_uint64)a[12]) * b[ 4] - + ((sp_uint64)a[13]) * b[ 3]; - r[15] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 4]) * b[13] - + ((sp_uint64)a[ 5]) * b[12] - + ((sp_uint64)a[ 6]) * b[11] - + ((sp_uint64)a[ 7]) * b[10] - + ((sp_uint64)a[ 8]) * b[ 9] - + ((sp_uint64)a[ 9]) * b[ 8] - + ((sp_uint64)a[10]) * b[ 7] - + ((sp_uint64)a[11]) * b[ 6] - + ((sp_uint64)a[12]) * b[ 5] - + ((sp_uint64)a[13]) * b[ 4]; - r[16] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 5]) * b[13] - + ((sp_uint64)a[ 6]) * b[12] - + ((sp_uint64)a[ 7]) * b[11] - + ((sp_uint64)a[ 8]) * b[10] - + ((sp_uint64)a[ 9]) * b[ 9] - + ((sp_uint64)a[10]) * b[ 8] - + ((sp_uint64)a[11]) * b[ 7] - + ((sp_uint64)a[12]) * b[ 6] - + ((sp_uint64)a[13]) * b[ 5]; - r[17] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 6]) * b[13] - + ((sp_uint64)a[ 7]) * b[12] - + ((sp_uint64)a[ 8]) * b[11] - + ((sp_uint64)a[ 9]) * b[10] - + ((sp_uint64)a[10]) * b[ 9] - + ((sp_uint64)a[11]) * b[ 8] - + ((sp_uint64)a[12]) * b[ 7] - + ((sp_uint64)a[13]) * b[ 6]; - r[18] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 7]) * b[13] - + ((sp_uint64)a[ 8]) * b[12] - + ((sp_uint64)a[ 9]) * b[11] - + ((sp_uint64)a[10]) * b[10] - + ((sp_uint64)a[11]) * b[ 9] - + ((sp_uint64)a[12]) * b[ 8] - + ((sp_uint64)a[13]) * b[ 7]; - r[19] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[ 8]) * b[13] - + ((sp_uint64)a[ 9]) * b[12] - + ((sp_uint64)a[10]) * b[11] - + ((sp_uint64)a[11]) * b[10] - + ((sp_uint64)a[12]) * b[ 9] - + ((sp_uint64)a[13]) * b[ 8]; - r[20] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[ 9]) * b[13] - + ((sp_uint64)a[10]) * b[12] - + ((sp_uint64)a[11]) * b[11] - + ((sp_uint64)a[12]) * b[10] - + ((sp_uint64)a[13]) * b[ 9]; - r[21] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[10]) * b[13] - + ((sp_uint64)a[11]) * b[12] - + ((sp_uint64)a[12]) * b[11] - + ((sp_uint64)a[13]) * b[10]; - r[22] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[11]) * b[13] - + ((sp_uint64)a[12]) * b[12] - + ((sp_uint64)a[13]) * b[11]; - r[23] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = ((sp_uint64)a[12]) * b[13] - + ((sp_uint64)a[13]) * b[12]; - r[24] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[13]) * b[13]; - r[25] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - r[26] = (sp_digit)(t0 & 0xfffffff); - r[27] = (sp_digit)(t0 >> 28); - XMEMCPY(r, t, sizeof(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. - */ -SP_NOINLINE static int sp_3072_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; -} - -/* 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_28(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] + b[24]; - r[25] = a[25] + b[25]; - r[26] = a[26] + b[26]; - r[27] = a[27] + b[27]; - - 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_3072_sub_28(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] - b[24]; - r[25] = a[25] - b[25]; - r[26] = a[26] - b[26]; - r[27] = a[27] - b[27]; - - return 0; -} - -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_14(sp_digit* a) -{ - a[1] += a[0] >> 28; a[0] &= 0xfffffff; - a[2] += a[1] >> 28; a[1] &= 0xfffffff; - a[3] += a[2] >> 28; a[2] &= 0xfffffff; - a[4] += a[3] >> 28; a[3] &= 0xfffffff; - a[5] += a[4] >> 28; a[4] &= 0xfffffff; - a[6] += a[5] >> 28; a[5] &= 0xfffffff; - a[7] += a[6] >> 28; a[6] &= 0xfffffff; - a[8] += a[7] >> 28; a[7] &= 0xfffffff; - a[9] += a[8] >> 28; a[8] &= 0xfffffff; - a[10] += a[9] >> 28; a[9] &= 0xfffffff; - a[11] += a[10] >> 28; a[10] &= 0xfffffff; - a[12] += a[11] >> 28; a[11] &= 0xfffffff; - a[13] += a[12] >> 28; a[12] &= 0xfffffff; -} - -/* 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_3072_mul_28(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[28]; - sp_digit* a1 = z1; - sp_digit b1[14]; - sp_digit* z2 = r + 28; - (void)sp_3072_add_14(a1, a, &a[14]); - sp_3072_norm_14(a1); - (void)sp_3072_add_14(b1, b, &b[14]); - sp_3072_norm_14(b1); - sp_3072_mul_14(z2, &a[14], &b[14]); - sp_3072_mul_14(z0, a, b); - sp_3072_mul_14(z1, a1, b1); - (void)sp_3072_sub_28(z1, z1, z2); - (void)sp_3072_sub_28(z1, z1, z0); - (void)sp_3072_add_28(r + 14, r + 14, z1); - sp_3072_norm_56(r); -} - -/* 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_56(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 56; 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]; - } - - 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_3072_sub_56(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 56; 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]; - } - - return 0; -} - -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_28(sp_digit* a) -{ - int i; - for (i = 0; i < 24; i += 8) { - a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff; - a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff; - a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff; - a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff; - a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff; - a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff; - a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff; - a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff; - } - a[25] += a[24] >> 28; a[24] &= 0xfffffff; - a[26] += a[25] >> 28; a[25] &= 0xfffffff; - a[27] += a[26] >> 28; a[26] &= 0xfffffff; -} - -/* 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_3072_mul_56(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[56]; - sp_digit* a1 = z1; - sp_digit b1[28]; - sp_digit* z2 = r + 56; - (void)sp_3072_add_28(a1, a, &a[28]); - sp_3072_norm_28(a1); - (void)sp_3072_add_28(b1, b, &b[28]); - sp_3072_norm_28(b1); - sp_3072_mul_28(z2, &a[28], &b[28]); - sp_3072_mul_28(z0, a, b); - sp_3072_mul_28(z1, a1, b1); - (void)sp_3072_sub_56(z1, z1, z2); - (void)sp_3072_sub_56(z1, z1, z0); - (void)sp_3072_add_56(r + 28, r + 28, z1); - sp_3072_norm_112(r); -} - -/* 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_112(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 112; 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]; - } - - 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_3072_sub_112(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 112; 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]; - } - - return 0; -} - -/* Normalize the values in each word to 28 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_224(sp_digit* a) -{ - int i; - for (i = 0; i < 216; i += 8) { - a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff; - a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff; - a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff; - a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff; - a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff; - a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff; - a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff; - a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff; - } - a[217] += a[216] >> 28; a[216] &= 0xfffffff; - a[218] += a[217] >> 28; a[217] &= 0xfffffff; - a[219] += a[218] >> 28; a[218] &= 0xfffffff; - a[220] += a[219] >> 28; a[219] &= 0xfffffff; - a[221] += a[220] >> 28; a[220] &= 0xfffffff; - a[222] += a[221] >> 28; a[221] &= 0xfffffff; - a[223] += a[222] >> 28; a[222] &= 0xfffffff; -} - -/* 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_3072_mul_112(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[112]; - sp_digit* a1 = z1; - sp_digit b1[56]; - sp_digit* z2 = r + 112; - (void)sp_3072_add_56(a1, a, &a[56]); - sp_3072_norm_56(a1); - (void)sp_3072_add_56(b1, b, &b[56]); - sp_3072_norm_56(b1); - sp_3072_mul_56(z2, &a[56], &b[56]); - sp_3072_mul_56(z0, a, b); - sp_3072_mul_56(z1, a1, b1); - (void)sp_3072_sub_112(z1, z1, z2); - (void)sp_3072_sub_112(z1, z1, z0); - (void)sp_3072_add_112(r + 56, r + 56, z1); - sp_3072_norm_224(r); -} - -/* 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_3072_sqr_14(sp_digit* r, const sp_digit* a) -{ - sp_uint64 t0; - sp_uint64 t1; - sp_digit t[14]; - - t0 = ((sp_uint64)a[ 0]) * a[ 0]; - t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 0]) * a[ 2]) * 2 - + ((sp_uint64)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 0]) * a[ 3] - + ((sp_uint64)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 0]) * a[ 4] - + ((sp_uint64)a[ 1]) * a[ 3]) * 2 - + ((sp_uint64)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 0]) * a[ 5] - + ((sp_uint64)a[ 1]) * a[ 4] - + ((sp_uint64)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 0]) * a[ 6] - + ((sp_uint64)a[ 1]) * a[ 5] - + ((sp_uint64)a[ 2]) * a[ 4]) * 2 - + ((sp_uint64)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 0]) * a[ 7] - + ((sp_uint64)a[ 1]) * a[ 6] - + ((sp_uint64)a[ 2]) * a[ 5] - + ((sp_uint64)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 0]) * a[ 8] - + ((sp_uint64)a[ 1]) * a[ 7] - + ((sp_uint64)a[ 2]) * a[ 6] - + ((sp_uint64)a[ 3]) * a[ 5]) * 2 - + ((sp_uint64)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 0]) * a[ 9] - + ((sp_uint64)a[ 1]) * a[ 8] - + ((sp_uint64)a[ 2]) * a[ 7] - + ((sp_uint64)a[ 3]) * a[ 6] - + ((sp_uint64)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 0]) * a[10] - + ((sp_uint64)a[ 1]) * a[ 9] - + ((sp_uint64)a[ 2]) * a[ 8] - + ((sp_uint64)a[ 3]) * a[ 7] - + ((sp_uint64)a[ 4]) * a[ 6]) * 2 - + ((sp_uint64)a[ 5]) * a[ 5]; - t[ 9] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 0]) * a[11] - + ((sp_uint64)a[ 1]) * a[10] - + ((sp_uint64)a[ 2]) * a[ 9] - + ((sp_uint64)a[ 3]) * a[ 8] - + ((sp_uint64)a[ 4]) * a[ 7] - + ((sp_uint64)a[ 5]) * a[ 6]) * 2; - t[10] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 0]) * a[12] - + ((sp_uint64)a[ 1]) * a[11] - + ((sp_uint64)a[ 2]) * a[10] - + ((sp_uint64)a[ 3]) * a[ 9] - + ((sp_uint64)a[ 4]) * a[ 8] - + ((sp_uint64)a[ 5]) * a[ 7]) * 2 - + ((sp_uint64)a[ 6]) * a[ 6]; - t[11] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 0]) * a[13] - + ((sp_uint64)a[ 1]) * a[12] - + ((sp_uint64)a[ 2]) * a[11] - + ((sp_uint64)a[ 3]) * a[10] - + ((sp_uint64)a[ 4]) * a[ 9] - + ((sp_uint64)a[ 5]) * a[ 8] - + ((sp_uint64)a[ 6]) * a[ 7]) * 2; - t[12] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 1]) * a[13] - + ((sp_uint64)a[ 2]) * a[12] - + ((sp_uint64)a[ 3]) * a[11] - + ((sp_uint64)a[ 4]) * a[10] - + ((sp_uint64)a[ 5]) * a[ 9] - + ((sp_uint64)a[ 6]) * a[ 8]) * 2 - + ((sp_uint64)a[ 7]) * a[ 7]; - t[13] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 2]) * a[13] - + ((sp_uint64)a[ 3]) * a[12] - + ((sp_uint64)a[ 4]) * a[11] - + ((sp_uint64)a[ 5]) * a[10] - + ((sp_uint64)a[ 6]) * a[ 9] - + ((sp_uint64)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 3]) * a[13] - + ((sp_uint64)a[ 4]) * a[12] - + ((sp_uint64)a[ 5]) * a[11] - + ((sp_uint64)a[ 6]) * a[10] - + ((sp_uint64)a[ 7]) * a[ 9]) * 2 - + ((sp_uint64)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 4]) * a[13] - + ((sp_uint64)a[ 5]) * a[12] - + ((sp_uint64)a[ 6]) * a[11] - + ((sp_uint64)a[ 7]) * a[10] - + ((sp_uint64)a[ 8]) * a[ 9]) * 2; - r[16] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 5]) * a[13] - + ((sp_uint64)a[ 6]) * a[12] - + ((sp_uint64)a[ 7]) * a[11] - + ((sp_uint64)a[ 8]) * a[10]) * 2 - + ((sp_uint64)a[ 9]) * a[ 9]; - r[17] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 6]) * a[13] - + ((sp_uint64)a[ 7]) * a[12] - + ((sp_uint64)a[ 8]) * a[11] - + ((sp_uint64)a[ 9]) * a[10]) * 2; - r[18] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 7]) * a[13] - + ((sp_uint64)a[ 8]) * a[12] - + ((sp_uint64)a[ 9]) * a[11]) * 2 - + ((sp_uint64)a[10]) * a[10]; - r[19] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[ 8]) * a[13] - + ((sp_uint64)a[ 9]) * a[12] - + ((sp_uint64)a[10]) * a[11]) * 2; - r[20] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[ 9]) * a[13] - + ((sp_uint64)a[10]) * a[12]) * 2 - + ((sp_uint64)a[11]) * a[11]; - r[21] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[10]) * a[13] - + ((sp_uint64)a[11]) * a[12]) * 2; - r[22] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = (((sp_uint64)a[11]) * a[13]) * 2 - + ((sp_uint64)a[12]) * a[12]; - r[23] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - t1 = (((sp_uint64)a[12]) * a[13]) * 2; - r[24] = (sp_digit)(t0 & 0xfffffff); t1 += t0 >> 28; - t0 = ((sp_uint64)a[13]) * a[13]; - r[25] = (sp_digit)(t1 & 0xfffffff); t0 += t1 >> 28; - r[26] = (sp_digit)(t0 & 0xfffffff); - r[27] = (sp_digit)(t0 >> 28); - XMEMCPY(r, t, sizeof(t)); -} - -/* 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_3072_sqr_28(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[28]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 28; - (void)sp_3072_add_14(a1, a, &a[14]); - sp_3072_norm_14(a1); - sp_3072_sqr_14(z2, &a[14]); - sp_3072_sqr_14(z0, a); - sp_3072_sqr_14(z1, a1); - (void)sp_3072_sub_28(z1, z1, z2); - (void)sp_3072_sub_28(z1, z1, z0); - (void)sp_3072_add_28(r + 14, r + 14, z1); - sp_3072_norm_56(r); -} - -/* 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_3072_sqr_56(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[56]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 56; - (void)sp_3072_add_28(a1, a, &a[28]); - sp_3072_norm_28(a1); - sp_3072_sqr_28(z2, &a[28]); - sp_3072_sqr_28(z0, a); - sp_3072_sqr_28(z1, a1); - (void)sp_3072_sub_56(z1, z1, z2); - (void)sp_3072_sub_56(z1, z1, z0); - (void)sp_3072_add_56(r + 28, r + 28, z1); - sp_3072_norm_112(r); -} - -/* 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_3072_sqr_112(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[112]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 112; - (void)sp_3072_add_56(a1, a, &a[56]); - sp_3072_norm_56(a1); - sp_3072_sqr_56(z2, &a[56]); - sp_3072_sqr_56(z0, a); - sp_3072_sqr_56(z1, a1); - (void)sp_3072_sub_112(z1, z1, z2); - (void)sp_3072_sub_112(z1, z1, z0); - (void)sp_3072_add_112(r + 56, r + 56, z1); - sp_3072_norm_224(r); -} - -#endif /* !WOLFSSL_SP_SMALL */ -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x &= 0xfffffff; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 28) - x; -} - -/* 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_3072_mul_d_112(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 112; 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 & 0xfffffff); - t >>= 28; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 3] = (sp_digit)t2; - } - r[112] = (sp_digit)(t & 0xfffffff); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_56(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 48; i += 8) { - r[i + 0] = 0xfffffff; - r[i + 1] = 0xfffffff; - r[i + 2] = 0xfffffff; - r[i + 3] = 0xfffffff; - r[i + 4] = 0xfffffff; - r[i + 5] = 0xfffffff; - r[i + 6] = 0xfffffff; - r[i + 7] = 0xfffffff; - } - r[48] = 0xfffffff; - r[49] = 0xfffffff; - r[50] = 0xfffffff; - r[51] = 0xfffffff; - r[52] = 0xfffffff; - r[53] = 0xfffffff; - r[54] = 0xffffffL; - r[55] = 0; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_56(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_56(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i = 48; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 27); - } - - 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_3072_cond_sub_56(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 56; 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); - } -} - -/* 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_3072_mul_add_56(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 56; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0xfffffff; - t >>= 28; - } - r[56] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 48; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0xfffffff); - t[1] += t[0] >> 28; - r[i+1] = (sp_digit)(t[1] & 0xfffffff); - t[2] += t[1] >> 28; - r[i+2] = (sp_digit)(t[2] & 0xfffffff); - t[3] += t[2] >> 28; - r[i+3] = (sp_digit)(t[3] & 0xfffffff); - t[4] += t[3] >> 28; - r[i+4] = (sp_digit)(t[4] & 0xfffffff); - t[5] += t[4] >> 28; - r[i+5] = (sp_digit)(t[5] & 0xfffffff); - t[6] += t[5] >> 28; - r[i+6] = (sp_digit)(t[6] & 0xfffffff); - t[7] += t[6] >> 28; - r[i+7] = (sp_digit)(t[7] & 0xfffffff); - t[0] = t[7] >> 28; - } - t[0] += (tb * a[48]) + r[48]; - t[1] = (tb * a[49]) + r[49]; - t[2] = (tb * a[50]) + r[50]; - t[3] = (tb * a[51]) + r[51]; - t[4] = (tb * a[52]) + r[52]; - t[5] = (tb * a[53]) + r[53]; - t[6] = (tb * a[54]) + r[54]; - t[7] = (tb * a[55]) + r[55]; - r[48] = (sp_digit)(t[0] & 0xfffffff); - t[1] += t[0] >> 28; - r[49] = (sp_digit)(t[1] & 0xfffffff); - t[2] += t[1] >> 28; - r[50] = (sp_digit)(t[2] & 0xfffffff); - t[3] += t[2] >> 28; - r[51] = (sp_digit)(t[3] & 0xfffffff); - t[4] += t[3] >> 28; - r[52] = (sp_digit)(t[4] & 0xfffffff); - t[5] += t[4] >> 28; - r[53] = (sp_digit)(t[5] & 0xfffffff); - t[6] += t[5] >> 28; - r[54] = (sp_digit)(t[6] & 0xfffffff); - t[7] += t[6] >> 28; - r[55] = (sp_digit)(t[7] & 0xfffffff); - r[56] += (sp_digit)(t[7] >> 28); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 1536 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_56(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[54] >> 24; - n += ((sp_int64)a[55]) << 4; - for (i = 0; i < 48; i += 8) { - r[i + 0] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 56]) << 4; - r[i + 1] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 57]) << 4; - r[i + 2] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 58]) << 4; - r[i + 3] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 59]) << 4; - r[i + 4] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 60]) << 4; - r[i + 5] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 61]) << 4; - r[i + 6] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 62]) << 4; - r[i + 7] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 63]) << 4; - } - r[48] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[104]) << 4; - r[49] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[105]) << 4; - r[50] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[106]) << 4; - r[51] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[107]) << 4; - r[52] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[108]) << 4; - r[53] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[109]) << 4; - r[54] = (sp_digit)n; - XMEMSET(&r[55], 0, sizeof(*r) * 55U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_56(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_56(a + 55); - - for (i=0; i<54; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff); - sp_3072_mul_add_56(a+i, m, mu); - a[i+1] += a[i] >> 28; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xffffffL); - sp_3072_mul_add_56(a+i, m, mu); - a[i+1] += a[i] >> 28; - a[i] &= 0xfffffff; - sp_3072_mont_shift_56(a, a); - over = a[54] - m[54]; - sp_3072_cond_sub_56(a, a, m, ~((over - 1) >> 31)); - sp_3072_norm_56(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_mul_56(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_3072_mul_56(r, a, b); - sp_3072_mont_reduce_56(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_sqr_56(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_3072_sqr_56(r, a); - sp_3072_mont_reduce_56(r, m, mp); -} - -/* 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_3072_mul_d_56(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 56; 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 & 0xfffffff); - t >>= 28; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 3] = (sp_digit)t2; - } - r[56] = (sp_digit)(t & 0xfffffff); -} - -#ifndef 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_3072_cond_add_56(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 56; 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); - } -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_3072_rshift_56(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<48; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (28 - n)) & 0xfffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (28 - n)) & 0xfffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (28 - n)) & 0xfffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (28 - n)) & 0xfffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (28 - n)) & 0xfffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (28 - n)) & 0xfffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (28 - n)) & 0xfffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (28 - n)) & 0xfffffff); - } - r[48] = (a[48] >> n) | (sp_digit)((a[49] << (28 - n)) & 0xfffffff); - r[49] = (a[49] >> n) | (sp_digit)((a[50] << (28 - n)) & 0xfffffff); - r[50] = (a[50] >> n) | (sp_digit)((a[51] << (28 - n)) & 0xfffffff); - r[51] = (a[51] >> n) | (sp_digit)((a[52] << (28 - n)) & 0xfffffff); - r[52] = (a[52] >> n) | (sp_digit)((a[53] << (28 - n)) & 0xfffffff); - r[53] = (a[53] >> n) | (sp_digit)((a[54] << (28 - n)) & 0xfffffff); - r[54] = (a[54] >> n) | (sp_digit)((a[55] << (28 - n)) & 0xfffffff); - r[55] = a[55] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_56(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 28) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 28) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 28) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 28); - sp_digit t0 = (sp_digit)(d & 0xfffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 26; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 27) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 28); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 56) - (sp_digit)(d >> 56); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 28) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 13) + 1; - - t = (sp_digit)(d >> 26); - t = (t / dv) << 13; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 11); - t = t / (dv << 2); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_56(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_56(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 56 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 56 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 112 + 1; - sd = t2 + 56 + 1; - - sp_3072_mul_d_56(sd, d, (sp_digit)1 << 4); - sp_3072_mul_d_112(t1, a, (sp_digit)1 << 4); - dv = sd[54]; - t1[55 + 55] += t1[55 + 55 - 1] >> 28; - t1[55 + 55 - 1] &= 0xfffffff; - for (i=55; i>=0; i--) { - r1 = sp_3072_div_word_56(t1[55 + i], t1[55 + i - 1], dv); - - sp_3072_mul_d_56(t2, sd, r1); - (void)sp_3072_sub_56(&t1[i], &t1[i], t2); - sp_3072_norm_55(&t1[i]); - t1[55 + i] += t1[55 + i - 1] >> 28; - t1[55 + i - 1] &= 0xfffffff; - r1 = sp_3072_div_word_56(-t1[55 + i], -t1[55 + i - 1], dv); - r1 -= t1[55 + i]; - sp_3072_mul_d_56(t2, sd, r1); - (void)sp_3072_add_56(&t1[i], &t1[i], t2); - t1[55 + i] += t1[55 + i - 1] >> 28; - t1[55 + i - 1] &= 0xfffffff; - } - t1[55 - 1] += t1[55 - 2] >> 28; - t1[55 - 2] &= 0xfffffff; - r1 = sp_3072_word_div_word_56(t1[55 - 1], dv); - - sp_3072_mul_d_56(t2, sd, r1); - sp_3072_sub_56(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 112U); - for (i=0; i<54; i++) { - r[i+1] += r[i] >> 28; - r[i] &= 0xfffffff; - } - sp_3072_cond_add_56(r, r, sd, r[54] >> 31); - - sp_3072_norm_55(r); - sp_3072_rshift_56(r, r, 4); - r[55] = 0; - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_56(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_56(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_56(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 112); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 112, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 56 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 56U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_56(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_56(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 56U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_56(t[1], t[1], norm); - err = sp_3072_mod_56(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 28; - c = bits % 28; - n = e[i--] << (28 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 28; - } - - y = (int)((n >> 27) & 1); - n <<= 1; - - sp_3072_mont_mul_56(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 56 * 2); - sp_3072_mont_sqr_56(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 56 * 2); - } - - sp_3072_mont_reduce_56(t[0], m, mp); - n = sp_3072_cmp_56(t[0], m); - sp_3072_cond_sub_56(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 56 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 112); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 112, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 56 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_56(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_56(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_56(t[1], t[1], norm); - err = sp_3072_mod_56(t[1], t[1], m); - } - } - else { - sp_3072_mul_56(t[1], a, norm); - err = sp_3072_mod_56(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 28; - c = bits % 28; - n = e[i--] << (28 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 28; - } - - y = (int)((n >> 27) & 1); - n <<= 1; - - sp_3072_mont_mul_56(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 56 * 2); - sp_3072_mont_sqr_56(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 56 * 2); - } - - sp_3072_mont_reduce_56(t[0], m, mp); - n = sp_3072_cmp_56(t[0], m); - sp_3072_cond_sub_56(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 56 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 112) + 112); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 112) + 112, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 112; - rt = td + 3584; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_56(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_56(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_56(t[1], t[1], norm); - err = sp_3072_mod_56(t[1], t[1], m); - } - } - else { - sp_3072_mul_56(t[1], a, norm); - err = sp_3072_mod_56(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_56(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_56(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_56(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_56(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_56(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_56(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_56(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_56(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_56(t[10], t[ 5], m, mp); - sp_3072_mont_mul_56(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_56(t[12], t[ 6], m, mp); - sp_3072_mont_mul_56(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_56(t[14], t[ 7], m, mp); - sp_3072_mont_mul_56(t[15], t[ 8], t[ 7], m, mp); - sp_3072_mont_sqr_56(t[16], t[ 8], m, mp); - sp_3072_mont_mul_56(t[17], t[ 9], t[ 8], m, mp); - sp_3072_mont_sqr_56(t[18], t[ 9], m, mp); - sp_3072_mont_mul_56(t[19], t[10], t[ 9], m, mp); - sp_3072_mont_sqr_56(t[20], t[10], m, mp); - sp_3072_mont_mul_56(t[21], t[11], t[10], m, mp); - sp_3072_mont_sqr_56(t[22], t[11], m, mp); - sp_3072_mont_mul_56(t[23], t[12], t[11], m, mp); - sp_3072_mont_sqr_56(t[24], t[12], m, mp); - sp_3072_mont_mul_56(t[25], t[13], t[12], m, mp); - sp_3072_mont_sqr_56(t[26], t[13], m, mp); - sp_3072_mont_mul_56(t[27], t[14], t[13], m, mp); - sp_3072_mont_sqr_56(t[28], t[14], m, mp); - sp_3072_mont_mul_56(t[29], t[15], t[14], m, mp); - sp_3072_mont_sqr_56(t[30], t[15], m, mp); - sp_3072_mont_mul_56(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 27) / 28) - 1; - c = bits % 28; - if (c == 0) { - c = 28; - } - if (i < 56) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (4 - c); - c += 28; - } - y = (int)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 112); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 4; - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c = 23; - } - else { - y = (byte)((n >> 27) & 0x1f); - n = e[i--] << 4; - c = 5 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 28 - c; - } - - sp_3072_mont_sqr_56(rt, rt, m, mp); - sp_3072_mont_sqr_56(rt, rt, m, mp); - sp_3072_mont_sqr_56(rt, rt, m, mp); - sp_3072_mont_sqr_56(rt, rt, m, mp); - sp_3072_mont_sqr_56(rt, rt, m, mp); - - sp_3072_mont_mul_56(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_56(rt, m, mp); - n = sp_3072_cmp_56(rt, m); - sp_3072_cond_sub_56(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 112); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_112(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 104; i += 8) { - r[i + 0] = 0xfffffff; - r[i + 1] = 0xfffffff; - r[i + 2] = 0xfffffff; - r[i + 3] = 0xfffffff; - r[i + 4] = 0xfffffff; - r[i + 5] = 0xfffffff; - r[i + 6] = 0xfffffff; - r[i + 7] = 0xfffffff; - } - r[104] = 0xfffffff; - r[105] = 0xfffffff; - r[106] = 0xfffffff; - r[107] = 0xfffffff; - r[108] = 0xfffffff; - r[109] = 0xfffffL; - r[110] = 0; - r[111] = 0; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_112(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_112(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i = 104; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 27); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 27); - } - - 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_3072_cond_sub_112(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 112; 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); - } -} - -/* 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_3072_mul_add_112(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 112; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0xfffffff; - t >>= 28; - } - r[112] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 104; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0xfffffff); - t[1] += t[0] >> 28; - r[i+1] = (sp_digit)(t[1] & 0xfffffff); - t[2] += t[1] >> 28; - r[i+2] = (sp_digit)(t[2] & 0xfffffff); - t[3] += t[2] >> 28; - r[i+3] = (sp_digit)(t[3] & 0xfffffff); - t[4] += t[3] >> 28; - r[i+4] = (sp_digit)(t[4] & 0xfffffff); - t[5] += t[4] >> 28; - r[i+5] = (sp_digit)(t[5] & 0xfffffff); - t[6] += t[5] >> 28; - r[i+6] = (sp_digit)(t[6] & 0xfffffff); - t[7] += t[6] >> 28; - r[i+7] = (sp_digit)(t[7] & 0xfffffff); - t[0] = t[7] >> 28; - } - t[0] += (tb * a[104]) + r[104]; - t[1] = (tb * a[105]) + r[105]; - t[2] = (tb * a[106]) + r[106]; - t[3] = (tb * a[107]) + r[107]; - t[4] = (tb * a[108]) + r[108]; - t[5] = (tb * a[109]) + r[109]; - t[6] = (tb * a[110]) + r[110]; - t[7] = (tb * a[111]) + r[111]; - r[104] = (sp_digit)(t[0] & 0xfffffff); - t[1] += t[0] >> 28; - r[105] = (sp_digit)(t[1] & 0xfffffff); - t[2] += t[1] >> 28; - r[106] = (sp_digit)(t[2] & 0xfffffff); - t[3] += t[2] >> 28; - r[107] = (sp_digit)(t[3] & 0xfffffff); - t[4] += t[3] >> 28; - r[108] = (sp_digit)(t[4] & 0xfffffff); - t[5] += t[4] >> 28; - r[109] = (sp_digit)(t[5] & 0xfffffff); - t[6] += t[5] >> 28; - r[110] = (sp_digit)(t[6] & 0xfffffff); - t[7] += t[6] >> 28; - r[111] = (sp_digit)(t[7] & 0xfffffff); - r[112] += (sp_digit)(t[7] >> 28); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 3072 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_112(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[109] >> 20; - n += ((sp_int64)a[110]) << 8; - for (i = 0; i < 104; i += 8) { - r[i + 0] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 111]) << 8; - r[i + 1] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 112]) << 8; - r[i + 2] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 113]) << 8; - r[i + 3] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 114]) << 8; - r[i + 4] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 115]) << 8; - r[i + 5] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 116]) << 8; - r[i + 6] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 117]) << 8; - r[i + 7] = (sp_digit)(n & 0xfffffff); - n >>= 28; n += ((sp_int64)a[i + 118]) << 8; - } - r[104] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[215]) << 8; - r[105] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[216]) << 8; - r[106] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[217]) << 8; - r[107] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[218]) << 8; - r[108] = (sp_digit)(n & 0xfffffff); n >>= 28; n += ((sp_int64)a[219]) << 8; - r[109] = (sp_digit)n; - XMEMSET(&r[110], 0, sizeof(*r) * 110U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_112(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_112(a + 110); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<109; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff); - sp_3072_mul_add_112(a+i, m, mu); - a[i+1] += a[i] >> 28; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL); - sp_3072_mul_add_112(a+i, m, mu); - a[i+1] += a[i] >> 28; - a[i] &= 0xfffffff; - } - else { - for (i=0; i<109; i++) { - mu = (sp_digit)(a[i] & 0xfffffff); - sp_3072_mul_add_112(a+i, m, mu); - a[i+1] += a[i] >> 28; - } - mu = (sp_digit)(a[i] & 0xfffffL); - sp_3072_mul_add_112(a+i, m, mu); - a[i+1] += a[i] >> 28; - a[i] &= 0xfffffff; - } -#else - for (i=0; i<109; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff); - sp_3072_mul_add_112(a+i, m, mu); - a[i+1] += a[i] >> 28; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL); - sp_3072_mul_add_112(a+i, m, mu); - a[i+1] += a[i] >> 28; - a[i] &= 0xfffffff; -#endif - sp_3072_mont_shift_112(a, a); - over = a[109] - m[109]; - sp_3072_cond_sub_112(a, a, m, ~((over - 1) >> 31)); - sp_3072_norm_112(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_mul_112(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_3072_mul_112(r, a, b); - sp_3072_mont_reduce_112(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_sqr_112(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_3072_sqr_112(r, a); - sp_3072_mont_reduce_112(r, m, mp); -} - -/* 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_3072_mul_d_224(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 224; 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 & 0xfffffff); - t >>= 28; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0xfffffff); - t >>= 28; - r[i + 3] = (sp_digit)t2; - } - r[224] = (sp_digit)(t & 0xfffffff); -} - -#ifndef 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_3072_cond_add_112(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 112; 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); - } -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_3072_rshift_112(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<104; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (28 - n)) & 0xfffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (28 - n)) & 0xfffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (28 - n)) & 0xfffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (28 - n)) & 0xfffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (28 - n)) & 0xfffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (28 - n)) & 0xfffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (28 - n)) & 0xfffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (28 - n)) & 0xfffffff); - } - r[104] = (a[104] >> n) | (sp_digit)((a[105] << (28 - n)) & 0xfffffff); - r[105] = (a[105] >> n) | (sp_digit)((a[106] << (28 - n)) & 0xfffffff); - r[106] = (a[106] >> n) | (sp_digit)((a[107] << (28 - n)) & 0xfffffff); - r[107] = (a[107] >> n) | (sp_digit)((a[108] << (28 - n)) & 0xfffffff); - r[108] = (a[108] >> n) | (sp_digit)((a[109] << (28 - n)) & 0xfffffff); - r[109] = (a[109] >> n) | (sp_digit)((a[110] << (28 - n)) & 0xfffffff); - r[110] = (a[110] >> n) | (sp_digit)((a[111] << (28 - n)) & 0xfffffff); - r[111] = a[111] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_112(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 28) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 28) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 28) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 28); - sp_digit t0 = (sp_digit)(d & 0xfffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 26; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 27) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 28); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 56) - (sp_digit)(d >> 56); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 28) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 13) + 1; - - t = (sp_digit)(d >> 26); - t = (t / dv) << 13; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 11); - t = t / (dv << 2); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_112(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_112(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 112 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 112 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 224 + 1; - sd = t2 + 112 + 1; - - sp_3072_mul_d_112(sd, d, (sp_digit)1 << 8); - sp_3072_mul_d_224(t1, a, (sp_digit)1 << 8); - dv = sd[109]; - t1[110 + 110] += t1[110 + 110 - 1] >> 28; - t1[110 + 110 - 1] &= 0xfffffff; - for (i=110; i>=0; i--) { - r1 = sp_3072_div_word_112(t1[110 + i], t1[110 + i - 1], dv); - - sp_3072_mul_d_112(t2, sd, r1); - (void)sp_3072_sub_112(&t1[i], &t1[i], t2); - sp_3072_norm_110(&t1[i]); - t1[110 + i] += t1[110 + i - 1] >> 28; - t1[110 + i - 1] &= 0xfffffff; - r1 = sp_3072_div_word_112(-t1[110 + i], -t1[110 + i - 1], dv); - r1 -= t1[110 + i]; - sp_3072_mul_d_112(t2, sd, r1); - (void)sp_3072_add_112(&t1[i], &t1[i], t2); - t1[110 + i] += t1[110 + i - 1] >> 28; - t1[110 + i - 1] &= 0xfffffff; - } - t1[110 - 1] += t1[110 - 2] >> 28; - t1[110 - 2] &= 0xfffffff; - r1 = sp_3072_word_div_word_112(t1[110 - 1], dv); - - sp_3072_mul_d_112(t2, sd, r1); - sp_3072_sub_112(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 224U); - for (i=0; i<109; i++) { - r[i+1] += r[i] >> 28; - r[i] &= 0xfffffff; - } - sp_3072_cond_add_112(r, r, sd, r[109] >> 31); - - sp_3072_norm_110(r); - sp_3072_rshift_112(r, r, 8); - r[110] = 0; - r[111] = 0; - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_112(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_112(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_112(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 224); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 224, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 112 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 112U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_112(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_112(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 112U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_112(t[1], t[1], norm); - err = sp_3072_mod_112(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 28; - c = bits % 28; - n = e[i--] << (28 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 28; - } - - y = (int)((n >> 27) & 1); - n <<= 1; - - sp_3072_mont_mul_112(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 112 * 2); - sp_3072_mont_sqr_112(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 112 * 2); - } - - sp_3072_mont_reduce_112(t[0], m, mp); - n = sp_3072_cmp_112(t[0], m); - sp_3072_cond_sub_112(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 112 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 224); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 224, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 112 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_112(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_112(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_112(t[1], t[1], norm); - err = sp_3072_mod_112(t[1], t[1], m); - } - } - else { - sp_3072_mul_112(t[1], a, norm); - err = sp_3072_mod_112(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 28; - c = bits % 28; - n = e[i--] << (28 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 28; - } - - y = (int)((n >> 27) & 1); - n <<= 1; - - sp_3072_mont_mul_112(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 112 * 2); - sp_3072_mont_sqr_112(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 112 * 2); - } - - sp_3072_mont_reduce_112(t[0], m, mp); - n = sp_3072_cmp_112(t[0], m); - sp_3072_cond_sub_112(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 112 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 224) + 224); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 224) + 224, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 224; - rt = td + 3584; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_112(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_112(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_112(t[1], t[1], norm); - err = sp_3072_mod_112(t[1], t[1], m); - } - } - else { - sp_3072_mul_112(t[1], a, norm); - err = sp_3072_mod_112(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_112(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_112(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_112(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_112(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_112(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_112(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_112(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_112(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_112(t[10], t[ 5], m, mp); - sp_3072_mont_mul_112(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_112(t[12], t[ 6], m, mp); - sp_3072_mont_mul_112(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_112(t[14], t[ 7], m, mp); - sp_3072_mont_mul_112(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 27) / 28) - 1; - c = bits % 28; - if (c == 0) { - c = 28; - } - if (i < 112) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (4 - c); - c += 28; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 224); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 4; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 24; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 4; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 28 - c; - } - - sp_3072_mont_sqr_112(rt, rt, m, mp); - sp_3072_mont_sqr_112(rt, rt, m, mp); - sp_3072_mont_sqr_112(rt, rt, m, mp); - sp_3072_mont_sqr_112(rt, rt, m, mp); - - sp_3072_mont_mul_112(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_112(rt, m, mp); - n = sp_3072_cmp_112(rt, m); - sp_3072_cond_sub_112(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 224); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 112 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 112 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 112 * 2; - m = r + 112 * 2; - norm = r; - - sp_3072_from_bin(a, 112, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_3072_from_mp(m, 112, mm); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_112(norm, m); - } - if (err == MP_OKAY) { - sp_3072_mul_112(a, a, norm); - err = sp_3072_mod_112(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 112 * 2); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_112(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_112(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_112(r, m, mp); - mp = sp_3072_cmp_112(r, m); - sp_3072_cond_sub_112(r, r, m, ~(mp >> 31)); - - sp_3072_to_bin_112(r, out); - *outLen = 384; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 112 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 112 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 112 * 2; - m = r + 112 * 2; - - sp_3072_from_bin(a, 112, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_3072_from_mp(m, 112, mm); - - if (e[0] == 0x3) { - sp_3072_sqr_112(r, a); - err = sp_3072_mod_112(r, r, m); - if (err == MP_OKAY) { - sp_3072_mul_112(r, a, r); - err = sp_3072_mod_112(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_112(norm, m); - - sp_3072_mul_112(a, a, norm); - err = sp_3072_mod_112(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 224U); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_112(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_112(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_112(r, m, mp); - mp = sp_3072_cmp_112(r, m); - sp_3072_cond_sub_112(r, r, m, ~(mp >> 31)); - } - } - } - - if (err == MP_OKAY) { - sp_3072_to_bin_112(r, out); - *outLen = 384; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 112 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 112 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 112; - m = a + 224; - r = a; - - sp_3072_from_bin(a, 112, in, inLen); - sp_3072_from_mp(d, 112, dm); - sp_3072_from_mp(m, 112, mm); - err = sp_3072_mod_exp_112(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_112(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 112, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 112 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 112 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 112; - m = a + 224; - r = a; - - sp_3072_from_bin(a, 112, in, inLen); - sp_3072_from_mp(d, 112, dm); - sp_3072_from_mp(m, 112, mm); - err = sp_3072_mod_exp_112(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_112(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 112, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 56 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 56 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 112; - qi = dq = dp = p + 56; - tmpa = qi + 56; - tmpb = tmpa + 112; - r = a; - - sp_3072_from_bin(a, 112, in, inLen); - sp_3072_from_mp(p, 56, pm); - sp_3072_from_mp(dp, 56, dpm); - err = sp_3072_mod_exp_56(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 56, qm); - sp_3072_from_mp(dq, 56, dqm); - err = sp_3072_mod_exp_56(tmpb, a, dq, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 56, pm); - (void)sp_3072_sub_56(tmpa, tmpa, tmpb); - sp_3072_norm_55(tmpa); - sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31)); - sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31)); - sp_3072_norm_56(tmpa); - - sp_3072_from_mp(qi, 56, qim); - sp_3072_mul_56(tmpa, tmpa, qi); - err = sp_3072_mod_56(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_from_mp(p, 56, qm); - sp_3072_mul_56(tmpa, p, tmpa); - (void)sp_3072_add_112(r, tmpb, tmpa); - sp_3072_norm_112(r); - - sp_3072_to_bin_112(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 56 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 56 * 13); - 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 56 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 112 * 2; - q = p + 56; - dp = q + 56; - dq = dp + 56; - qi = dq + 56; - tmpa = qi + 56; - tmpb = tmpa + 112; - r = a; - - sp_3072_from_bin(a, 112, in, inLen); - sp_3072_from_mp(p, 56, pm); - sp_3072_from_mp(q, 56, qm); - sp_3072_from_mp(dp, 56, dpm); - sp_3072_from_mp(dq, 56, dqm); - sp_3072_from_mp(qi, 56, qim); - - err = sp_3072_mod_exp_56(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - err = sp_3072_mod_exp_56(tmpb, a, dq, 1536, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_3072_sub_56(tmpa, tmpa, tmpb); - sp_3072_norm_55(tmpa); - sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31)); - sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31)); - sp_3072_norm_56(tmpa); - sp_3072_mul_56(tmpa, tmpa, qi); - err = sp_3072_mod_56(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_mul_56(tmpa, tmpa, q); - (void)sp_3072_add_112(r, tmpb, tmpa); - sp_3072_norm_112(r); - - sp_3072_to_bin_112(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 56 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_3072_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 28 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 110); - r->used = 110; - mp_clamp(r); -#elif DIGIT_BIT < 28 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 110; 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 <= 28) { - 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 = 28 - s; - } - r->used = (3072 + 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 < 110; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 28 >= 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 = 28 - s; - } - else { - s += 28; - } - } - r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 112 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 112 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 112 * 2; - m = e + 112; - r = b; - - sp_3072_from_mp(b, 112, base); - sp_3072_from_mp(e, 112, exp); - sp_3072_from_mp(m, 112, mod); - - err = sp_3072_mod_exp_112(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 112U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 112 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 112 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 112 * 2; - m = e + 112; - r = b; - - sp_3072_from_mp(b, 112, base); - sp_3072_from_mp(e, 112, exp); - sp_3072_from_mp(m, 112, mod); - - err = sp_3072_mod_exp_112(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 112U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_3072 -SP_NOINLINE static void sp_3072_lshift_112(sp_digit* r, const sp_digit* a, - byte n) -{ - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[111]; - r[112] = s >> (28U - n); - s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]); - r[111] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]); - r[110] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]); - r[109] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]); - r[108] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]); - r[107] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]); - r[106] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]); - r[105] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]); - r[104] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]); - r[103] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]); - r[102] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]); - r[101] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]); - r[100] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]); - r[99] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]); - r[98] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]); - r[97] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]); - r[96] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]); - r[95] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]); - r[94] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]); - r[93] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]); - r[92] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]); - r[91] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]); - r[90] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]); - r[89] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]); - r[88] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]); - r[87] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]); - r[86] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]); - r[85] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]); - r[84] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]); - r[83] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]); - r[82] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]); - r[81] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]); - r[80] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]); - r[79] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]); - r[78] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); - r[77] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); - r[76] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); - r[75] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); - r[74] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); - r[73] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); - r[72] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); - r[71] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); - r[70] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); - r[69] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); - r[68] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); - r[67] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); - r[66] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); - r[65] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); - r[64] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); - r[63] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); - r[62] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); - r[61] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); - r[60] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); - r[59] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); - r[58] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); - r[57] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); - r[56] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); - r[55] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); - r[54] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); - r[53] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); - r[52] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); - r[51] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); - r[50] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); - r[49] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); - r[48] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); - r[47] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); - r[46] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); - r[45] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); - r[44] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); - r[43] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); - r[42] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); - r[41] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); - r[40] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); - r[39] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); - r[38] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); - r[37] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); - r[36] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (28U - n))) & 0xfffffff); - r[0] = (sp_digit)((a[0] << n) & 0xfffffff); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_3072_mod_exp_2_112(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 337); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 337, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 224; - XMEMSET(td, 0, sizeof(sp_digit) * 337); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_112(norm, m); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 27) / 28) - 1; - c = bits % 28; - if (c == 0) { - c = 28; - } - if (i < 112) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (4 - c); - c += 28; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - sp_3072_lshift_112(r, norm, (byte)y); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 4; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 24; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 4; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 28 - c; - } - - sp_3072_mont_sqr_112(r, r, m, mp); - sp_3072_mont_sqr_112(r, r, m, mp); - sp_3072_mont_sqr_112(r, r, m, mp); - sp_3072_mont_sqr_112(r, r, m, mp); - - sp_3072_lshift_112(r, r, (byte)y); - sp_3072_mul_d_112(tmp, norm, (r[110] << 8) + (r[109] >> 20)); - r[110] = 0; - r[109] &= 0xfffffL; - (void)sp_3072_add_112(r, r, tmp); - sp_3072_norm_112(r); - o = sp_3072_cmp_112(r, m); - sp_3072_cond_sub_112(r, r, m, ~(o >> 31)); - } - - sp_3072_mont_reduce_112(r, m, mp); - n = sp_3072_cmp_112(r, m); - sp_3072_cond_sub_112(r, r, m, (sp_digit)~(n >> 31)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_3072 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 112 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 112 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 112 * 2; - m = e + 112; - r = b; - - sp_3072_from_mp(b, 112, base); - sp_3072_from_bin(e, 112, exp, expLen); - sp_3072_from_mp(m, 112, mod); - - #ifdef HAVE_FFDHE_3072 - if (base->used == 1 && base->dp[0] == 2U && - (m[109] >> 4) == 0xffffL) { - err = sp_3072_mod_exp_2_112(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_3072_mod_exp_112(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_3072 - } - #endif - } - - if (err == MP_OKAY) { - sp_3072_to_bin_112(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 112U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 56 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 56 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 56 * 2; - m = e + 56; - r = b; - - sp_3072_from_mp(b, 56, base); - sp_3072_from_mp(e, 56, exp); - sp_3072_from_mp(m, 56, mod); - - err = sp_3072_mod_exp_56(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 56, 0, sizeof(*r) * 56U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 112U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 56 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 56 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 56 * 2; - m = e + 56; - r = b; - - sp_3072_from_mp(b, 56, base); - sp_3072_from_mp(e, 56, exp); - sp_3072_from_mp(m, 56, mod); - - err = sp_3072_mod_exp_56(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 56, 0, sizeof(*r) * 56U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 112U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#endif /* WOLFSSL_SP_SMALL */ -#endif /* !WOLFSSL_SP_NO_3072 */ - -#ifdef WOLFSSL_SP_4096 -#ifdef WOLFSSL_SP_SMALL -/* 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_4096_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 >= 21U) { - r[j] &= 0x1fffffff; - s = 29U - 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; - } -} - -/* 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_4096_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 29 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 28); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 28); - } -#elif DIGIT_BIT > 29 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x1fffffff; - s = 29U - 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 + 29U) <= (word32)DIGIT_BIT) { - s += 29U; - r[j] &= 0x1fffffff; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 29) { - r[j] &= 0x1fffffff; - if (j + 1 >= size) { - break; - } - s = 29 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 512 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_4096_to_bin_142(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<141; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - j = 4103 / 8 - 1; - a[j] = 0; - for (i=0; i<142 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 29) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 29); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_71(sp_digit* a) -{ - int i; - for (i = 0; i < 70; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -} - -#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_142(sp_digit* a) -{ - int i; - for (i = 0; i < 141; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -} - -/* 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_4096_mul_142(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[141]) * b[141]; - r[283] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 281; k >= 0; k--) { - if (k >= 142) { - i = k - 141; - imax = 141; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - lo &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - } - r[0] = (sp_digit)c; -} - -/* 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_4096_sqr_142(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[141]) * a[141]; - r[283] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 281; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 141) { - imax = k; - } - else { - imax = 141; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint64 hi; - - hi = c >> 29; - c &= 0x1fffffff; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 29; - c &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(hi >> 29); - r[k + 1] = (sp_digit)(hi & 0x1fffffff); - c <<= 29; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - } - r[0] = (sp_digit)(c >> 29); -} - -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x &= 0x1fffffff; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 29) - x; -} - -/* 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_4096_mul_d_142(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 142; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[142] = (sp_digit)t; -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* 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_71(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 71; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_71(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<70; i++) { - r[i] = 0x1fffffff; - } - r[70] = 0x3ffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_71(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_71(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=70; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } - - 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_4096_cond_sub_71(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 71; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_4096_mul_add_71(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 71; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[71] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 68; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[68]) + r[68]; - t[1] = (tb * a[69]) + r[69]; - t[2] = (tb * a[70]) + r[70]; - r[68] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[69] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[70] = (sp_digit)(t[2] & 0x1fffffff); - r[71] += (sp_digit)(t[2] >> 29); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_71(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[70] >> 18; - n += ((sp_int64)a[71]) << 11; - - for (i = 0; i < 70; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[72 + i]) << 11; - } - r[70] = (sp_digit)n; - XMEMSET(&r[71], 0, sizeof(*r) * 71U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_71(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_71(a + 71); - - for (i=0; i<70; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_4096_mul_add_71(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL); - sp_4096_mul_add_71(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - sp_4096_mont_shift_71(a, a); - over = a[70] - m[70]; - sp_4096_cond_sub_71(a, a, m, ~((over - 1) >> 31)); - sp_4096_norm_71(a); -} - -/* 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_4096_mul_71(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[70]) * b[70]; - r[141] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 139; k >= 0; k--) { - if (k >= 71) { - i = k - 70; - imax = 70; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - lo &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - } - r[0] = (sp_digit)c; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_mul_71(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_4096_mul_71(r, a, b); - sp_4096_mont_reduce_71(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_4096_sqr_71(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[70]) * a[70]; - r[141] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 139; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 70) { - imax = k; - } - else { - imax = 70; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint64 hi; - - hi = c >> 29; - c &= 0x1fffffff; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 29; - c &= 0x1fffffff; - } - r[k + 2] += (sp_digit)(hi >> 29); - r[k + 1] = (sp_digit)(hi & 0x1fffffff); - c <<= 29; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - } - r[0] = (sp_digit)(c >> 29); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_sqr_71(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_4096_sqr_71(r, a); - sp_4096_mont_reduce_71(r, m, mp); -} - -/* 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_4096_mul_d_71(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 71; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[71] = (sp_digit)t; -} - -#ifdef 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_4096_cond_add_71(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 71; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_4096_add_71(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 71; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_4096_rshift_71(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<70; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } - r[70] = a[70] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_71(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 29) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 29); - sp_digit t0 = (sp_digit)(d & 0x1fffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 27; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 28) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 29); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 14) + 1; - - t = (sp_digit)(d >> 28); - t = (t / dv) << 14; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 1); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_71(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_71(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 71 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 71 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 142 + 1; - sd = t2 + 71 + 1; - - sp_4096_mul_d_71(sd, d, (sp_digit)1 << 11); - sp_4096_mul_d_142(t1, a, (sp_digit)1 << 11); - dv = sd[70]; - t1[71 + 71] += t1[71 + 71 - 1] >> 29; - t1[71 + 71 - 1] &= 0x1fffffff; - for (i=71; i>=0; i--) { - r1 = sp_4096_div_word_71(t1[71 + i], t1[71 + i - 1], dv); - - sp_4096_mul_d_71(t2, sd, r1); - (void)sp_4096_sub_71(&t1[i], &t1[i], t2); - sp_4096_norm_71(&t1[i]); - t1[71 + i] -= t2[71]; - t1[71 + i] += t1[71 + i - 1] >> 29; - t1[71 + i - 1] &= 0x1fffffff; - r1 = sp_4096_div_word_71(-t1[71 + i], -t1[71 + i - 1], dv); - r1 -= t1[71 + i]; - sp_4096_mul_d_71(t2, sd, r1); - (void)sp_4096_add_71(&t1[i], &t1[i], t2); - t1[71 + i] += t1[71 + i - 1] >> 29; - t1[71 + i - 1] &= 0x1fffffff; - } - t1[71 - 1] += t1[71 - 2] >> 29; - t1[71 - 2] &= 0x1fffffff; - r1 = sp_4096_word_div_word_71(t1[71 - 1], dv); - - sp_4096_mul_d_71(t2, sd, r1); - sp_4096_sub_71(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 142U); - for (i=0; i<70; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - sp_4096_cond_add_71(r, r, sd, r[70] >> 31); - - sp_4096_norm_71(r); - sp_4096_rshift_71(r, r, 11); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_71(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_71(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_71(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 142); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 142, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 71 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 71U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_71(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_71(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 71U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_71(t[1], t[1], norm); - err = sp_4096_mod_71(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_4096_mont_mul_71(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 71 * 2); - sp_4096_mont_sqr_71(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 71 * 2); - } - - sp_4096_mont_reduce_71(t[0], m, mp); - n = sp_4096_cmp_71(t[0], m); - sp_4096_cond_sub_71(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 71 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 142); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 142, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 71 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_71(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_71(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_71(t[1], t[1], norm); - err = sp_4096_mod_71(t[1], t[1], m); - } - } - else { - sp_4096_mul_71(t[1], a, norm); - err = sp_4096_mod_71(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_4096_mont_mul_71(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 71 * 2); - sp_4096_mont_sqr_71(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 71 * 2); - } - - sp_4096_mont_reduce_71(t[0], m, mp); - n = sp_4096_cmp_71(t[0], m); - sp_4096_cond_sub_71(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 71 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 142) + 142); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 142) + 142, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 142; - rt = td + 4544; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_71(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_71(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_71(t[1], t[1], norm); - err = sp_4096_mod_71(t[1], t[1], m); - } - } - else { - sp_4096_mul_71(t[1], a, norm); - err = sp_4096_mod_71(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_71(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_71(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_71(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_71(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_71(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_71(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_71(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_71(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_71(t[10], t[ 5], m, mp); - sp_4096_mont_mul_71(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_71(t[12], t[ 6], m, mp); - sp_4096_mont_mul_71(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_71(t[14], t[ 7], m, mp); - sp_4096_mont_mul_71(t[15], t[ 8], t[ 7], m, mp); - sp_4096_mont_sqr_71(t[16], t[ 8], m, mp); - sp_4096_mont_mul_71(t[17], t[ 9], t[ 8], m, mp); - sp_4096_mont_sqr_71(t[18], t[ 9], m, mp); - sp_4096_mont_mul_71(t[19], t[10], t[ 9], m, mp); - sp_4096_mont_sqr_71(t[20], t[10], m, mp); - sp_4096_mont_mul_71(t[21], t[11], t[10], m, mp); - sp_4096_mont_sqr_71(t[22], t[11], m, mp); - sp_4096_mont_mul_71(t[23], t[12], t[11], m, mp); - sp_4096_mont_sqr_71(t[24], t[12], m, mp); - sp_4096_mont_mul_71(t[25], t[13], t[12], m, mp); - sp_4096_mont_sqr_71(t[26], t[13], m, mp); - sp_4096_mont_mul_71(t[27], t[14], t[13], m, mp); - sp_4096_mont_sqr_71(t[28], t[14], m, mp); - sp_4096_mont_mul_71(t[29], t[15], t[14], m, mp); - sp_4096_mont_sqr_71(t[30], t[15], m, mp); - sp_4096_mont_mul_71(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 71) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 142); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c = 24; - } - else { - y = (byte)((n >> 27) & 0x1f); - n = e[i--] << 3; - c = 5 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_4096_mont_sqr_71(rt, rt, m, mp); - sp_4096_mont_sqr_71(rt, rt, m, mp); - sp_4096_mont_sqr_71(rt, rt, m, mp); - sp_4096_mont_sqr_71(rt, rt, m, mp); - sp_4096_mont_sqr_71(rt, rt, m, mp); - - sp_4096_mont_mul_71(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_71(rt, m, mp); - n = sp_4096_cmp_71(rt, m); - sp_4096_cond_sub_71(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 142); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ - -/* 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_142(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 142; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_142(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<141; i++) { - r[i] = 0x1fffffff; - } - r[141] = 0x7fL; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_142(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_142(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=141; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } - - 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_4096_cond_sub_142(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 142; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_4096_mul_add_142(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 142; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[142] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 140; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[140]) + r[140]; - t[1] = (tb * a[141]) + r[141]; - r[140] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[141] = (sp_digit)(t[1] & 0x1fffffff); - r[142] += (sp_digit)(t[1] >> 29); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 4096 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_142(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[141] >> 7; - n += ((sp_int64)a[142]) << 22; - - for (i = 0; i < 141; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[143 + i]) << 22; - } - r[141] = (sp_digit)n; - XMEMSET(&r[142], 0, sizeof(*r) * 142U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_142(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_142(a + 142); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<141; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_4096_mul_add_142(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x7fL); - sp_4096_mul_add_142(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } - else { - for (i=0; i<141; i++) { - mu = (sp_digit)(a[i] & 0x1fffffff); - sp_4096_mul_add_142(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(a[i] & 0x7fL); - sp_4096_mul_add_142(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - for (i=0; i<141; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_4096_mul_add_142(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x7fL); - sp_4096_mul_add_142(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; -#endif - sp_4096_mont_shift_142(a, a); - over = a[141] - m[141]; - sp_4096_cond_sub_142(a, a, m, ~((over - 1) >> 31)); - sp_4096_norm_142(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_mul_142(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_4096_mul_142(r, a, b); - sp_4096_mont_reduce_142(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_sqr_142(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_4096_sqr_142(r, a); - sp_4096_mont_reduce_142(r, m, mp); -} - -/* 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_4096_mul_d_284(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 284; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[284] = (sp_digit)t; -} - -#ifdef 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_4096_cond_add_142(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 142; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_4096_add_142(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 142; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_4096_rshift_142(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<141; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } - r[141] = a[141] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_142(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 29) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 29); - sp_digit t0 = (sp_digit)(d & 0x1fffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 27; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 28) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 29); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 29) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 14) + 1; - - t = (sp_digit)(d >> 28); - t = (t / dv) << 14; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 1); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_142(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_142(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 142 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 142 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 284 + 1; - sd = t2 + 142 + 1; - - sp_4096_mul_d_142(sd, d, (sp_digit)1 << 22); - sp_4096_mul_d_284(t1, a, (sp_digit)1 << 22); - dv = sd[141]; - t1[142 + 142] += t1[142 + 142 - 1] >> 29; - t1[142 + 142 - 1] &= 0x1fffffff; - for (i=142; i>=0; i--) { - r1 = sp_4096_div_word_142(t1[142 + i], t1[142 + i - 1], dv); - - sp_4096_mul_d_142(t2, sd, r1); - (void)sp_4096_sub_142(&t1[i], &t1[i], t2); - sp_4096_norm_142(&t1[i]); - t1[142 + i] -= t2[142]; - t1[142 + i] += t1[142 + i - 1] >> 29; - t1[142 + i - 1] &= 0x1fffffff; - r1 = sp_4096_div_word_142(-t1[142 + i], -t1[142 + i - 1], dv); - r1 -= t1[142 + i]; - sp_4096_mul_d_142(t2, sd, r1); - (void)sp_4096_add_142(&t1[i], &t1[i], t2); - t1[142 + i] += t1[142 + i - 1] >> 29; - t1[142 + i - 1] &= 0x1fffffff; - } - t1[142 - 1] += t1[142 - 2] >> 29; - t1[142 - 2] &= 0x1fffffff; - r1 = sp_4096_word_div_word_142(t1[142 - 1], dv); - - sp_4096_mul_d_142(t2, sd, r1); - sp_4096_sub_142(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 284U); - for (i=0; i<141; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - sp_4096_cond_add_142(r, r, sd, r[141] >> 31); - - sp_4096_norm_142(r); - sp_4096_rshift_142(r, r, 22); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_142(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_142(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_142(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 284); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 284, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 142 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 142U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_142(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_142(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 142U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_142(t[1], t[1], norm); - err = sp_4096_mod_142(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_4096_mont_mul_142(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 142 * 2); - sp_4096_mont_sqr_142(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 142 * 2); - } - - sp_4096_mont_reduce_142(t[0], m, mp); - n = sp_4096_cmp_142(t[0], m); - sp_4096_cond_sub_142(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 142 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 284); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 284, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 142 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_142(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_142(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_142(t[1], t[1], norm); - err = sp_4096_mod_142(t[1], t[1], m); - } - } - else { - sp_4096_mul_142(t[1], a, norm); - err = sp_4096_mod_142(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 29; - c = bits % 29; - n = e[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 29; - } - - y = (int)((n >> 28) & 1); - n <<= 1; - - sp_4096_mont_mul_142(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 142 * 2); - sp_4096_mont_sqr_142(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 142 * 2); - } - - sp_4096_mont_reduce_142(t[0], m, mp); - n = sp_4096_cmp_142(t[0], m); - sp_4096_cond_sub_142(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 142 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 284) + 284); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 284) + 284, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 284; - rt = td + 4544; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_142(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_142(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_142(t[1], t[1], norm); - err = sp_4096_mod_142(t[1], t[1], m); - } - } - else { - sp_4096_mul_142(t[1], a, norm); - err = sp_4096_mod_142(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_142(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_142(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_142(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_142(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_142(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_142(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_142(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_142(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_142(t[10], t[ 5], m, mp); - sp_4096_mont_mul_142(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_142(t[12], t[ 6], m, mp); - sp_4096_mont_mul_142(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_142(t[14], t[ 7], m, mp); - sp_4096_mont_mul_142(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 142) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 284); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 25; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_4096_mont_sqr_142(rt, rt, m, mp); - sp_4096_mont_sqr_142(rt, rt, m, mp); - sp_4096_mont_sqr_142(rt, rt, m, mp); - sp_4096_mont_sqr_142(rt, rt, m, mp); - - sp_4096_mont_mul_142(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_142(rt, m, mp); - n = sp_4096_cmp_142(rt, m); - sp_4096_cond_sub_142(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 284); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 142 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 142 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 142 * 2; - m = r + 142 * 2; - norm = r; - - sp_4096_from_bin(a, 142, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_4096_from_mp(m, 142, mm); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_142(norm, m); - } - if (err == MP_OKAY) { - sp_4096_mul_142(a, a, norm); - err = sp_4096_mod_142(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 142 * 2); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_142(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_142(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_142(r, m, mp); - mp = sp_4096_cmp_142(r, m); - sp_4096_cond_sub_142(r, r, m, ~(mp >> 31)); - - sp_4096_to_bin_142(r, out); - *outLen = 512; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 142 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 142 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 142 * 2; - m = r + 142 * 2; - - sp_4096_from_bin(a, 142, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_4096_from_mp(m, 142, mm); - - if (e[0] == 0x3) { - sp_4096_sqr_142(r, a); - err = sp_4096_mod_142(r, r, m); - if (err == MP_OKAY) { - sp_4096_mul_142(r, a, r); - err = sp_4096_mod_142(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_142(norm, m); - - sp_4096_mul_142(a, a, norm); - err = sp_4096_mod_142(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 284U); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_142(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_142(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_142(r, m, mp); - mp = sp_4096_cmp_142(r, m); - sp_4096_cond_sub_142(r, r, m, ~(mp >> 31)); - } - } - } - - if (err == MP_OKAY) { - sp_4096_to_bin_142(r, out); - *outLen = 512; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 142 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 142 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 142; - m = a + 284; - r = a; - - sp_4096_from_bin(a, 142, in, inLen); - sp_4096_from_mp(d, 142, dm); - sp_4096_from_mp(m, 142, mm); - err = sp_4096_mod_exp_142(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_142(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 142, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 142 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 142 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 142; - m = a + 284; - r = a; - - sp_4096_from_bin(a, 142, in, inLen); - sp_4096_from_mp(d, 142, dm); - sp_4096_from_mp(m, 142, mm); - err = sp_4096_mod_exp_142(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_142(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 142, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 71 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 71 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 142; - qi = dq = dp = p + 71; - tmpa = qi + 71; - tmpb = tmpa + 142; - r = a; - - sp_4096_from_bin(a, 142, in, inLen); - sp_4096_from_mp(p, 71, pm); - sp_4096_from_mp(dp, 71, dpm); - err = sp_4096_mod_exp_71(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 71, qm); - sp_4096_from_mp(dq, 71, dqm); - err = sp_4096_mod_exp_71(tmpb, a, dq, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 71, pm); - (void)sp_4096_sub_71(tmpa, tmpa, tmpb); - sp_4096_norm_71(tmpa); - sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31)); - sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31)); - sp_4096_norm_71(tmpa); - - sp_4096_from_mp(qi, 71, qim); - sp_4096_mul_71(tmpa, tmpa, qi); - err = sp_4096_mod_71(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_from_mp(p, 71, qm); - sp_4096_mul_71(tmpa, p, tmpa); - (void)sp_4096_add_142(r, tmpb, tmpa); - sp_4096_norm_142(r); - - sp_4096_to_bin_142(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 71 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 71 * 13); - 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 71 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 142 * 2; - q = p + 71; - dp = q + 71; - dq = dp + 71; - qi = dq + 71; - tmpa = qi + 71; - tmpb = tmpa + 142; - r = a; - - sp_4096_from_bin(a, 142, in, inLen); - sp_4096_from_mp(p, 71, pm); - sp_4096_from_mp(q, 71, qm); - sp_4096_from_mp(dp, 71, dpm); - sp_4096_from_mp(dq, 71, dqm); - sp_4096_from_mp(qi, 71, qim); - - err = sp_4096_mod_exp_71(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - err = sp_4096_mod_exp_71(tmpb, a, dq, 2048, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_4096_sub_71(tmpa, tmpa, tmpb); - sp_4096_norm_71(tmpa); - sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31)); - sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31)); - sp_4096_norm_71(tmpa); - sp_4096_mul_71(tmpa, tmpa, qi); - err = sp_4096_mod_71(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_mul_71(tmpa, tmpa, q); - (void)sp_4096_add_142(r, tmpb, tmpa); - sp_4096_norm_142(r); - - sp_4096_to_bin_142(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 71 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_4096_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 29 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 142); - r->used = 142; - mp_clamp(r); -#elif DIGIT_BIT < 29 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 142; 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 <= 29) { - 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 = 29 - s; - } - r->used = (4096 + 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 < 142; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 29 >= 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 = 29 - s; - } - else { - s += 29; - } - } - r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 142 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 142 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 142 * 2; - m = e + 142; - r = b; - - sp_4096_from_mp(b, 142, base); - sp_4096_from_mp(e, 142, exp); - sp_4096_from_mp(m, 142, mod); - - err = sp_4096_mod_exp_142(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 142U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 142 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 142 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 142 * 2; - m = e + 142; - r = b; - - sp_4096_from_mp(b, 142, base); - sp_4096_from_mp(e, 142, exp); - sp_4096_from_mp(m, 142, mod); - - err = sp_4096_mod_exp_142(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 142U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_4096 -SP_NOINLINE static void sp_4096_lshift_142(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - r[142] = a[141] >> (29 - n); - for (i=141; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff); - } - r[0] = (sp_digit)((a[0] << n) & 0x1fffffff); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_4096_mod_exp_2_142(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 427); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 427, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 284; - XMEMSET(td, 0, sizeof(sp_digit) * 427); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_142(norm, m); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 28) / 29) - 1; - c = bits % 29; - if (c == 0) { - c = 29; - } - if (i < 142) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 29; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - sp_4096_lshift_142(r, norm, (byte)y); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 25; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 29 - c; - } - - sp_4096_mont_sqr_142(r, r, m, mp); - sp_4096_mont_sqr_142(r, r, m, mp); - sp_4096_mont_sqr_142(r, r, m, mp); - sp_4096_mont_sqr_142(r, r, m, mp); - - sp_4096_lshift_142(r, r, (byte)y); - sp_4096_mul_d_142(tmp, norm, (r[142] << 22) + (r[141] >> 7)); - r[142] = 0; - r[141] &= 0x7fL; - (void)sp_4096_add_142(r, r, tmp); - sp_4096_norm_142(r); - o = sp_4096_cmp_142(r, m); - sp_4096_cond_sub_142(r, r, m, ~(o >> 31)); - } - - sp_4096_mont_reduce_142(r, m, mp); - n = sp_4096_cmp_142(r, m); - sp_4096_cond_sub_142(r, r, m, (sp_digit)~(n >> 31)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_4096 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 142 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 142 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 142 * 2; - m = e + 142; - r = b; - - sp_4096_from_mp(b, 142, base); - sp_4096_from_bin(e, 142, exp, expLen); - sp_4096_from_mp(m, 142, mod); - - #ifdef HAVE_FFDHE_4096 - if (base->used == 1 && base->dp[0] == 2U && - ((m[141] << 9) | (m[140] >> 20)) == 0xffffL) { - err = sp_4096_mod_exp_2_142(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_4096_mod_exp_142(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_4096 - } - #endif - } - - if (err == MP_OKAY) { - sp_4096_to_bin_142(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 142U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#else -/* 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_4096_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 >= 18U) { - r[j] &= 0x3ffffff; - s = 26U - 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; - } -} - -/* 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_4096_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 26 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 25); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 25); - } -#elif DIGIT_BIT > 26 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 512 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_4096_to_bin_162(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<161; i++) { - r[i+1] += r[i] >> 26; - r[i] &= 0x3ffffff; - } - j = 4103 / 8 - 1; - a[j] = 0; - for (i=0; i<158 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 26) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 26); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_81(sp_digit* a) -{ - int i; - for (i = 0; i < 80; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_79(sp_digit* a) -{ - int i; - for (i = 0; i < 72; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[73] += a[72] >> 26; a[72] &= 0x3ffffff; - a[74] += a[73] >> 26; a[73] &= 0x3ffffff; - a[75] += a[74] >> 26; a[74] &= 0x3ffffff; - a[76] += a[75] >> 26; a[75] &= 0x3ffffff; - a[77] += a[76] >> 26; a[76] &= 0x3ffffff; - a[78] += a[77] >> 26; a[77] &= 0x3ffffff; -} - -#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_162(sp_digit* a) -{ - int i; - for (i = 0; i < 160; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[161] += a[160] >> 26; a[160] &= 0x3ffffff; -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_158(sp_digit* a) -{ - int i; - for (i = 0; i < 152; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[153] += a[152] >> 26; a[152] &= 0x3ffffff; - a[154] += a[153] >> 26; a[153] &= 0x3ffffff; - a[155] += a[154] >> 26; a[154] &= 0x3ffffff; - a[156] += a[155] >> 26; a[155] &= 0x3ffffff; - a[157] += a[156] >> 26; a[156] &= 0x3ffffff; -} - -#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_4096_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_uint64 t0; - sp_uint64 t1; - sp_digit t[9]; - - t0 = ((sp_uint64)a[ 0]) * b[ 0]; - t1 = ((sp_uint64)a[ 0]) * b[ 1] - + ((sp_uint64)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 0]) * b[ 2] - + ((sp_uint64)a[ 1]) * b[ 1] - + ((sp_uint64)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 0]) * b[ 3] - + ((sp_uint64)a[ 1]) * b[ 2] - + ((sp_uint64)a[ 2]) * b[ 1] - + ((sp_uint64)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 0]) * b[ 4] - + ((sp_uint64)a[ 1]) * b[ 3] - + ((sp_uint64)a[ 2]) * b[ 2] - + ((sp_uint64)a[ 3]) * b[ 1] - + ((sp_uint64)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 0]) * b[ 5] - + ((sp_uint64)a[ 1]) * b[ 4] - + ((sp_uint64)a[ 2]) * b[ 3] - + ((sp_uint64)a[ 3]) * b[ 2] - + ((sp_uint64)a[ 4]) * b[ 1] - + ((sp_uint64)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 0]) * b[ 6] - + ((sp_uint64)a[ 1]) * b[ 5] - + ((sp_uint64)a[ 2]) * b[ 4] - + ((sp_uint64)a[ 3]) * b[ 3] - + ((sp_uint64)a[ 4]) * b[ 2] - + ((sp_uint64)a[ 5]) * b[ 1] - + ((sp_uint64)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 0]) * b[ 7] - + ((sp_uint64)a[ 1]) * b[ 6] - + ((sp_uint64)a[ 2]) * b[ 5] - + ((sp_uint64)a[ 3]) * b[ 4] - + ((sp_uint64)a[ 4]) * b[ 3] - + ((sp_uint64)a[ 5]) * b[ 2] - + ((sp_uint64)a[ 6]) * b[ 1] - + ((sp_uint64)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 0]) * b[ 8] - + ((sp_uint64)a[ 1]) * b[ 7] - + ((sp_uint64)a[ 2]) * b[ 6] - + ((sp_uint64)a[ 3]) * b[ 5] - + ((sp_uint64)a[ 4]) * b[ 4] - + ((sp_uint64)a[ 5]) * b[ 3] - + ((sp_uint64)a[ 6]) * b[ 2] - + ((sp_uint64)a[ 7]) * b[ 1] - + ((sp_uint64)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 1]) * b[ 8] - + ((sp_uint64)a[ 2]) * b[ 7] - + ((sp_uint64)a[ 3]) * b[ 6] - + ((sp_uint64)a[ 4]) * b[ 5] - + ((sp_uint64)a[ 5]) * b[ 4] - + ((sp_uint64)a[ 6]) * b[ 3] - + ((sp_uint64)a[ 7]) * b[ 2] - + ((sp_uint64)a[ 8]) * b[ 1]; - t[ 8] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 2]) * b[ 8] - + ((sp_uint64)a[ 3]) * b[ 7] - + ((sp_uint64)a[ 4]) * b[ 6] - + ((sp_uint64)a[ 5]) * b[ 5] - + ((sp_uint64)a[ 6]) * b[ 4] - + ((sp_uint64)a[ 7]) * b[ 3] - + ((sp_uint64)a[ 8]) * b[ 2]; - r[ 9] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 3]) * b[ 8] - + ((sp_uint64)a[ 4]) * b[ 7] - + ((sp_uint64)a[ 5]) * b[ 6] - + ((sp_uint64)a[ 6]) * b[ 5] - + ((sp_uint64)a[ 7]) * b[ 4] - + ((sp_uint64)a[ 8]) * b[ 3]; - r[10] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 4]) * b[ 8] - + ((sp_uint64)a[ 5]) * b[ 7] - + ((sp_uint64)a[ 6]) * b[ 6] - + ((sp_uint64)a[ 7]) * b[ 5] - + ((sp_uint64)a[ 8]) * b[ 4]; - r[11] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 5]) * b[ 8] - + ((sp_uint64)a[ 6]) * b[ 7] - + ((sp_uint64)a[ 7]) * b[ 6] - + ((sp_uint64)a[ 8]) * b[ 5]; - r[12] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 6]) * b[ 8] - + ((sp_uint64)a[ 7]) * b[ 7] - + ((sp_uint64)a[ 8]) * b[ 6]; - r[13] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_uint64)a[ 7]) * b[ 8] - + ((sp_uint64)a[ 8]) * b[ 7]; - r[14] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 8]) * b[ 8]; - r[15] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - r[16] = (sp_digit)(t0 & 0x3ffffff); - r[17] = (sp_digit)(t0 >> 26); - XMEMCPY(r, t, sizeof(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. - */ -SP_NOINLINE static int sp_4096_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; -} - -/* 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_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; -} - -/* 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_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; -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_9(sp_digit* a) -{ - a[1] += a[0] >> 26; a[0] &= 0x3ffffff; - a[2] += a[1] >> 26; a[1] &= 0x3ffffff; - a[3] += a[2] >> 26; a[2] &= 0x3ffffff; - a[4] += a[3] >> 26; a[3] &= 0x3ffffff; - a[5] += a[4] >> 26; a[4] &= 0x3ffffff; - a[6] += a[5] >> 26; a[5] &= 0x3ffffff; - a[7] += a[6] >> 26; a[6] &= 0x3ffffff; - a[8] += a[7] >> 26; a[7] &= 0x3ffffff; -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_18(sp_digit* a) -{ - int i; - for (i = 0; i < 16; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[17] += a[16] >> 26; a[16] &= 0x3ffffff; -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_54(sp_digit* a) -{ - int i; - for (i = 0; i < 48; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[49] += a[48] >> 26; a[48] &= 0x3ffffff; - a[50] += a[49] >> 26; a[49] &= 0x3ffffff; - a[51] += a[50] >> 26; a[50] &= 0x3ffffff; - a[52] += a[51] >> 26; a[51] &= 0x3ffffff; - a[53] += a[52] >> 26; a[52] &= 0x3ffffff; -} - -/* 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_4096_mul_27(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit p0[18]; - sp_digit p1[18]; - sp_digit p2[18]; - sp_digit p3[18]; - sp_digit p4[18]; - sp_digit p5[18]; - sp_digit t0[18]; - sp_digit t1[18]; - sp_digit t2[18]; - sp_digit a0[9]; - sp_digit a1[9]; - sp_digit a2[9]; - sp_digit b0[9]; - sp_digit b1[9]; - sp_digit b2[9]; - (void)sp_4096_add_9(a0, a, &a[9]); - sp_4096_norm_9(a0); - (void)sp_4096_add_9(b0, b, &b[9]); - sp_4096_norm_9(b0); - (void)sp_4096_add_9(a1, &a[9], &a[18]); - sp_4096_norm_9(a1); - (void)sp_4096_add_9(b1, &b[9], &b[18]); - sp_4096_norm_9(b1); - (void)sp_4096_add_9(a2, a0, &a[18]); - sp_4096_norm_9(a1); - (void)sp_4096_add_9(b2, b0, &b[18]); - sp_4096_norm_9(b2); - sp_4096_mul_9(p0, a, b); - sp_4096_mul_9(p2, &a[9], &b[9]); - sp_4096_mul_9(p4, &a[18], &b[18]); - sp_4096_mul_9(p1, a0, b0); - sp_4096_mul_9(p3, a1, b1); - sp_4096_mul_9(p5, a2, b2); - XMEMSET(r, 0, sizeof(*r)*2U*27U); - (void)sp_4096_sub_18(t0, p3, p2); - (void)sp_4096_sub_18(t1, p1, p2); - (void)sp_4096_sub_18(t2, p5, t0); - (void)sp_4096_sub_18(t2, t2, t1); - sp_4096_norm_18(t2); - (void)sp_4096_sub_18(t0, t0, p4); - sp_4096_norm_18(t0); - (void)sp_4096_sub_18(t1, t1, p0); - sp_4096_norm_18(t1); - (void)sp_4096_add_18(r, r, p0); - (void)sp_4096_add_18(&r[9], &r[9], t1); - (void)sp_4096_add_18(&r[18], &r[18], t2); - (void)sp_4096_add_18(&r[27], &r[27], t0); - (void)sp_4096_add_18(&r[36], &r[36], p4); - sp_4096_norm_54(r); -} - -/* 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_27(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] + b[24]; - r[25] = a[25] + b[25]; - r[26] = a[26] + b[26]; - - 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_4096_sub_54(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 48; 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[48] = a[48] - b[48]; - r[49] = a[49] - b[49]; - r[50] = a[50] - b[50]; - r[51] = a[51] - b[51]; - r[52] = a[52] - b[52]; - r[53] = a[53] - b[53]; - - 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_4096_add_54(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 48; 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[48] = a[48] + b[48]; - r[49] = a[49] + b[49]; - r[50] = a[50] + b[50]; - r[51] = a[51] + b[51]; - r[52] = a[52] + b[52]; - r[53] = a[53] + b[53]; - - return 0; -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_27(sp_digit* a) -{ - int i; - for (i = 0; i < 24; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[25] += a[24] >> 26; a[24] &= 0x3ffffff; - a[26] += a[25] >> 26; a[25] &= 0x3ffffff; -} - -/* 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_4096_mul_81(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit p0[54]; - sp_digit p1[54]; - sp_digit p2[54]; - sp_digit p3[54]; - sp_digit p4[54]; - sp_digit p5[54]; - sp_digit t0[54]; - sp_digit t1[54]; - sp_digit t2[54]; - sp_digit a0[27]; - sp_digit a1[27]; - sp_digit a2[27]; - sp_digit b0[27]; - sp_digit b1[27]; - sp_digit b2[27]; - (void)sp_4096_add_27(a0, a, &a[27]); - sp_4096_norm_27(a0); - (void)sp_4096_add_27(b0, b, &b[27]); - sp_4096_norm_27(b0); - (void)sp_4096_add_27(a1, &a[27], &a[54]); - sp_4096_norm_27(a1); - (void)sp_4096_add_27(b1, &b[27], &b[54]); - sp_4096_norm_27(b1); - (void)sp_4096_add_27(a2, a0, &a[54]); - sp_4096_norm_27(a1); - (void)sp_4096_add_27(b2, b0, &b[54]); - sp_4096_norm_27(b2); - sp_4096_mul_27(p0, a, b); - sp_4096_mul_27(p2, &a[27], &b[27]); - sp_4096_mul_27(p4, &a[54], &b[54]); - sp_4096_mul_27(p1, a0, b0); - sp_4096_mul_27(p3, a1, b1); - sp_4096_mul_27(p5, a2, b2); - XMEMSET(r, 0, sizeof(*r)*2U*81U); - (void)sp_4096_sub_54(t0, p3, p2); - (void)sp_4096_sub_54(t1, p1, p2); - (void)sp_4096_sub_54(t2, p5, t0); - (void)sp_4096_sub_54(t2, t2, t1); - sp_4096_norm_54(t2); - (void)sp_4096_sub_54(t0, t0, p4); - sp_4096_norm_54(t0); - (void)sp_4096_sub_54(t1, t1, p0); - sp_4096_norm_54(t1); - (void)sp_4096_add_54(r, r, p0); - (void)sp_4096_add_54(&r[27], &r[27], t1); - (void)sp_4096_add_54(&r[54], &r[54], t2); - (void)sp_4096_add_54(&r[81], &r[81], t0); - (void)sp_4096_add_54(&r[108], &r[108], p4); - sp_4096_norm_162(r); -} - -/* 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_81(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 80; 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[80] = a[80] + b[80]; - - 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_4096_add_162(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 160; 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[160] = a[160] + b[160]; - r[161] = a[161] + b[161]; - - 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_4096_sub_162(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 160; 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[160] = a[160] - b[160]; - r[161] = a[161] - b[161]; - - return 0; -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_324(sp_digit* a) -{ - int i; - for (i = 0; i < 320; i += 8) { - a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff; - a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff; - a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff; - a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff; - a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff; - a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff; - a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff; - a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff; - } - a[321] += a[320] >> 26; a[320] &= 0x3ffffff; - a[322] += a[321] >> 26; a[321] &= 0x3ffffff; - a[323] += a[322] >> 26; a[322] &= 0x3ffffff; -} - -/* 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_4096_mul_162(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[162]; - sp_digit* a1 = z1; - sp_digit b1[81]; - sp_digit* z2 = r + 162; - (void)sp_4096_add_81(a1, a, &a[81]); - sp_4096_norm_81(a1); - (void)sp_4096_add_81(b1, b, &b[81]); - sp_4096_norm_81(b1); - sp_4096_mul_81(z2, &a[81], &b[81]); - sp_4096_mul_81(z0, a, b); - sp_4096_mul_81(z1, a1, b1); - (void)sp_4096_sub_162(z1, z1, z2); - (void)sp_4096_sub_162(z1, z1, z0); - (void)sp_4096_add_162(r + 81, r + 81, z1); - sp_4096_norm_324(r); -} - -/* 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_4096_sqr_9(sp_digit* r, const sp_digit* a) -{ - sp_uint64 t0; - sp_uint64 t1; - sp_digit t[9]; - - t0 = ((sp_uint64)a[ 0]) * a[ 0]; - t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 0]) * a[ 2]) * 2 - + ((sp_uint64)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 0]) * a[ 3] - + ((sp_uint64)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 0]) * a[ 4] - + ((sp_uint64)a[ 1]) * a[ 3]) * 2 - + ((sp_uint64)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 0]) * a[ 5] - + ((sp_uint64)a[ 1]) * a[ 4] - + ((sp_uint64)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 0]) * a[ 6] - + ((sp_uint64)a[ 1]) * a[ 5] - + ((sp_uint64)a[ 2]) * a[ 4]) * 2 - + ((sp_uint64)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 0]) * a[ 7] - + ((sp_uint64)a[ 1]) * a[ 6] - + ((sp_uint64)a[ 2]) * a[ 5] - + ((sp_uint64)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 0]) * a[ 8] - + ((sp_uint64)a[ 1]) * a[ 7] - + ((sp_uint64)a[ 2]) * a[ 6] - + ((sp_uint64)a[ 3]) * a[ 5]) * 2 - + ((sp_uint64)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 1]) * a[ 8] - + ((sp_uint64)a[ 2]) * a[ 7] - + ((sp_uint64)a[ 3]) * a[ 6] - + ((sp_uint64)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 2]) * a[ 8] - + ((sp_uint64)a[ 3]) * a[ 7] - + ((sp_uint64)a[ 4]) * a[ 6]) * 2 - + ((sp_uint64)a[ 5]) * a[ 5]; - r[ 9] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 3]) * a[ 8] - + ((sp_uint64)a[ 4]) * a[ 7] - + ((sp_uint64)a[ 5]) * a[ 6]) * 2; - r[10] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 4]) * a[ 8] - + ((sp_uint64)a[ 5]) * a[ 7]) * 2 - + ((sp_uint64)a[ 6]) * a[ 6]; - r[11] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 5]) * a[ 8] - + ((sp_uint64)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_uint64)a[ 6]) * a[ 8]) * 2 - + ((sp_uint64)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_uint64)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_uint64)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - r[16] = (sp_digit)(t0 & 0x3ffffff); - r[17] = (sp_digit)(t0 >> 26); - XMEMCPY(r, t, sizeof(t)); -} - -/* Square a into r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_4096_sqr_27(sp_digit* r, const sp_digit* a) -{ - sp_digit p0[18]; - sp_digit p1[18]; - sp_digit p2[18]; - sp_digit p3[18]; - sp_digit p4[18]; - sp_digit p5[18]; - sp_digit t0[18]; - sp_digit t1[18]; - sp_digit t2[18]; - sp_digit a0[9]; - sp_digit a1[9]; - sp_digit a2[9]; - (void)sp_4096_add_9(a0, a, &a[9]); - sp_4096_norm_9(a0); - (void)sp_4096_add_9(a1, &a[9], &a[18]); - sp_4096_norm_9(a1); - (void)sp_4096_add_9(a2, a0, &a[18]); - sp_4096_norm_9(a2); - sp_4096_sqr_9(p0, a); - sp_4096_sqr_9(p2, &a[9]); - sp_4096_sqr_9(p4, &a[18]); - sp_4096_sqr_9(p1, a0); - sp_4096_sqr_9(p3, a1); - sp_4096_sqr_9(p5, a2); - XMEMSET(r, 0, sizeof(*r)*2U*27U); - (void)sp_4096_sub_18(t0, p3, p2); - (void)sp_4096_sub_18(t1, p1, p2); - (void)sp_4096_sub_18(t2, p5, t0); - (void)sp_4096_sub_18(t2, t2, t1); - sp_4096_norm_18(t2); - (void)sp_4096_sub_18(t0, t0, p4); - sp_4096_norm_18(t0); - (void)sp_4096_sub_18(t1, t1, p0); - sp_4096_norm_18(t1); - (void)sp_4096_add_18(r, r, p0); - (void)sp_4096_add_18(&r[9], &r[9], t1); - (void)sp_4096_add_18(&r[18], &r[18], t2); - (void)sp_4096_add_18(&r[27], &r[27], t0); - (void)sp_4096_add_18(&r[36], &r[36], p4); - sp_4096_norm_54(r); -} - -/* Square a into r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_4096_sqr_81(sp_digit* r, const sp_digit* a) -{ - sp_digit p0[54]; - sp_digit p1[54]; - sp_digit p2[54]; - sp_digit p3[54]; - sp_digit p4[54]; - sp_digit p5[54]; - sp_digit t0[54]; - sp_digit t1[54]; - sp_digit t2[54]; - sp_digit a0[27]; - sp_digit a1[27]; - sp_digit a2[27]; - (void)sp_4096_add_27(a0, a, &a[27]); - sp_4096_norm_27(a0); - (void)sp_4096_add_27(a1, &a[27], &a[54]); - sp_4096_norm_27(a1); - (void)sp_4096_add_27(a2, a0, &a[54]); - sp_4096_norm_27(a2); - sp_4096_sqr_27(p0, a); - sp_4096_sqr_27(p2, &a[27]); - sp_4096_sqr_27(p4, &a[54]); - sp_4096_sqr_27(p1, a0); - sp_4096_sqr_27(p3, a1); - sp_4096_sqr_27(p5, a2); - XMEMSET(r, 0, sizeof(*r)*2U*81U); - (void)sp_4096_sub_54(t0, p3, p2); - (void)sp_4096_sub_54(t1, p1, p2); - (void)sp_4096_sub_54(t2, p5, t0); - (void)sp_4096_sub_54(t2, t2, t1); - sp_4096_norm_54(t2); - (void)sp_4096_sub_54(t0, t0, p4); - sp_4096_norm_54(t0); - (void)sp_4096_sub_54(t1, t1, p0); - sp_4096_norm_54(t1); - (void)sp_4096_add_54(r, r, p0); - (void)sp_4096_add_54(&r[27], &r[27], t1); - (void)sp_4096_add_54(&r[54], &r[54], t2); - (void)sp_4096_add_54(&r[81], &r[81], t0); - (void)sp_4096_add_54(&r[108], &r[108], p4); - sp_4096_norm_162(r); -} - -/* 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_4096_sqr_162(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[162]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 162; - (void)sp_4096_add_81(a1, a, &a[81]); - sp_4096_norm_81(a1); - sp_4096_sqr_81(z2, &a[81]); - sp_4096_sqr_81(z0, a); - sp_4096_sqr_81(z1, a1); - (void)sp_4096_sub_162(z1, z1, z2); - (void)sp_4096_sub_162(z1, z1, z0); - (void)sp_4096_add_162(r + 81, r + 81, z1); - sp_4096_norm_324(r); -} - -#endif /* !WOLFSSL_SP_SMALL */ -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x &= 0x3ffffff; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 26) - x; -} - -/* 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_4096_mul_d_162(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 160; 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 & 0x3ffffff); - t >>= 26; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 3] = (sp_digit)t2; - } - t += tb * a[160]; - r[160] = (sp_digit)(t & 0x3ffffff); - t >>= 26; - t += tb * a[161]; - r[161] = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[162] = (sp_digit)(t & 0x3ffffff); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* 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_81(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 80; 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[80] = a[80] - b[80]; - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_81(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 72; i += 8) { - r[i + 0] = 0x3ffffff; - r[i + 1] = 0x3ffffff; - r[i + 2] = 0x3ffffff; - r[i + 3] = 0x3ffffff; - r[i + 4] = 0x3ffffff; - r[i + 5] = 0x3ffffff; - r[i + 6] = 0x3ffffff; - r[i + 7] = 0x3ffffff; - } - r[72] = 0x3ffffff; - r[73] = 0x3ffffff; - r[74] = 0x3ffffff; - r[75] = 0x3ffffff; - r[76] = 0x3ffffff; - r[77] = 0x3ffffff; - r[78] = 0xfffffL; - r[79] = 0; - r[80] = 0; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_81(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_81(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[80] - b[80]) & (0 - (sp_digit)1); - for (i = 72; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 25); - } - - 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_4096_cond_sub_81(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 80; 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[80] = a[80] - (b[80] & m); -} - -/* 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_4096_mul_add_81(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 81; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x3ffffff; - t >>= 26; - } - r[81] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 80; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0x3ffffff); - t[1] += t[0] >> 26; - r[i+1] = (sp_digit)(t[1] & 0x3ffffff); - t[2] += t[1] >> 26; - r[i+2] = (sp_digit)(t[2] & 0x3ffffff); - t[3] += t[2] >> 26; - r[i+3] = (sp_digit)(t[3] & 0x3ffffff); - t[4] += t[3] >> 26; - r[i+4] = (sp_digit)(t[4] & 0x3ffffff); - t[5] += t[4] >> 26; - r[i+5] = (sp_digit)(t[5] & 0x3ffffff); - t[6] += t[5] >> 26; - r[i+6] = (sp_digit)(t[6] & 0x3ffffff); - t[7] += t[6] >> 26; - r[i+7] = (sp_digit)(t[7] & 0x3ffffff); - t[0] = t[7] >> 26; - } - t[0] += (tb * a[80]) + r[80]; - r[80] = (sp_digit)(t[0] & 0x3ffffff); - r[81] += (sp_digit)(t[0] >> 26); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_81(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[78] >> 20; - n += ((sp_int64)a[79]) << 6; - for (i = 0; i < 72; i += 8) { - r[i + 0] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 80]) << 6; - r[i + 1] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 81]) << 6; - r[i + 2] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 82]) << 6; - r[i + 3] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 83]) << 6; - r[i + 4] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 84]) << 6; - r[i + 5] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 85]) << 6; - r[i + 6] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 86]) << 6; - r[i + 7] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 87]) << 6; - } - r[72] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[152]) << 6; - r[73] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[153]) << 6; - r[74] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[154]) << 6; - r[75] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[155]) << 6; - r[76] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[156]) << 6; - r[77] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[157]) << 6; - r[78] = (sp_digit)n; - XMEMSET(&r[79], 0, sizeof(*r) * 79U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_81(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_81(a + 79); - - for (i=0; i<78; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff); - sp_4096_mul_add_81(a+i, m, mu); - a[i+1] += a[i] >> 26; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL); - sp_4096_mul_add_81(a+i, m, mu); - a[i+1] += a[i] >> 26; - a[i] &= 0x3ffffff; - sp_4096_mont_shift_81(a, a); - over = a[78] - m[78]; - sp_4096_cond_sub_81(a, a, m, ~((over - 1) >> 31)); - sp_4096_norm_81(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_mul_81(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_4096_mul_81(r, a, b); - sp_4096_mont_reduce_81(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_sqr_81(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_4096_sqr_81(r, a); - sp_4096_mont_reduce_81(r, m, mp); -} - -/* 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_4096_mul_d_81(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 80; 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 & 0x3ffffff); - t >>= 26; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 3] = (sp_digit)t2; - } - t += tb * a[80]; - r[80] = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[81] = (sp_digit)(t & 0x3ffffff); -} - -#ifndef 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_4096_cond_add_81(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 80; 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[80] = a[80] + (b[80] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_4096_rshift_81(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<80; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (26 - n)) & 0x3ffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (26 - n)) & 0x3ffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (26 - n)) & 0x3ffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (26 - n)) & 0x3ffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (26 - n)) & 0x3ffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (26 - n)) & 0x3ffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (26 - n)) & 0x3ffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (26 - n)) & 0x3ffffff); - } - r[80] = a[80] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_81(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 26) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 26) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 26) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 26); - sp_digit t0 = (sp_digit)(d & 0x3ffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 24; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 25) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 26); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 52) - (sp_digit)(d >> 52); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 26) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 11) + 1; - - t = (sp_digit)(d >> 22); - t = (t / dv) << 11; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 7); - t = t / (dv << 4); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_81(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_81(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 81 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 81 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 162 + 1; - sd = t2 + 81 + 1; - - sp_4096_mul_d_81(sd, d, (sp_digit)1 << 6); - sp_4096_mul_d_162(t1, a, (sp_digit)1 << 6); - dv = sd[78]; - t1[79 + 79] += t1[79 + 79 - 1] >> 26; - t1[79 + 79 - 1] &= 0x3ffffff; - for (i=79; i>=0; i--) { - r1 = sp_4096_div_word_81(t1[79 + i], t1[79 + i - 1], dv); - - sp_4096_mul_d_81(t2, sd, r1); - (void)sp_4096_sub_81(&t1[i], &t1[i], t2); - sp_4096_norm_79(&t1[i]); - t1[79 + i] += t1[79 + i - 1] >> 26; - t1[79 + i - 1] &= 0x3ffffff; - r1 = sp_4096_div_word_81(-t1[79 + i], -t1[79 + i - 1], dv); - r1 -= t1[79 + i]; - sp_4096_mul_d_81(t2, sd, r1); - (void)sp_4096_add_81(&t1[i], &t1[i], t2); - t1[79 + i] += t1[79 + i - 1] >> 26; - t1[79 + i - 1] &= 0x3ffffff; - } - t1[79 - 1] += t1[79 - 2] >> 26; - t1[79 - 2] &= 0x3ffffff; - r1 = sp_4096_word_div_word_81(t1[79 - 1], dv); - - sp_4096_mul_d_81(t2, sd, r1); - sp_4096_sub_81(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 162U); - for (i=0; i<78; i++) { - r[i+1] += r[i] >> 26; - r[i] &= 0x3ffffff; - } - sp_4096_cond_add_81(r, r, sd, r[78] >> 31); - - sp_4096_norm_79(r); - sp_4096_rshift_81(r, r, 6); - r[79] = 0; - r[80] = 0; - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_81(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_81(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_81(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 162); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 162, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 81 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 81U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_81(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_81(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 81U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_81(t[1], t[1], norm); - err = sp_4096_mod_81(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 26; - c = bits % 26; - n = e[i--] << (26 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 26; - } - - y = (int)((n >> 25) & 1); - n <<= 1; - - sp_4096_mont_mul_81(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 81 * 2); - sp_4096_mont_sqr_81(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 81 * 2); - } - - sp_4096_mont_reduce_81(t[0], m, mp); - n = sp_4096_cmp_81(t[0], m); - sp_4096_cond_sub_81(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 81 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 162); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 162, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 81 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_81(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_81(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_81(t[1], t[1], norm); - err = sp_4096_mod_81(t[1], t[1], m); - } - } - else { - sp_4096_mul_81(t[1], a, norm); - err = sp_4096_mod_81(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 26; - c = bits % 26; - n = e[i--] << (26 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 26; - } - - y = (int)((n >> 25) & 1); - n <<= 1; - - sp_4096_mont_mul_81(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 81 * 2); - sp_4096_mont_sqr_81(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 81 * 2); - } - - sp_4096_mont_reduce_81(t[0], m, mp); - n = sp_4096_cmp_81(t[0], m); - sp_4096_cond_sub_81(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 81 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 162) + 162); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 162) + 162, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 162; - rt = td + 5184; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_81(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_81(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_81(t[1], t[1], norm); - err = sp_4096_mod_81(t[1], t[1], m); - } - } - else { - sp_4096_mul_81(t[1], a, norm); - err = sp_4096_mod_81(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_81(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_81(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_81(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_81(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_81(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_81(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_81(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_81(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_81(t[10], t[ 5], m, mp); - sp_4096_mont_mul_81(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_81(t[12], t[ 6], m, mp); - sp_4096_mont_mul_81(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_81(t[14], t[ 7], m, mp); - sp_4096_mont_mul_81(t[15], t[ 8], t[ 7], m, mp); - sp_4096_mont_sqr_81(t[16], t[ 8], m, mp); - sp_4096_mont_mul_81(t[17], t[ 9], t[ 8], m, mp); - sp_4096_mont_sqr_81(t[18], t[ 9], m, mp); - sp_4096_mont_mul_81(t[19], t[10], t[ 9], m, mp); - sp_4096_mont_sqr_81(t[20], t[10], m, mp); - sp_4096_mont_mul_81(t[21], t[11], t[10], m, mp); - sp_4096_mont_sqr_81(t[22], t[11], m, mp); - sp_4096_mont_mul_81(t[23], t[12], t[11], m, mp); - sp_4096_mont_sqr_81(t[24], t[12], m, mp); - sp_4096_mont_mul_81(t[25], t[13], t[12], m, mp); - sp_4096_mont_sqr_81(t[26], t[13], m, mp); - sp_4096_mont_mul_81(t[27], t[14], t[13], m, mp); - sp_4096_mont_sqr_81(t[28], t[14], m, mp); - sp_4096_mont_mul_81(t[29], t[15], t[14], m, mp); - sp_4096_mont_sqr_81(t[30], t[15], m, mp); - sp_4096_mont_mul_81(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 25) / 26) - 1; - c = bits % 26; - if (c == 0) { - c = 26; - } - if (i < 81) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (6 - c); - c += 26; - } - y = (int)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 162); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 6; - y = (byte)((n >> 27) & 0x1f); - n <<= 5; - c = 21; - } - else { - y = (byte)((n >> 27) & 0x1f); - n = e[i--] << 6; - c = 5 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 26 - c; - } - - sp_4096_mont_sqr_81(rt, rt, m, mp); - sp_4096_mont_sqr_81(rt, rt, m, mp); - sp_4096_mont_sqr_81(rt, rt, m, mp); - sp_4096_mont_sqr_81(rt, rt, m, mp); - sp_4096_mont_sqr_81(rt, rt, m, mp); - - sp_4096_mont_mul_81(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_81(rt, m, mp); - n = sp_4096_cmp_81(rt, m); - sp_4096_cond_sub_81(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 162); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_162(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 152; i += 8) { - r[i + 0] = 0x3ffffff; - r[i + 1] = 0x3ffffff; - r[i + 2] = 0x3ffffff; - r[i + 3] = 0x3ffffff; - r[i + 4] = 0x3ffffff; - r[i + 5] = 0x3ffffff; - r[i + 6] = 0x3ffffff; - r[i + 7] = 0x3ffffff; - } - r[152] = 0x3ffffff; - r[153] = 0x3ffffff; - r[154] = 0x3ffffff; - r[155] = 0x3ffffff; - r[156] = 0x3ffffff; - r[157] = 0x3fffL; - r[158] = 0; - r[159] = 0; - r[160] = 0; - r[161] = 0; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_162(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_162(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[161] - b[161]) & (0 - (sp_digit)1); - r |= (a[160] - b[160]) & ~(((sp_digit)0 - r) >> 25); - for (i = 152; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 25); - } - - 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_4096_cond_sub_162(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 160; 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[160] = a[160] - (b[160] & m); - r[161] = a[161] - (b[161] & m); -} - -/* 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_4096_mul_add_162(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 162; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x3ffffff; - t >>= 26; - } - r[162] += (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 160; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0x3ffffff); - t[1] += t[0] >> 26; - r[i+1] = (sp_digit)(t[1] & 0x3ffffff); - t[2] += t[1] >> 26; - r[i+2] = (sp_digit)(t[2] & 0x3ffffff); - t[3] += t[2] >> 26; - r[i+3] = (sp_digit)(t[3] & 0x3ffffff); - t[4] += t[3] >> 26; - r[i+4] = (sp_digit)(t[4] & 0x3ffffff); - t[5] += t[4] >> 26; - r[i+5] = (sp_digit)(t[5] & 0x3ffffff); - t[6] += t[5] >> 26; - r[i+6] = (sp_digit)(t[6] & 0x3ffffff); - t[7] += t[6] >> 26; - r[i+7] = (sp_digit)(t[7] & 0x3ffffff); - t[0] = t[7] >> 26; - } - t[0] += (tb * a[160]) + r[160]; - t[1] = (tb * a[161]) + r[161]; - r[160] = (sp_digit)(t[0] & 0x3ffffff); - t[1] += t[0] >> 26; - r[161] = (sp_digit)(t[1] & 0x3ffffff); - r[162] += (sp_digit)(t[1] >> 26); -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Shift the result in the high 4096 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_162(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int64 n = a[157] >> 14; - n += ((sp_int64)a[158]) << 12; - for (i = 0; i < 152; i += 8) { - r[i + 0] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 159]) << 12; - r[i + 1] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 160]) << 12; - r[i + 2] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 161]) << 12; - r[i + 3] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 162]) << 12; - r[i + 4] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 163]) << 12; - r[i + 5] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 164]) << 12; - r[i + 6] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 165]) << 12; - r[i + 7] = (sp_digit)(n & 0x3ffffff); - n >>= 26; n += ((sp_int64)a[i + 166]) << 12; - } - r[152] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[311]) << 12; - r[153] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[312]) << 12; - r[154] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[313]) << 12; - r[155] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[314]) << 12; - r[156] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[315]) << 12; - r[157] = (sp_digit)n; - XMEMSET(&r[158], 0, sizeof(*r) * 158U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_162(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_162(a + 158); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<157; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff); - sp_4096_mul_add_162(a+i, m, mu); - a[i+1] += a[i] >> 26; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3fffL); - sp_4096_mul_add_162(a+i, m, mu); - a[i+1] += a[i] >> 26; - a[i] &= 0x3ffffff; - } - else { - for (i=0; i<157; i++) { - mu = (sp_digit)(a[i] & 0x3ffffff); - sp_4096_mul_add_162(a+i, m, mu); - a[i+1] += a[i] >> 26; - } - mu = (sp_digit)(a[i] & 0x3fffL); - sp_4096_mul_add_162(a+i, m, mu); - a[i+1] += a[i] >> 26; - a[i] &= 0x3ffffff; - } -#else - for (i=0; i<157; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff); - sp_4096_mul_add_162(a+i, m, mu); - a[i+1] += a[i] >> 26; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3fffL); - sp_4096_mul_add_162(a+i, m, mu); - a[i+1] += a[i] >> 26; - a[i] &= 0x3ffffff; -#endif - sp_4096_mont_shift_162(a, a); - over = a[157] - m[157]; - sp_4096_cond_sub_162(a, a, m, ~((over - 1) >> 31)); - sp_4096_norm_162(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_mul_162(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_4096_mul_162(r, a, b); - sp_4096_mont_reduce_162(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_sqr_162(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_4096_sqr_162(r, a); - sp_4096_mont_reduce_162(r, m, mp); -} - -/* 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_4096_mul_d_324(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 324; 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 & 0x3ffffff); - t >>= 26; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x3ffffff); - t >>= 26; - r[i + 3] = (sp_digit)t2; - } - r[324] = (sp_digit)(t & 0x3ffffff); -} - -#ifndef 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_4096_cond_add_162(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 160; 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[160] = a[160] + (b[160] & m); - r[161] = a[161] + (b[161] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_4096_rshift_162(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<160; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (26 - n)) & 0x3ffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (26 - n)) & 0x3ffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (26 - n)) & 0x3ffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (26 - n)) & 0x3ffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (26 - n)) & 0x3ffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (26 - n)) & 0x3ffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (26 - n)) & 0x3ffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (26 - n)) & 0x3ffffff); - } - r[160] = (a[160] >> n) | (sp_digit)((a[161] << (26 - n)) & 0x3ffffff); - r[161] = a[161] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_162(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 26) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 26) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 26) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 26); - sp_digit t0 = (sp_digit)(d & 0x3ffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 24; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 25) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 26); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 52) - (sp_digit)(d >> 52); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 26) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 11) + 1; - - t = (sp_digit)(d >> 22); - t = (t / dv) << 11; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 7); - t = t / (dv << 4); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_162(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_162(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 162 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 162 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 324 + 1; - sd = t2 + 162 + 1; - - sp_4096_mul_d_162(sd, d, (sp_digit)1 << 12); - sp_4096_mul_d_324(t1, a, (sp_digit)1 << 12); - dv = sd[157]; - t1[158 + 158] += t1[158 + 158 - 1] >> 26; - t1[158 + 158 - 1] &= 0x3ffffff; - for (i=158; i>=0; i--) { - r1 = sp_4096_div_word_162(t1[158 + i], t1[158 + i - 1], dv); - - sp_4096_mul_d_162(t2, sd, r1); - (void)sp_4096_sub_162(&t1[i], &t1[i], t2); - sp_4096_norm_158(&t1[i]); - t1[158 + i] += t1[158 + i - 1] >> 26; - t1[158 + i - 1] &= 0x3ffffff; - r1 = sp_4096_div_word_162(-t1[158 + i], -t1[158 + i - 1], dv); - r1 -= t1[158 + i]; - sp_4096_mul_d_162(t2, sd, r1); - (void)sp_4096_add_162(&t1[i], &t1[i], t2); - t1[158 + i] += t1[158 + i - 1] >> 26; - t1[158 + i - 1] &= 0x3ffffff; - } - t1[158 - 1] += t1[158 - 2] >> 26; - t1[158 - 2] &= 0x3ffffff; - r1 = sp_4096_word_div_word_162(t1[158 - 1], dv); - - sp_4096_mul_d_162(t2, sd, r1); - sp_4096_sub_162(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 324U); - for (i=0; i<157; i++) { - r[i+1] += r[i] >> 26; - r[i] &= 0x3ffffff; - } - sp_4096_cond_add_162(r, r, sd, r[157] >> 31); - - sp_4096_norm_158(r); - sp_4096_rshift_162(r, r, 12); - r[158] = 0; - r[159] = 0; - r[160] = 0; - r[161] = 0; - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_162(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_162(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_162(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 324); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 324, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 162 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 162U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_162(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_162(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 162U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_162(t[1], t[1], norm); - err = sp_4096_mod_162(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 26; - c = bits % 26; - n = e[i--] << (26 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 26; - } - - y = (int)((n >> 25) & 1); - n <<= 1; - - sp_4096_mont_mul_162(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 162 * 2); - sp_4096_mont_sqr_162(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 162 * 2); - } - - sp_4096_mont_reduce_162(t[0], m, mp); - n = sp_4096_cmp_162(t[0], m); - sp_4096_cond_sub_162(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 162 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 324); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 324, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 162 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_162(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_162(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_162(t[1], t[1], norm); - err = sp_4096_mod_162(t[1], t[1], m); - } - } - else { - sp_4096_mul_162(t[1], a, norm); - err = sp_4096_mod_162(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 26; - c = bits % 26; - n = e[i--] << (26 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 26; - } - - y = (int)((n >> 25) & 1); - n <<= 1; - - sp_4096_mont_mul_162(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 162 * 2); - sp_4096_mont_sqr_162(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 162 * 2); - } - - sp_4096_mont_reduce_162(t[0], m, mp); - n = sp_4096_cmp_162(t[0], m); - sp_4096_cond_sub_162(t[0], t[0], m, (sp_digit)~(n >> 31)); - XMEMCPY(r, t[0], sizeof(*r) * 162 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 324) + 324); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 324) + 324, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 324; - rt = td + 5184; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_162(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_162(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_162(t[1], t[1], norm); - err = sp_4096_mod_162(t[1], t[1], m); - } - } - else { - sp_4096_mul_162(t[1], a, norm); - err = sp_4096_mod_162(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_162(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_162(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_162(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_162(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_162(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_162(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_162(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_162(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_162(t[10], t[ 5], m, mp); - sp_4096_mont_mul_162(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_162(t[12], t[ 6], m, mp); - sp_4096_mont_mul_162(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_162(t[14], t[ 7], m, mp); - sp_4096_mont_mul_162(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 25) / 26) - 1; - c = bits % 26; - if (c == 0) { - c = 26; - } - if (i < 162) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (6 - c); - c += 26; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 324); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 6; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 22; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 6; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 26 - c; - } - - sp_4096_mont_sqr_162(rt, rt, m, mp); - sp_4096_mont_sqr_162(rt, rt, m, mp); - sp_4096_mont_sqr_162(rt, rt, m, mp); - sp_4096_mont_sqr_162(rt, rt, m, mp); - - sp_4096_mont_mul_162(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_162(rt, m, mp); - n = sp_4096_cmp_162(rt, m); - sp_4096_cond_sub_162(rt, rt, m, (sp_digit)~(n >> 31)); - XMEMCPY(r, rt, sizeof(sp_digit) * 324); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 162 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 162 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 162 * 2; - m = r + 162 * 2; - norm = r; - - sp_4096_from_bin(a, 162, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_4096_from_mp(m, 162, mm); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_162(norm, m); - } - if (err == MP_OKAY) { - sp_4096_mul_162(a, a, norm); - err = sp_4096_mod_162(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 162 * 2); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_162(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_162(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_162(r, m, mp); - mp = sp_4096_cmp_162(r, m); - sp_4096_cond_sub_162(r, r, m, ~(mp >> 31)); - - sp_4096_to_bin_162(r, out); - *outLen = 512; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 162 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 162 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 162 * 2; - m = r + 162 * 2; - - sp_4096_from_bin(a, 162, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_4096_from_mp(m, 162, mm); - - if (e[0] == 0x3) { - sp_4096_sqr_162(r, a); - err = sp_4096_mod_162(r, r, m); - if (err == MP_OKAY) { - sp_4096_mul_162(r, a, r); - err = sp_4096_mod_162(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_162(norm, m); - - sp_4096_mul_162(a, a, norm); - err = sp_4096_mod_162(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 324U); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_162(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_162(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_162(r, m, mp); - mp = sp_4096_cmp_162(r, m); - sp_4096_cond_sub_162(r, r, m, ~(mp >> 31)); - } - } - } - - if (err == MP_OKAY) { - sp_4096_to_bin_162(r, out); - *outLen = 512; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 162 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 162 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 162; - m = a + 324; - r = a; - - sp_4096_from_bin(a, 162, in, inLen); - sp_4096_from_mp(d, 162, dm); - sp_4096_from_mp(m, 162, mm); - err = sp_4096_mod_exp_162(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_162(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 162, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 162 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 162 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 162; - m = a + 324; - r = a; - - sp_4096_from_bin(a, 162, in, inLen); - sp_4096_from_mp(d, 162, dm); - sp_4096_from_mp(m, 162, mm); - err = sp_4096_mod_exp_162(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_162(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 162, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 81 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 81 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 162; - qi = dq = dp = p + 81; - tmpa = qi + 81; - tmpb = tmpa + 162; - r = a; - - sp_4096_from_bin(a, 162, in, inLen); - sp_4096_from_mp(p, 81, pm); - sp_4096_from_mp(dp, 81, dpm); - err = sp_4096_mod_exp_81(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 81, qm); - sp_4096_from_mp(dq, 81, dqm); - err = sp_4096_mod_exp_81(tmpb, a, dq, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 81, pm); - (void)sp_4096_sub_81(tmpa, tmpa, tmpb); - sp_4096_norm_79(tmpa); - sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31)); - sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31)); - sp_4096_norm_81(tmpa); - - sp_4096_from_mp(qi, 81, qim); - sp_4096_mul_81(tmpa, tmpa, qi); - err = sp_4096_mod_81(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_from_mp(p, 81, qm); - sp_4096_mul_81(tmpa, p, tmpa); - (void)sp_4096_add_162(r, tmpb, tmpa); - sp_4096_norm_162(r); - - sp_4096_to_bin_162(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 81 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 81 * 13); - 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 81 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 162 * 2; - q = p + 81; - dp = q + 81; - dq = dp + 81; - qi = dq + 81; - tmpa = qi + 81; - tmpb = tmpa + 162; - r = a; - - sp_4096_from_bin(a, 162, in, inLen); - sp_4096_from_mp(p, 81, pm); - sp_4096_from_mp(q, 81, qm); - sp_4096_from_mp(dp, 81, dpm); - sp_4096_from_mp(dq, 81, dqm); - sp_4096_from_mp(qi, 81, qim); - - err = sp_4096_mod_exp_81(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - err = sp_4096_mod_exp_81(tmpb, a, dq, 2048, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_4096_sub_81(tmpa, tmpa, tmpb); - sp_4096_norm_79(tmpa); - sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31)); - sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31)); - sp_4096_norm_81(tmpa); - sp_4096_mul_81(tmpa, tmpa, qi); - err = sp_4096_mod_81(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_mul_81(tmpa, tmpa, q); - (void)sp_4096_add_162(r, tmpb, tmpa); - sp_4096_norm_162(r); - - sp_4096_to_bin_162(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 81 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_4096_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (4096 + 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) * 158); - r->used = 158; - mp_clamp(r); -#elif DIGIT_BIT < 26 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 158; 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 = (4096 + 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 < 158; 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 = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 162 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 162 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 162 * 2; - m = e + 162; - r = b; - - sp_4096_from_mp(b, 162, base); - sp_4096_from_mp(e, 162, exp); - sp_4096_from_mp(m, 162, mod); - - err = sp_4096_mod_exp_162(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 162U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 162 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 162 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 162 * 2; - m = e + 162; - r = b; - - sp_4096_from_mp(b, 162, base); - sp_4096_from_mp(e, 162, exp); - sp_4096_from_mp(m, 162, mod); - - err = sp_4096_mod_exp_162(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 162U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_4096 -SP_NOINLINE static void sp_4096_lshift_162(sp_digit* r, const sp_digit* a, - byte n) -{ - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[161]; - r[162] = s >> (26U - n); - s = (sp_int_digit)(a[161]); t = (sp_int_digit)(a[160]); - r[161] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[160]); t = (sp_int_digit)(a[159]); - r[160] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[159]); t = (sp_int_digit)(a[158]); - r[159] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[158]); t = (sp_int_digit)(a[157]); - r[158] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[157]); t = (sp_int_digit)(a[156]); - r[157] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[156]); t = (sp_int_digit)(a[155]); - r[156] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[155]); t = (sp_int_digit)(a[154]); - r[155] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[154]); t = (sp_int_digit)(a[153]); - r[154] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[153]); t = (sp_int_digit)(a[152]); - r[153] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[152]); t = (sp_int_digit)(a[151]); - r[152] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[151]); t = (sp_int_digit)(a[150]); - r[151] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[150]); t = (sp_int_digit)(a[149]); - r[150] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[149]); t = (sp_int_digit)(a[148]); - r[149] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[148]); t = (sp_int_digit)(a[147]); - r[148] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[147]); t = (sp_int_digit)(a[146]); - r[147] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[146]); t = (sp_int_digit)(a[145]); - r[146] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[145]); t = (sp_int_digit)(a[144]); - r[145] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[144]); t = (sp_int_digit)(a[143]); - r[144] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[143]); t = (sp_int_digit)(a[142]); - r[143] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[142]); t = (sp_int_digit)(a[141]); - r[142] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[141]); t = (sp_int_digit)(a[140]); - r[141] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[140]); t = (sp_int_digit)(a[139]); - r[140] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[139]); t = (sp_int_digit)(a[138]); - r[139] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[138]); t = (sp_int_digit)(a[137]); - r[138] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[137]); t = (sp_int_digit)(a[136]); - r[137] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[136]); t = (sp_int_digit)(a[135]); - r[136] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[135]); t = (sp_int_digit)(a[134]); - r[135] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[134]); t = (sp_int_digit)(a[133]); - r[134] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[133]); t = (sp_int_digit)(a[132]); - r[133] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[132]); t = (sp_int_digit)(a[131]); - r[132] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[131]); t = (sp_int_digit)(a[130]); - r[131] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[130]); t = (sp_int_digit)(a[129]); - r[130] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[129]); t = (sp_int_digit)(a[128]); - r[129] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[128]); t = (sp_int_digit)(a[127]); - r[128] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[127]); t = (sp_int_digit)(a[126]); - r[127] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[126]); t = (sp_int_digit)(a[125]); - r[126] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[125]); t = (sp_int_digit)(a[124]); - r[125] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[124]); t = (sp_int_digit)(a[123]); - r[124] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[123]); t = (sp_int_digit)(a[122]); - r[123] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[122]); t = (sp_int_digit)(a[121]); - r[122] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[121]); t = (sp_int_digit)(a[120]); - r[121] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[120]); t = (sp_int_digit)(a[119]); - r[120] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[119]); t = (sp_int_digit)(a[118]); - r[119] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[118]); t = (sp_int_digit)(a[117]); - r[118] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[117]); t = (sp_int_digit)(a[116]); - r[117] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[116]); t = (sp_int_digit)(a[115]); - r[116] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[115]); t = (sp_int_digit)(a[114]); - r[115] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[114]); t = (sp_int_digit)(a[113]); - r[114] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[113]); t = (sp_int_digit)(a[112]); - r[113] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[112]); t = (sp_int_digit)(a[111]); - r[112] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]); - r[111] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]); - r[110] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]); - r[109] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]); - r[108] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]); - r[107] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]); - r[106] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]); - r[105] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]); - r[104] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]); - r[103] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]); - r[102] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]); - r[101] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]); - r[100] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]); - r[99] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]); - r[98] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]); - r[97] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]); - r[96] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]); - r[95] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]); - r[94] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]); - r[93] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]); - r[92] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]); - r[91] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]); - r[90] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]); - r[89] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]); - r[88] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]); - r[87] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]); - r[86] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]); - r[85] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]); - r[84] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]); - r[83] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]); - r[82] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]); - r[81] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]); - r[80] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]); - r[79] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]); - r[78] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); - r[77] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); - r[76] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); - r[75] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); - r[74] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); - r[73] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); - r[72] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); - r[71] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); - r[70] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); - r[69] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); - r[68] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); - r[67] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); - r[66] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); - r[65] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); - r[64] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); - r[63] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); - r[62] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); - r[61] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); - r[60] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); - r[59] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); - r[58] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); - r[57] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); - r[56] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); - r[55] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); - r[54] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); - r[53] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); - r[52] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); - r[51] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); - r[50] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); - r[49] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); - r[48] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); - r[47] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); - r[46] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); - r[45] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); - r[44] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); - r[43] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); - r[42] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); - r[41] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); - r[40] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); - r[39] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); - r[38] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); - r[37] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); - r[36] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - r[0] = (sp_digit)((a[0] << n) & 0x3ffffff); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_4096_mod_exp_2_162(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 487); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 487, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 324; - XMEMSET(td, 0, sizeof(sp_digit) * 487); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_162(norm, m); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 25) / 26) - 1; - c = bits % 26; - if (c == 0) { - c = 26; - } - if (i < 162) { - n = e[i--] << (32 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (6 - c); - c += 26; - } - y = (int)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - sp_4096_lshift_162(r, norm, (byte)y); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 6; - y = (byte)((n >> 28) & 0xf); - n <<= 4; - c = 22; - } - else { - y = (byte)((n >> 28) & 0xf); - n = e[i--] << 6; - c = 4 - c; - y |= (byte)((n >> (32 - c)) & ((1 << c) - 1)); - n <<= c; - c = 26 - c; - } - - sp_4096_mont_sqr_162(r, r, m, mp); - sp_4096_mont_sqr_162(r, r, m, mp); - sp_4096_mont_sqr_162(r, r, m, mp); - sp_4096_mont_sqr_162(r, r, m, mp); - - sp_4096_lshift_162(r, r, (byte)y); - sp_4096_mul_d_162(tmp, norm, (r[158] << 12) + (r[157] >> 14)); - r[158] = 0; - r[157] &= 0x3fffL; - (void)sp_4096_add_162(r, r, tmp); - sp_4096_norm_162(r); - o = sp_4096_cmp_162(r, m); - sp_4096_cond_sub_162(r, r, m, ~(o >> 31)); - } - - sp_4096_mont_reduce_162(r, m, mp); - n = sp_4096_cmp_162(r, m); - sp_4096_cond_sub_162(r, r, m, (sp_digit)~(n >> 31)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_4096 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 162 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 162 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 162 * 2; - m = e + 162; - r = b; - - sp_4096_from_mp(b, 162, base); - sp_4096_from_bin(e, 162, exp, expLen); - sp_4096_from_mp(m, 162, mod); - - #ifdef HAVE_FFDHE_4096 - if (base->used == 1 && base->dp[0] == 2U && - ((m[157] << 2) | (m[156] >> 24)) == 0xffffL) { - err = sp_4096_mod_exp_2_162(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_4096_mod_exp_162(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_4096 - } - #endif - } - - if (err == MP_OKAY) { - sp_4096_to_bin_162(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 162U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#endif /* WOLFSSL_SP_SMALL */ -#endif /* WOLFSSL_SP_4096 */ - -#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 * 9]; - /* Y ordinate of point. */ - sp_digit y[2 * 9]; - /* Z ordinate of point. */ - sp_digit z[2 * 9]; - /* Indicates point is at infinity. */ - int infinity; -} sp_point_256; - -/* The modulus (prime) of the curve P256. */ -static const sp_digit p256_mod[9] = { - 0x1fffffff,0x1fffffff,0x1fffffff,0x000001ff,0x00000000,0x00000000, - 0x00040000,0x1fe00000,0x00ffffff -}; -/* The Montgomery normalizer for modulus of the curve P256. */ -static const sp_digit p256_norm_mod[9] = { - 0x00000001,0x00000000,0x00000000,0x1ffffe00,0x1fffffff,0x1fffffff, - 0x1ffbffff,0x001fffff,0x00000000 -}; -/* The Montgomery multiplier for modulus of the curve P256. */ -static const sp_digit p256_mp_mod = 0x0000001; -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -/* The order of the curve P256. */ -static const sp_digit p256_order[9] = { - 0x1c632551,0x1dce5617,0x05e7a13c,0x0df55b4e,0x1ffffbce,0x1fffffff, - 0x0003ffff,0x1fe00000,0x00ffffff -}; -#endif -#ifndef WC_NO_RNG -/* The order of the curve P256 minus 2. */ -static const sp_digit p256_order2[9] = { - 0x1c63254f,0x1dce5617,0x05e7a13c,0x0df55b4e,0x1ffffbce,0x1fffffff, - 0x0003ffff,0x1fe00000,0x00ffffff -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery normalizer for order of the curve P256. */ -static const sp_digit p256_norm_order[9] = { - 0x039cdaaf,0x0231a9e8,0x1a185ec3,0x120aa4b1,0x00000431,0x00000000, - 0x1ffc0000,0x001fffff,0x00000000 -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery multiplier for order of the curve P256. */ -static const sp_digit p256_mp_order = 0xe00bc4f; -#endif -/* The base point of curve P256. */ -static const sp_point_256 p256_base = { - /* X ordinate */ - { - 0x1898c296,0x0509ca2e,0x1acce83d,0x06fb025b,0x040f2770,0x1372b1d2, - 0x091fe2f3,0x1e5c2588,0x006b17d1, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Y ordinate */ - { - 0x17bf51f5,0x1db20341,0x0c57b3b2,0x1c66aed6,0x19e162bc,0x15a53e07, - 0x1e6e3b9f,0x1c5fc34f,0x004fe342, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Z ordinate */ - { - 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) || \ - defined(HAVE_COMP_KEY) -static const sp_digit p256_b[9] = { - 0x07d2604b,0x1e71e1f1,0x14ec3d8e,0x1a0d6198,0x086bc651,0x1eaabb4c, - 0x0f9ecfae,0x1b154752,0x005ac635 -}; -#endif - -#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. - */ -SP_NOINLINE static void sp_256_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[8]) * b[8]; - r[17] = (sp_digit)(c >> 29); - c &= 0x1fffffff; - for (k = 15; k >= 0; k--) { - if (k >= 9) { - i = k - 8; - imax = 8; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 29; - r[k + 2] += (sp_digit)(c >> 29); - r[k + 1] = (sp_digit)(c & 0x1fffffff); - c = lo & 0x1fffffff; - } - r[0] = (sp_digit)c; -} - -#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_256_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_int64 t0; - sp_int64 t1; - sp_digit t[9]; - - t0 = ((sp_int64)a[ 0]) * b[ 0]; - t1 = ((sp_int64)a[ 0]) * b[ 1] - + ((sp_int64)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 0]) * b[ 2] - + ((sp_int64)a[ 1]) * b[ 1] - + ((sp_int64)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 0]) * b[ 3] - + ((sp_int64)a[ 1]) * b[ 2] - + ((sp_int64)a[ 2]) * b[ 1] - + ((sp_int64)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 0]) * b[ 4] - + ((sp_int64)a[ 1]) * b[ 3] - + ((sp_int64)a[ 2]) * b[ 2] - + ((sp_int64)a[ 3]) * b[ 1] - + ((sp_int64)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 0]) * b[ 5] - + ((sp_int64)a[ 1]) * b[ 4] - + ((sp_int64)a[ 2]) * b[ 3] - + ((sp_int64)a[ 3]) * b[ 2] - + ((sp_int64)a[ 4]) * b[ 1] - + ((sp_int64)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 0]) * b[ 6] - + ((sp_int64)a[ 1]) * b[ 5] - + ((sp_int64)a[ 2]) * b[ 4] - + ((sp_int64)a[ 3]) * b[ 3] - + ((sp_int64)a[ 4]) * b[ 2] - + ((sp_int64)a[ 5]) * b[ 1] - + ((sp_int64)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 0]) * b[ 7] - + ((sp_int64)a[ 1]) * b[ 6] - + ((sp_int64)a[ 2]) * b[ 5] - + ((sp_int64)a[ 3]) * b[ 4] - + ((sp_int64)a[ 4]) * b[ 3] - + ((sp_int64)a[ 5]) * b[ 2] - + ((sp_int64)a[ 6]) * b[ 1] - + ((sp_int64)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 0]) * b[ 8] - + ((sp_int64)a[ 1]) * b[ 7] - + ((sp_int64)a[ 2]) * b[ 6] - + ((sp_int64)a[ 3]) * b[ 5] - + ((sp_int64)a[ 4]) * b[ 4] - + ((sp_int64)a[ 5]) * b[ 3] - + ((sp_int64)a[ 6]) * b[ 2] - + ((sp_int64)a[ 7]) * b[ 1] - + ((sp_int64)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 1]) * b[ 8] - + ((sp_int64)a[ 2]) * b[ 7] - + ((sp_int64)a[ 3]) * b[ 6] - + ((sp_int64)a[ 4]) * b[ 5] - + ((sp_int64)a[ 5]) * b[ 4] - + ((sp_int64)a[ 6]) * b[ 3] - + ((sp_int64)a[ 7]) * b[ 2] - + ((sp_int64)a[ 8]) * b[ 1]; - t[ 8] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 2]) * b[ 8] - + ((sp_int64)a[ 3]) * b[ 7] - + ((sp_int64)a[ 4]) * b[ 6] - + ((sp_int64)a[ 5]) * b[ 5] - + ((sp_int64)a[ 6]) * b[ 4] - + ((sp_int64)a[ 7]) * b[ 3] - + ((sp_int64)a[ 8]) * b[ 2]; - r[ 9] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 3]) * b[ 8] - + ((sp_int64)a[ 4]) * b[ 7] - + ((sp_int64)a[ 5]) * b[ 6] - + ((sp_int64)a[ 6]) * b[ 5] - + ((sp_int64)a[ 7]) * b[ 4] - + ((sp_int64)a[ 8]) * b[ 3]; - r[10] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 4]) * b[ 8] - + ((sp_int64)a[ 5]) * b[ 7] - + ((sp_int64)a[ 6]) * b[ 6] - + ((sp_int64)a[ 7]) * b[ 5] - + ((sp_int64)a[ 8]) * b[ 4]; - r[11] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 5]) * b[ 8] - + ((sp_int64)a[ 6]) * b[ 7] - + ((sp_int64)a[ 7]) * b[ 6] - + ((sp_int64)a[ 8]) * b[ 5]; - r[12] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 6]) * b[ 8] - + ((sp_int64)a[ 7]) * b[ 7] - + ((sp_int64)a[ 8]) * b[ 6]; - r[13] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = ((sp_int64)a[ 7]) * b[ 8] - + ((sp_int64)a[ 8]) * b[ 7]; - r[14] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 8]) * b[ 8]; - r[15] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - r[16] = (sp_digit)(t0 & 0x1fffffff); - r[17] = (sp_digit)(t0 >> 29); - XMEMCPY(r, t, sizeof(t)); -} - -#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_9(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[8]) * a[8]; - r[17] = (sp_digit)(c >> 29); - c = (c & 0x1fffffff) << 29; - for (k = 15; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 8) { - imax = k; - } - else { - imax = 8; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 58); - r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff); - c = (c & 0x1fffffff) << 29; - } - r[0] = (sp_digit)(c >> 29); -} - -#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_9(sp_digit* r, const sp_digit* a) -{ - sp_int64 t0; - sp_int64 t1; - sp_digit t[9]; - - t0 = ((sp_int64)a[ 0]) * a[ 0]; - t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 0]) * a[ 2]) * 2 - + ((sp_int64)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 0]) * a[ 3] - + ((sp_int64)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 0]) * a[ 4] - + ((sp_int64)a[ 1]) * a[ 3]) * 2 - + ((sp_int64)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 0]) * a[ 5] - + ((sp_int64)a[ 1]) * a[ 4] - + ((sp_int64)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 0]) * a[ 6] - + ((sp_int64)a[ 1]) * a[ 5] - + ((sp_int64)a[ 2]) * a[ 4]) * 2 - + ((sp_int64)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 0]) * a[ 7] - + ((sp_int64)a[ 1]) * a[ 6] - + ((sp_int64)a[ 2]) * a[ 5] - + ((sp_int64)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 0]) * a[ 8] - + ((sp_int64)a[ 1]) * a[ 7] - + ((sp_int64)a[ 2]) * a[ 6] - + ((sp_int64)a[ 3]) * a[ 5]) * 2 - + ((sp_int64)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 1]) * a[ 8] - + ((sp_int64)a[ 2]) * a[ 7] - + ((sp_int64)a[ 3]) * a[ 6] - + ((sp_int64)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 2]) * a[ 8] - + ((sp_int64)a[ 3]) * a[ 7] - + ((sp_int64)a[ 4]) * a[ 6]) * 2 - + ((sp_int64)a[ 5]) * a[ 5]; - r[ 9] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 3]) * a[ 8] - + ((sp_int64)a[ 4]) * a[ 7] - + ((sp_int64)a[ 5]) * a[ 6]) * 2; - r[10] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 4]) * a[ 8] - + ((sp_int64)a[ 5]) * a[ 7]) * 2 - + ((sp_int64)a[ 6]) * a[ 6]; - r[11] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 5]) * a[ 8] - + ((sp_int64)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = (((sp_int64)a[ 6]) * a[ 8]) * 2 - + ((sp_int64)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - t1 = (((sp_int64)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x1fffffff); t1 += t0 >> 29; - t0 = ((sp_int64)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x1fffffff); t0 += t1 >> 29; - r[16] = (sp_digit)(t0 & 0x1fffffff); - r[17] = (sp_digit)(t0 >> 29); - XMEMCPY(r, t, sizeof(t)); -} - -#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_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 9; 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_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; -} - -#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_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 9; 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_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; -} - -#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 == 29 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 28); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 28); - } -#elif DIGIT_BIT > 29 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x1fffffff; - s = 29U - 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 + 29U) <= (word32)DIGIT_BIT) { - s += 29U; - r[j] &= 0x1fffffff; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 29) { - r[j] &= 0x1fffffff; - if (j + 1 >= size) { - break; - } - s = 29 - 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_9(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, 9, pm->x); - sp_256_from_mp(p->y, 9, pm->y); - sp_256_from_mp(p->z, 9, 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 == 29 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 9); - r->used = 9; - mp_clamp(r); -#elif DIGIT_BIT < 29 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 9; 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 <= 29) { - 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 = 29 - 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 < 9; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 29 >= 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 = 29 - s; - } - else { - s += 29; - } - } - 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_9(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; -} - -/* 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_256_cmp_9(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=8; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28); - } -#else - r |= (a[ 8] - b[ 8]) & (0 - (sp_digit)1); - r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 28); - r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 28); -#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_256_cond_sub_9(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 < 9; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - r[ 0] = a[ 0] - (b[ 0] & m); - r[ 1] = a[ 1] - (b[ 1] & m); - r[ 2] = a[ 2] - (b[ 2] & m); - r[ 3] = a[ 3] - (b[ 3] & m); - r[ 4] = a[ 4] - (b[ 4] & m); - r[ 5] = a[ 5] - (b[ 5] & m); - r[ 6] = a[ 6] - (b[ 6] & m); - r[ 7] = a[ 7] - (b[ 7] & m); - r[ 8] = a[ 8] - (b[ 8] & 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_256_mul_add_9(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifndef WOLFSSL_SP_LARGE_CODE - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 9; i++) { - t += r[i]; - t += tb * a[i]; - r[i] = ((sp_digit)t) & 0x1fffffff; - t >>= 29; - } - r[9] += (sp_digit)t; -#else -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 8; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[0] = t[3] >> 29; - } - t[0] += (tb * a[8]) + r[8]; - r[8] = (sp_digit)(t[0] & 0x1fffffff); - r[9] += (sp_digit)(t[0] >> 29); -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = 0; - for (i = 0; i < 8; i += 8) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - t[4] = (tb * a[i+4]) + r[i+4]; - t[5] = (tb * a[i+5]) + r[i+5]; - t[6] = (tb * a[i+6]) + r[i+6]; - t[7] = (tb * a[i+7]) + r[i+7]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffff); - t[1] += t[0] >> 29; - r[i+1] = (sp_digit)(t[1] & 0x1fffffff); - t[2] += t[1] >> 29; - r[i+2] = (sp_digit)(t[2] & 0x1fffffff); - t[3] += t[2] >> 29; - r[i+3] = (sp_digit)(t[3] & 0x1fffffff); - t[4] += t[3] >> 29; - r[i+4] = (sp_digit)(t[4] & 0x1fffffff); - t[5] += t[4] >> 29; - r[i+5] = (sp_digit)(t[5] & 0x1fffffff); - t[6] += t[5] >> 29; - r[i+6] = (sp_digit)(t[6] & 0x1fffffff); - t[7] += t[6] >> 29; - r[i+7] = (sp_digit)(t[7] & 0x1fffffff); - t[0] = t[7] >> 29; - } - t[0] += (tb * a[8]) + r[8]; - r[8] = (sp_digit)(t[0] & 0x1fffffff); - r[9] += (sp_digit)(t[0] >> 29); -#endif /* WOLFSSL_SP_SMALL */ -#endif /* !WOLFSSL_SP_LARGE_CODE */ -} - -/* Normalize the values in each word to 29 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_256_norm_9(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 8; i++) { - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - } -#else - a[1] += a[0] >> 29; a[0] &= 0x1fffffff; - a[2] += a[1] >> 29; a[1] &= 0x1fffffff; - a[3] += a[2] >> 29; a[2] &= 0x1fffffff; - a[4] += a[3] >> 29; a[3] &= 0x1fffffff; - a[5] += a[4] >> 29; a[4] &= 0x1fffffff; - a[6] += a[5] >> 29; a[5] &= 0x1fffffff; - a[7] += a[6] >> 29; a[6] &= 0x1fffffff; - a[8] += a[7] >> 29; a[7] &= 0x1fffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Shift the result in the high 256 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_256_mont_shift_9(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_int64 n = a[8] >> 24; - n += ((sp_int64)a[9]) << 5; - - for (i = 0; i < 8; i++) { - r[i] = (sp_digit)(n & 0x1fffffff); - n >>= 29; - n += ((sp_int64)a[10 + i]) << 5; - } - r[8] = (sp_digit)n; -#else - sp_int64 n = a[8] >> 24; - n += ((sp_int64)a[9]) << 5; - r[ 0] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[10]) << 5; - r[ 1] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[11]) << 5; - r[ 2] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[12]) << 5; - r[ 3] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[13]) << 5; - r[ 4] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[14]) << 5; - r[ 5] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[15]) << 5; - r[ 6] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[16]) << 5; - r[ 7] = (sp_digit)(n & 0x1fffffff); n >>= 29; n += ((sp_int64)a[17]) << 5; - r[8] = (sp_digit)n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[9], 0, sizeof(*r) * 9U); -} - -/* 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. - */ -static void sp_256_mont_reduce_order_9(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_256_norm_9(a + 9); - - for (i=0; i<8; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff); - sp_256_mul_add_9(a+i, m, mu); - a[i+1] += a[i] >> 29; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xffffffL); - sp_256_mul_add_9(a+i, m, mu); - a[i+1] += a[i] >> 29; - a[i] &= 0x1fffffff; - sp_256_mont_shift_9(a, a); - over = a[8] >> 24; - sp_256_cond_sub_9(a, a, m, ~((over - 1) >> 31)); - sp_256_norm_9(a); -} - -/* 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. - */ -static void sp_256_mont_reduce_9(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit am; - - (void)m; - (void)mp; - - for (i = 0; i < 8; i++) { - am = (sp_digit)(a[i] & 0x1fffffff); - a[i + 3] += (sp_digit)((am << 9) & 0x1fffffff); - a[i + 4] += am >> 20; - a[i + 6] += (sp_digit)((am << 18) & 0x1fffffff); - a[i + 7] += (am >> 11) - (sp_digit)((am << 21) & 0x1fffffff); - a[i + 8] += -(am >> 8) + (sp_digit)((am << 24) & 0x1fffffff); - a[i + 9] += am >> 5; - - a[i + 1] += a[i] >> 29; - } - am = (sp_digit)(a[8] & 0xffffff); - a[8 + 3] += (sp_digit)((am << 9) & 0x1fffffff); - a[8 + 4] += am >> 20; - a[8 + 6] += (sp_digit)((am << 18) & 0x1fffffff); - a[8 + 7] += (am >> 11) - (sp_digit)((am << 21) & 0x1fffffff); - a[8 + 8] += -(am >> 8) + (sp_digit)((am << 24) & 0x1fffffff); - a[8 + 9] += am >> 5; - - a[0] = (a[ 8] >> 24) + (sp_digit)((a[ 9] << 5) & 0x1fffffff); - a[1] = (a[ 9] >> 24) + (sp_digit)((a[10] << 5) & 0x1fffffff); - a[2] = (a[10] >> 24) + (sp_digit)((a[11] << 5) & 0x1fffffff); - a[3] = (a[11] >> 24) + (sp_digit)((a[12] << 5) & 0x1fffffff); - a[4] = (a[12] >> 24) + (sp_digit)((a[13] << 5) & 0x1fffffff); - a[5] = (a[13] >> 24) + (sp_digit)((a[14] << 5) & 0x1fffffff); - a[6] = (a[14] >> 24) + (sp_digit)((a[15] << 5) & 0x1fffffff); - a[7] = (a[15] >> 24) + (sp_digit)((a[16] << 5) & 0x1fffffff); - a[8] = (a[16] >> 24) + (a[17] << 5); - - a[1] += a[0] >> 29; a[0] &= 0x1fffffff; - a[2] += a[1] >> 29; a[1] &= 0x1fffffff; - a[3] += a[2] >> 29; a[2] &= 0x1fffffff; - a[4] += a[3] >> 29; a[3] &= 0x1fffffff; - a[5] += a[4] >> 29; a[4] &= 0x1fffffff; - a[6] += a[5] >> 29; a[5] &= 0x1fffffff; - a[7] += a[6] >> 29; a[6] &= 0x1fffffff; - a[8] += a[7] >> 29; a[7] &= 0x1fffffff; - - /* Get the bit over, if any. */ - am = a[8] >> 24; - /* Create mask. */ - am = 0 - am; - - a[0] -= (sp_digit)(0x1fffffff & am); - a[1] -= (sp_digit)(0x1fffffff & am); - a[2] -= (sp_digit)(0x1fffffff & am); - a[3] -= (sp_digit)(0x000001ff & am); - /* p256_mod[4] is zero */ - /* p256_mod[5] is zero */ - a[6] -= (sp_digit)(0x00040000 & am); - a[7] -= (sp_digit)(0x1fe00000 & am); - a[8] -= (sp_digit)(0x00ffffff & am); - - a[1] += a[0] >> 29; a[0] &= 0x1fffffff; - a[2] += a[1] >> 29; a[1] &= 0x1fffffff; - a[3] += a[2] >> 29; a[2] &= 0x1fffffff; - a[4] += a[3] >> 29; a[3] &= 0x1fffffff; - a[5] += a[4] >> 29; a[4] &= 0x1fffffff; - a[6] += a[5] >> 29; a[5] &= 0x1fffffff; - a[7] += a[6] >> 29; a[6] &= 0x1fffffff; - a[8] += a[7] >> 29; a[7] &= 0x1fffffff; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_256_mont_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_256_mul_9(r, a, b); - sp_256_mont_reduce_9(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_256_mont_sqr_9(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_256_sqr_9(r, a); - sp_256_mont_reduce_9(r, m, mp); -} - -#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) -/* Square the Montgomery form number a number of times. (r = a ^ n mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * n Number of times to square. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_256_mont_sqr_n_9(sp_digit* r, - const sp_digit* a, int n, const sp_digit* m, sp_digit mp) -{ - sp_256_mont_sqr_9(r, a, m, mp); - for (; n > 1; n--) { - sp_256_mont_sqr_9(r, r, m, mp); - } -} - -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ -#ifdef WOLFSSL_SP_SMALL -/* Mod-2 for the P256 curve. */ -static const word32 p256_mod_minus_2[8] = { - 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U, - 0x00000001U,0xffffffffU -}; -#endif /* !WOLFSSL_SP_SMALL */ - -/* Invert the number, in Montgomery form, modulo the modulus (prime) of the - * P256 curve. (r = 1 / a mod m) - * - * r Inverse result. - * a Number to invert. - * td Temporary data. - */ -static void sp_256_mont_inv_9(sp_digit* r, const sp_digit* a, sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 9); - for (i=254; i>=0; i--) { - sp_256_mont_sqr_9(t, t, p256_mod, p256_mp_mod); - if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) - sp_256_mont_mul_9(t, t, a, p256_mod, p256_mp_mod); - } - XMEMCPY(r, t, sizeof(sp_digit) * 9); -#else - sp_digit* t1 = td; - sp_digit* t2 = td + 2 * 9; - sp_digit* t3 = td + 4 * 9; - /* 0x2 */ - sp_256_mont_sqr_9(t1, a, p256_mod, p256_mp_mod); - /* 0x3 */ - sp_256_mont_mul_9(t2, t1, a, p256_mod, p256_mp_mod); - /* 0xc */ - sp_256_mont_sqr_n_9(t1, t2, 2, p256_mod, p256_mp_mod); - /* 0xd */ - sp_256_mont_mul_9(t3, t1, a, p256_mod, p256_mp_mod); - /* 0xf */ - sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xf0 */ - sp_256_mont_sqr_n_9(t1, t2, 4, p256_mod, p256_mp_mod); - /* 0xfd */ - sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod); - /* 0xff */ - sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xff00 */ - sp_256_mont_sqr_n_9(t1, t2, 8, p256_mod, p256_mp_mod); - /* 0xfffd */ - sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod); - /* 0xffff */ - sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xffff0000 */ - sp_256_mont_sqr_n_9(t1, t2, 16, p256_mod, p256_mp_mod); - /* 0xfffffffd */ - sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod); - /* 0xffffffff */ - sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xffffffff00000000 */ - sp_256_mont_sqr_n_9(t1, t2, 32, p256_mod, p256_mp_mod); - /* 0xffffffffffffffff */ - sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xffffffff00000001 */ - sp_256_mont_mul_9(r, t1, a, p256_mod, p256_mp_mod); - /* 0xffffffff000000010000000000000000000000000000000000000000 */ - sp_256_mont_sqr_n_9(r, r, 160, p256_mod, p256_mp_mod); - /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ - sp_256_mont_mul_9(r, r, t2, p256_mod, p256_mp_mod); - /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ - sp_256_mont_sqr_n_9(r, r, 32, p256_mod, p256_mp_mod); - /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ - sp_256_mont_mul_9(r, r, t3, p256_mod, p256_mp_mod); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_9(sp_point_256* r, const sp_point_256* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*9; - sp_int32 n; - - sp_256_mont_inv_9(t1, p->z, t + 2*9); - - sp_256_mont_sqr_9(t2, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t1, t2, t1, p256_mod, p256_mp_mod); - - /* x /= z^2 */ - sp_256_mont_mul_9(r->x, p->x, t2, p256_mod, p256_mp_mod); - XMEMSET(r->x + 9, 0, sizeof(sp_digit) * 9U); - sp_256_mont_reduce_9(r->x, p256_mod, p256_mp_mod); - /* Reduce x to less than modulus */ - n = sp_256_cmp_9(r->x, p256_mod); - sp_256_cond_sub_9(r->x, r->x, p256_mod, (sp_digit)~(n >> 28)); - sp_256_norm_9(r->x); - - /* y /= z^3 */ - sp_256_mont_mul_9(r->y, p->y, t1, p256_mod, p256_mp_mod); - XMEMSET(r->y + 9, 0, sizeof(sp_digit) * 9U); - sp_256_mont_reduce_9(r->y, p256_mod, p256_mp_mod); - /* Reduce y to less than modulus */ - n = sp_256_cmp_9(r->y, p256_mod); - sp_256_cond_sub_9(r->y, r->y, p256_mod, (sp_digit)~(n >> 28)); - sp_256_norm_9(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_add_9(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - sp_digit over; - (void)sp_256_add_9(r, a, b); - sp_256_norm_9(r); - over = r[8] >> 24; - sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31)); - sp_256_norm_9(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_dbl_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_256_add_9(r, a, a); - sp_256_norm_9(r); - over = r[8] >> 24; - sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31)); - sp_256_norm_9(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_tpl_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_256_add_9(r, a, a); - sp_256_norm_9(r); - over = r[8] >> 24; - sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31)); - sp_256_norm_9(r); - (void)sp_256_add_9(r, r, a); - sp_256_norm_9(r); - over = r[8] >> 24; - sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31)); - sp_256_norm_9(r); -} - -#ifdef 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_256_cond_add_9(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 9; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_256_cond_add_9(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - r[ 0] = a[ 0] + (b[ 0] & m); - r[ 1] = a[ 1] + (b[ 1] & m); - r[ 2] = a[ 2] + (b[ 2] & m); - r[ 3] = a[ 3] + (b[ 3] & m); - r[ 4] = a[ 4] + (b[ 4] & m); - r[ 5] = a[ 5] + (b[ 5] & m); - r[ 6] = a[ 6] + (b[ 6] & m); - r[ 7] = a[ 7] + (b[ 7] & m); - r[ 8] = a[ 8] + (b[ 8] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_sub_9(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_256_sub_9(r, a, b); - sp_256_norm_9(r); - sp_256_cond_add_9(r, r, m, r[8] >> 24); - sp_256_norm_9(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -SP_NOINLINE static void sp_256_rshift1_9(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=0; i<8; i++) { - r[i] = (a[i] >> 1) + (sp_digit)((a[i + 1] << 28) & 0x1fffffff); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 28) & 0x1fffffff); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 28) & 0x1fffffff); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 28) & 0x1fffffff); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 28) & 0x1fffffff); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 28) & 0x1fffffff); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 28) & 0x1fffffff); - r[6] = (a[6] >> 1) + (sp_digit)((a[7] << 28) & 0x1fffffff); - r[7] = (a[7] >> 1) + (sp_digit)((a[8] << 28) & 0x1fffffff); -#endif - r[8] = a[8] >> 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_256_mont_div2_9(sp_digit* r, const sp_digit* a, - const sp_digit* m) -{ - sp_256_cond_add_9(r, a, m, 0 - (a[0] & 1)); - sp_256_norm_9(r); - sp_256_rshift1_9(r, r); -} - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static void sp_256_proj_point_dbl_9(sp_point_256* r, const sp_point_256* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*9; - 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_256_mont_sqr_9(t1, p->z, p256_mod, p256_mp_mod); - /* Z = Y * Z */ - sp_256_mont_mul_9(z, p->y, p->z, p256_mod, p256_mp_mod); - /* Z = 2Z */ - sp_256_mont_dbl_9(z, z, p256_mod); - /* T2 = X - T1 */ - sp_256_mont_sub_9(t2, p->x, t1, p256_mod); - /* T1 = X + T1 */ - sp_256_mont_add_9(t1, p->x, t1, p256_mod); - /* T2 = T1 * T2 */ - sp_256_mont_mul_9(t2, t1, t2, p256_mod, p256_mp_mod); - /* T1 = 3T2 */ - sp_256_mont_tpl_9(t1, t2, p256_mod); - /* Y = 2Y */ - sp_256_mont_dbl_9(y, p->y, p256_mod); - /* Y = Y * Y */ - sp_256_mont_sqr_9(y, y, p256_mod, p256_mp_mod); - /* T2 = Y * Y */ - sp_256_mont_sqr_9(t2, y, p256_mod, p256_mp_mod); - /* T2 = T2/2 */ - sp_256_mont_div2_9(t2, t2, p256_mod); - /* Y = Y * X */ - sp_256_mont_mul_9(y, y, p->x, p256_mod, p256_mp_mod); - /* X = T1 * T1 */ - sp_256_mont_sqr_9(x, t1, p256_mod, p256_mp_mod); - /* X = X - Y */ - sp_256_mont_sub_9(x, x, y, p256_mod); - /* X = X - Y */ - sp_256_mont_sub_9(x, x, y, p256_mod); - /* Y = Y - X */ - sp_256_mont_sub_9(y, y, x, p256_mod); - /* Y = Y * T1 */ - sp_256_mont_mul_9(y, y, t1, p256_mod, p256_mp_mod); - /* Y = Y - T2 */ - sp_256_mont_sub_9(y, y, t2, p256_mod); -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_256_proj_point_dbl_9_ctx { - int state; - sp_digit* t1; - sp_digit* t2; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_256_proj_point_dbl_9_ctx; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static int sp_256_proj_point_dbl_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_point_256* p, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_256_proj_point_dbl_9_ctx* ctx = (sp_256_proj_point_dbl_9_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - ctx->t1 = t; - ctx->t2 = t + 2*9; - 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_256_mont_sqr_9(ctx->t1, p->z, p256_mod, p256_mp_mod); - ctx->state = 2; - break; - case 2: - /* Z = Y * Z */ - sp_256_mont_mul_9(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); - ctx->state = 3; - break; - case 3: - /* Z = 2Z */ - sp_256_mont_dbl_9(ctx->z, ctx->z, p256_mod); - ctx->state = 4; - break; - case 4: - /* T2 = X - T1 */ - sp_256_mont_sub_9(ctx->t2, p->x, ctx->t1, p256_mod); - ctx->state = 5; - break; - case 5: - /* T1 = X + T1 */ - sp_256_mont_add_9(ctx->t1, p->x, ctx->t1, p256_mod); - ctx->state = 6; - break; - case 6: - /* T2 = T1 * T2 */ - sp_256_mont_mul_9(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 7; - break; - case 7: - /* T1 = 3T2 */ - sp_256_mont_tpl_9(ctx->t1, ctx->t2, p256_mod); - ctx->state = 8; - break; - case 8: - /* Y = 2Y */ - sp_256_mont_dbl_9(ctx->y, p->y, p256_mod); - ctx->state = 9; - break; - case 9: - /* Y = Y * Y */ - sp_256_mont_sqr_9(ctx->y, ctx->y, p256_mod, p256_mp_mod); - ctx->state = 10; - break; - case 10: - /* T2 = Y * Y */ - sp_256_mont_sqr_9(ctx->t2, ctx->y, p256_mod, p256_mp_mod); - ctx->state = 11; - break; - case 11: - /* T2 = T2/2 */ - sp_256_mont_div2_9(ctx->t2, ctx->t2, p256_mod); - ctx->state = 12; - break; - case 12: - /* Y = Y * X */ - sp_256_mont_mul_9(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); - ctx->state = 13; - break; - case 13: - /* X = T1 * T1 */ - sp_256_mont_sqr_9(ctx->x, ctx->t1, p256_mod, p256_mp_mod); - ctx->state = 14; - break; - case 14: - /* X = X - Y */ - sp_256_mont_sub_9(ctx->x, ctx->x, ctx->y, p256_mod); - ctx->state = 15; - break; - case 15: - /* X = X - Y */ - sp_256_mont_sub_9(ctx->x, ctx->x, ctx->y, p256_mod); - ctx->state = 16; - break; - case 16: - /* Y = Y - X */ - sp_256_mont_sub_9(ctx->y, ctx->y, ctx->x, p256_mod); - ctx->state = 17; - break; - case 17: - /* Y = Y * T1 */ - sp_256_mont_mul_9(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); - ctx->state = 18; - break; - case 18: - /* Y = Y - T2 */ - sp_256_mont_sub_9(ctx->y, ctx->y, ctx->t2, p256_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 */ -/* 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_256_cmp_equal_9(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])) == 0; -} - -/* 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_256_iszero_9(const sp_digit* a) -{ - return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | - a[8]) == 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. - */ -static void sp_256_proj_point_add_9(sp_point_256* r, - const sp_point_256* p, const sp_point_256* q, sp_digit* t) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*9; - sp_digit* t2 = t + 4*9; - sp_digit* t3 = t + 6*9; - sp_digit* t4 = t + 8*9; - sp_digit* t5 = t + 10*9; - - /* U1 = X1*Z2^2 */ - sp_256_mont_sqr_9(t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t3, t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t1, t1, p->x, p256_mod, p256_mp_mod); - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_9(t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t4, t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_256_mont_mul_9(t3, t3, p->y, p256_mod, p256_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_256_cmp_equal_9(t2, t1) & - sp_256_cmp_equal_9(t4, t3)) { - sp_256_proj_point_dbl_9(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* H = U2 - U1 */ - sp_256_mont_sub_9(t2, t2, t1, p256_mod); - /* R = S2 - S1 */ - sp_256_mont_sub_9(t4, t4, t3, p256_mod); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(y, t1, t5, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod); - /* Z3 = H*Z1*Z2 */ - sp_256_mont_mul_9(z, p->z, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(z, z, q->z, p256_mod, p256_mp_mod); - sp_256_mont_sqr_9(x, t4, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(x, x, t5, p256_mod); - sp_256_mont_mul_9(t5, t5, t3, p256_mod, p256_mp_mod); - sp_256_mont_dbl_9(t3, y, p256_mod); - sp_256_mont_sub_9(x, x, t3, p256_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_256_mont_sub_9(y, y, x, p256_mod); - sp_256_mont_mul_9(y, y, t4, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(y, y, t5, p256_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 9; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_256_proj_point_add_9_ctx { - int state; - sp_256_proj_point_dbl_9_ctx dbl_ctx; - const sp_point_256* ap[2]; - sp_point_256* rp[2]; - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; - sp_digit* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_256_proj_point_add_9_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -static int sp_256_proj_point_add_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_point_256* p, const sp_point_256* q, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_256_proj_point_add_9_ctx* ctx = (sp_256_proj_point_add_9_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_256_proj_point_add_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_256* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*9; - ctx->t2 = t + 4*9; - ctx->t3 = t + 6*9; - ctx->t4 = t + 8*9; - ctx->t5 = t + 10*9; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_256_mont_sqr_9(ctx->t1, q->z, p256_mod, p256_mp_mod); - ctx->state = 2; - break; - case 2: - sp_256_mont_mul_9(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); - ctx->state = 3; - break; - case 3: - sp_256_mont_mul_9(ctx->t1, ctx->t1, p->x, p256_mod, p256_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_9(ctx->t2, p->z, p256_mod, p256_mp_mod); - ctx->state = 5; - break; - case 5: - sp_256_mont_mul_9(ctx->t4, ctx->t2, p->z, p256_mod, p256_mp_mod); - ctx->state = 6; - break; - case 6: - sp_256_mont_mul_9(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_256_mont_mul_9(ctx->t3, ctx->t3, p->y, p256_mod, p256_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_9(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_256_cmp_equal_9(ctx->t2, ctx->t1) & - sp_256_cmp_equal_9(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_256_proj_point_dbl_9(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_256_mont_sub_9(ctx->t2, ctx->t2, ctx->t1, p256_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_256_mont_sub_9(ctx->t4, ctx->t4, ctx->t3, p256_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_256_mont_sqr_9(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 13; - break; - case 13: - sp_256_mont_mul_9(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); - ctx->state = 14; - break; - case 14: - sp_256_mont_mul_9(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_256_mont_mul_9(ctx->z, p->z, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 16; - break; - case 16: - sp_256_mont_mul_9(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); - ctx->state = 17; - break; - case 17: - sp_256_mont_sqr_9(ctx->x, ctx->t4, p256_mod, p256_mp_mod); - ctx->state = 18; - break; - case 18: - sp_256_mont_sub_9(ctx->x, ctx->x, ctx->t5, p256_mod); - ctx->state = 19; - break; - case 19: - sp_256_mont_mul_9(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); - ctx->state = 20; - break; - case 20: - sp_256_mont_dbl_9(ctx->t3, ctx->y, p256_mod); - sp_256_mont_sub_9(ctx->x, ctx->x, ctx->t3, p256_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_256_mont_sub_9(ctx->y, ctx->y, ctx->x, p256_mod); - ctx->state = 22; - break; - case 22: - sp_256_mont_mul_9(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); - ctx->state = 23; - break; - case 23: - sp_256_mont_sub_9(ctx->y, ctx->y, ctx->t5, p256_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 9; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -/* Multiply a number by Montgomery 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_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - SP_DECL_VAR(int64_t, t, 2 * 8); - int64_t* a32 = NULL; - int64_t o; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(int64_t, t, 2 * 8, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - a32 = t + 8; - - a32[0] = a[0]; - a32[0] |= (int64_t)a[1] << 29U; - a32[0] &= 0xffffffffL; - a32[1] = (a[1] >> 3); - a32[1] |= (int64_t)a[2] << 26U; - a32[1] &= 0xffffffffL; - a32[2] = (a[2] >> 6); - a32[2] |= (int64_t)a[3] << 23U; - a32[2] &= 0xffffffffL; - a32[3] = (a[3] >> 9); - a32[3] |= (int64_t)a[4] << 20U; - a32[3] &= 0xffffffffL; - a32[4] = (a[4] >> 12); - a32[4] |= (int64_t)a[5] << 17U; - a32[4] &= 0xffffffffL; - a32[5] = (a[5] >> 15); - a32[5] |= (int64_t)a[6] << 14U; - a32[5] &= 0xffffffffL; - a32[6] = (a[6] >> 18); - a32[6] |= (int64_t)a[7] << 11U; - a32[6] &= 0xffffffffL; - a32[7] = (a[7] >> 21); - a32[7] |= (int64_t)a[8] << 8U; - 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]) & 0x1fffffffL; - r[1] = (sp_digit)(t[0] >> 29U); - r[1] |= (sp_digit)(t[1] << 3U); - r[1] &= 0x1fffffffL; - r[2] = (sp_digit)(t[1] >> 26U); - r[2] |= (sp_digit)(t[2] << 6U); - r[2] &= 0x1fffffffL; - r[3] = (sp_digit)(t[2] >> 23U); - r[3] |= (sp_digit)(t[3] << 9U); - r[3] &= 0x1fffffffL; - r[4] = (sp_digit)(t[3] >> 20U); - r[4] |= (sp_digit)(t[4] << 12U); - r[4] &= 0x1fffffffL; - r[5] = (sp_digit)(t[4] >> 17U); - r[5] |= (sp_digit)(t[5] << 15U); - r[5] &= 0x1fffffffL; - r[6] = (sp_digit)(t[5] >> 14U); - r[6] |= (sp_digit)(t[6] << 18U); - r[6] &= 0x1fffffffL; - r[7] = (sp_digit)(t[6] >> 11U); - r[7] |= (sp_digit)(t[7] << 21U); - r[7] &= 0x1fffffffL; - r[8] = (sp_digit)(t[7] >> 8U); - } - - SP_FREE_VAR(t, NULL, DYNAMIC_TYPE_ECC); - - 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. - * 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_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_256, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_256, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_256) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod); - } - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod); - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod); - - if (err == MP_OKAY) { - i = 8; - c = 24; - n = k[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 29; - } - - y = (n >> 28) & 1; - n <<= 1; - - sp_256_proj_point_add_9(&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_256)); - sp_256_proj_point_dbl_9(&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_256)); - } - - if (map != 0) { - sp_256_map_9(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_256)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_256, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_256_ecc_mulmod_9_ctx { - int state; - union { - sp_256_proj_point_dbl_9_ctx dbl_ctx; - sp_256_proj_point_add_9_ctx add_ctx; - }; - sp_point_256 t[3]; - sp_digit tmp[2 * 9 * 6]; - sp_digit n; - int i; - int c; - int y; -} sp_256_ecc_mulmod_9_ctx; - -static int sp_256_ecc_mulmod_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_256_ecc_mulmod_9_ctx* ctx = (sp_256_ecc_mulmod_9_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_9_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_256) * 3); - ctx->i = 8; - ctx->c = 24; - ctx->n = k[ctx->i--] << (29 - 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_256_mod_mul_norm_9(ctx->t[1].x, g->x, p256_mod); - ctx->state = 2; - break; - case 2: /* T1Y */ - err = sp_256_mod_mul_norm_9(ctx->t[1].y, g->y, p256_mod); - ctx->state = 3; - break; - case 3: /* T1Z */ - err = sp_256_mod_mul_norm_9(ctx->t[1].z, g->z, p256_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 = 29; - } - ctx->y = (ctx->n >> 28) & 1; - ctx->n <<= 1; - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 5; - break; - case 5: /* ADD */ - err = sp_256_proj_point_add_9_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_256)); - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 6; - } - break; - case 6: /* DBL */ - err = sp_256_proj_point_dbl_9_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_256)); - ctx->state = 4; - ctx->c--; - } - break; - case 7: /* MAP */ - if (map != 0) { - sp_256_map_9(r, &ctx->t[0], ctx->tmp); - } - else { - XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256)); - } - 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 */ - -#else -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_256 { - sp_digit x[9]; - sp_digit y[9]; -} sp_table_entry_256; - -/* 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_256_cond_copy_9(sp_digit* r, const sp_digit* a, const sp_digit m) -{ - sp_digit t[9]; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i = 0; i < 9; i++) { - t[i] = r[i] ^ a[i]; - } - for (i = 0; i < 9; 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]; - 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; -#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_256_proj_point_dbl_n_9(sp_point_256* p, int i, - sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*9; - sp_digit* b = t + 4*9; - sp_digit* t1 = t + 6*9; - sp_digit* t2 = t + 8*9; - sp_digit* x; - sp_digit* y; - sp_digit* z; - volatile int n = i - 1; - - x = p->x; - y = p->y; - z = p->z; - - /* Y = 2*Y */ - sp_256_mont_dbl_9(y, y, p256_mod); - /* W = Z^4 */ - sp_256_mont_sqr_9(w, z, p256_mod, p256_mp_mod); - sp_256_mont_sqr_9(w, w, p256_mod, p256_mp_mod); -#ifndef WOLFSSL_SP_SMALL - while (n > 0) -#else - while (n >= 0) -#endif - { - /* A = 3*(X^2 - W) */ - sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(t1, t1, w, p256_mod); - sp_256_mont_tpl_9(a, t1, p256_mod); - /* B = X*Y^2 */ - sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod); - /* X = A^2 - 2B */ - sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_9(t2, b, p256_mod); - sp_256_mont_sub_9(x, x, t2, p256_mod); - /* B = 2.(B - X) */ - sp_256_mont_sub_9(t2, b, x, p256_mod); - sp_256_mont_dbl_9(b, t2, p256_mod); - /* Z = Z*Y */ - sp_256_mont_mul_9(z, z, y, p256_mod, p256_mp_mod); - /* t1 = Y^4 */ - sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod); -#ifdef WOLFSSL_SP_SMALL - if (n != 0) -#endif - { - /* W = W*Y^4 */ - sp_256_mont_mul_9(w, w, t1, p256_mod, p256_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(y, y, t1, p256_mod); - n = n - 1; - } -#ifndef WOLFSSL_SP_SMALL - /* A = 3*(X^2 - W) */ - sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(t1, t1, w, p256_mod); - sp_256_mont_tpl_9(a, t1, p256_mod); - /* B = X*Y^2 */ - sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod); - /* X = A^2 - 2B */ - sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_9(t2, b, p256_mod); - sp_256_mont_sub_9(x, x, t2, p256_mod); - /* B = 2.(B - X) */ - sp_256_mont_sub_9(t2, b, x, p256_mod); - sp_256_mont_dbl_9(b, t2, p256_mod); - /* Z = Z*Y */ - sp_256_mont_mul_9(z, z, y, p256_mod, p256_mp_mod); - /* t1 = Y^4 */ - sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(y, y, t1, p256_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_256_mont_div2_9(y, y, p256_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_256_proj_point_dbl_n_store_9(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*9; - sp_digit* b = t + 4*9; - sp_digit* t1 = t + 6*9; - sp_digit* t2 = t + 8*9; - sp_digit* x = r[2*m].x; - sp_digit* y = r[(1<x[i]; - } - for (i=0; i<9; i++) { - y[i] = p->y[i]; - } - for (i=0; i<9; i++) { - z[i] = p->z[i]; - } - - /* Y = 2*Y */ - sp_256_mont_dbl_9(y, y, p256_mod); - /* W = Z^4 */ - sp_256_mont_sqr_9(w, z, p256_mod, p256_mp_mod); - sp_256_mont_sqr_9(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_9(t1, x, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(t1, t1, w, p256_mod); - sp_256_mont_tpl_9(a, t1, p256_mod); - /* B = X*Y^2 */ - sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod); - x = r[j].x; - /* X = A^2 - 2B */ - sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_9(t2, b, p256_mod); - sp_256_mont_sub_9(x, x, t2, p256_mod); - /* B = 2.(B - X) */ - sp_256_mont_sub_9(t2, b, x, p256_mod); - sp_256_mont_dbl_9(b, t2, p256_mod); - /* Z = Z*Y */ - sp_256_mont_mul_9(r[j].z, z, y, p256_mod, p256_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod); - if (i != n) { - /* W = W*Y^4 */ - sp_256_mont_mul_9(w, w, t1, p256_mod, p256_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(y, y, t1, p256_mod); - /* Y = Y/2 */ - sp_256_mont_div2_9(r[j].y, y, p256_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_256_proj_point_add_sub_9(sp_point_256* ra, - sp_point_256* rs, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*9; - sp_digit* t3 = t + 4*9; - sp_digit* t4 = t + 6*9; - sp_digit* t5 = t + 8*9; - sp_digit* t6 = t + 10*9; - sp_digit* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, p->z, sizeof(p->z) / 2); - ra->infinity = 0; - rs->infinity = 0; - - /* U1 = X1*Z2^2 */ - sp_256_mont_sqr_9(t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t3, t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t1, t1, xa, p256_mod, p256_mp_mod); - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_9(t2, za, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t4, t2, za, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_256_mont_mul_9(t3, t3, ya, p256_mod, p256_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod); - /* H = U2 - U1 */ - sp_256_mont_sub_9(t2, t2, t1, p256_mod); - /* RS = S2 + S1 */ - sp_256_mont_add_9(t6, t4, t3, p256_mod); - /* R = S2 - S1 */ - sp_256_mont_sub_9(t4, t4, t3, p256_mod); - /* Z3 = H*Z1*Z2 */ - /* ZS = H*Z1*Z2 */ - sp_256_mont_mul_9(za, za, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(za, za, t2, p256_mod, p256_mp_mod); - XMEMCPY(zs, za, sizeof(p->z)/2); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - /* XS = RS^2 - H^3 - 2*U1*H^2 */ - sp_256_mont_sqr_9(xa, t4, p256_mod, p256_mp_mod); - sp_256_mont_sqr_9(xs, t6, p256_mod, p256_mp_mod); - sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(ya, t1, t5, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(xa, xa, t5, p256_mod); - sp_256_mont_sub_9(xs, xs, t5, p256_mod); - sp_256_mont_dbl_9(t1, ya, p256_mod); - sp_256_mont_sub_9(xa, xa, t1, p256_mod); - sp_256_mont_sub_9(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_9(ys, ya, xs, p256_mod); - sp_256_mont_sub_9(ya, ya, xa, p256_mod); - sp_256_mont_mul_9(ya, ya, t4, p256_mod, p256_mp_mod); - sp_256_sub_9(t6, p256_mod, t6); - sp_256_mont_mul_9(ys, ys, t6, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t5, t5, t3, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(ya, ya, t5, p256_mod); - sp_256_mont_sub_9(ys, ys, t5, p256_mod); -} - -/* Structure used to describe recoding of scalar multiplication. */ -typedef struct ecc_recode_256 { - /* Index into pre-computation table. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_256; - -/* The index into pre-computation table to use. */ -static const word8 recode_index_9_6[66] = { - 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, 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 word8 recode_neg_9_6[66] = { - 0, 0, 0, 0, 0, 0, 0, 0, 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, - 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_256_ecc_recode_6_9(const sp_digit* k, ecc_recode_256* v) -{ - int i; - int j; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<43; i++) { - y = (word8)(int8_t)n; - if (o + 6 < 29) { - y &= 0x3f; - n >>= 6; - o += 6; - } - else if (o + 6 == 29) { - n >>= 6; - if (++j < 9) - n = k[j]; - o = 0; - } - else if (++j < 9) { - n = k[j]; - y |= (word8)((n << (29 - o)) & 0x3f); - o -= 23; - n >>= o; - } - - y = (word8)(y + carry); - v[i].i = recode_index_9_6[y]; - v[i].neg = recode_neg_9_6[y]; - carry = (y >> 6) + v[i].neg; - } -} - -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible point that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_256_get_point_33_9(sp_point_256* r, const sp_point_256* 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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - r->z[0] = 0; - r->z[1] = 0; - r->z[2] = 0; - r->z[3] = 0; - r->z[4] = 0; - r->z[5] = 0; - r->z[6] = 0; - r->z[7] = 0; - r->z[8] = 0; - for (i = 1; i < 33; i++) { - mask = (sp_digit)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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - r->z[0] |= mask & table[i].z[0]; - r->z[1] |= mask & table[i].z[1]; - r->z[2] |= mask & table[i].z[2]; - r->z[3] |= mask & table[i].z[3]; - r->z[4] |= mask & table[i].z[4]; - r->z[5] |= mask & table[i].z[5]; - r->z[6] |= mask & table[i].z[6]; - r->z[7] |= mask & table[i].z[7]; - r->z[8] |= mask & table[i].z[8]; - } -} -#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. - * - * Window technique of 6 bits. (Add-Sub variation.) - * Calculate 0..32 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_256_ecc_mulmod_win_add_sub_9(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_256, t, 33+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - sp_point_256* rt = NULL; - sp_point_256* p = NULL; - sp_digit* negy; - int i; - ecc_recode_256 v[43]; - int err = MP_OKAY; - - /* Constant time used for cache attack resistance implementation. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_256, t, 33+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - 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_9(t[1].x, g->x, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod); - } - - if (err == MP_OKAY) { - t[1].infinity = 0; - /* t[2] ... t[32] */ - sp_256_proj_point_dbl_n_store_9(t, &t[ 1], 5, 1, tmp); - sp_256_proj_point_add_9(&t[ 3], &t[ 2], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[ 6], &t[ 3], tmp); - sp_256_proj_point_add_sub_9(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[10], &t[ 5], tmp); - sp_256_proj_point_add_sub_9(&t[11], &t[ 9], &t[10], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[12], &t[ 6], tmp); - sp_256_proj_point_dbl_9(&t[14], &t[ 7], tmp); - sp_256_proj_point_add_sub_9(&t[15], &t[13], &t[14], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[18], &t[ 9], tmp); - sp_256_proj_point_add_sub_9(&t[19], &t[17], &t[18], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[20], &t[10], tmp); - sp_256_proj_point_dbl_9(&t[22], &t[11], tmp); - sp_256_proj_point_add_sub_9(&t[23], &t[21], &t[22], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[24], &t[12], tmp); - sp_256_proj_point_dbl_9(&t[26], &t[13], tmp); - sp_256_proj_point_add_sub_9(&t[27], &t[25], &t[26], &t[ 1], tmp); - sp_256_proj_point_dbl_9(&t[28], &t[14], tmp); - sp_256_proj_point_dbl_9(&t[30], &t[15], tmp); - sp_256_proj_point_add_sub_9(&t[31], &t[29], &t[30], &t[ 1], tmp); - - negy = t[0].y; - - sp_256_ecc_recode_6_9(k, v); - - i = 42; - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_point_33_9(rt, t, v[i].i); - rt->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_256)); - } - for (--i; i>=0; i--) { - sp_256_proj_point_dbl_n_9(rt, 6, tmp); - - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_point_33_9(p, t, v[i].i); - p->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256)); - } - sp_256_sub_9(negy, p256_mod, p->y); - sp_256_norm_9(negy); - sp_256_cond_copy_9(p->y, negy, (sp_digit)0 - v[i].neg); - sp_256_proj_point_add_9(rt, rt, p, tmp); - } - - if (map != 0) { - sp_256_map_9(r, rt, tmp); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_256)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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_256_proj_point_add_qz1_9(sp_point_256* r, - const sp_point_256* p, const sp_point_256* q, sp_digit* t) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*9; - sp_digit* t6 = t + 4*9; - sp_digit* t1 = t + 6*9; - sp_digit* t4 = t + 8*9; - sp_digit* t5 = t + 10*9; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_9(t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t4, t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod); - - if ((~p->infinity) & (~q->infinity) & - sp_256_cmp_equal_9(p->x, t2) & - sp_256_cmp_equal_9(p->y, t4)) { - sp_256_proj_point_dbl_9(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_256_mont_sub_9(t2, t2, p->x, p256_mod); - /* R = S2 - Y1 */ - sp_256_mont_sub_9(t4, t4, p->y, p256_mod); - /* Z3 = H*Z1 */ - sp_256_mont_mul_9(z, p->z, t2, p256_mod, p256_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_256_mont_sqr_9(t1, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t3, p->x, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod); - sp_256_mont_sqr_9(t2, t4, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(t2, t2, t1, p256_mod); - sp_256_mont_dbl_9(t5, t3, p256_mod); - sp_256_mont_sub_9(x, t2, t5, p256_mod); - /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_256_mont_sub_9(t3, t3, x, p256_mod); - sp_256_mont_mul_9(t3, t3, t4, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t1, t1, p->y, p256_mod, p256_mp_mod); - sp_256_mont_sub_9(y, t3, t1, p256_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 9; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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_9(sp_point_256* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 9; - sp_digit* tmp = t + 4 * 9; - - sp_256_mont_inv_9(t1, a->z, tmp); - - sp_256_mont_sqr_9(t2, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(t1, t2, t1, p256_mod, p256_mp_mod); - - sp_256_mont_mul_9(a->x, a->x, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(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 = 8 - * 256 entries - * 32 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_256_gen_stripe_table_9(const sp_point_256* a, - sp_table_entry_256* table, sp_digit* tmp, void* heap) -{ - SP_DECL_VAR(sp_point_256, t, 3); - sp_point_256* s1 = NULL; - sp_point_256* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_256, t, 3, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - s1 = t + 1; - s2 = t + 2; - - err = sp_256_mod_mul_norm_9(t->x, a->x, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_9(t->y, a->y, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_9(t->z, a->z, p256_mod); - } - if (err == MP_OKAY) { - t->infinity = 0; - sp_256_proj_to_affine_9(t, tmp); - - XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); - s1->infinity = 0; - XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); - s2->infinity = 0; - - /* table[0] = {0, 0, infinity} */ - XMEMSET(&table[0], 0, sizeof(sp_table_entry_256)); - /* 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_256_proj_point_dbl_n_9(t, 32, tmp); - sp_256_proj_to_affine_9(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_256_proj_point_add_qz1_9(t, s1, s2, tmp); - sp_256_proj_to_affine_9(t, tmp); - XMEMCPY(table[j].x, t->x, sizeof(table->x)); - XMEMCPY(table[j].y, t->y, sizeof(table->y)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible entry that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_256_get_entry_256_9(sp_point_256* r, - const sp_table_entry_256* 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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - for (i = 1; i < 256; i++) { - sp_digit gte = (sp_digit)((((sp_uint32)i - (sp_uint32)idx) >> 31) - 1); - sp_digit lte = (sp_digit)((((sp_uint32)idx - (sp_uint32)i) >> 31) - 1); - mask = gte & lte; - 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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - } -} -#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^32, ... - * 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_256_ecc_mulmod_stripe_9(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) -{ - SP_DECL_VAR(sp_point_256, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 9 * 6); - sp_point_256* 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; - - - SP_ALLOC_VAR(sp_point_256, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - 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; - x = 31; - for (j=0; j<8; j++) { - y |= (int)(((k[x / 29] >> (x % 29)) & 1) << j); - x += 32; - } - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_entry_256_9(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=30; i>=0; i--) { - y = 0; - x = i; - for (j=0; j<8; j++) { - y |= (int)(((k[x / 29] >> (x % 29)) & 1) << j); - x += 32; - } - - sp_256_proj_point_dbl_9(rt, rt, t); - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_entry_256_9(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_256_proj_point_add_qz1_9(rt, rt, p, t); - } - - if (map != 0) { - sp_256_map_9(r, rt, t); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_256)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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_256_t { - /* X ordinate of point that table was generated from. */ - sp_digit x[9]; - /* Y ordinate of point that table was generated from. */ - sp_digit y[9]; - /* Precomputation table for point. */ - sp_table_entry_256 table[256]; - /* Count of entries in table. */ - word32 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 - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_256 = 0; - #endif - static wolfSSL_Mutex sp_cache_256_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_256_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * 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; - int j; - word32 least; - - if (sp_cache_256_inited == 0) { - for (i=0; ix, sp_cache_256[i].x) & - sp_256_cmp_equal_9(g->y, sp_cache_256[i].y)) { - sp_cache_256[i].cnt++; - break; - } - } - - /* No match. */ - if (i == FP_ENTRIES) { - /* Find empty entry. */ - i = (sp_cache_256_last + 1) % FP_ENTRIES; - for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { - if (!sp_cache_256[i].set) { - break; - } - } - - /* Evict least used. */ - if (i == sp_cache_256_last) { - least = sp_cache_256[0].cnt; - for (j=1; jx, sizeof(sp_cache_256[i].x)); - XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); - sp_cache_256[i].set = 1; - sp_cache_256[i].cnt = 1; - } - - *cache = &sp_cache_256[i]; - sp_cache_256_last = i; -} -#endif /* FP_ECC */ - -/* Multiply the base point of P256 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_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#ifndef FP_ECC - return sp_256_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap); -#else - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - sp_cache_256_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_256 == 0) { - wc_InitMutex(&sp_cache_256_lock); - initCacheMutex_256 = 1; - } - #endif - if (wc_LockMutex(&sp_cache_256_lock) != 0) { - err = BAD_MUTEX_E; - } - } -#endif /* HAVE_THREAD_LS */ - - if (err == MP_OKAY) { - sp_ecc_get_cache_256(g, &cache); - if (cache->cnt == 2) - sp_256_gen_stripe_table_9(g, cache->table, tmp, heap); - -#ifndef HAVE_THREAD_LS - wc_UnLockMutex(&sp_cache_256_lock); -#endif /* HAVE_THREAD_LS */ - - if (cache->cnt < 2) { - err = sp_256_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap); - } - else { - err = sp_256_ecc_mulmod_stripe_9(r, g, cache->table, k, - map, ct, heap); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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_256(const mp_int* km, const ecc_point* gm, ecc_point* r, - int map, void* heap) -{ - SP_DECL_VAR(sp_point_256, point, 1); - SP_DECL_VAR(sp_digit, k, 9); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(k, 9, km); - sp_256_point_from_ecc_point_9(point, gm); - - err = sp_256_ecc_mulmod_9(point, point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_256, point, 2); - SP_DECL_VAR(sp_digit, k, 9 + 9 * 2 * 6); - sp_point_256* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9 + 9 * 2 * 6, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - addP = point + 1; - tmp = k + 9; - - sp_256_from_mp(k, 9, km); - sp_256_point_from_ecc_point_9(point, gm); - sp_256_point_from_ecc_point_9(addP, am); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_256_mod_mul_norm_9(addP->x, addP->x, p256_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_256_mod_mul_norm_9(addP->y, addP->y, p256_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_256_mod_mul_norm_9(addP->z, addP->z, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_9(point, point, k, 0, 0, heap); - } - if (err == MP_OKAY) { - sp_256_proj_point_add_9(point, point, addP, tmp); - - if (map) { - sp_256_map_9(point, point, tmp); - } - - err = sp_256_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef 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. - * - * 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_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k, - int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_256_ecc_mulmod_9(r, &p256_base, k, map, ct, heap); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_256_ecc_mulmod_base_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_256_ecc_mulmod_9_nb(sp_ctx, r, &p256_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - /* 1 */ - { { 0x18a9143c,0x0f3986a0,0x1b6d805e,0x152bf8bf,0x0251075b,0x1995bbb1, - 0x1719e7ed,0x0ed4a6ea,0x0018905f }, - { 0x0e95560a,0x0f929abe,0x06791737,0x1571c974,0x1f3258b4,0x03446e90, - 0x16174ba2,0x0304b10b,0x008571ff } }, - /* 2 */ - { { 0x0147519a,0x01443012,0x0cdcbc08,0x103d584d,0x1ebc8d09,0x13e553c2, - 0x03a6a752,0x01bb7beb,0x00d953c5 }, - { 0x1d590f8f,0x0b1b0e67,0x19b245e7,0x12c4d689,0x164cf72e,0x10881175, - 0x03cdff65,0x0fd3d651,0x00863ebb } }, - /* 3 */ - { { 0x1cdb6485,0x02b5b11a,0x028be5de,0x1e1d445e,0x0300b808,0x0caa27bf, - 0x0280f9a3,0x0ab6bff0,0x00000760 }, - { 0x038d2010,0x11a75cdc,0x10dc229d,0x029f7664,0x06606540,0x1e9cc215, - 0x1b838391,0x0c2686e7,0x00830877 } }, - /* 4 */ - { { 0x16a0d2bb,0x1c917e28,0x188d2653,0x1982d834,0x02c8b0d5,0x079d2be3, - 0x19fe4907,0x0c3fa36c,0x002f5e69 }, - { 0x15a01797,0x00ae385f,0x05586497,0x01689ac1,0x1db523d2,0x0d9b838f, - 0x1dec1244,0x02d1ade1,0x00f648f9 } }, - /* 5 */ - { { 0x0137bbbc,0x12b3423f,0x1a82fb27,0x088d3d14,0x13463e43,0x13b0bceb, - 0x0056c710,0x10a267a0,0x005abe02 }, - { 0x004c7dab,0x15541be6,0x098301e4,0x1b3e9886,0x0cc37573,0x0ab13c73, - 0x0e0c324c,0x0b6d6dee,0x0094bb72 } }, - /* 6 */ - { { 0x120f141c,0x1fcda47b,0x1d6f1d2e,0x13679a5b,0x045c4619,0x1094a088, - 0x13bf70fd,0x1965efb8,0x00cdd6bb }, - { 0x0af436fd,0x0533805f,0x04c9afb3,0x08fedb73,0x125226f6,0x13c900a7, - 0x17d8303e,0x17a97b5c,0x00a361be } }, - /* 7 */ - { { 0x197c13c7,0x05512ac2,0x0df0f84a,0x1ac6bea1,0x09d1dc38,0x0d7679e0, - 0x04b01c0e,0x013896a5,0x00ba12ca }, - { 0x19f91dfd,0x12047d22,0x1a81fee7,0x0876cd9d,0x00b293af,0x1844cebc, - 0x1d2c7b3a,0x13ae03fd,0x0053ebb9 } }, - /* 8 */ - { { 0x10e63d34,0x1f3f718d,0x1953ead3,0x000ae553,0x1b5a4f46,0x199a6af3, - 0x00c70124,0x1240daa9,0x008589fb }, - { 0x0583553a,0x1387ae63,0x1592796a,0x121295c4,0x04652087,0x02838802, - 0x113f3241,0x0da04a83,0x00ebb069 } }, - /* 9 */ - { { 0x0c1647c5,0x10b650ad,0x13d5e651,0x04fa8f89,0x1fbacb81,0x1551bb26, - 0x168f7199,0x197a364f,0x00eb2820 }, - { 0x0a87e008,0x0037c6c3,0x08de3ce5,0x1bf53b24,0x0ecb2d87,0x17214066, - 0x08755bb4,0x136ab4fb,0x001f2828 } }, - /* 10 */ - { { 0x1b89da99,0x1dd50601,0x0a1008aa,0x05af3d70,0x005e8a6f,0x1c315c0e, - 0x158c9e11,0x0b20bca9,0x00337a4b }, - { 0x01f7794a,0x033a8069,0x1b5fd84f,0x000b6efa,0x1d6e8207,0x1bc08267, - 0x0f582968,0x1abe985f,0x000d65e0 } }, - /* 11 */ - { { 0x15275d38,0x0e84ddf5,0x1828d636,0x114e8a17,0x0b265426,0x17fa4b9f, - 0x08cbc1d8,0x084a5e94,0x00c23da2 }, - { 0x0b94520c,0x0d0dc278,0x16f5e397,0x0ccec760,0x09ea1096,0x05c34a69, - 0x1fc4e937,0x1198f219,0x0019de3b } }, - /* 12 */ - { { 0x06c5fe04,0x01d38b61,0x0e86f6c6,0x11bc1677,0x1712c3b2,0x02c35265, - 0x0ff5d0cb,0x1a923f99,0x00e34dcb }, - { 0x0aa58403,0x0046a35d,0x1a5e94ed,0x12e90d05,0x0a8af9a6,0x00939b55, - 0x1dfe78e4,0x088f69c1,0x00e7641f } }, - /* 13 */ - { { 0x1f64ba59,0x0ba9ca0e,0x0090bf1f,0x1e21d816,0x01859d33,0x0fe350ac, - 0x1efd3c1b,0x0ae0a54a,0x004a12df }, - { 0x1439dbd0,0x1d319c7c,0x194f87ef,0x0497a97b,0x1b314d3c,0x07fd10f8, - 0x091bf579,0x12776b7d,0x006af5aa } }, - /* 14 */ - { { 0x10c91999,0x1085b4c8,0x16012476,0x09688054,0x020900a2,0x0a5a5c66, - 0x004cf802,0x0b4cd488,0x005fe347 }, - { 0x193e7b4b,0x07c655ef,0x08fe46ac,0x16a034f8,0x06263292,0x04d7668f, - 0x04590ba2,0x011d9fd5,0x00b544e3 } }, - /* 15 */ - { { 0x16ddfdce,0x03c63748,0x045e7999,0x0522cdf1,0x067e12c3,0x173b26a7, - 0x082d3a35,0x17b4d618,0x00e0b6b2 }, - { 0x1b7efb57,0x09896f95,0x031001c3,0x181bbcf2,0x1c9441aa,0x1b56b3cd, - 0x1dd3e40c,0x1bc4b4c6,0x0071c023 } }, - /* 16 */ - { { 0x1fe20925,0x15461225,0x173a19d8,0x0335871f,0x0706391c,0x12eaee9c, - 0x13d96a5a,0x1a843a64,0x0061d587 }, - { 0x037173ea,0x03b39d15,0x1de2d97a,0x090010a6,0x0b43e238,0x020f02dd, - 0x1ef843e1,0x0248c43d,0x00fa11fe } }, - /* 17 */ - { { 0x0cb19ffd,0x0448f959,0x048f08c7,0x151ab763,0x1ca8e01b,0x1eb3c562, - 0x1b72db40,0x0983e277,0x00586eb0 }, - { 0x07e8ed09,0x01ae3729,0x067b7883,0x03467830,0x052fa1e8,0x0b602b63, - 0x1c449e3f,0x010e10c9,0x0019d5ac } }, - /* 18 */ - { { 0x109a4e1f,0x14cfac09,0x09c01d07,0x1bce37d2,0x08d20ab7,0x1785f7e9, - 0x18fc9a97,0x07eff38a,0x00e7c007 }, - { 0x0ef59f76,0x1b6b31d0,0x1f2c1407,0x1676a841,0x002d4669,0x0fbd3d33, - 0x102b0230,0x1fd8cb67,0x00e08504 } }, - /* 19 */ - { { 0x0031b3ca,0x04c7b46d,0x169b59bc,0x19573dcd,0x046e86d1,0x00fd4a79, - 0x1ad16ff6,0x104b6132,0x0078f018 }, - { 0x1a25787f,0x1f77ef21,0x132b26ed,0x0df01a3b,0x1fc36801,0x043bd9ad, - 0x11e833a9,0x170fd28e,0x0043a773 } }, - /* 20 */ - { { 0x12b533d5,0x12bbb9a6,0x0f777018,0x1715ed43,0x0c293673,0x1e4d53cf, - 0x1ac55df9,0x0a38764c,0x00bb6de6 }, - { 0x165259b3,0x1f4981d5,0x0e9d2039,0x015fa7a0,0x0fc27d6a,0x01e8cd9e, - 0x066f16b2,0x134ba317,0x0060b461 } }, - /* 21 */ - { { 0x1ae5aa1c,0x0b51c708,0x19cd962f,0x0eca5693,0x187edb8b,0x000a772f, - 0x1f342c4c,0x1655dd7f,0x009d0f27 }, - { 0x1a730a55,0x1492318b,0x0ef20eb2,0x0ab65fbb,0x19a719c9,0x0ff05600, - 0x12341f07,0x0da6add8,0x00244a56 } }, - /* 22 */ - { { 0x0acf1f96,0x0d81ca57,0x1309c71b,0x02455204,0x1d3b99f2,0x160dc165, - 0x1da4989a,0x10e6b03d,0x0045e58c }, - { 0x038f9dbc,0x1ffa3ced,0x02281034,0x15e28dd1,0x0bed7a8a,0x0fd92370, - 0x1e92516b,0x03983c96,0x00c040e2 } }, - /* 23 */ - { { 0x0f8117b6,0x03d78003,0x08d50ce1,0x12d3fee7,0x075eb651,0x1abb0eca, - 0x1b1d20ac,0x12ed058d,0x001cdf5c }, - { 0x11f04839,0x0dbbada0,0x1785a61f,0x1d59e891,0x132197db,0x0ee8db85, - 0x1cf6ca48,0x1f1525bf,0x00046755 } }, - /* 24 */ - { { 0x1ce8ffcd,0x04562e95,0x1986a0b3,0x0789165f,0x0d6c70d5,0x10b93901, - 0x17cfdbc5,0x02277074,0x00046e5e }, - { 0x18007f01,0x1dc7fb26,0x1d0c60f9,0x03de24b5,0x1a03c7fb,0x0f531af0, - 0x016c1171,0x186607a0,0x006e0106 } }, - /* 25 */ - { { 0x08dd73b1,0x0639ac24,0x17b43652,0x00e11f32,0x02ab7767,0x0f5462b5, - 0x1c7ce0e1,0x1dbd2039,0x00442594 }, - { 0x12d4b65b,0x07d51648,0x12430dfe,0x0468772d,0x18d1f94c,0x1250af4b, - 0x1a3b4c9b,0x0a2985dc,0x00a796fa } }, - /* 26 */ - { { 0x023addd7,0x0cfdb024,0x19a4eccd,0x14c307ca,0x13c809e2,0x1bc71e5f, - 0x1ba7e216,0x1538d2ec,0x00e4ad2d }, - { 0x0e048a61,0x0bfbfa14,0x04b6680d,0x1a331981,0x0d8ef082,0x0d7a601f, - 0x050ff0e8,0x08d86f6a,0x00c5e940 } }, - /* 27 */ - { { 0x0be75f9e,0x1b529c61,0x048e9e11,0x0353d196,0x1c04b6fd,0x06f85884, - 0x1d1f6179,0x15fb68c8,0x0063283d }, - { 0x1af2df15,0x139467bd,0x1669fd33,0x0588aa15,0x0bcc3e59,0x1356f41a, - 0x04e3eac8,0x15633035,0x0068bd19 } }, - /* 28 */ - { { 0x1887d659,0x04756a88,0x164c16b0,0x09abe966,0x14fe3337,0x14c0e7f3, - 0x1f5a5a61,0x1ea78dfb,0x00495292 }, - { 0x1acec896,0x143c64f0,0x16d12112,0x096421d8,0x160a7d96,0x1bf13326, - 0x00dd9a5b,0x01a4c06d,0x000ec753 } }, - /* 29 */ - { { 0x0d2687bb,0x0d09d02d,0x0b887e8b,0x1076d5e6,0x0607ba1f,0x0f7a8eea, - 0x1c2ce43d,0x14cc90c7,0x000f6207 }, - { 0x0f138233,0x0b3f1dd8,0x0aa9c62f,0x0d72d84e,0x088aedd6,0x02039376, - 0x173e3b40,0x0e411dad,0x00ff0db0 } }, - /* 30 */ - { { 0x0c95d553,0x04fd080a,0x1a02a29d,0x00a5faba,0x1566fa44,0x018bff9d, - 0x1a8c60ed,0x07910e81,0x00313b51 }, - { 0x08d11549,0x00171560,0x17b8872d,0x1dc21769,0x0320e071,0x03eea3f9, - 0x1e049ae6,0x1f30de33,0x002d3abc } }, - /* 31 */ - { { 0x015581a2,0x0144280c,0x08846bd3,0x14daacc6,0x12e999a0,0x1d078655, - 0x137c66e9,0x021bdb31,0x00c036fa }, - { 0x01fbd009,0x0d7045d6,0x1456058a,0x1163200d,0x00d8f0b6,0x193bcdcf, - 0x06530bac,0x1896da80,0x00a6b2a2 } }, - /* 32 */ - { { 0x0d3549cf,0x019f287b,0x135997b5,0x06d2dff5,0x1fcb46f3,0x1ed66708, - 0x0181a56f,0x0a55ef93,0x00810ee2 }, - { 0x1159bb2c,0x0a287f0b,0x02cd5ed9,0x1f7d7ceb,0x1ea72f7d,0x1f3a6b4f, - 0x1d14ac15,0x0f524e62,0x00d48571 } }, - /* 33 */ - { { 0x10cb5a98,0x0ba0d457,0x0c442fc4,0x151f263e,0x02adfd3d,0x1165d59c, - 0x01386653,0x14e5f34c,0x006a6045 }, - { 0x02b2411d,0x186069fd,0x03a5b805,0x1d707ca2,0x1b3ccbe0,0x0fb9c432, - 0x1e40ef32,0x1f5f3c2a,0x00d3e45c } }, - /* 34 */ - { { 0x083f7669,0x10fb4ddf,0x01df5af3,0x115d04e5,0x0278d09f,0x172a1922, - 0x06725522,0x1bdc7858,0x00207755 }, - { 0x0fef1945,0x1deb0ecb,0x0b4a30e1,0x0279df62,0x164aa188,0x08eb396f, - 0x00367ef3,0x1cae2a96,0x0048dc5e } }, - /* 35 */ - { { 0x17e5a199,0x11bc85ff,0x0732edc4,0x1f719f31,0x19c79e0e,0x15ff0528, - 0x111709e8,0x1dbbfede,0x00f2fb0a }, - { 0x10b5025f,0x0e04abaf,0x1ea7c890,0x0a87ae81,0x1fbd0550,0x04569c05, - 0x14963e8f,0x02bb651a,0x00a13e90 } }, - /* 36 */ - { { 0x02b65cbc,0x0fbd1a85,0x119089be,0x0972e454,0x107a10b0,0x1120f11f, - 0x09bc9973,0x160292ea,0x002bf0d6 }, - { 0x0b216fb7,0x1ea6e9fa,0x17689ab4,0x0f70cff7,0x0505cf7d,0x1c1fb384, - 0x027ebade,0x0b42c5fd,0x0042a94a } }, - /* 37 */ - { { 0x0aadf191,0x0235685f,0x089a35d6,0x1491204b,0x1c1f60f8,0x182824a6, - 0x18f7a180,0x0d38cbdb,0x002c2dd9 }, - { 0x13849c17,0x0810b8ec,0x0894375b,0x0911743b,0x05485460,0x03831e1d, - 0x16f12043,0x03e858ad,0x00f437fa } }, - /* 38 */ - { { 0x0a0f7dab,0x1506b8a2,0x1dba6b1a,0x092f262e,0x197860f0,0x10287af9, - 0x0aa14b02,0x066a8e0f,0x00aaf45b }, - { 0x018d364a,0x0f1be19e,0x125c5961,0x17360c7c,0x05444d40,0x0b408af6, - 0x0af3d05c,0x01be9e4e,0x00cdf631 } }, - /* 39 */ - { { 0x0ea8b7ef,0x039e311c,0x0f08a1dd,0x126a310b,0x08e3408e,0x13b915ed, - 0x1fc90655,0x175b53c5,0x00f0d008 }, - { 0x0414d3b1,0x089338e9,0x067a9d8a,0x0a930b60,0x1cbdbb37,0x1cb6a29d, - 0x0e2d7186,0x1eb9510f,0x005bd5c2 } }, - /* 40 */ - { { 0x149a3154,0x187a34f7,0x0acba6bb,0x0b4b2adc,0x04a9c3e8,0x160f5549, - 0x1c6516ab,0x191413c8,0x00aa12df }, - { 0x0df69f1d,0x1793913a,0x1fd79cc9,0x09905945,0x1dd44e0e,0x0739dbd4, - 0x0406e763,0x0e7c9195,0x006c036e } }, - /* 41 */ - { { 0x0f6e3138,0x07d70950,0x0b4d1697,0x0dde004b,0x12bc5696,0x0325a2b3, - 0x1892264f,0x0b12d5f7,0x00292ff6 }, - { 0x1e213402,0x09286a22,0x04b27fb5,0x101c4e87,0x072e8f65,0x1cbfed0e, - 0x09d825ec,0x1206236e,0x00644e0c } }, - /* 42 */ - { { 0x047153f0,0x0f210f0d,0x01063278,0x1876f324,0x17672b86,0x0743b82e, - 0x09de4ef7,0x127956f3,0x00f25ae7 }, - { 0x0d869d0c,0x198ca51b,0x01b09907,0x0b910493,0x0945e9d5,0x0f5184b7, - 0x08f927ed,0x0a627b61,0x0039b8e6 } }, - /* 43 */ - { { 0x16fd2e59,0x1baa1005,0x157263cd,0x0580cd24,0x0573935e,0x190d0715, - 0x0c1b676a,0x05e1e33b,0x0039122f }, - { 0x03cad53c,0x1de70f00,0x1705f8f3,0x16581fcc,0x13877225,0x18e94d50, - 0x1e35caeb,0x1f19d01f,0x008de80a } }, - /* 44 */ - { { 0x007bbb76,0x1df546c9,0x1e09d62b,0x18fcf842,0x036b1921,0x1ba58e02, - 0x10137e8a,0x00c5c6d1,0x00871949 }, - { 0x03993df5,0x0fc945dd,0x0cf49aad,0x1aeb6be7,0x15050639,0x13c542da, - 0x1784046a,0x0d4b6e9f,0x00fc315e } }, - /* 45 */ - { { 0x08d6ecfa,0x10fea0d7,0x1b1fe195,0x1889ec35,0x0741d5f8,0x153da492, - 0x02226114,0x15bdc712,0x00e6d4a7 }, - { 0x0593c75d,0x02a9768a,0x09c45898,0x0e1b49ba,0x0c7db70a,0x0f49bdd1, - 0x195f4abb,0x13537c55,0x0035dfaf } }, - /* 46 */ - { { 0x0a736636,0x1cab7e6d,0x0b2adf9a,0x0a3b2f5c,0x0996609f,0x1fa0879a, - 0x14afec42,0x1ae39061,0x001da5c7 }, - { 0x1cce6825,0x020f2419,0x15cf0ed7,0x1a231ff2,0x036b815a,0x0963f918, - 0x075a8a15,0x1fbb7e97,0x007077c0 } }, - /* 47 */ - { { 0x06b9661c,0x1b1ffc6a,0x0b3f5c6f,0x1fa6d61a,0x1f8f7a1d,0x10a05423, - 0x19100dcf,0x05dca1df,0x0053a863 }, - { 0x096d8051,0x0bb7fb43,0x13d1a282,0x18192b8e,0x026bddae,0x06e1af27, - 0x13058a65,0x0da69c3f,0x00028ca7 } }, - /* 48 */ - { { 0x1c9877ee,0x08ea3ee7,0x074000b4,0x06c42100,0x060b6c8b,0x008baa61, - 0x011b400b,0x1b0d2c5e,0x0004c17c }, - { 0x10daddf5,0x0cde84a5,0x1395701b,0x046aea49,0x003b5bea,0x0b73396d, - 0x11d198cd,0x1d3fdb2e,0x00f7ba4d } }, - /* 49 */ - { { 0x0be1263f,0x06dfd1a7,0x0b9f39b4,0x0c6e6ae3,0x0f523557,0x02a9c153, - 0x11074910,0x000a4263,0x00e31f96 }, - { 0x0a6b6ec6,0x0ddc90b7,0x10bf1134,0x03a25ce7,0x0a29437a,0x1f5644e8, - 0x11ef0439,0x0b39c69a,0x00aa3a62 } }, - /* 50 */ - { { 0x16f3dcd3,0x1e7cefa9,0x0fdcd83e,0x1bdaa1a5,0x04f5b6ce,0x087d6fa8, - 0x0bb9245c,0x0c4fcf3b,0x002398dd }, - { 0x0d09569e,0x1a382d1b,0x127dda73,0x0c3376a2,0x0034cea0,0x01bb9afb, - 0x0843fe70,0x1643808c,0x005717f5 } }, - /* 51 */ - { { 0x01dd895e,0x1f114e49,0x10a11467,0x030a0081,0x17ecd8e5,0x091c8eb1, - 0x037be84f,0x0ac1c785,0x00660a2c }, - { 0x167fcbd0,0x06544576,0x0a7c25a7,0x0e48f01d,0x12b4dc84,0x1a40b974, - 0x114ccacb,0x0989ea44,0x00624ee5 } }, - /* 52 */ - { { 0x1897eccc,0x0aa4e726,0x06202a82,0x13a3b27f,0x07c204d4,0x1211821d, - 0x0f01c8f0,0x1f7257bf,0x004f392a }, - { 0x1de44fd9,0x0b4fc7d3,0x0cc8559a,0x19f7c8af,0x0bc3cb66,0x14019b47, - 0x06736cbe,0x0ef99b67,0x008a3e79 } }, - /* 53 */ - { { 0x06c4b125,0x0f0c40f8,0x18f2a337,0x09c601ed,0x013e9ae3,0x0cef2e3d, - 0x1013bda6,0x046e1848,0x003888d0 }, - { 0x04f91081,0x11401ab2,0x0055411d,0x1f9ec2be,0x0d36e3d9,0x16e43196, - 0x0cd8609f,0x08e30204,0x00a5e62e } }, - /* 54 */ - { { 0x0facd6c8,0x1412f719,0x0f2f1986,0x18c6a8a9,0x19931699,0x16fbcc6f, - 0x0b70338f,0x1cc8cd4b,0x002c4768 }, - { 0x10a64bc9,0x1a37fc64,0x1de7d72c,0x14c041c8,0x1e884630,0x08325e02, - 0x0a836527,0x083f3cca,0x007b5e64 } }, - /* 55 */ - { { 0x1d28444a,0x0b4a1160,0x04da8e48,0x0d8bb17c,0x07fcee99,0x17f2fd86, - 0x11288e1e,0x196191ae,0x00b8af73 }, - { 0x138b86fd,0x1ef41d51,0x02973fd7,0x07e2b14b,0x09433fee,0x07b79056, - 0x025727ba,0x0befe7e1,0x00a03639 } }, - /* 56 */ - { { 0x010f7770,0x039e35dd,0x0a838923,0x02db0342,0x02b9fa6f,0x1b4128de, - 0x14cc4037,0x0030ebf6,0x004be36b }, - { 0x1fb56dbb,0x11304374,0x19e93e24,0x1fdf160f,0x12f20306,0x0602b36a, - 0x0303bab3,0x10e37b80,0x008cbc9a } }, - /* 57 */ - { { 0x00dac4ab,0x098c4ae6,0x0bfc44b8,0x094880e2,0x0ee57a87,0x173e350e, - 0x17e18cca,0x07c18106,0x0044e755 }, - { 0x1734002d,0x0a81fffb,0x0d10971b,0x0b971616,0x138b59d3,0x013b0743, - 0x106257dc,0x074bd71f,0x00470a68 } }, - /* 58 */ - { { 0x10513482,0x0dbb0ee4,0x1a49daa0,0x0e405403,0x13083028,0x00f70673, - 0x1bbf3691,0x1218c7b8,0x00164106 }, - { 0x0d06a2ed,0x081a5033,0x06c402fd,0x1aee8a31,0x018c9dd4,0x173955c1, - 0x0d3f6452,0x1faf5797,0x00d73479 } }, - /* 59 */ - { { 0x1ad4c6e5,0x16f7d8b2,0x01b4135f,0x19e11eb6,0x1cb14262,0x0dd8c2ba, - 0x19ac4bb5,0x1c60ee2c,0x00816469 }, - { 0x161e291e,0x1d5cebca,0x17859875,0x1b5e4583,0x00513eb9,0x13f589af, - 0x1e73d260,0x047e1ba7,0x000a36dd } }, - /* 60 */ - { { 0x01d5533c,0x0c69963a,0x0118a3c2,0x1eb53d0d,0x1bd117c5,0x1456f1a4, - 0x0460e688,0x1adfb756,0x00e331df }, - { 0x0bcc6ed8,0x08055b43,0x1e898394,0x01877bde,0x050d7716,0x0cd3de74, - 0x0e26418f,0x054925c6,0x00d3b478 } }, - /* 61 */ - { { 0x13821f90,0x0a4db747,0x1adeab68,0x1bb3dacd,0x1311692e,0x14a98d00, - 0x16f42ed9,0x0b4990d4,0x00728127 }, - { 0x13ff47e5,0x01c2c7be,0x00591054,0x0c2d78c2,0x19bb15e1,0x188d3efe, - 0x01658ac3,0x0fd9c28a,0x002c062e } }, - /* 62 */ - { { 0x0159ac2e,0x1b7ccb78,0x16c9c4e9,0x1cee6d97,0x06047281,0x09440472, - 0x1bc4ab5b,0x1f2589cf,0x00282a35 }, - { 0x00ce5cd2,0x01aa58f6,0x1e708a67,0x13df9226,0x0c11ecf9,0x179c1f41, - 0x0af664b2,0x026aa9a5,0x00c71cd5 } }, - /* 63 */ - { { 0x09b578f4,0x042ef4e0,0x0bfe9e92,0x09c4b1c7,0x02f1f188,0x18dbac8c, - 0x0e8e3dda,0x0819e8fe,0x00c50f67 }, - { 0x174b68ea,0x0e256f99,0x0597f8aa,0x0de646d3,0x13050a40,0x111142d2, - 0x0370be1a,0x14e4252b,0x00b9ecb3 } }, - /* 64 */ - { { 0x14f8b16a,0x17c20877,0x1ec99a95,0x0835fd88,0x087c1972,0x15c736ce, - 0x0c6c2901,0x0059a855,0x00803f3e }, - { 0x04dbec69,0x18184d40,0x0eb417df,0x170bee77,0x0197fa83,0x1939d6c7, - 0x17071825,0x01ca0cf5,0x00c09744 } }, - /* 65 */ - { { 0x0379ab34,0x0352b796,0x077e3461,0x1c0d1708,0x068efa8e,0x022c8bb6, - 0x1cc080c5,0x1ab22be3,0x00f1af32 }, - { 0x1d75bd50,0x0e1ba98a,0x0bd9ef26,0x19ff75ee,0x1723f837,0x120c246b, - 0x122c184e,0x061c5a83,0x0023d0f1 } }, - /* 66 */ - { { 0x141500d9,0x0bd5b76f,0x0fab6a21,0x1215cbf9,0x059510d8,0x032444b9, - 0x0b754bfa,0x1ad8147f,0x00b0288d }, - { 0x050bcb08,0x09907983,0x175b85a1,0x1ec626d2,0x1aa7671a,0x1053dcc4, - 0x0348c7d4,0x09fe8119,0x00ffd372 } }, - /* 67 */ - { { 0x1458e6cb,0x1cb47325,0x1e974a14,0x1b5a4062,0x15f56992,0x1705bd53, - 0x1b7ce052,0x095af184,0x00f5590f }, - { 0x0f0ba55a,0x1e125e9e,0x1de2eb83,0x08e49418,0x1674a0fc,0x0327b41d, - 0x088073a6,0x0a9edee9,0x0018d6da } }, - /* 68 */ - { { 0x15be5a2b,0x0c9f112e,0x0d3cf1bb,0x0f3306b2,0x06ffc6fe,0x04931131, - 0x05a90c50,0x1b2f3204,0x0050bbb4 }, - { 0x057ec63e,0x1c0c8e37,0x07736c8d,0x04588030,0x0e0f6654,0x04cd811b, - 0x070d06a0,0x03003fc9,0x002b1001 } }, - /* 69 */ - { { 0x1b391593,0x0345ae2c,0x009c3f3f,0x0beb44b3,0x0dcbbc38,0x19d568cd, - 0x1831c513,0x13307f75,0x00dd5589 }, - { 0x14b82ff4,0x1dc45c73,0x19cd3264,0x007880e3,0x0322ad2e,0x0f57a1e0, - 0x010669ea,0x0a2293ac,0x00e6e4c5 } }, - /* 70 */ - { { 0x1e9af288,0x0fb2add8,0x0b6a4c55,0x1c34c9ef,0x020e5647,0x1f25e594, - 0x1bfd0da5,0x1620fdaa,0x0051e00d }, - { 0x171c327e,0x1e8b4dc3,0x05b0ab50,0x1b641695,0x1477929c,0x08fa9ef5, - 0x05df01f5,0x08293052,0x00e22f42 } }, - /* 71 */ - { { 0x035f1abb,0x0a2f47a3,0x14e21d33,0x18196ad0,0x0034d7ed,0x160fdad4, - 0x0327251c,0x07aa5b89,0x00f70937 }, - { 0x08af30d6,0x00cb35dd,0x0deda710,0x1ebe95e2,0x1c47e95b,0x0b1549b0, - 0x0c44e598,0x111ce4eb,0x00bd52d2 } }, - /* 72 */ - { { 0x1c5fa877,0x18aae3d4,0x0e8f522a,0x15ace4fa,0x189d817d,0x1fcf39e8, - 0x1e990fd0,0x1c99154e,0x00a0d0f8 }, - { 0x0c94f92d,0x1df57ec6,0x1376ce82,0x11917c18,0x0ba14d81,0x12fc5c17, - 0x08008b31,0x18f28dad,0x00a56c78 } }, - /* 73 */ - { { 0x0dd09529,0x0b11c8d8,0x0b77f3ca,0x1c1d4c7b,0x1f481803,0x1a8fadad, - 0x19e8b1dc,0x1f0e6346,0x00d8befd }, - { 0x1c0157f4,0x1c8cea17,0x1239942a,0x195daffd,0x08b0af51,0x05a0016a, - 0x11e337e7,0x14b9d3ec,0x00854a68 } }, - /* 74 */ - { { 0x03506ea5,0x01afb3db,0x1f8359b7,0x0d891349,0x1cd4d928,0x0e9dff4a, - 0x0a54fc40,0x0173108d,0x005cacea }, - { 0x1ceac44d,0x086fb064,0x13470eaa,0x0535e86a,0x1babe3db,0x1ef456ae, - 0x1ea42374,0x0246bc9d,0x00e4982d } }, - /* 75 */ - { { 0x034cd55e,0x18825116,0x00344c88,0x12b7664d,0x1d943586,0x0d7d0fd0, - 0x1267ecd1,0x1ec2d640,0x008046b7 }, - { 0x18e7d098,0x099ac0f1,0x1bc2dc2d,0x0c3d1be8,0x178c4d7f,0x14f52265, - 0x1d54c37a,0x0f721055,0x00eb17ca } }, - /* 76 */ - { { 0x16a145b9,0x1a8dacc3,0x0f1c7b05,0x1ed61f83,0x115bba5c,0x1ab29c93, - 0x04c74f80,0x175f56bc,0x00097b00 }, - { 0x165f69e1,0x1336474a,0x0f94666a,0x11eeb56b,0x1d98477e,0x1d08ed27, - 0x127980ce,0x0f75fb79,0x00f95c74 } }, - /* 77 */ - { { 0x1ebae45e,0x0c780e9d,0x0f1a5555,0x17d3e189,0x04fc6a8e,0x02d8ede3, - 0x00debadc,0x03cacddb,0x00351260 }, - { 0x1a1161cd,0x19b78f0f,0x197be1e4,0x1571aa98,0x121e5328,0x17713927, - 0x0dad1d5f,0x046c0d15,0x000ef971 } }, - /* 78 */ - { { 0x14ca4226,0x12cc67ba,0x190b2380,0x1bc271f0,0x017905ee,0x1fba2347, - 0x12552258,0x066769f7,0x00fc16d9 }, - { 0x07c800ca,0x14b7d98f,0x1e2b6aaf,0x00c6624c,0x1e8b5138,0x024bb7f9, - 0x085cf589,0x1e372baf,0x0014ca4a } }, - /* 79 */ - { { 0x1d2f81d5,0x123b8dd5,0x1df4659e,0x1f3ad203,0x1c9071a5,0x1f7be56c, - 0x0c776262,0x0c7eb384,0x004057b0 }, - { 0x09c05c0a,0x1fec17f4,0x1037e16f,0x0238de3b,0x016dbe49,0x065751ad, - 0x0c4cefbf,0x0c9e2661,0x001c3b5d } }, - /* 80 */ - { { 0x00ec21fe,0x1f0a5ff4,0x156fa097,0x1c22d584,0x05d67f6c,0x0d0397a5, - 0x0ebe62f1,0x091b6fcc,0x00fad271 }, - { 0x09ab05b3,0x0605b561,0x0946b9a4,0x1350789c,0x0de7d37a,0x043ae155, - 0x0a1029f7,0x1c73e1c3,0x0077387d } }, - /* 81 */ - { { 0x056c0dd7,0x14f6624d,0x021b1d07,0x1ff9b08c,0x1aecea5c,0x0a047a82, - 0x11fa3de8,0x1817de18,0x00b37b85 }, - { 0x0c0e6a8f,0x0cb5b726,0x0e23c8cd,0x1a977ed6,0x0ef4efd6,0x09fd61ce, - 0x0356ae91,0x191f3ec5,0x009c135a } }, - /* 82 */ - { { 0x04e35743,0x15519014,0x08f37bcc,0x1ad5630b,0x19819320,0x18bb0ef8, - 0x147ee086,0x03f88670,0x00572136 }, - { 0x11fc9168,0x186d9b53,0x17100f07,0x1174e6bc,0x0d8f55f9,0x143f1bde, - 0x06f7d932,0x193cd762,0x00dcbac3 } }, - /* 83 */ - { { 0x0518cbe2,0x00eccb42,0x07ac13bc,0x05f83139,0x1eebfd24,0x11e3f23f, - 0x0189c9d9,0x13c5ac4d,0x00b8c1c8 }, - { 0x08e1d569,0x0d2c5eee,0x16233414,0x1013916f,0x131eb563,0x1fecf88f, - 0x0b509b09,0x1b45f284,0x005d23bb } }, - /* 84 */ - { { 0x15c8f8be,0x10e394a4,0x1cd8afc2,0x03890077,0x1d4ac296,0x0201efb1, - 0x04027906,0x19723d9d,0x00c109f9 }, - { 0x18945705,0x1684ae82,0x1ae17030,0x107b2dbb,0x0449bb90,0x15c6bd20, - 0x1b8611a4,0x09e5ddc3,0x009bc334 } }, - /* 85 */ - { { 0x02913074,0x0ad71ab2,0x0950ac43,0x12364e91,0x0732a554,0x1332d988, - 0x13051a72,0x0a4be349,0x0029591d }, - { 0x184f983f,0x1b7adb5d,0x17e13879,0x1dde833e,0x0a189be7,0x0a4b405d, - 0x0cb04803,0x03e31de6,0x00637655 } }, - /* 86 */ - { { 0x162976cc,0x0d2f8a72,0x1c4b0e2f,0x1947cc1d,0x0985222b,0x18323665, - 0x01eaefe8,0x19011c53,0x00bdb79d }, - { 0x0b06a772,0x0965ae4e,0x14db73bf,0x08eb55fc,0x15db838f,0x10113e15, - 0x052b0a8f,0x0035ba78,0x008ee860 } }, - /* 87 */ - { { 0x04ade873,0x1f4b4c0d,0x1ee92332,0x13549b89,0x14ba57ee,0x144cad02, - 0x092cb3b8,0x0f4deef5,0x0092e51d }, - { 0x1190a34d,0x045d7d43,0x0f47b465,0x11eeb7ed,0x11144d69,0x13718657, - 0x0aab403b,0x0de14ad5,0x005182f8 } }, - /* 88 */ - { { 0x1a4cc99c,0x1d310963,0x1b67287e,0x0136d07c,0x18c5aff6,0x13e5ad64, - 0x1bc976ec,0x0ba80e74,0x0091dcab }, - { 0x1f575a70,0x0db661ea,0x0361fe80,0x06c272df,0x017360cb,0x074644cc, - 0x1cac5975,0x1b72f2e9,0x0017a0ce } }, - /* 89 */ - { { 0x076c8d3a,0x0430f150,0x03e492ce,0x155a7242,0x035d9701,0x157209d4, - 0x1d065343,0x0d8fe99b,0x002e8ce3 }, - { 0x037a862b,0x0939ed58,0x19323ea4,0x15376ec1,0x0f2dd01b,0x09c419dd, - 0x03cfe591,0x19669ecd,0x00f4ccc6 } }, - /* 90 */ - { { 0x11f79687,0x077a92e7,0x1bea0551,0x12a92b25,0x18d297c5,0x0ba0d2e3, - 0x0f27848c,0x111341be,0x00ac0db4 }, - { 0x1f01747f,0x15fe388e,0x05f7c4e1,0x1726b1de,0x16bb5592,0x0727ae65, - 0x128b9620,0x0c32992e,0x0095a64a } }, - /* 91 */ - { { 0x015a4c93,0x160f7ed6,0x1614505c,0x0d36e704,0x10bad402,0x1d8e0b65, - 0x19ddaa37,0x17452420,0x00231e54 }, - { 0x0ae6d2dc,0x186fc8bc,0x044a4629,0x154c7e72,0x172234d6,0x1935af2d, - 0x0787d89d,0x065b14e6,0x00ab0be0 } }, - /* 92 */ - { { 0x0d131f2d,0x0bd6874c,0x013c4042,0x1e13c676,0x1a748637,0x10cb6af4, - 0x19e46b21,0x10059ed4,0x00f1bcc8 }, - { 0x08daacb4,0x0e348a07,0x1d940249,0x1c80aac1,0x137a63c4,0x047e23bc, - 0x09c56473,0x0d2b5d76,0x00851694 } }, - /* 93 */ - { { 0x11dcf593,0x11ae0a1f,0x062f8ef7,0x00565360,0x19d3d782,0x16e14dee, - 0x1763a736,0x1a5b55aa,0x008f67d9 }, - { 0x1481ea5f,0x0088b2b3,0x13164321,0x05bbd3c6,0x13fa8e7d,0x01fa0282, - 0x0d77ff75,0x17380e51,0x00f84572 } }, - /* 94 */ - { { 0x17af71c9,0x10d3d38c,0x1cd95957,0x092888f4,0x15063a14,0x1703870e, - 0x106686d2,0x020c2d65,0x00edee27 }, - { 0x11734121,0x1781a7a8,0x097a7c2c,0x18dcaa94,0x02ecf1ca,0x0479d206, - 0x1fd23705,0x13689d7a,0x009fd27e } }, - /* 95 */ - { { 0x16e2cb16,0x063b2c57,0x16466d8f,0x16fa59fc,0x15583e3e,0x0c0b0b46, - 0x0e1d6a31,0x16d2b1fe,0x00a40c2f }, - { 0x1edcc158,0x04f62b07,0x1c8c15a3,0x10098cab,0x07e127ad,0x13824d18, - 0x1b3f64e5,0x170fb8db,0x0099bc9b } }, - /* 96 */ - { { 0x127dafc6,0x054a90ec,0x02734661,0x03f6d2b8,0x06dde52c,0x00d07c9b, - 0x19927656,0x01742daf,0x009abe21 }, - { 0x08915220,0x0057c252,0x1605b192,0x062ed49b,0x1ca5afa7,0x1cc38b40, - 0x12c31f54,0x0af0fe68,0x007881c2 } }, - /* 97 */ - { { 0x00bcf3ff,0x19ccda8f,0x1fdd3da4,0x05978a24,0x1d9680d0,0x12d16e80, - 0x05023ed1,0x033461d1,0x0015e6e3 }, - { 0x1e0e05f4,0x036b7069,0x16210119,0x0f7bb886,0x050d3fad,0x03e8e27c, - 0x0b3af987,0x19e3222e,0x000e55fa } }, - /* 98 */ - { { 0x18787564,0x14ecc037,0x1a17399f,0x062e4263,0x1e8d61a3,0x0c655c0c, - 0x15ddac05,0x0ecdfd2c,0x00d73d09 }, - { 0x1eb7206e,0x1241a128,0x062ed090,0x12521f8c,0x0a520a51,0x1c2caf18, - 0x142d772e,0x0e91e2b4,0x009250a3 } }, - /* 99 */ - { { 0x1e577410,0x17f847c5,0x1dea31b2,0x011406a0,0x063a4fd4,0x1944f605, - 0x102fc7d8,0x10583991,0x00774140 }, - { 0x0b0991cd,0x0d207d37,0x1f70a581,0x1410cc93,0x0fd40c1c,0x11e3d992, - 0x02e4e9a2,0x09a25d64,0x008cb04f } }, - /* 100 */ - { { 0x0906171c,0x0e1682ab,0x09030fec,0x07d39b60,0x06841907,0x15a7ec48, - 0x0d476e39,0x1de8e247,0x00e4e429 }, - { 0x18ec36f4,0x1c6ea9e1,0x12da89c2,0x05b803fe,0x09a48f9d,0x1703c3cd, - 0x15497419,0x1fe78dcc,0x0037bca2 } }, - /* 101 */ - { { 0x1f562470,0x06971e3e,0x0592b253,0x04e54581,0x193be44f,0x0efcc063, - 0x08a9f1b5,0x1b860056,0x0059913e }, - { 0x1750592a,0x109cd41a,0x00f7809e,0x003b01cf,0x1d64f99e,0x01baf502, - 0x089b3e30,0x0956027c,0x0043786e } }, - /* 102 */ - { { 0x1e56b5a6,0x1995876c,0x1f1a3e7f,0x01b34db3,0x046a7075,0x1422acbc, - 0x19ebb057,0x1316fcf3,0x008638ca }, - { 0x0afc24b2,0x1ad704b0,0x0b3a3c8b,0x131d5e9b,0x1a78f053,0x0ee85765, - 0x1bc0edd9,0x0d4f6754,0x001ecdd3 } }, - /* 103 */ - { { 0x0c5ff2f3,0x09d66b13,0x1cea5e17,0x0a2d8050,0x10d54a2d,0x04fd6908, - 0x0cb6b653,0x10ba8b3e,0x00d85d0f }, - { 0x10b11da3,0x1b805c68,0x00c63127,0x0458614f,0x0decdd2c,0x047a4904, - 0x118955a6,0x18769da7,0x00a04f19 } }, - /* 104 */ - { { 0x0d7f93bd,0x03c92647,0x0bd47d82,0x0958ba72,0x171afcb6,0x1985410d, - 0x02c1f2b8,0x1d4b812a,0x0092b2ee }, - { 0x05b6e235,0x0d6264a4,0x0db03c21,0x19495252,0x08891ab2,0x1359f028, - 0x1db203ea,0x042b0684,0x001ee782 } }, - /* 105 */ - { { 0x063e79f7,0x10517007,0x067641a9,0x01cf65e7,0x1c09df59,0x02a53303, - 0x05424084,0x1b0af4dc,0x00f3f2ce }, - { 0x110d9b55,0x0028879f,0x19099208,0x1f9f59b0,0x10e7c9d2,0x0d53f45e, - 0x0843958c,0x0a87b47c,0x000f56a4 } }, - /* 106 */ - { { 0x1043e0df,0x190dffd0,0x001f9b56,0x096d9938,0x0517a6c7,0x17606a54, - 0x098c6995,0x08232d3c,0x00bd8f17 }, - { 0x1eb7494a,0x14dddc35,0x1cee0e22,0x0fa8de8b,0x1a79a156,0x0953d272, - 0x08277de8,0x06a6199f,0x002d1a1c } }, - /* 107 */ - { { 0x106508da,0x0971c09a,0x15e569c6,0x03018943,0x144b3336,0x0ca4bd4c, - 0x091b376d,0x0bd723f7,0x00a107a6 }, - { 0x0f94d639,0x168e8e28,0x162df5f9,0x15e6eb14,0x1ca1c8b4,0x0ac25e9b, - 0x0bc869f1,0x015f0f53,0x00183d76 } }, - /* 108 */ - { { 0x0dde59a4,0x0eb4b888,0x02fbe1ca,0x1b1a0e1d,0x0be78f1a,0x04b1a797, - 0x1d508a6d,0x13b84d3a,0x001d4417 }, - { 0x0390d30e,0x196e067c,0x1a04432c,0x164ea61b,0x0339a0a3,0x0ee295e0, - 0x0988c6bc,0x1852c0da,0x00771f9c } }, - /* 109 */ - { { 0x05040739,0x0cc9f3bc,0x09aa4e66,0x073b7300,0x0fc26445,0x1b797afc, - 0x063b3d03,0x06206c4e,0x0064427a }, - { 0x05428aa8,0x1a796c3c,0x1ed26a13,0x15b87fd7,0x101ac7b7,0x1636f91e, - 0x15b4806c,0x092d5d21,0x0049d9b7 } }, - /* 110 */ - { { 0x035d1099,0x03c6c5e2,0x03468233,0x179a9d1d,0x08a412ad,0x1150165b, - 0x11140b0b,0x0367ec0a,0x009037d8 }, - { 0x074c7b61,0x06dd6138,0x0ff5cb9f,0x006356af,0x15352fe2,0x164b2cb6, - 0x0e718733,0x0d4f980c,0x0008c3de } }, - /* 111 */ - { { 0x16d552ab,0x07ee8107,0x13607c48,0x15ff300b,0x1129156b,0x1e1f489a, - 0x0cbc1bed,0x0848af2d,0x00c69094 }, - { 0x01231bd1,0x1d9d74e2,0x11608145,0x18dd0eb9,0x0a1221ea,0x1bd5fceb, - 0x0b008220,0x00595fc7,0x003fa3db } }, - /* 112 */ - { { 0x05058880,0x1ad1f328,0x0e50fcb5,0x06cbdec8,0x049257da,0x030e7d59, - 0x03fd051e,0x161fb701,0x00c5c4bd }, - { 0x1272b56b,0x1a89f1a5,0x0e410e9c,0x04fd2a23,0x04969c83,0x11befc42, - 0x1ad7f633,0x1288d856,0x002d56db } }, - /* 113 */ - { { 0x1f46ac6b,0x030bc17f,0x08b90949,0x1ef24c0f,0x08de1d19,0x11e204d2, - 0x090bebfa,0x13bca077,0x000f56bd }, - { 0x145cda49,0x1bea7689,0x1bca6744,0x02b1f902,0x03402821,0x12a5575a, - 0x17c79f1a,0x13a22e76,0x004003bb } }, - /* 114 */ - { { 0x00803387,0x1c740c4d,0x12f5010e,0x022bea73,0x17f21ece,0x1046e943, - 0x1e790a5c,0x04540fe5,0x00537655 }, - { 0x08a4182d,0x04c0510d,0x0677de69,0x17a0f464,0x1a2d4a2b,0x05170d0c, - 0x15259d34,0x0b0d8ba8,0x007a056f } }, - /* 115 */ - { { 0x1d8a2a47,0x03592ac4,0x17c9dcd9,0x10529187,0x0d5395b5,0x000755f8, - 0x19d547b0,0x1e2f4344,0x0077d482 }, - { 0x07853948,0x050decac,0x1efffbae,0x102f7ad9,0x01e47a6f,0x002bc034, - 0x0392adbb,0x05656716,0x00411501 } }, - /* 116 */ - { { 0x0de28ced,0x039f87a3,0x04fb11cf,0x1b4ec136,0x063921d5,0x074f372e, - 0x051986e3,0x0e5f7d41,0x00cdf045 }, - { 0x0c53c3b0,0x059e2c5b,0x1ee10f07,0x1c782088,0x1780e97f,0x0570965c, - 0x0427ecae,0x1b52e706,0x00ee703d } }, - /* 117 */ - { { 0x1f57e43a,0x028a8a07,0x0e046e0d,0x0cc1a763,0x0b986d44,0x0effc7a1, - 0x1884aced,0x13b42c59,0x002a0ad8 }, - { 0x0bc277ba,0x072534a3,0x10709d99,0x1192a982,0x16274c78,0x1326655f, - 0x1964506a,0x0cf58568,0x00d62d0b } }, - /* 118 */ - { { 0x0c054ac4,0x0e2ec3d9,0x1f7de20e,0x00b0b3e4,0x128d6570,0x05f9d8c0, - 0x109bb7df,0x1e532384,0x00b39a23 }, - { 0x10b16ae5,0x094250af,0x0dbd46e5,0x140b6342,0x007830c6,0x009bf938, - 0x1314758f,0x12580ce9,0x0004ed00 } }, - /* 119 */ - { { 0x1ae90393,0x1a0c2e8c,0x0f593987,0x0f685294,0x0fc14304,0x00d34c2a, - 0x0e1eb800,0x18202ef8,0x00a0a91f }, - { 0x0e2c831e,0x1851f80d,0x1c9f85bf,0x0d5d0456,0x075b4bb7,0x0450ad18, - 0x11063c4b,0x1113da41,0x00084cf9 } }, - /* 120 */ - { { 0x1ca6becf,0x0c284ef7,0x1fecca36,0x1d5d00fb,0x0e8b92fc,0x0ae223bc, - 0x1df97628,0x164e757e,0x00d57955 }, - { 0x11b5d4f1,0x086d3cf1,0x1e9e8708,0x05e09679,0x1c20baa5,0x1044ee13, - 0x07c75344,0x08405a28,0x008e14ea } }, - /* 121 */ - { { 0x12897042,0x16a81a2f,0x100b12bb,0x0a663e86,0x1fb218d0,0x00ca645e, - 0x05632367,0x06e5549a,0x00597e1a }, - { 0x0f0bd68c,0x193f60d6,0x00925140,0x17c1b956,0x03e846d4,0x06bd64ff, - 0x17a96e72,0x06c33369,0x00ca3f02 } }, - /* 122 */ - { { 0x0170bd20,0x095085ab,0x0fd779d6,0x112fe2da,0x0ade20ea,0x1ff8a259, - 0x1f928cd8,0x0fc61380,0x00bde7fd }, - { 0x18f5432c,0x0b5db695,0x10d112d4,0x1b8397c0,0x15b5a210,0x0f37fc7c, - 0x0660f6c0,0x01c14fba,0x00b623ad } }, - /* 123 */ - { { 0x00c7b65b,0x1adeb3ab,0x0928a269,0x18ab2047,0x06795ab8,0x07e86bd9, - 0x0defe088,0x08cb1d82,0x00d6aa2e }, - { 0x1138bb85,0x055e005a,0x0cea5704,0x03a243b0,0x0a32e8c3,0x18058b81, - 0x04eac93f,0x1c05b98a,0x00111662 } }, - /* 124 */ - { { 0x0fb42b87,0x008a00af,0x1b137fde,0x1ebae036,0x1c129bd9,0x066bd3eb, - 0x03e19bb3,0x197296ea,0x00db3ee1 }, - { 0x134837cf,0x1379ed87,0x15e353ec,0x1da31772,0x0657de7e,0x0fc9be2b, - 0x096574b3,0x084a440d,0x00886a64 } }, - /* 125 */ - { { 0x05b569ea,0x011a67db,0x0846704f,0x022283ee,0x0619e200,0x042ed0ad, - 0x1ef22eb7,0x1d603142,0x00a70cf4 }, - { 0x0c4a6a65,0x127cbd74,0x0d0de3c8,0x0b9e4e02,0x0096036e,0x104f27bf, - 0x0ddef8e9,0x157a2e8f,0x00aa4772 } }, - /* 126 */ - { { 0x1aa60cc0,0x1b3b098b,0x1a0457d9,0x02c6c206,0x1bb5ac79,0x05da5de0, - 0x05d37b66,0x1b861f5f,0x00611a6d }, - { 0x015ee47a,0x073c65e6,0x0365a94c,0x12c5049c,0x1ed882e8,0x0d6f9eec, - 0x1220dbcd,0x1f02c853,0x005cfffa } }, - /* 127 */ - { { 0x1b7a99cd,0x06aa67fc,0x0f116870,0x07733b08,0x139e17bf,0x0847b163, - 0x05300e2a,0x046fb833,0x006e5a6b }, - { 0x0ba5db77,0x1c5a2a70,0x1d8358fb,0x1100ff59,0x08378b7b,0x00633b30, - 0x0f339647,0x11a485b5,0x00481a23 } }, - /* 128 */ - { { 0x15d0b34a,0x1a0bde01,0x09f029f8,0x1670d706,0x162d1440,0x1316d601, - 0x050e3edc,0x099c19bf,0x002c4111 }, - { 0x0d95a0b1,0x1d2e778d,0x1550d88a,0x166f50cf,0x086c9c09,0x06e900f2, - 0x0a5c9b5b,0x17e85ff2,0x0020477a } }, - /* 129 */ - { { 0x18d65dbf,0x1ba8b9e0,0x07b6b60b,0x1f281c67,0x1001c77b,0x0935ee78, - 0x1ad9c08b,0x1358ee72,0x00ac6640 }, - { 0x06261cc3,0x185d9b7e,0x039fa422,0x1ef79232,0x06c10213,0x075d522f, - 0x1e159507,0x0eb98245,0x00ce8e69 } }, - /* 130 */ - { { 0x1c0a67d2,0x1890da0d,0x13492283,0x08ec1488,0x1473762d,0x078eb2cd, - 0x12a03811,0x0ca4a176,0x0008fde3 }, - { 0x048bf287,0x07761ed4,0x0da75bab,0x0c4305a6,0x09482c2a,0x0fee4922, - 0x135cd60b,0x1a4acbad,0x002f7e2f } }, - /* 131 */ - { { 0x03770fa7,0x125c96de,0x0410fe6b,0x1d1ab86f,0x01171095,0x074e8bbb, - 0x0ab953cd,0x05d20ee0,0x00c65be9 }, - { 0x16fd0a40,0x1ac5181f,0x139e12c9,0x1045c779,0x167bfe7d,0x1ac2a7cb, - 0x0ce9eb93,0x08fa2327,0x004bff8e } }, - /* 132 */ - { { 0x00ff1480,0x0a0e90f8,0x1536c5b3,0x11f6fa0e,0x0f3ea2ab,0x0977ddf0, - 0x19f6b207,0x1ccaee52,0x003e4e4a }, - { 0x1c5303e6,0x10c79b69,0x0988e5df,0x13329724,0x0c3c03bd,0x07130992, - 0x00a27b5c,0x1fab1d8c,0x005388ae } }, - /* 133 */ - { { 0x1e5d7713,0x0898bf5a,0x179276ab,0x130bdceb,0x1b26109b,0x1e27e3a7, - 0x1838cbd6,0x1a29eeb7,0x005cf908 }, - { 0x0e657b12,0x1021a884,0x1bb6799d,0x08434b72,0x0ccc2bfd,0x1a8fc4b8, - 0x138838a7,0x080c1e01,0x00a698ba } }, - /* 134 */ - { { 0x0f748fec,0x1ed8b437,0x074b3e5c,0x0eab44fd,0x05effe6e,0x12a26713, - 0x16358c2d,0x114f5d75,0x00b142ef }, - { 0x17d5770a,0x098d7cf8,0x0cd04beb,0x1e76ce59,0x159de66a,0x068def99, - 0x01d5af58,0x12cb0a2a,0x00d1896a } }, - /* 135 */ - { { 0x13c41c08,0x02cabd59,0x1a38b87b,0x1d2958a8,0x12f6c87d,0x15b9d623, - 0x08e46205,0x016f303b,0x00267b0e }, - { 0x0e62b988,0x12aa72ec,0x1b4879db,0x1b8eaa22,0x06f99d8d,0x1d781e95, - 0x0e4d1843,0x0f542232,0x00b54e28 } }, - /* 136 */ - { { 0x178a876b,0x100915a8,0x14412d02,0x1f2dfe10,0x09f7651f,0x18d58a79, - 0x1398142c,0x116bf0fa,0x0084abb2 }, - { 0x0270790a,0x0f6a1cfc,0x18fd1af5,0x196b3b0b,0x022122d6,0x0e0db60f, - 0x1901d7d5,0x0ce2ecaa,0x00e5436f } }, - /* 137 */ - { { 0x0286e8d5,0x1fc812f1,0x1114ef94,0x192b690c,0x0e3a0353,0x1adef204, - 0x067b60cb,0x116b739d,0x000404f6 }, - { 0x0781e8e5,0x1699def5,0x0f0bd6f2,0x1ea0302c,0x1caa33cd,0x14b0008c, - 0x1c055d5d,0x1be15838,0x003a4263 } }, - /* 138 */ - { { 0x1aeb596d,0x14b2f664,0x0f24ad30,0x1407ce04,0x1396101e,0x1a5b1700, - 0x0d9d1c12,0x07f20bd4,0x000ca8fd }, - { 0x151b2b61,0x1291d212,0x03f341a4,0x0f513872,0x0a63e1eb,0x095f01c9, - 0x10cf9fc7,0x0c89bb61,0x0096dca2 } }, - /* 139 */ - { { 0x187510af,0x01dda1d1,0x08da8048,0x1fd55153,0x10378846,0x0bb817ca, - 0x077348e9,0x024755ab,0x004363e2 }, - { 0x00246a47,0x121d0e3a,0x17749372,0x0571a5ca,0x1af96b36,0x03022ec7, - 0x0313e6c2,0x0b9b1773,0x00840e11 } }, - /* 140 */ - { { 0x1023e8a7,0x09102f10,0x171e82fc,0x11519bb1,0x05ddfc80,0x11390b1d, - 0x1b538a4a,0x17a61bda,0x005e0d6a }, - { 0x1cfc0f64,0x1d390e13,0x157b6201,0x1d803a1c,0x19db242e,0x1f7c8e8f, - 0x09689a9e,0x1e8528b4,0x007dea48 } }, - /* 141 */ - { { 0x05060a81,0x1efb78e7,0x1e55856a,0x1f38e5f1,0x0268be79,0x162a0356, - 0x1b473f4d,0x17dd7fa2,0x00abc2a2 }, - { 0x13e2eac7,0x16337c8e,0x174119a2,0x0174c7a5,0x0d31b6f1,0x11bb8141, - 0x1f059e43,0x128d8fdd,0x004ea353 } }, - /* 142 */ - { { 0x1266309d,0x0c517c6a,0x05168fbb,0x038d8103,0x05dc10a5,0x1a2d2bc6, - 0x1f0f3b2b,0x1123929f,0x003a76e6 }, - { 0x1d7b0d0f,0x15674523,0x161297e6,0x159d2d1e,0x17fbe963,0x06392734, - 0x1191468c,0x0148cbcc,0x008212a1 } }, - /* 143 */ - { { 0x0fab8caa,0x1be30e1e,0x0508e43b,0x171d081c,0x133ca18e,0x1fb3bf4b, - 0x05933477,0x0e2b3396,0x00aa7cab }, - { 0x1c837bd1,0x17e4939d,0x1abd75c0,0x080fa186,0x1da49c06,0x09497a11, - 0x1f0c5d88,0x0e7fc0c2,0x0040e380 } }, - /* 144 */ - { { 0x07bf9b7c,0x07c04125,0x0f8c343d,0x1a46407f,0x19ce3365,0x09904be7, - 0x149afef9,0x001660aa,0x00e36047 }, - { 0x0cc6c2c7,0x0e5cc88b,0x132fb993,0x106e1174,0x0d9ec726,0x0a1a31bd, - 0x057f737b,0x0ef47bdc,0x006542d6 } }, - /* 145 */ - { { 0x1b6c377a,0x1995b683,0x0d122f8f,0x00708f20,0x08af76cb,0x09d4106d, - 0x1c875bf7,0x1dc1376d,0x00a6534a }, - { 0x1035facf,0x050bc068,0x12d1f98c,0x0ab4673b,0x1f39335e,0x07f0e223, - 0x1c89ba94,0x05fb935d,0x00f3cb67 } }, - /* 146 */ - { { 0x1b55fd83,0x19b8cff1,0x1777443a,0x0f48d90e,0x0a784e0d,0x0fd482e7, - 0x039cceb2,0x05d55d0e,0x007cafaa }, - { 0x1d53b338,0x1c0a6820,0x01f9b1a6,0x198141df,0x12b0fe0a,0x088408b3, - 0x08bbee4f,0x183737aa,0x000aab13 } }, - /* 147 */ - { { 0x12681297,0x0e6713c6,0x02551ab7,0x0a1d636a,0x1aaf2cb3,0x18b9bb30, - 0x0ba4b710,0x00508e02,0x004b91a6 }, - { 0x12f8ddcf,0x07f884ab,0x0446bd37,0x17ec3d35,0x0430e08e,0x1b0561b9, - 0x12ad23d0,0x0a6e4643,0x0049534c } }, - /* 148 */ - { { 0x107b7e9d,0x1efbeb8f,0x13545be0,0x11df4627,0x07ee3a47,0x1325b602, - 0x17b9e3bc,0x09facb58,0x00caf46c }, - { 0x12aa8266,0x026863bc,0x0da12ee8,0x08a8cd22,0x116b0edf,0x08b45725, - 0x1c3d5b99,0x0ae098ce,0x0014ce9e } }, - /* 149 */ - { { 0x165e8f91,0x0a22f1f4,0x03c924a6,0x19437596,0x0a0a0d3a,0x0387c864, - 0x09c74c73,0x14a7c993,0x001bb708 }, - { 0x158bdd7a,0x0e54f34a,0x0289ac75,0x140a1003,0x0f1ec734,0x1538a64e, - 0x040ac24e,0x1e5b4600,0x00f9d126 } }, - /* 150 */ - { { 0x0ff9563e,0x04de53d5,0x0645281d,0x0ef5fd69,0x11671dd0,0x0188dfaf, - 0x11a789e8,0x172e53d9,0x00807afc }, - { 0x09b08b77,0x1c5499be,0x0f1f8e1f,0x074f0a88,0x1d8ba86c,0x1d2ca3b7, - 0x163217eb,0x1a2cad19,0x00751adc } }, - /* 151 */ - { { 0x10715c0d,0x1751c5a0,0x1da5fde2,0x07d4e31e,0x1f06dd11,0x158a49fd, - 0x10fd997a,0x0d04a6ee,0x0029ec44 }, - { 0x150bebbc,0x0ca38ce5,0x1415088f,0x1dcb7fc8,0x1edb1399,0x0d9d4696, - 0x1df64335,0x1c725480,0x00ff9370 } }, - /* 152 */ - { { 0x06b75b65,0x0d16b4de,0x19947156,0x11f1aa4c,0x1d7d2418,0x199f1ef4, - 0x0068a2a7,0x1174553a,0x00977647 }, - { 0x129af2c7,0x0293116c,0x1a4248e2,0x1ebada9c,0x051e9334,0x03f2d44d, - 0x0beb39b3,0x07f585f0,0x0074a631 } }, - /* 153 */ - { { 0x175f079c,0x17a6feed,0x18dbeeec,0x00f92a31,0x136dd85b,0x1e7873e6, - 0x18f46db3,0x02a1fe90,0x00ab75be }, - { 0x173fc9b7,0x0d9b3e00,0x1653f420,0x14e841a4,0x11236b90,0x1f81e204, - 0x07d857f6,0x05c1688b,0x004ebeac } }, - /* 154 */ - { { 0x1c9f2c53,0x1b62ff3a,0x0ba5047a,0x0440231d,0x0c5d8d25,0x1b19fcad, - 0x1ff32221,0x0f658375,0x00df9988 }, - { 0x050aaecb,0x1bc77694,0x15a89cae,0x12303603,0x1bcac9d4,0x0a88d8e6, - 0x01625e37,0x14eef3e8,0x0027b040 } }, - /* 155 */ - { { 0x173b2eb2,0x0202edbf,0x06c84624,0x1f0a111c,0x0327ee0d,0x18a92cb1, - 0x0fd5406d,0x06fc99f4,0x00b393dd }, - { 0x1fd75165,0x091873d9,0x14cd5528,0x06898579,0x15022d66,0x18df07bd, - 0x1065b0db,0x025a08c6,0x0009588c } }, - /* 156 */ - { { 0x02601c3b,0x043049f8,0x170cd7f8,0x04a5f19e,0x0ff28fb0,0x194044a5, - 0x122e5573,0x153b73ec,0x0081c879 }, - { 0x06f56c51,0x007343e6,0x05d86301,0x08e2d27e,0x1353bfed,0x0520c82c, - 0x0f1113e2,0x1eabf823,0x00fa0d48 } }, - /* 157 */ - { { 0x01608e4d,0x0370e4ef,0x00a08b2f,0x1bb4226b,0x0c2d7010,0x0ee08abf, - 0x1f5bdadf,0x0ad6d46c,0x008ea0e1 }, - { 0x0383b3b4,0x1aa70179,0x007d4f28,0x0cd7287e,0x03ca5699,0x119596f0, - 0x16b13fd9,0x049f4016,0x003f5ab9 } }, - /* 158 */ - { { 0x19739efb,0x1bdd86ca,0x1afb034c,0x0361e9cf,0x067d1c75,0x16eb208d, - 0x15b8b694,0x10e56e84,0x008bc768 }, - { 0x02d3d253,0x0df1db94,0x035de7e9,0x0cf343eb,0x167bba9f,0x00b470b3, - 0x0d3e872b,0x120c1f9e,0x00b386f1 } }, - /* 159 */ - { { 0x0fedcfc2,0x0f9e09a9,0x1e2bc34c,0x0d7ec4c5,0x088c2539,0x1a7572b9, - 0x1136680a,0x1ee360d3,0x004cb460 }, - { 0x1b8095ea,0x133da69a,0x101d80eb,0x17f0b2df,0x0a16592b,0x0fb35b0a, - 0x088f851d,0x0112bdea,0x0052c0d5 } }, - /* 160 */ - { { 0x15339848,0x18e10870,0x1de32348,0x1451d0e0,0x0e170e87,0x1330b4ab, - 0x102e7477,0x07057613,0x004ac3c9 }, - { 0x0998987d,0x0df02a8b,0x027d3586,0x06ed895c,0x1933d8b2,0x1bb28d1f, - 0x17d07782,0x18fc72e0,0x00380d94 } }, - /* 161 */ - { { 0x01542e75,0x0d1aad54,0x006e6dc0,0x0e4943dc,0x1708796c,0x14bbb126, - 0x1ebdace8,0x0e3bc4c6,0x002ce3e1 }, - { 0x15d5bc1a,0x1f7f5a4f,0x1df8ad73,0x0ac0fc4e,0x1756ca65,0x1617ca89, - 0x19353faa,0x0a416c49,0x002e6cd8 } }, - /* 162 */ - { { 0x0c31c31d,0x142caa5c,0x1c86830d,0x067a00b7,0x19ec9685,0x11373ae3, - 0x15502f5d,0x08e858d3,0x00ca1775 }, - { 0x16d2dbb2,0x0376d7ff,0x12a74633,0x1b197a2e,0x178e8fd0,0x03c9d522, - 0x139a1d7a,0x02739565,0x00a976a7 } }, - /* 163 */ - { { 0x13fb353d,0x1328f8dc,0x1f3e9c82,0x195716af,0x15281d75,0x07d398d8, - 0x0666aa23,0x02e143e9,0x008720a7 }, - { 0x093e1b90,0x01f469bb,0x1db7f0e3,0x0bb8162d,0x08742d34,0x08055a95, - 0x04f23aa3,0x0538ed31,0x009719ef } }, - /* 164 */ - { { 0x18e35909,0x10776c6a,0x177045a0,0x0db1b867,0x05026936,0x0ce83710, - 0x13075fe6,0x0edc2ae0,0x00a50729 }, - { 0x04e70b2e,0x0151bf56,0x042aa280,0x19ecaed1,0x12a5c84d,0x1f8c322d, - 0x1c9735c6,0x13bef6ee,0x0099389c } }, - /* 165 */ - { { 0x1ada7a4b,0x1c604793,0x0e24d988,0x1d3a07fa,0x1512c3ab,0x1744bb37, - 0x0b91ad9c,0x15440590,0x00a88806 }, - { 0x1380184e,0x10102256,0x1aa2e159,0x16f18824,0x04f17a8c,0x186056c2, - 0x13f9e759,0x1f68e71b,0x000043bf } }, - /* 166 */ - { { 0x16d5192e,0x0acdaee1,0x042cabe3,0x110ba68b,0x01781acf,0x168508b0, - 0x019a0d59,0x00374d89,0x0052f3ef }, - { 0x0edcb64d,0x0c339950,0x1a0de7ce,0x10584700,0x0f3090a4,0x12fd3820, - 0x19d45b2f,0x1133de4f,0x003296bd } }, - /* 167 */ - { { 0x054d81d7,0x1b55d44a,0x1ae6cf11,0x1bcfdea3,0x179869ea,0x10e6c0e2, - 0x07a58668,0x17f5dcae,0x003b90fe }, - { 0x1496f7cb,0x1c9811f2,0x0d46f124,0x1c83b0ff,0x0b5ce55b,0x0ea44cdf, - 0x0c600fc7,0x13b3f021,0x006e8806 } }, - /* 168 */ - { { 0x143ea1db,0x11bd588d,0x1674a4b3,0x1fe352a4,0x0f1860a7,0x0110c7c2, - 0x144e146c,0x1d5bdf55,0x00a7222b }, - { 0x0b0a9144,0x1563c761,0x1e967168,0x0480a3e5,0x1ce385a0,0x1652b0a3, - 0x1a424747,0x04778558,0x00be94d5 } }, - /* 169 */ - { { 0x0b226ce7,0x17a4a2f0,0x1fa2dc1c,0x1fae8f2c,0x0c63eb8a,0x0378c2d3, - 0x1d9bb7a9,0x1fd37d18,0x007782de }, - { 0x1db38626,0x10695521,0x1d9eb45d,0x15cf0eed,0x19cdb460,0x037e2a24, - 0x192cd06e,0x0cf45125,0x00038385 } }, - /* 170 */ - { { 0x19ec1a0f,0x0c6d77eb,0x0ce725cb,0x19adfb9d,0x01a953bb,0x0ffe2c7b, - 0x1083d55d,0x1895bef6,0x00dbd986 }, - { 0x15f39eb7,0x0d5440a0,0x0365db20,0x05f9eb73,0x1717d6ee,0x03aee797, - 0x0f415195,0x188d0c17,0x008e24d3 } }, - /* 171 */ - { { 0x1a587390,0x04ec72a4,0x0fb1621d,0x16329e19,0x183c612b,0x1ed2592c, - 0x1f211b81,0x18880f75,0x00541a99 }, - { 0x024c8842,0x1920b493,0x1b017ff6,0x098255b0,0x1cf62604,0x0a5a27bf, - 0x17471674,0x093eafa6,0x00c0092c } }, - /* 172 */ - { { 0x1f2e61ef,0x1e63ae1e,0x06cd72b4,0x1083905c,0x129f47e8,0x1868c84f, - 0x113718b4,0x068e50d2,0x0075e406 }, - { 0x1bc237d0,0x1ea0fe2d,0x13c07279,0x06f7e1d8,0x1d534c95,0x0d0b1415, - 0x161a4714,0x0b18f090,0x005b7cb6 } }, - /* 173 */ - { { 0x0a28ead1,0x12538424,0x0ed1fda5,0x1b8a11fa,0x05b39802,0x1fe8bb3f, - 0x1e866b92,0x1751be12,0x007ae13e }, - { 0x0add384e,0x090b77c7,0x0cbfc1bf,0x0345b36d,0x1b5f3036,0x0c3c25e6, - 0x0ff4812e,0x0e9c551c,0x00787d80 } }, - /* 174 */ - { { 0x157fbb1c,0x0f12eb5b,0x08077af1,0x17bb6594,0x033ffe47,0x14d1b691, - 0x12112957,0x0333de50,0x005c2228 }, - { 0x08315250,0x19ea542c,0x1c25f05d,0x04345704,0x1d33f21b,0x0750ef7a, - 0x0ac2adf1,0x15775e1e,0x00e45d37 } }, - /* 175 */ - { { 0x08511c8a,0x16f8f1a1,0x129b34f4,0x0453917b,0x039a7ebb,0x18d3b13e, - 0x074d5e29,0x04509bf7,0x00ed7bc1 }, - { 0x13dea561,0x191536fc,0x03c3b473,0x07e31ba9,0x123e8544,0x10a02dd6, - 0x149f62e1,0x1928b94d,0x00aac97c } }, - /* 176 */ - { { 0x016bd00a,0x1aa753a5,0x102f307a,0x13d35beb,0x1fc06d83,0x1bf88fcd, - 0x113824ae,0x16622c7b,0x00318f97 }, - { 0x030d7138,0x06062df6,0x10c0883b,0x11be4757,0x0360644e,0x0b97d811, - 0x1d34aede,0x1433509f,0x00fa41fa } }, - /* 177 */ - { { 0x06642269,0x0016cba5,0x0de0ef51,0x10299d37,0x1e60bc81,0x1c723ca0, - 0x0788e634,0x0583a4dd,0x0038bb6b }, - { 0x0a577f87,0x1272512b,0x047f8731,0x05a4a7b8,0x007288b5,0x155fb114, - 0x0697fccd,0x00b9cec0,0x0094dd09 } }, - /* 178 */ - { { 0x1e93f92a,0x0b67bee6,0x0d7cc545,0x06679713,0x1e750a01,0x06fce4ca, - 0x0ba40901,0x0cfa4b85,0x00920778 }, - { 0x0bf39d44,0x1238f008,0x0ed4f5f8,0x1920412d,0x03d8f5f2,0x1bd9ae4e, - 0x0d453112,0x117a537d,0x0081e842 } }, - /* 179 */ - { { 0x0477199f,0x0ece15d6,0x17b3765b,0x11dddcd6,0x0fd0e8cb,0x0d9ff720, - 0x12c62bdf,0x0c5b77f4,0x001b94ab }, - { 0x0e47f143,0x0786c59e,0x1d1858d1,0x0c47f8c7,0x1938351e,0x1387e62c, - 0x03bbc63c,0x0500aab2,0x0006a38e } }, - /* 180 */ - { { 0x13355b49,0x12d809cd,0x1afe66cb,0x04cac169,0x1f3dc20e,0x1d35e934, - 0x13e3023f,0x04107b3a,0x00a7b36c }, - { 0x1b3e8830,0x068ae1d0,0x07e702d9,0x19d5c351,0x16930d5f,0x12517168, - 0x08833fbb,0x16945045,0x00be54c6 } }, - /* 181 */ - { { 0x0d91167c,0x166d9efc,0x099897b5,0x187ef3cf,0x0c7f4517,0x12479a35, - 0x0aedc415,0x157d5c04,0x00bf30a5 }, - { 0x13828a68,0x13bc2df4,0x0fbc0da3,0x038664fe,0x146b2516,0x0ff5ac90, - 0x04eb846d,0x1bc4e65a,0x00d1c820 } }, - /* 182 */ - { { 0x1038b363,0x01f09a3c,0x01794641,0x023ea8d6,0x0cad158c,0x1d5f3013, - 0x168d3f95,0x1dad1431,0x00b7d17b }, - { 0x029c2559,0x0652c48f,0x1fff6111,0x1406ecb7,0x069484f7,0x1257ba72, - 0x11912637,0x0bcc8259,0x003997fd } }, - /* 183 */ - { { 0x0bd61507,0x103a3414,0x09934abc,0x0265aa69,0x015e329e,0x0fd84545, - 0x0fa3ffb7,0x05278d82,0x000eeb89 }, - { 0x07e259f8,0x0db4d1f5,0x0f9f99fa,0x1b6fcda2,0x1a685ce1,0x0c7b568f, - 0x1bbc9dcc,0x1f192456,0x00228916 } }, - /* 184 */ - { { 0x0a12ab5b,0x0cd712d8,0x1ef04da5,0x022e3f2a,0x02b0ccc1,0x014f68b7, - 0x05fa0161,0x03add261,0x00ec05ad }, - { 0x0c3f3708,0x0bdd2df5,0x0d675dc5,0x15f26a61,0x034e531b,0x091b88c1, - 0x0cdd1ed5,0x0acffe23,0x007d3141 } }, - /* 185 */ - { { 0x16dfefab,0x1ece02e7,0x0cddc1de,0x1e44d1b9,0x0bb95be2,0x16cb9d1c, - 0x1e8f94fa,0x1f93783a,0x00e9ce66 }, - { 0x0f6a02a1,0x0d50abb3,0x19803b5d,0x010fbec1,0x1c1b938c,0x1f9a3466, - 0x1947e251,0x002e4500,0x00d9650b } }, - /* 186 */ - { { 0x1a057e60,0x025a6252,0x1bc97914,0x19877d1b,0x1ccbdcbc,0x19040be0, - 0x1e8a98d4,0x135009d6,0x0014d669 }, - { 0x1b1f411a,0x045420ae,0x035da70b,0x175e17f0,0x177ad09f,0x17c80e17, - 0x062ad37b,0x0821a86b,0x006f4c68 } }, - /* 187 */ - { { 0x16c24a96,0x1936fa74,0x0f6668e1,0x1b790bf9,0x0e30a534,0x17794595, - 0x0aecf119,0x1fac2313,0x004c4350 }, - { 0x1855b8da,0x0b3fb8b7,0x0f0e284a,0x0847288c,0x1334341a,0x0a09f574, - 0x02d70df8,0x084b4623,0x00a726d2 } }, - /* 188 */ - { { 0x148c1086,0x17359f74,0x14e8b876,0x1ca07b97,0x022f3f1d,0x169f81e8, - 0x0e48fcd7,0x10598d9e,0x0013639e }, - { 0x0dafaa86,0x1649c7de,0x15289626,0x178bf64c,0x11329f45,0x19372282, - 0x168c658e,0x1c383466,0x00ca9365 } }, - /* 189 */ - { { 0x0c3b2d20,0x10ad63aa,0x138906cd,0x14a82f20,0x1071d742,0x10e2664e, - 0x0a96c214,0x0692e16e,0x009ce29c }, - { 0x0d3e0ad6,0x0640fb9b,0x1e10d323,0x01b53de5,0x062d9806,0x0e8d3674, - 0x1e60d7b4,0x1af56855,0x0048c4ab } }, - /* 190 */ - { { 0x00c7485a,0x110d8662,0x09d36ff4,0x08ab77ca,0x1d2e8ead,0x1b4c4931, - 0x0f2d24f1,0x065ecf66,0x0078017c }, - { 0x130cb5ee,0x0e9abb4c,0x1023b4ae,0x029d2818,0x11a4dc0d,0x1faa9397, - 0x1013e2de,0x0a9bcb83,0x0053cd04 } }, - /* 191 */ - { { 0x1d28ccac,0x06ac2fd2,0x16dd1baf,0x047cac00,0x123aa5f8,0x1850e680, - 0x0a3df1e7,0x183a7aff,0x00eea465 }, - { 0x0551803b,0x00832cf8,0x19abdc1e,0x16b33ef9,0x08e706c0,0x13b81494, - 0x064d0656,0x148f5cd2,0x001b6e42 } }, - /* 192 */ - { { 0x167d04c3,0x14049be7,0x1bae044b,0x0257c513,0x14d601e3,0x0c43c92c, - 0x14f55ad7,0x02830ff7,0x000224da }, - { 0x0c5fe36f,0x1d5dc318,0x1d47d7e1,0x1e78c09d,0x029ec580,0x18dfd9da, - 0x1cce593e,0x1e0857ff,0x0060838e } }, - /* 193 */ - { { 0x1e0bbe99,0x19659793,0x0a8e7b90,0x1489e609,0x139037bd,0x1e3d4fd4, - 0x190d7d25,0x0045a662,0x00636eb2 }, - { 0x13ae00aa,0x07e8730c,0x0b9b4bff,0x1401fc63,0x1901c875,0x0c514fc9, - 0x0eb3d0d9,0x16c72431,0x008844ee } }, - /* 194 */ - { { 0x0b3bae58,0x0a0b8e93,0x18e7cf84,0x07bee22f,0x0eada7db,0x1e3fc0d4, - 0x027b34de,0x1b8a3f6f,0x0027ba83 }, - { 0x1bf54de5,0x1efa1cff,0x1f869c69,0x0e06176b,0x17a48727,0x071aed94, - 0x12ad0bba,0x0690fe74,0x00adb62d } }, - /* 195 */ - { { 0x0175df2a,0x188b4515,0x030cba66,0x15409ec3,0x10916082,0x19738a35, - 0x02cb2793,0x0ecebcf9,0x00b990fd }, - { 0x0df37313,0x014ecb5a,0x0d01e242,0x00aaf3a1,0x077111c2,0x17253c04, - 0x06359b26,0x1f29a21a,0x0081707e } }, - /* 196 */ - { { 0x03d6ff96,0x1ebe5590,0x010cd825,0x0a37f81b,0x0db4b5b8,0x11e26821, - 0x09709a20,0x1d5ab515,0x003792da }, - { 0x141afa0b,0x140c432c,0x160d9c54,0x13ce8285,0x0e0a7f3e,0x1293adf2, - 0x06e85f20,0x0bd29600,0x005abd63 } }, - /* 197 */ - { { 0x0ac4927c,0x13fd4270,0x1233c8dc,0x10c06b4f,0x0a0dfe38,0x0af5256e, - 0x184292f3,0x04308d56,0x005995bf }, - { 0x029dfa33,0x087c305c,0x03f062fa,0x1fc55d2b,0x10366caa,0x17a23c31, - 0x047a6cee,0x145a9068,0x0044c32c } }, - /* 198 */ - { { 0x040ed80c,0x1a54bf8f,0x14b2a0a9,0x07196263,0x16ad95f9,0x0925be16, - 0x15314fc8,0x1f701054,0x001f2162 }, - { 0x120b173e,0x1233e62b,0x17c4be5f,0x114ccc10,0x165dc40e,0x0107264e, - 0x1f2633af,0x05787d20,0x008f1d40 } }, - /* 199 */ - { { 0x1bc4058a,0x1ac97ce7,0x0bd59c13,0x1c296c52,0x18c57b15,0x1f1bde0e, - 0x0fe71573,0x08724ddb,0x00b1980f }, - { 0x12c76b09,0x0619f049,0x0c1fde26,0x0a4f3a67,0x1b4611df,0x156a431d, - 0x1915bc23,0x1366e891,0x002828ad } }, - /* 200 */ - { { 0x04cf4ac5,0x0b391626,0x1992beda,0x18347fbb,0x10832f5a,0x1d517044, - 0x0e401546,0x04eb4296,0x004973f1 }, - { 0x122eac5d,0x0cec19a9,0x166d5a39,0x0fddea17,0x083935e0,0x1907d12c, - 0x0b1eacd9,0x1a1b62d1,0x006dac8e } }, - /* 201 */ - { { 0x0da835ef,0x1daa2d77,0x043b547d,0x0227a43a,0x01b094aa,0x12f009ba, - 0x19300d69,0x0b24173b,0x004b23ef }, - { 0x1c4c7341,0x015db401,0x162f0dfa,0x0ee0da7e,0x03ee8d45,0x1c31d28f, - 0x0939cd49,0x069bbe93,0x004dd715 } }, - /* 202 */ - { { 0x15476cd9,0x1ca23394,0x069c96ef,0x1a0e5fc6,0x167e0648,0x045c7e25, - 0x16ec5107,0x0005e949,0x00fd3170 }, - { 0x0995d0e1,0x05a1ffa4,0x1dca6a87,0x0d2ba21d,0x1898276e,0x1cbb20bc, - 0x0d978357,0x1192ad3e,0x0014fac5 } }, - /* 203 */ - { { 0x1312ae18,0x0cd0032f,0x124ff26b,0x0b1b81f9,0x12846519,0x0120453e, - 0x09436685,0x0a26d57b,0x00ed7c76 }, - { 0x05d4abbc,0x113878d1,0x0844fa91,0x1bb1e7e3,0x1952f9b5,0x183aada8, - 0x1d4f1826,0x1ee9a5d3,0x00fefcb7 } }, - /* 204 */ - { { 0x1a119185,0x084a4bd5,0x1116e92f,0x1d186155,0x01179d54,0x1cef5529, - 0x002d2491,0x0fd0fc1b,0x001801a5 }, - { 0x1cafffb0,0x19e9fc6f,0x09549001,0x0678175c,0x1dfbc6cf,0x1b1dadaf, - 0x0191e075,0x03c3d5a2,0x009f8fc1 } }, - /* 205 */ - { { 0x1e69544c,0x0c1d0b8a,0x12de04c5,0x1f0acfe0,0x04c320ea,0x147e93c5, - 0x06a4788a,0x13a7a74d,0x00a9d380 }, - { 0x19a2da3b,0x1b616162,0x057211e4,0x1979ec31,0x1086938c,0x122731ea, - 0x1bdd7994,0x15dc22f1,0x003006b9 } }, - /* 206 */ - { { 0x09eead28,0x1d8f9586,0x1d37ef02,0x1ec6bb13,0x089397ee,0x0bfed967, - 0x1d841d1d,0x1ae8bf1e,0x000ab85f }, - { 0x1e5b4549,0x06d3e499,0x048bc87b,0x0576b92f,0x180404be,0x093a5a1d, - 0x0b089868,0x0ea23d28,0x00b122d6 } }, - /* 207 */ - { { 0x06a5ae7a,0x1f303df3,0x0b72f8ce,0x0e07f4ed,0x0e5c501e,0x0180a75b, - 0x0bb2be41,0x18212fb7,0x009f599d }, - { 0x0ff250ed,0x0badb8c0,0x0688371b,0x122ae869,0x027a38eb,0x02d20859, - 0x0de10958,0x1c114529,0x007d5528 } }, - /* 208 */ - { { 0x00c26def,0x07ac7b31,0x0acb47bc,0x0b0bd4b0,0x03881025,0x0bcd80e7, - 0x1cc3ef9f,0x002607e2,0x0028ccea }, - { 0x19644ba5,0x0ed5e68b,0x1ffc2e34,0x0c87d00d,0x1e17b1fc,0x1b7e3359, - 0x0efe9829,0x09143a02,0x00c18baf } }, - /* 209 */ - { { 0x1dc4216d,0x0731c642,0x1850ab0d,0x0020ce40,0x1064a00c,0x10b8cafa, - 0x05af514e,0x13b6f52b,0x009def80 }, - { 0x07ab8d2c,0x0f432173,0x0de8ad90,0x080866c4,0x0218bb42,0x1536b262, - 0x1395f541,0x160d1011,0x000357f8 } }, - /* 210 */ - { { 0x0cd2cc88,0x14edf322,0x0e3ce763,0x03851be1,0x0a0c8cc6,0x0c3a6698, - 0x021d28c2,0x1ba36913,0x00e4a01a }, - { 0x157cd8f9,0x168f7567,0x1653120b,0x0cfa7d7a,0x0f7871b7,0x0e38bde9, - 0x10c29ca5,0x0f39c219,0x00466d7d } }, - /* 211 */ - { { 0x1dada2c7,0x1e98c494,0x06a89f51,0x014d871f,0x059e14fa,0x1e944105, - 0x146a4393,0x0448a3d5,0x00c672a5 }, - { 0x1d86b655,0x0303e642,0x0b52bc4c,0x06ba77f3,0x172a6f02,0x03402b88, - 0x144e6682,0x1f5e54ce,0x005e3d64 } }, - /* 212 */ - { { 0x1b3b4416,0x1320863c,0x0c9b666a,0x1f9f0bd5,0x16a74cd8,0x1ba56db2, - 0x0bf17aff,0x12bd71c8,0x006c8a7a }, - { 0x102a63bd,0x06305d3d,0x03c011c4,0x1e460717,0x190b06b2,0x1b9c1896, - 0x0a4631b0,0x0455b059,0x00348ae4 } }, - /* 213 */ - { { 0x1ccda2fb,0x1a3a331a,0x01c9b49f,0x1995431c,0x11f2022a,0x1bc12495, - 0x14ba16b7,0x1c1b3de5,0x00c1074d }, - { 0x0e9a65b3,0x079e7225,0x15c546ff,0x03c9580b,0x09788fd7,0x0fa86735, - 0x1ff351c4,0x1b793ca9,0x00fbadfb } }, - /* 214 */ - { { 0x00a99363,0x189f8e69,0x1c89dd45,0x0acb1ed9,0x159b2b91,0x1ae69269, - 0x1f365a05,0x16906e2d,0x00b7f976 }, - { 0x1d6dbf74,0x1ac7126a,0x10ebcd95,0x0775fae3,0x1dfe38d2,0x1bb00121, - 0x001523d1,0x05d95f99,0x00f4d41b } }, - /* 215 */ - { { 0x1dabd48d,0x0f8e7947,0x101e2914,0x037c6c65,0x146e9ce8,0x14ba08b8, - 0x1c41ab38,0x1d5c02c1,0x00180824 }, - { 0x06e58358,0x1c3b4c5b,0x1b28d600,0x0d0ea59c,0x1e6c5635,0x071a2f20, - 0x149608e0,0x073079ed,0x0067e5f6 } }, - /* 216 */ - { { 0x0f4899ef,0x04e65c6e,0x0ed1303e,0x002be13d,0x18ec9949,0x093b592c, - 0x1f1951be,0x13409823,0x009fef78 }, - { 0x13d2a071,0x09b3f67a,0x1466c25b,0x1c34ff48,0x02eefb10,0x1fd8308f, - 0x188329ac,0x10353389,0x00bc80c1 } }, - /* 217 */ - { { 0x05eb82e6,0x1929b7c7,0x1b2e4825,0x109f8fea,0x1da5e1a4,0x10b8a85a, - 0x1c431e38,0x0c53f19b,0x0049270e }, - { 0x0a6b50ad,0x11cdbddf,0x0e23ff06,0x05098344,0x1197b9a0,0x158bc083, - 0x1dfd500f,0x1f2c26e5,0x00d2ee52 } }, - /* 218 */ - { { 0x08e0362a,0x1be6942c,0x09765374,0x1f514f1f,0x0a526442,0x1b72d21a, - 0x1ccebfe0,0x17dcb576,0x00dfb478 }, - { 0x073eede6,0x08f8e73b,0x16cbc12a,0x1215a856,0x0da2fa53,0x1bdfaa98, - 0x1ce9799b,0x16811be8,0x00d9a140 } }, - /* 219 */ - { { 0x0e8ea498,0x10110dab,0x18fb8243,0x08f0526a,0x12ade623,0x01c899ae, - 0x0c6b81ae,0x11ac47e9,0x00760c05 }, - { 0x0198aa79,0x1c4dac66,0x1eae9fc2,0x1121a5e0,0x0556af74,0x00887ef1, - 0x10253881,0x05b1e320,0x00714198 } }, - /* 220 */ - { { 0x0d4b0f45,0x1850719a,0x0aa5385b,0x10167072,0x01d5ed92,0x126359e3, - 0x191cebcc,0x19d13aa9,0x003af9d1 }, - { 0x00930371,0x0c7bcc09,0x105c25ff,0x04cc9843,0x0309beda,0x02ee6e21, - 0x17583a55,0x186e72af,0x00b1f815 } }, - /* 221 */ - { { 0x09fec44a,0x07d53c74,0x0a932be1,0x055c8e79,0x0a624c8c,0x003ee0db, - 0x0149a472,0x0282a87e,0x00a41aed }, - { 0x1d5ffe04,0x121a9ccb,0x16db8810,0x1965bec4,0x177758ba,0x105f43c0, - 0x03be1759,0x1bb0df6c,0x00d6e9c1 } }, - /* 222 */ - { { 0x06853264,0x15174bf6,0x0c1282ce,0x0a676fc4,0x0e9be771,0x15dbdc75, - 0x03086e44,0x0215d37f,0x009c9c6e }, - { 0x0030b74c,0x1184d2cf,0x18c7a428,0x0e929ad4,0x179f24ed,0x0591d24d, - 0x06da27d1,0x12c81f4c,0x00566bd5 } }, - /* 223 */ - { { 0x018061f3,0x136008c6,0x00ff1c01,0x164ba6f9,0x13245190,0x04701393, - 0x117bc17f,0x121ea4a6,0x00cf2c73 }, - { 0x10eb30cf,0x04de75a0,0x1ddc0ea8,0x05d7741a,0x1f255cfd,0x021d0a87, - 0x05e7a10b,0x0ab15441,0x0002f517 } }, - /* 224 */ - { { 0x0ddb7d07,0x0b77bca5,0x1155400e,0x1f8e8448,0x0a3ce0b4,0x075663c5, - 0x05f7ebfe,0x14bd1a9b,0x0014e9ad }, - { 0x0f7079e2,0x15240509,0x0c2003b6,0x15479bc9,0x0157d45b,0x0f16bc1c, - 0x0ba005d9,0x1571d3b3,0x00a0ad4f } }, - /* 225 */ - { { 0x0a653618,0x1fdbb10a,0x1aaa97c2,0x05027863,0x09d5e187,0x139ba24a, - 0x1478554f,0x170dcadd,0x00bcd530 }, - { 0x12e9c47b,0x14df4299,0x00166ac5,0x0eedfd6a,0x1fbb4dc2,0x0bb08c95, - 0x107736ea,0x19ed2f26,0x00909283 } }, - /* 226 */ - { { 0x16e81a13,0x1d801923,0x05c48e59,0x1c3532c4,0x019d69be,0x1b0de997, - 0x126823b4,0x19359c2a,0x0035eeb7 }, - { 0x1e4e5bdc,0x140572d3,0x13bb1b84,0x1a59a76d,0x06bc12dc,0x11263713, - 0x01914b90,0x1e88915d,0x009a8b2c } }, - /* 227 */ - { { 0x09d03b59,0x1238df90,0x16bcaafd,0x1cc5476c,0x1eec9c90,0x18b475ea, - 0x0de7fdff,0x1e9a8922,0x006bdb60 }, - { 0x0a55bc30,0x16d7f5e4,0x025ff836,0x1d5a2c20,0x03bddc79,0x0ba0a60f, - 0x02a50b86,0x1fb29741,0x0001ec3c } }, - /* 228 */ - { { 0x1c9485c2,0x1313bf5e,0x1ec431ee,0x1934f245,0x08d8a48c,0x0b07b851, - 0x13d93d87,0x1808ea8c,0x00d1acb1 }, - { 0x06f36612,0x13481589,0x186362f4,0x07489dc0,0x157ee59c,0x14099841, - 0x1b0937e2,0x13a80ac4,0x007dcd07 } }, - /* 229 */ - { { 0x105a4b48,0x073ea69f,0x08c1dc97,0x1a52a46e,0x0915aadc,0x1cb8c095, - 0x06e3463d,0x1126efa3,0x000bf535 }, - { 0x0c68ea73,0x0f66cad3,0x0e96134d,0x07779504,0x1a723c7f,0x1a637a39, - 0x1bf27ed9,0x1b3c2cd0,0x00d28be4 } }, - /* 230 */ - { { 0x18fa8e4b,0x095cc831,0x0ff63f17,0x1e30dd12,0x1b6fc559,0x115521b7, - 0x0338e9b7,0x154a21f1,0x00d76007 }, - { 0x123a4988,0x088555b2,0x17409ccb,0x0b9e88e9,0x07278b45,0x184151a0, - 0x0c05fd19,0x0d166077,0x00f2b52f } }, - /* 231 */ - { { 0x1835b4ca,0x0abf57d4,0x19a72f03,0x0465f976,0x031982d2,0x1b406332, - 0x14ea3bba,0x11d98b5d,0x00d8dbe9 }, - { 0x05a02709,0x1d4df1fe,0x0e87ea32,0x1cd1cbeb,0x0a85230b,0x01e6f887, - 0x1c17faf5,0x147dcab2,0x00e01593 } }, - /* 232 */ - { { 0x0a75a0a6,0x1f2d7a87,0x01600cf4,0x044d58af,0x16406512,0x0a87e80b, - 0x1c19bf9b,0x1635d71d,0x00afec07 }, - { 0x00bb0a31,0x1dccab3c,0x0c26ab9f,0x15e7986e,0x1f3896f1,0x10ad00d5, - 0x1f76454e,0x0a8dc5b7,0x00a71b93 } }, - /* 233 */ - { { 0x18f593d2,0x1c709700,0x1e048aef,0x12085140,0x0f2add1a,0x02ed85d2, - 0x0f645414,0x0b8c50a4,0x0053a200 }, - { 0x07f2b935,0x1e45b1cf,0x00a58681,0x1f2eb583,0x0ca2c2bf,0x1753ba8c, - 0x18f61af3,0x1367ab11,0x00bf47d1 } }, - /* 234 */ - { { 0x1d7665d5,0x194b3d3e,0x0bd37959,0x0060ae5e,0x0903f4e3,0x02d7406a, - 0x06d85100,0x0fe73934,0x00001c2c }, - { 0x09efc6d6,0x01d400a3,0x11e9c905,0x017b54f7,0x150a4c81,0x1385d3c0, - 0x066d7d95,0x1cf0dff7,0x00fdadf8 } }, - /* 235 */ - { { 0x1fc00785,0x09c65c47,0x123ad9ff,0x14eb2276,0x08fbc77f,0x082adf9b, - 0x12501153,0x09ab5487,0x003a838e }, - { 0x1e97bb9a,0x10b31949,0x07653655,0x1266c688,0x12a839eb,0x08d3056d, - 0x168d4556,0x0af0e7c3,0x003cdb82 } }, - /* 236 */ - { { 0x1de77eab,0x1b8a054b,0x19204244,0x038a1a82,0x1d0dff7e,0x05696758, - 0x1ee9d8b7,0x113e3eaf,0x005a60cc }, - { 0x00d45673,0x059b1c12,0x04f19560,0x057c32b2,0x0b7411b8,0x025c6eb2, - 0x1f0015ca,0x0dfb7fb1,0x00922ff5 } }, - /* 237 */ - { { 0x09a129a1,0x1932ef76,0x0a138106,0x039caf98,0x1be3ca5b,0x0623675f, - 0x158810e0,0x0fbed8b9,0x0072919a }, - { 0x0fb90f9a,0x0c7a29d4,0x1900c6ca,0x13801711,0x11856d71,0x073bbcb7, - 0x026b8cb0,0x1006c481,0x005e7917 } }, - /* 238 */ - { { 0x1f63cdfb,0x00b762ab,0x12b93f57,0x146ae3e3,0x197ca8e6,0x15f52b02, - 0x1eaff389,0x0e3c4985,0x004e0a53 }, - { 0x05765357,0x1b52069d,0x1ce8ad09,0x135e881a,0x11a323c8,0x185720e8, - 0x13bae3cd,0x031aacc0,0x00f5ff78 } }, - /* 239 */ - { { 0x1a09df21,0x1f9f1ff0,0x1ba391fe,0x0ba51dcc,0x0901526d,0x1e8514e4, - 0x1990825a,0x1d2a67eb,0x00e41df0 }, - { 0x13ba9e3f,0x02fed205,0x0136254c,0x0819d64c,0x167c7f23,0x10c93f81, - 0x157c219b,0x0dd589e2,0x008edd7d } }, - /* 240 */ - { { 0x0bfc8ff3,0x0d0ee070,0x0dbd0bf2,0x1fb057d2,0x181ef14e,0x17be6651, - 0x1a599c05,0x195db15d,0x001432c1 }, - { 0x10b23c26,0x0342414b,0x0d6c9cfb,0x1fd0e60e,0x10f5aa64,0x1b72f577, - 0x0b1b8e27,0x016b591a,0x00caef48 } }, - /* 241 */ - { { 0x15315922,0x122e4bc3,0x18f32954,0x12a2e260,0x0f2cbd82,0x10685b27, - 0x08dbcf39,0x0fd1df5c,0x00d0ba17 }, - { 0x11b3af60,0x1d4d747d,0x0b688394,0x12d5ca7a,0x0ef281a7,0x1b02efcf, - 0x18580758,0x0f838a95,0x00f31c95 } }, - /* 242 */ - { { 0x09cc4597,0x07ac6a92,0x18280a30,0x002b6175,0x0814adc5,0x1e2ab9a5, - 0x10ebbf17,0x1972dc2f,0x00013404 }, - { 0x09a824bf,0x14f12c2e,0x07abb5ec,0x0630bc00,0x168acd59,0x134130f7, - 0x19b235bb,0x09723267,0x006f377c } }, - /* 243 */ - { { 0x08333fd2,0x1c9dd68d,0x0aa56e27,0x060404b4,0x15acea89,0x081bf57b, - 0x14188479,0x09da5a12,0x006dba3e }, - { 0x104399cd,0x0477cc66,0x0dceb7a9,0x038cddcd,0x0caf3181,0x03a960bf, - 0x129dcbd8,0x08477d9e,0x00f13cf3 } }, - /* 244 */ - { { 0x0919e2eb,0x175cf605,0x0b03da33,0x13432bec,0x0229983a,0x1ddb3d5d, - 0x0b4f3ee8,0x1524e977,0x00c83fa9 }, - { 0x02fa1ce0,0x0be8d85b,0x063befc3,0x16c1ea68,0x06f04e58,0x17cf2938, - 0x1a0efea3,0x1e8bae04,0x00b49d70 } }, - /* 245 */ - { { 0x1ad5513b,0x0a63a887,0x1d478b64,0x065dd962,0x19d5905f,0x020c6cfd, - 0x073db614,0x1761861e,0x0059cfad }, - { 0x15cb7fd6,0x0b3d611a,0x0109a8f8,0x06cf7104,0x18864249,0x02c64853, - 0x0d9fabbb,0x0c46a949,0x005babf3 } }, - /* 246 */ - { { 0x0e424865,0x1e4c0e8f,0x1955dfcd,0x0050f1e5,0x0c0588b0,0x1878dcf0, - 0x03c1c0a5,0x14f204d9,0x006188c6 }, - { 0x10f244da,0x17cd0cde,0x02021cc1,0x19dab9f6,0x136371ec,0x07cdcf90, - 0x0764d51c,0x0ebbea17,0x00993fe4 } }, - /* 247 */ - { { 0x1b2c3609,0x0718e6fc,0x11b53a9a,0x16338058,0x1510184e,0x160d4d3b, - 0x05adeb27,0x0cc9900c,0x0081f764 }, - { 0x15fbe978,0x0be152d3,0x00ecd587,0x07fda7e3,0x1d2bf674,0x0f82280e, - 0x18360e34,0x054bfd20,0x00564a81 } }, - /* 248 */ - { { 0x1a817d1d,0x12d327a7,0x0a0b83de,0x12d0897d,0x1f9aa55f,0x0d07e6ab, - 0x15b2d7fd,0x19e01ca3,0x00226bf3 }, - { 0x0f2833cf,0x168d4fc9,0x13e26a35,0x0146b49e,0x17f7720a,0x1624c79f, - 0x00d8454d,0x08ffe4af,0x0068779f } }, - /* 249 */ - { { 0x13043d08,0x0d860e0b,0x10083e9e,0x08cee83f,0x126d0a54,0x1f144d36, - 0x182f4dd9,0x1a3d6125,0x0097bcb0 }, - { 0x132ed3c3,0x15b75547,0x006f120a,0x09e2a365,0x178f3c8a,0x1a79dfd0, - 0x1955346f,0x1d014f08,0x00a872ff } }, - /* 250 */ - { { 0x032b2086,0x0d5bc9ad,0x183d21ac,0x16e21d02,0x0e6bee1e,0x06c89db5, - 0x0daa6f43,0x1f96e654,0x0002812b }, - { 0x0f605318,0x11febe56,0x1f5b4769,0x1cbaa1fb,0x0d619646,0x01cc1081, - 0x1abe875a,0x193fca72,0x0007391c } }, - /* 251 */ - { { 0x0b80d02b,0x080abf84,0x01dfdff1,0x0667a2c5,0x142ae6b8,0x0d7c3c6a, - 0x0821eb28,0x1b8fcda5,0x00355d2a }, - { 0x087386e1,0x00f99ad1,0x190c9d6d,0x0e5529f1,0x189eafd2,0x1166f3cc, - 0x09e4a1b2,0x1c6f8547,0x003dc2b1 } }, - /* 252 */ - { { 0x04581352,0x144e90e0,0x19e0afb5,0x01904a6e,0x1701f0a0,0x0ac84ff6, - 0x11ac80ef,0x020799b0,0x00c47869 }, - { 0x04c768ed,0x0dd3b841,0x107d95d7,0x1dd404d0,0x0ce0e72f,0x1f6ab566, - 0x14c9ccc4,0x0d1ab769,0x00ccc429 } }, - /* 253 */ - { { 0x1d7620b9,0x07286f09,0x04a95aa5,0x14b914b3,0x087c9d89,0x1b2033aa, - 0x073f7001,0x0855490e,0x00e147eb }, - { 0x0cf3ae46,0x1a55a775,0x0d43ef89,0x126df6a0,0x040eafd4,0x1f23a464, - 0x1b8f7cab,0x08e101d2,0x00239ac0 } }, - /* 254 */ - { { 0x0bfee8d4,0x00e8f9a9,0x1ec3fb12,0x016b9ff4,0x1af3cce8,0x064f1674, - 0x16744171,0x147ebefc,0x00c55fa1 }, - { 0x0257c227,0x0c378a74,0x0af802cc,0x02ca7e68,0x04fb2c5b,0x04cc5548, - 0x1a6426bf,0x139a9e96,0x00094cd9 } }, - /* 255 */ - { { 0x1703beba,0x14c0e426,0x13aca462,0x03a2a065,0x149ec863,0x1964f1de, - 0x14ce9117,0x16c85575,0x00b90a30 }, - { 0x14a5abf9,0x032a027d,0x16dd80ed,0x0ea186eb,0x1d89f004,0x0166651a, - 0x13ddbe69,0x13436f24,0x00019f8b } }, -}; - -/* 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. - * 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_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k, - int map, int ct, void* heap) -{ - return sp_256_ecc_mulmod_stripe_9(r, &p256_base, p256_table, - k, map, ct, heap); -} - -#endif - -/* Multiply the base point of P256 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_256(const mp_int* km, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_256, point, 1); - SP_DECL_VAR(sp_digit, k, 9); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(k, 9, km); - - err = sp_256_ecc_mulmod_base_9(point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_256, point, 2); - SP_DECL_VAR(sp_digit, k, 9 + 9 * 2 * 6); - sp_point_256* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9 + 9 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - addP = point + 1; - tmp = k + 9; - - sp_256_from_mp(k, 9, km); - sp_256_point_from_ecc_point_9(addP, am); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_256_mod_mul_norm_9(addP->x, addP->x, p256_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_256_mod_mul_norm_9(addP->y, addP->y, p256_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_256_mod_mul_norm_9(addP->z, addP->z, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_9(point, k, 0, 0, heap); - } - if (err == MP_OKAY) { - sp_256_proj_point_add_9(point, point, addP, tmp); - - if (map) { - sp_256_map_9(point, point, tmp); - } - - err = sp_256_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ -#ifndef WC_NO_RNG -/* Add 1 to a. (a = a + 1) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_add_one_9(sp_digit* a) -{ - a[0]++; - sp_256_norm_9(a); -} - -#endif -/* 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_256_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 >= 21U) { - r[j] &= 0x1fffffff; - s = 29U - 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; - } -} - -/* Generates a scalar that is in the range 1..order-1. - * - * rng Random number generator. - * k Scalar value. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. - */ -static int sp_256_ecc_gen_k_9(WC_RNG* rng, sp_digit* k) -{ -#ifndef WC_NO_RNG - int err; - byte buf[32]; - - do { - err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); - if (err == 0) { - sp_256_from_bin(k, 9, buf, (int)sizeof(buf)); - if (sp_256_cmp_9(k, p256_order2) <= 0) { - sp_256_add_one_9(k); - break; - } - } - } - while (err == 0); - - return err; -#else - (void)rng; - (void)k; - return NOT_COMPILED_IN; -#endif -} - -/* Makes a random EC key pair. - * - * rng Random number generator. - * priv Generated private value. - * pub Generated public point. - * heap Heap to use for allocation. - * returns ECC_INF_E when the point does not have the correct order, RNG - * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) -{ -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_DECL_VAR(sp_point_256, point, 2); -#else - SP_DECL_VAR(sp_point_256, point, 1); -#endif - SP_DECL_VAR(sp_digit, k, 9); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256* infinity = NULL; -#endif - int err = MP_OKAY; - - - (void)heap; - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_ALLOC_VAR(sp_point_256, point, 2, heap, DYNAMIC_TYPE_ECC); -#else - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); -#endif - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - infinity = point + 1; - #endif - - err = sp_256_ecc_gen_k_9(rng, k); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, NULL); - } - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_9(infinity, point, p256_order, 1, 1, NULL); - } - if (err == MP_OKAY) { - if (sp_256_iszero_9(point->x) || sp_256_iszero_9(point->y)) { - err = ECC_INF_E; - } - } -#endif - - if (err == MP_OKAY) { - err = sp_256_to_mp(k, priv); - } - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_9(point, pub); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - /* point is not sensitive, so no need to zeroize */ - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_key_gen_256_ctx { - int state; - sp_256_ecc_mulmod_9_ctx mulmod_ctx; - sp_digit k[9]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 point[2]; -#else - sp_point_256 point[1]; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ -} sp_ecc_key_gen_256_ctx; - -int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, - ecc_point* pub, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256* infinity = ctx->point + 1; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - - typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) - >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - err = sp_256_ecc_gen_k_9(rng, ctx->k); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - ctx->state = 1; - } - break; - case 1: - err = sp_256_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - #else - ctx->state = 3; - #endif - } - break; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - case 2: - err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p256_order, 1, 1); - if (err == MP_OKAY) { - if (sp_256_iszero_9(ctx->point->x) || - sp_256_iszero_9(ctx->point->y)) { - err = ECC_INF_E; - } - else { - err = FP_WOULDBLOCK; - ctx->state = 3; - } - } - break; - #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - case 3: - err = sp_256_to_mp(ctx->k, priv); - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_9(ctx->point, pub); - } - break; - } - - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#ifdef HAVE_ECC_DHE -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 32 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_256_to_bin_9(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<8; i++) { - r[i+1] += r[i] >> 29; - r[i] &= 0x1fffffff; - } - j = 263 / 8 - 1; - a[j] = 0; - for (i=0; i<9 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 29) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 29); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Multiply the point by the scalar and serialize the X ordinate. - * The number is 0 padded to maximum size on output. - * - * priv Scalar to multiply the point by. - * pub Point to multiply. - * out Buffer to hold X ordinate. - * outLen On entry, size of the buffer in bytes. - * On exit, length of data in buffer in bytes. - * heap Heap to use for allocation. - * 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(const mp_int* priv, const ecc_point* pub, byte* out, - word32* outLen, void* heap) -{ - SP_DECL_VAR(sp_point_256, point, 1); - SP_DECL_VAR(sp_digit, k, 9); - int err = MP_OKAY; - - if (*outLen < 32U) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(k, 9, priv); - sp_256_point_from_ecc_point_9(point, pub); - err = sp_256_ecc_mulmod_9(point, point, k, 1, 1, heap); - } - if (err == MP_OKAY) { - sp_256_to_bin_9(point->x, out); - *outLen = 32; - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sec_gen_256_ctx { - int state; - union { - sp_256_ecc_mulmod_9_ctx mulmod_ctx; - }; - sp_digit k[9]; - sp_point_256 point; -} sp_ecc_sec_gen_256_ctx; - -int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, - const ecc_point* pub, byte* out, word32* outLen, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - if (*outLen < 32U) { - err = BUFFER_E; - } - - switch (ctx->state) { - case 0: - sp_256_from_mp(ctx->k, 9, priv); - sp_256_point_from_ecc_point_9(&ctx->point, pub); - ctx->state = 1; - break; - case 1: - err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - sp_256_to_bin_9(ctx->point.x, out); - *outLen = 32; - } - break; - } - - if (err == MP_OKAY && ctx->state != 1) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_DHE */ - -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -SP_NOINLINE static void sp_256_rshift_9(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<8; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff); - } -#else - for (i=0; i<8; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (29 - n)) & 0x1fffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (29 - n)) & 0x1fffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (29 - n)) & 0x1fffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (29 - n)) & 0x1fffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (29 - n)) & 0x1fffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (29 - n)) & 0x1fffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (29 - n)) & 0x1fffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (29 - n)) & 0x1fffffff); - } -#endif /* WOLFSSL_SP_SMALL */ - r[8] = a[8] >> n; -} - -/* 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_256_mul_d_9(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 9; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffff); - t >>= 29; - } - r[9] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[9]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - t[ 7] = tb * a[ 7]; - t[ 8] = tb * a[ 8]; - r[ 0] = (sp_digit) (t[ 0] & 0x1fffffff); - r[ 1] = (sp_digit)((t[ 0] >> 29) + (t[ 1] & 0x1fffffff)); - r[ 2] = (sp_digit)((t[ 1] >> 29) + (t[ 2] & 0x1fffffff)); - r[ 3] = (sp_digit)((t[ 2] >> 29) + (t[ 3] & 0x1fffffff)); - r[ 4] = (sp_digit)((t[ 3] >> 29) + (t[ 4] & 0x1fffffff)); - r[ 5] = (sp_digit)((t[ 4] >> 29) + (t[ 5] & 0x1fffffff)); - r[ 6] = (sp_digit)((t[ 5] >> 29) + (t[ 6] & 0x1fffffff)); - r[ 7] = (sp_digit)((t[ 6] >> 29) + (t[ 7] & 0x1fffffff)); - r[ 8] = (sp_digit)((t[ 7] >> 29) + (t[ 8] & 0x1fffffff)); - r[ 9] = (sp_digit) (t[ 8] >> 29); -#endif /* WOLFSSL_SP_SMALL */ -} - -SP_NOINLINE static void sp_256_lshift_18(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[18] = a[17] >> (29 - n); - for (i=17; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[17]; - r[18] = s >> (29U - n); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (29U - n))) & 0x1fffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0x1fffffff); -} - -/* 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. - * - * Simplified based on top word of divisor being (1 << 29) - 1 - * - * 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_9(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 9 + 3); - int i; - sp_digit r1; - sp_digit mask; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 9 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 18 + 1; - sd = t2 + 9 + 1; - - sp_256_mul_d_9(sd, d, (sp_digit)1 << 5); - sp_256_lshift_18(t1, a, 5); - t1[9 + 9] += t1[9 + 9 - 1] >> 29; - t1[9 + 9 - 1] &= 0x1fffffff; - for (i=8; i>=0; i--) { - r1 = t1[9 + i]; - sp_256_mul_d_9(t2, sd, r1); - (void)sp_256_sub_9(&t1[i], &t1[i], t2); - t1[9 + i] -= t2[9]; - sp_256_norm_9(&t1[i + 1]); - - mask = ~((t1[9 + i] - 1) >> 31); - sp_256_cond_sub_9(t1 + i, t1 + i, sd, mask); - sp_256_norm_9(&t1[i + 1]); - } - sp_256_norm_9(t1); - sp_256_rshift_9(r, t1, 5); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_256_mod_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_256_div_9(a, m, NULL, r); -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply two number mod the order of P256 curve. (r = a * b mod order) - * - * r Result of the multiplication. - * a First operand of the multiplication. - * b Second operand of the multiplication. - */ -static void sp_256_mont_mul_order_9(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_256_mul_9(r, a, b); - sp_256_mont_reduce_order_9(r, p256_order, p256_mp_order); -} - -#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL)) -#ifdef WOLFSSL_SP_SMALL -/* Order-2 for the P256 curve. */ -static const word32 p256_order_minus_2[8] = { - 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, - 0x00000000U,0xffffffffU -}; -#else -/* The low half of the order-2 of the P256 curve. */ -static const sp_int_digit p256_order_low[4] = { - 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU -}; -#endif /* WOLFSSL_SP_SMALL */ - -/* Square number mod the order of P256 curve. (r = a * a mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_256_mont_sqr_order_9(sp_digit* r, const sp_digit* a) -{ - sp_256_sqr_9(r, a); - sp_256_mont_reduce_order_9(r, p256_order, p256_mp_order); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square number mod the order of P256 curve a number of times. - * (r = a ^ n mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_256_mont_sqr_n_order_9(sp_digit* r, const sp_digit* a, int n) -{ - int i; - - sp_256_mont_sqr_order_9(r, a); - for (i=1; i= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - XMEMCPY(t, a, sizeof(sp_digit) * 9); - ctx->i = 254; - ctx->state = 1; - break; - case 1: - sp_256_mont_sqr_order_9(t, t); - ctx->state = 2; - break; - case 2: - if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { - sp_256_mont_mul_order_9(t, t, a); - } - ctx->i--; - ctx->state = (ctx->i >= 0) ? 1 : 3; - break; - case 3: - XMEMCPY(r, t, sizeof(sp_digit) * 9U); - err = MP_OKAY; - break; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -static void sp_256_mont_inv_order_9(sp_digit* r, const sp_digit* a, - sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 9); - for (i=254; i>=0; i--) { - sp_256_mont_sqr_order_9(t, t); - if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_256_mont_mul_order_9(t, t, a); - } - } - XMEMCPY(r, t, sizeof(sp_digit) * 9U); -#else - sp_digit* t = td; - sp_digit* t2 = td + 2 * 9; - sp_digit* t3 = td + 4 * 9; - int i; - - /* t = a^2 */ - sp_256_mont_sqr_order_9(t, a); - /* t = a^3 = t * a */ - sp_256_mont_mul_order_9(t, t, a); - /* t2= a^c = t ^ 2 ^ 2 */ - sp_256_mont_sqr_n_order_9(t2, t, 2); - /* t3= a^f = t2 * t */ - sp_256_mont_mul_order_9(t3, t2, t); - /* t2= a^f0 = t3 ^ 2 ^ 4 */ - sp_256_mont_sqr_n_order_9(t2, t3, 4); - /* t = a^ff = t2 * t3 */ - sp_256_mont_mul_order_9(t, t2, t3); - /* t2= a^ff00 = t ^ 2 ^ 8 */ - sp_256_mont_sqr_n_order_9(t2, t, 8); - /* t = a^ffff = t2 * t */ - sp_256_mont_mul_order_9(t, t2, t); - /* t2= a^ffff0000 = t ^ 2 ^ 16 */ - sp_256_mont_sqr_n_order_9(t2, t, 16); - /* t = a^ffffffff = t2 * t */ - sp_256_mont_mul_order_9(t, t2, t); - /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ - sp_256_mont_sqr_n_order_9(t2, t, 64); - /* t2= a^ffffffff00000000ffffffff = t2 * t */ - sp_256_mont_mul_order_9(t2, t2, t); - /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ - sp_256_mont_sqr_n_order_9(t2, t2, 32); - /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ - sp_256_mont_mul_order_9(t2, t2, t); - /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ - sp_256_mont_sqr_order_9(t2, t2); - sp_256_mont_mul_order_9(t2, t2, a); - sp_256_mont_sqr_n_order_9(t2, t2, 5); - sp_256_mont_mul_order_9(t2, t2, t3); - for (i=121; i>=112; i--) { - sp_256_mont_sqr_order_9(t2, t2); - if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_256_mont_mul_order_9(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ - sp_256_mont_sqr_n_order_9(t2, t2, 4); - sp_256_mont_mul_order_9(t2, t2, t3); - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ - for (i=107; i>=64; i--) { - sp_256_mont_sqr_order_9(t2, t2); - if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_256_mont_mul_order_9(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ - sp_256_mont_sqr_n_order_9(t2, t2, 4); - sp_256_mont_mul_order_9(t2, t2, t3); - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ - for (i=59; i>=32; i--) { - sp_256_mont_sqr_order_9(t2, t2); - if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_256_mont_mul_order_9(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ - sp_256_mont_sqr_n_order_9(t2, t2, 4); - sp_256_mont_mul_order_9(t2, t2, t3); - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ - for (i=27; i>=0; i--) { - sp_256_mont_sqr_order_9(t2, t2); - if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_256_mont_mul_order_9(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ - sp_256_mont_sqr_n_order_9(t2, t2, 4); - /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ - sp_256_mont_mul_order_9(r, t2, t3); -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */ -#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_9(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; - sp_int32 c; - sp_digit* kInv = k; - - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_9(k, k, p256_norm_order); - err = sp_256_mod_9(k, k, p256_order); - if (err == MP_OKAY) { - sp_256_norm_9(k); - - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_9(kInv, k, tmp); - sp_256_norm_9(kInv); - - /* s = r * x + e */ - sp_256_mul_9(x, x, r); - err = sp_256_mod_9(x, x, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_9(x); - carry = sp_256_add_9(s, e, x); - sp_256_cond_sub_9(s, s, p256_order, 0 - carry); - sp_256_norm_9(s); - c = sp_256_cmp_9(s, p256_order); - sp_256_cond_sub_9(s, s, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_9(s); - - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_9(s, s, kInv); - sp_256_norm_9(s); - } - - return err; -} - -/* Sign the hash using the private key. - * e = [hash, 256 bits] from binary - * r = (k.G)->x mod order - * s = (r * x + e) / k mod order - * The hash is truncated to the first 256 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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. - */ -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) -{ - SP_DECL_VAR(sp_digit, e, 7 * 2 * 9); - SP_DECL_VAR(sp_point_256, point, 1); - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, e, 7 * 2 * 9, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - x = e + 2 * 9; - k = e + 4 * 9; - r = e + 6 * 9; - tmp = e + 8 * 9; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_9(rng, k); - } - else { - sp_256_from_mp(k, 9, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); - sp_256_norm_9(r); - c = sp_256_cmp_9(r, p256_order); - sp_256_cond_sub_9(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_9(r); - - if (!sp_256_iszero_9(r)) { - /* x is modified in calculation of s. */ - sp_256_from_mp(x, 9, priv); - /* s ptr == e ptr, e is modified in calculation of s. */ - sp_256_from_bin(e, 9, hash, (int)hashLen); - - err = sp_256_calc_s_9(s, r, k, x, e, tmp); - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (!sp_256_iszero_9(s))) { - break; - } - } - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - - SP_ZEROFREE_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_digit, e, 7 * 2 * 9, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sign_256_ctx { - int state; - union { - sp_256_ecc_mulmod_9_ctx mulmod_ctx; - sp_256_mont_inv_order_9_ctx mont_inv_order_ctx; - }; - sp_digit e[2*9]; - sp_digit x[2*9]; - sp_digit k[2*9]; - sp_digit r[2*9]; - sp_digit tmp[3 * 2*9]; - sp_point_256 point; - sp_digit* s; - sp_digit* kInv; - 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 err = FP_WOULDBLOCK; - sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - ctx->s = ctx->e; - ctx->kInv = ctx->k; - - ctx->i = SP_ECC_MAX_SIG_GEN; - ctx->state = 1; - break; - case 1: /* GEN */ - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_9(rng, ctx->k); - } - else { - sp_256_from_mp(ctx->k, 9, km); - mp_zero(km); - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - break; - case 2: /* MULMOD */ - err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &p256_base, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - ctx->state = 3; - } - break; - case 3: /* MODORDER */ - { - sp_int32 c; - /* r = point->x mod order */ - XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 9U); - sp_256_norm_9(ctx->r); - c = sp_256_cmp_9(ctx->r, p256_order); - sp_256_cond_sub_9(ctx->r, ctx->r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_9(ctx->r); - - if (hashLen > 32U) { - hashLen = 32U; - } - sp_256_from_mp(ctx->x, 9, priv); - sp_256_from_bin(ctx->e, 9, hash, (int)hashLen); - ctx->state = 4; - break; - } - case 4: /* KMODORDER */ - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_9(ctx->k, ctx->k, p256_norm_order); - err = sp_256_mod_9(ctx->k, ctx->k, p256_order); - if (err == MP_OKAY) { - sp_256_norm_9(ctx->k); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 5; - } - break; - case 5: /* KINV */ - /* kInv = 1/k mod order */ - err = sp_256_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); - if (err == MP_OKAY) { - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 6; - } - break; - case 6: /* KINVNORM */ - sp_256_norm_9(ctx->kInv); - ctx->state = 7; - break; - case 7: /* R */ - /* s = r * x + e */ - sp_256_mul_9(ctx->x, ctx->x, ctx->r); - ctx->state = 8; - break; - case 8: /* S1 */ - err = sp_256_mod_9(ctx->x, ctx->x, p256_order); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* S2 */ - { - sp_digit carry; - sp_int32 c; - sp_256_norm_9(ctx->x); - carry = sp_256_add_9(ctx->s, ctx->e, ctx->x); - sp_256_cond_sub_9(ctx->s, ctx->s, - p256_order, 0 - carry); - sp_256_norm_9(ctx->s); - c = sp_256_cmp_9(ctx->s, p256_order); - sp_256_cond_sub_9(ctx->s, ctx->s, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_9(ctx->s); - - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_9(ctx->s, ctx->s, ctx->kInv); - sp_256_norm_9(ctx->s); - - /* Check that signature is usable. */ - if (sp_256_iszero_9(ctx->s) == 0) { - ctx->state = 10; - break; - } - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - ctx->i = 1; - #endif - - /* not usable gen, try again */ - ctx->i--; - if (ctx->i == 0) { - err = RNG_FAILURE_E; - } - ctx->state = 1; - break; - } - case 10: /* RES */ - err = sp_256_to_mp(ctx->r, rm); - if (err == MP_OKAY) { - err = sp_256_to_mp(ctx->s, sm); - } - break; - } - - if (err == MP_OKAY && ctx->state != 10) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 9U); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_SIGN */ - -#ifndef WOLFSSL_SP_SMALL -static const char sp_256_tab32_9[32] = { - 1, 10, 2, 11, 14, 22, 3, 30, - 12, 15, 17, 19, 23, 26, 4, 31, - 9, 13, 21, 29, 16, 18, 25, 8, - 20, 28, 24, 7, 27, 6, 5, 32}; - -static int sp_256_num_bits_29_9(sp_digit v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return sp_256_tab32_9[(word32)(v*0x07C4ACDD) >> 27]; -} - -static int sp_256_num_bits_9(const sp_digit* a) -{ - int i; - int r = 0; - - for (i = 8; i >= 0; i--) { - if (a[i] != 0) { - r = sp_256_num_bits_29_9(a[i]); - r += i * 29; - break; - } - } - - return r; -} - -/* 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. - * @return MEMEORY_E when dynamic memory allocation fails. - */ -static int sp_256_mod_inv_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int err = MP_OKAY; - SP_DECL_VAR(sp_digit, u, 9 * 4); - sp_digit* v = NULL; - sp_digit* b = NULL; - sp_digit* d = NULL; - int ut; - int vt; - - SP_ALLOC_VAR(sp_digit, u, 9 * 4, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - v = u + 9; - b = u + 2 * 9; - d = u + 3 * 9; - - XMEMCPY(u, m, sizeof(sp_digit) * 9); - XMEMCPY(v, a, sizeof(sp_digit) * 9); - - ut = sp_256_num_bits_9(u); - vt = sp_256_num_bits_9(v); - - XMEMSET(b, 0, sizeof(sp_digit) * 9); - if ((v[0] & 1) == 0) { - sp_256_rshift1_9(v, v); - XMEMCPY(d, m, sizeof(sp_digit) * 9); - d[0]++; - sp_256_rshift1_9(d, d); - vt--; - - while ((v[0] & 1) == 0) { - sp_256_rshift1_9(v, v); - if (d[0] & 1) - sp_256_add_9(d, d, m); - sp_256_rshift1_9(d, d); - vt--; - } - } - else { - XMEMSET(d+1, 0, sizeof(sp_digit) * (9 - 1)); - d[0] = 1; - } - - while (ut > 1 && vt > 1) { - if ((ut > vt) || ((ut == vt) && - (sp_256_cmp_9(u, v) >= 0))) { - sp_256_sub_9(u, u, v); - sp_256_norm_9(u); - - sp_256_sub_9(b, b, d); - sp_256_norm_9(b); - if (b[8] < 0) - sp_256_add_9(b, b, m); - sp_256_norm_9(b); - ut = sp_256_num_bits_9(u); - - do { - sp_256_rshift1_9(u, u); - if (b[0] & 1) - sp_256_add_9(b, b, m); - sp_256_rshift1_9(b, b); - ut--; - } - while (ut > 0 && (u[0] & 1) == 0); - } - else { - sp_256_sub_9(v, v, u); - sp_256_norm_9(v); - - sp_256_sub_9(d, d, b); - sp_256_norm_9(d); - if (d[8] < 0) - sp_256_add_9(d, d, m); - sp_256_norm_9(d); - vt = sp_256_num_bits_9(v); - - do { - sp_256_rshift1_9(v, v); - if (d[0] & 1) - sp_256_add_9(d, d, m); - sp_256_rshift1_9(d, d); - vt--; - } - while (vt > 0 && (v[0] & 1) == 0); - } - } - - if (ut == 1) - XMEMCPY(r, b, sizeof(sp_digit) * 9); - else - XMEMCPY(r, d, sizeof(sp_digit) * 9); - } - SP_FREE_VAR(u, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#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_9(sp_point_256* p1, const sp_point_256* p2, - sp_digit* tmp) -{ - - sp_256_proj_point_add_9(p1, p1, p2, tmp); - if (sp_256_iszero_9(p1->z)) { - if (sp_256_iszero_9(p1->x) && sp_256_iszero_9(p1->y)) { - sp_256_proj_point_dbl_9(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; - 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 Temporary 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_9(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 - err = sp_256_mod_inv_9(s, s, p256_order); - if (err == MP_OKAY) -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_9(s, s, p256_norm_order); - err = sp_256_mod_9(s, s, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_9(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_9(s, s, tmp); - sp_256_mont_mul_order_9(u1, u1, s); - sp_256_mont_mul_order_9(u2, u2, s); - } -#else - { - sp_256_mont_mul_order_9(u1, u1, s); - sp_256_mont_mul_order_9(u2, u2, s); - } -#endif /* WOLFSSL_SP_SMALL */ - { - err = sp_256_ecc_mulmod_base_9(p1, u1, 0, 0, heap); - } - } - if ((err == MP_OKAY) && sp_256_iszero_9(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_9(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_9(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - sp_256_add_points_9(p1, p2, tmp); - } - - return err; -} - -#ifdef HAVE_ECC_VERIFY -/* Verify the signature values with the hash and public key. - * e = Truncate(hash, 256) - * u1 = e/s mod order - * u2 = r/s mod order - * r == (u1.G + u2.Q)->x mod order - * Optimization: Leave point in projective form. - * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') - * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' - * The hash is truncated to the first 256 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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 MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -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) -{ - SP_DECL_VAR(sp_digit, u1, 18 * 9); - SP_DECL_VAR(sp_point_256, p1, 2); - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, u1, 18 * 9, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p1, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - u2 = u1 + 2 * 9; - s = u1 + 4 * 9; - tmp = u1 + 6 * 9; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 9, hash, (int)hashLen); - sp_256_from_mp(u2, 9, rm); - sp_256_from_mp(s, 9, sm); - sp_256_from_mp(p2->x, 9, pX); - sp_256_from_mp(p2->y, 9, pY); - sp_256_from_mp(p2->z, 9, pZ); - - err = sp_256_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 9, rm); - err = sp_256_mod_mul_norm_9(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_9(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_9(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 9, rm); - carry = sp_256_add_9(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_9(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_9(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_9(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_9(p1->x, u1) == 0); - } - } - } - - SP_FREE_VAR(p1, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(u1, heap, DYNAMIC_TYPE_ECC); - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_verify_256_ctx { - int state; - union { - sp_256_ecc_mulmod_9_ctx mulmod_ctx; - sp_256_mont_inv_order_9_ctx mont_inv_order_ctx; - sp_256_proj_point_dbl_9_ctx dbl_ctx; - sp_256_proj_point_add_9_ctx add_ctx; - }; - sp_digit u1[2*9]; - sp_digit u2[2*9]; - sp_digit s[2*9]; - sp_digit tmp[2*9 * 6]; - sp_point_256 p1; - 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, 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; - - typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(ctx->u1, 9, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 9, rm); - sp_256_from_mp(ctx->s, 9, sm); - sp_256_from_mp(ctx->p2.x, 9, pX); - sp_256_from_mp(ctx->p2.y, 9, pY); - sp_256_from_mp(ctx->p2.z, 9, pZ); - ctx->state = 1; - break; - case 1: /* NORMS0 */ - sp_256_mul_9(ctx->s, ctx->s, p256_norm_order); - err = sp_256_mod_9(ctx->s, ctx->s, p256_order); - if (err == MP_OKAY) - ctx->state = 2; - break; - case 2: /* NORMS1 */ - sp_256_norm_9(ctx->s); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 3; - break; - case 3: /* NORMS2 */ - err = sp_256_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 4; - } - break; - case 4: /* NORMS3 */ - sp_256_mont_mul_order_9(ctx->u1, ctx->u1, ctx->s); - ctx->state = 5; - break; - case 5: /* NORMS4 */ - sp_256_mont_mul_order_9(ctx->u2, ctx->u2, ctx->s); - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 6; - break; - case 6: /* MULBASE */ - err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_256_iszero_9(ctx->p1.z)) { - ctx->p1.infinity = 1; - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 7; - } - break; - case 7: /* MULMOD */ - err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_256_iszero_9(ctx->p2.z)) { - ctx->p2.infinity = 1; - } - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 8; - } - break; - case 8: /* ADD */ - err = sp_256_proj_point_add_9_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); - if (err == MP_OKAY) - ctx->state = 9; - break; - 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, 9, rm); - err = sp_256_mod_mul_norm_9(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) - ctx->state = 10; - break; - case 10: /* SQR */ - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_9(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 11; - break; - case 11: /* MUL */ - sp_256_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 12; - break; - case 12: /* RES */ - { - sp_int32 c = 0; - err = MP_OKAY; /* math okay, now check result */ - *res = (int)(sp_256_cmp_9(ctx->p1.x, ctx->u1) == 0); - if (*res == 0) { - sp_digit carry; - - /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 9, rm); - carry = sp_256_add_9(ctx->u2, ctx->u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_9(ctx->u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_9(ctx->u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_9(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_9(ctx->p1.x, ctx->u1) == 0); - } - } - break; - } - } /* switch */ - - if (err == MP_OKAY && ctx->state != 12) { - err = FP_WOULDBLOCK; - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_VERIFY */ - -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* Check that the x and y ordinates 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_256_ecc_is_point_9(const sp_point_256* point, - void* heap) -{ - SP_DECL_VAR(sp_digit, t1, 9 * 4); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 9 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 9; - - /* y^2 - x^3 - a.x = b */ - sp_256_sqr_9(t1, point->y); - (void)sp_256_mod_9(t1, t1, p256_mod); - sp_256_sqr_9(t2, point->x); - (void)sp_256_mod_9(t2, t2, p256_mod); - sp_256_mul_9(t2, t2, point->x); - (void)sp_256_mod_9(t2, t2, p256_mod); - sp_256_mont_sub_9(t1, t1, t2, p256_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - sp_256_mont_add_9(t1, t1, point->x, p256_mod); - sp_256_mont_add_9(t1, t1, point->x, p256_mod); - sp_256_mont_add_9(t1, t1, point->x, p256_mod); - - - if (sp_256_cmp_9(t1, p256_b) != 0) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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_256(const mp_int* pX, const mp_int* pY) -{ - SP_DECL_VAR(sp_point_256, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, pub, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(pub->x, 9, pX); - sp_256_from_mp(pub->y, 9, pY); - sp_256_from_bin(pub->z, 9, one, (int)sizeof(one)); - - err = sp_256_ecc_is_point_9(pub, NULL); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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_256(const mp_int* pX, const mp_int* pY, - const mp_int* privm, void* heap) -{ - SP_DECL_VAR(sp_digit, priv, 9); - SP_DECL_VAR(sp_point_256, pub, 2); - 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 (((mp_count_bits(pX) > 256) || - (mp_count_bits(pY) > 256) || - ((privm != NULL) && (mp_count_bits(privm) > 256)))) { - err = ECC_OUT_OF_RANGE_E; - } - - SP_ALLOC_VAR(sp_digit, priv, 9, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, pub, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - p = pub + 1; - - sp_256_from_mp(pub->x, 9, pX); - sp_256_from_mp(pub->y, 9, pY); - sp_256_from_bin(pub->z, 9, one, (int)sizeof(one)); - if (privm) - sp_256_from_mp(priv, 9, privm); - - /* Check point at infinitiy. */ - if ((sp_256_iszero_9(pub->x) != 0) && - (sp_256_iszero_9(pub->y) != 0)) { - err = ECC_INF_E; - } - } - - /* Check range of X and Y */ - if ((err == MP_OKAY) && - ((sp_256_cmp_9(pub->x, p256_mod) >= 0) || - (sp_256_cmp_9(pub->y, p256_mod) >= 0))) { - err = ECC_OUT_OF_RANGE_E; - } - - if (err == MP_OKAY) { - /* Check point is on curve */ - err = sp_256_ecc_is_point_9(pub, heap); - } - - if (err == MP_OKAY) { - /* Point * order = infinity */ - err = sp_256_ecc_mulmod_9(p, pub, p256_order, 1, 1, heap); - } - /* Check result is infinity */ - if ((err == MP_OKAY) && ((sp_256_iszero_9(p->x) == 0) || - (sp_256_iszero_9(p->y) == 0))) { - err = ECC_INF_E; - } - - if (privm) { - if (err == MP_OKAY) { - /* Base * private = point */ - err = sp_256_ecc_mulmod_base_9(p, priv, 1, 1, heap); - } - /* Check result is public key */ - if ((err == MP_OKAY) && - ((sp_256_cmp_9(p->x, pub->x) != 0) || - (sp_256_cmp_9(p->y, pub->y) != 0))) { - err = ECC_PRIV_KEY_E; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL -/* Add two projective EC points together. - * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) - * - * pX First EC point's X ordinate. - * pY First EC point's Y ordinate. - * pZ First EC point's Z ordinate. - * qX Second EC point's X ordinate. - * qY Second EC point's Y ordinate. - * qZ Second EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - SP_DECL_VAR(sp_point_256, p, 2); - sp_point_256* q = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p, 2, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - q = p + 1; - - sp_256_from_mp(p->x, 9, pX); - sp_256_from_mp(p->y, 9, pY); - sp_256_from_mp(p->z, 9, pZ); - sp_256_from_mp(q->x, 9, qX); - sp_256_from_mp(q->y, 9, qY); - sp_256_from_mp(q->z, 9, qZ); - p->infinity = sp_256_iszero_9(p->x) & - sp_256_iszero_9(p->y); - q->infinity = sp_256_iszero_9(q->x) & - sp_256_iszero_9(q->y); - - sp_256_proj_point_add_9(p, p, q, tmp); - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Double a projective EC point. - * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 2); - SP_DECL_VAR(sp_point_256, p, 1); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(p->x, 9, pX); - sp_256_from_mp(p->y, 9, pY); - sp_256_from_mp(p->z, 9, pZ); - p->infinity = sp_256_iszero_9(p->x) & - sp_256_iszero_9(p->y); - - sp_256_proj_point_dbl_9(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Map a projective EC point to affine in place. - * pZ will be one. - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 4); - SP_DECL_VAR(sp_point_256, p, 1); - int err = MP_OKAY; - - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 4, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(p->x, 9, pX); - sp_256_from_mp(p->y, 9, pY); - sp_256_from_mp(p->z, 9, pZ); - p->infinity = sp_256_iszero_9(p->x) & - sp_256_iszero_9(p->y); - - sp_256_map_9(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(p->x, pX); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, pY); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, pZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifdef HAVE_COMP_KEY -/* Find the square root of a number mod the prime of the curve. - * - * y The number to operate on and the result. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -static int sp_256_mont_sqrt_9(sp_digit* y) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 9); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 9, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 9; - - { - /* t2 = y ^ 0x2 */ - sp_256_mont_sqr_9(t2, y, p256_mod, p256_mp_mod); - /* t1 = y ^ 0x3 */ - sp_256_mont_mul_9(t1, t2, y, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xc */ - sp_256_mont_sqr_n_9(t2, t1, 2, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xf */ - sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xf0 */ - sp_256_mont_sqr_n_9(t2, t1, 4, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xff */ - sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xff00 */ - sp_256_mont_sqr_n_9(t2, t1, 8, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffff */ - sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xffff0000 */ - sp_256_mont_sqr_n_9(t2, t1, 16, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff */ - sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000000 */ - sp_256_mont_sqr_n_9(t1, t1, 32, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000001 */ - sp_256_mont_mul_9(t1, t1, y, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ - sp_256_mont_sqr_n_9(t1, t1, 96, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ - sp_256_mont_mul_9(t1, t1, y, p256_mod, p256_mp_mod); - sp_256_mont_sqr_n_9(y, t1, 94, p256_mod, p256_mp_mod); - } - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - - -/* Uncompress the point given the X ordinate. - * - * xm X ordinate. - * odd Whether the Y ordinate is odd. - * ym Calculated Y ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) -{ - SP_DECL_VAR(sp_digit, x, 4 * 9); - sp_digit* y = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, x, 4 * 9, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - y = x + 2 * 9; - - sp_256_from_mp(x, 9, xm); - err = sp_256_mod_mul_norm_9(x, x, p256_mod); - } - if (err == MP_OKAY) { - /* y = x^3 */ - { - sp_256_mont_sqr_9(y, x, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(y, y, x, p256_mod, p256_mp_mod); - } - /* y = x^3 - 3x */ - sp_256_mont_sub_9(y, y, x, p256_mod); - sp_256_mont_sub_9(y, y, x, p256_mod); - sp_256_mont_sub_9(y, y, x, p256_mod); - /* y = x^3 - 3x + b */ - err = sp_256_mod_mul_norm_9(x, p256_b, p256_mod); - } - if (err == MP_OKAY) { - sp_256_mont_add_9(y, y, x, p256_mod); - /* y = sqrt(x^3 - 3x + b) */ - err = sp_256_mont_sqrt_9(y); - } - if (err == MP_OKAY) { - XMEMSET(y + 9, 0, 9U * sizeof(sp_digit)); - sp_256_mont_reduce_9(y, p256_mod, p256_mp_mod); - if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { - sp_256_mont_sub_9(y, p256_mod, y, p256_mod); - } - - err = sp_256_to_mp(y, ym); - } - - SP_FREE_VAR(x, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* !WOLFSSL_SP_NO_256 */ -#ifdef WOLFSSL_SP_384 - -/* 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 -}; -/* The Montgomery 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 -}; -/* The Montgomery multiplier for modulus of the curve P384. */ -static const sp_digit p384_mp_mod = 0x000001; -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -/* 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 -}; -#endif -#ifndef WC_NO_RNG -/* 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 -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery 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 -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery multiplier for order of the curve P384. */ -static const sp_digit p384_mp_order = 0x8fdc45; -#endif -/* The base point of curve P384. */ -static const sp_point_384 p384_base = { - /* X ordinate */ - { - 0x2760ab7,0x1178e1c,0x296c3a5,0x176fd54,0x05502f2,0x0950a8e,0x3741e08, - 0x26e6167,0x3628ba7,0x11b874e,0x3320ad7,0x2c71c7b,0x305378e,0x288afa2, - 0x00aa87c, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Y ordinate */ - { - 0x0ea0e5f,0x0c75f24,0x019d7a4,0x33875fa,0x00a60b1,0x17c2e30,0x1a3113b, - 0x051f3a7,0x1bd289a,0x27e3d07,0x1292dc2,0x27a62fe,0x22c6f5d,0x392a589, - 0x003617d, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Z ordinate */ - { - 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) || \ - 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 -}; -#endif - -#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. - */ -SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[14]) * b[14]; - r[29] = (sp_digit)(c >> 26); - c &= 0x3ffffff; - for (k = 27; k >= 0; k--) { - if (k >= 15) { - i = k - 14; - imax = 14; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 26; - r[k + 2] += (sp_digit)(c >> 26); - r[k + 1] = (sp_digit)(c & 0x3ffffff); - c = lo & 0x3ffffff; - } - r[0] = (sp_digit)c; -} - -#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_384_mul_15(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_int64 t0; - sp_int64 t1; - sp_digit t[15]; - - t0 = ((sp_int64)a[ 0]) * b[ 0]; - t1 = ((sp_int64)a[ 0]) * b[ 1] - + ((sp_int64)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[ 2] - + ((sp_int64)a[ 1]) * b[ 1] - + ((sp_int64)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 0]) * b[ 3] - + ((sp_int64)a[ 1]) * b[ 2] - + ((sp_int64)a[ 2]) * b[ 1] - + ((sp_int64)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[ 4] - + ((sp_int64)a[ 1]) * b[ 3] - + ((sp_int64)a[ 2]) * b[ 2] - + ((sp_int64)a[ 3]) * b[ 1] - + ((sp_int64)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 0]) * b[ 5] - + ((sp_int64)a[ 1]) * b[ 4] - + ((sp_int64)a[ 2]) * b[ 3] - + ((sp_int64)a[ 3]) * b[ 2] - + ((sp_int64)a[ 4]) * b[ 1] - + ((sp_int64)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[ 6] - + ((sp_int64)a[ 1]) * b[ 5] - + ((sp_int64)a[ 2]) * b[ 4] - + ((sp_int64)a[ 3]) * b[ 3] - + ((sp_int64)a[ 4]) * b[ 2] - + ((sp_int64)a[ 5]) * b[ 1] - + ((sp_int64)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 0]) * b[ 7] - + ((sp_int64)a[ 1]) * b[ 6] - + ((sp_int64)a[ 2]) * b[ 5] - + ((sp_int64)a[ 3]) * b[ 4] - + ((sp_int64)a[ 4]) * b[ 3] - + ((sp_int64)a[ 5]) * b[ 2] - + ((sp_int64)a[ 6]) * b[ 1] - + ((sp_int64)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[ 8] - + ((sp_int64)a[ 1]) * b[ 7] - + ((sp_int64)a[ 2]) * b[ 6] - + ((sp_int64)a[ 3]) * b[ 5] - + ((sp_int64)a[ 4]) * b[ 4] - + ((sp_int64)a[ 5]) * b[ 3] - + ((sp_int64)a[ 6]) * b[ 2] - + ((sp_int64)a[ 7]) * b[ 1] - + ((sp_int64)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 0]) * b[ 9] - + ((sp_int64)a[ 1]) * b[ 8] - + ((sp_int64)a[ 2]) * b[ 7] - + ((sp_int64)a[ 3]) * b[ 6] - + ((sp_int64)a[ 4]) * b[ 5] - + ((sp_int64)a[ 5]) * b[ 4] - + ((sp_int64)a[ 6]) * b[ 3] - + ((sp_int64)a[ 7]) * b[ 2] - + ((sp_int64)a[ 8]) * b[ 1] - + ((sp_int64)a[ 9]) * b[ 0]; - t[ 8] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[10] - + ((sp_int64)a[ 1]) * b[ 9] - + ((sp_int64)a[ 2]) * b[ 8] - + ((sp_int64)a[ 3]) * b[ 7] - + ((sp_int64)a[ 4]) * b[ 6] - + ((sp_int64)a[ 5]) * b[ 5] - + ((sp_int64)a[ 6]) * b[ 4] - + ((sp_int64)a[ 7]) * b[ 3] - + ((sp_int64)a[ 8]) * b[ 2] - + ((sp_int64)a[ 9]) * b[ 1] - + ((sp_int64)a[10]) * b[ 0]; - t[ 9] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 0]) * b[11] - + ((sp_int64)a[ 1]) * b[10] - + ((sp_int64)a[ 2]) * b[ 9] - + ((sp_int64)a[ 3]) * b[ 8] - + ((sp_int64)a[ 4]) * b[ 7] - + ((sp_int64)a[ 5]) * b[ 6] - + ((sp_int64)a[ 6]) * b[ 5] - + ((sp_int64)a[ 7]) * b[ 4] - + ((sp_int64)a[ 8]) * b[ 3] - + ((sp_int64)a[ 9]) * b[ 2] - + ((sp_int64)a[10]) * b[ 1] - + ((sp_int64)a[11]) * b[ 0]; - t[10] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[12] - + ((sp_int64)a[ 1]) * b[11] - + ((sp_int64)a[ 2]) * b[10] - + ((sp_int64)a[ 3]) * b[ 9] - + ((sp_int64)a[ 4]) * b[ 8] - + ((sp_int64)a[ 5]) * b[ 7] - + ((sp_int64)a[ 6]) * b[ 6] - + ((sp_int64)a[ 7]) * b[ 5] - + ((sp_int64)a[ 8]) * b[ 4] - + ((sp_int64)a[ 9]) * b[ 3] - + ((sp_int64)a[10]) * b[ 2] - + ((sp_int64)a[11]) * b[ 1] - + ((sp_int64)a[12]) * b[ 0]; - t[11] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 0]) * b[13] - + ((sp_int64)a[ 1]) * b[12] - + ((sp_int64)a[ 2]) * b[11] - + ((sp_int64)a[ 3]) * b[10] - + ((sp_int64)a[ 4]) * b[ 9] - + ((sp_int64)a[ 5]) * b[ 8] - + ((sp_int64)a[ 6]) * b[ 7] - + ((sp_int64)a[ 7]) * b[ 6] - + ((sp_int64)a[ 8]) * b[ 5] - + ((sp_int64)a[ 9]) * b[ 4] - + ((sp_int64)a[10]) * b[ 3] - + ((sp_int64)a[11]) * b[ 2] - + ((sp_int64)a[12]) * b[ 1] - + ((sp_int64)a[13]) * b[ 0]; - t[12] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 0]) * b[14] - + ((sp_int64)a[ 1]) * b[13] - + ((sp_int64)a[ 2]) * b[12] - + ((sp_int64)a[ 3]) * b[11] - + ((sp_int64)a[ 4]) * b[10] - + ((sp_int64)a[ 5]) * b[ 9] - + ((sp_int64)a[ 6]) * b[ 8] - + ((sp_int64)a[ 7]) * b[ 7] - + ((sp_int64)a[ 8]) * b[ 6] - + ((sp_int64)a[ 9]) * b[ 5] - + ((sp_int64)a[10]) * b[ 4] - + ((sp_int64)a[11]) * b[ 3] - + ((sp_int64)a[12]) * b[ 2] - + ((sp_int64)a[13]) * b[ 1] - + ((sp_int64)a[14]) * b[ 0]; - t[13] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 1]) * b[14] - + ((sp_int64)a[ 2]) * b[13] - + ((sp_int64)a[ 3]) * b[12] - + ((sp_int64)a[ 4]) * b[11] - + ((sp_int64)a[ 5]) * b[10] - + ((sp_int64)a[ 6]) * b[ 9] - + ((sp_int64)a[ 7]) * b[ 8] - + ((sp_int64)a[ 8]) * b[ 7] - + ((sp_int64)a[ 9]) * b[ 6] - + ((sp_int64)a[10]) * b[ 5] - + ((sp_int64)a[11]) * b[ 4] - + ((sp_int64)a[12]) * b[ 3] - + ((sp_int64)a[13]) * b[ 2] - + ((sp_int64)a[14]) * b[ 1]; - t[14] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 2]) * b[14] - + ((sp_int64)a[ 3]) * b[13] - + ((sp_int64)a[ 4]) * b[12] - + ((sp_int64)a[ 5]) * b[11] - + ((sp_int64)a[ 6]) * b[10] - + ((sp_int64)a[ 7]) * b[ 9] - + ((sp_int64)a[ 8]) * b[ 8] - + ((sp_int64)a[ 9]) * b[ 7] - + ((sp_int64)a[10]) * b[ 6] - + ((sp_int64)a[11]) * b[ 5] - + ((sp_int64)a[12]) * b[ 4] - + ((sp_int64)a[13]) * b[ 3] - + ((sp_int64)a[14]) * b[ 2]; - r[15] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 3]) * b[14] - + ((sp_int64)a[ 4]) * b[13] - + ((sp_int64)a[ 5]) * b[12] - + ((sp_int64)a[ 6]) * b[11] - + ((sp_int64)a[ 7]) * b[10] - + ((sp_int64)a[ 8]) * b[ 9] - + ((sp_int64)a[ 9]) * b[ 8] - + ((sp_int64)a[10]) * b[ 7] - + ((sp_int64)a[11]) * b[ 6] - + ((sp_int64)a[12]) * b[ 5] - + ((sp_int64)a[13]) * b[ 4] - + ((sp_int64)a[14]) * b[ 3]; - r[16] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 4]) * b[14] - + ((sp_int64)a[ 5]) * b[13] - + ((sp_int64)a[ 6]) * b[12] - + ((sp_int64)a[ 7]) * b[11] - + ((sp_int64)a[ 8]) * b[10] - + ((sp_int64)a[ 9]) * b[ 9] - + ((sp_int64)a[10]) * b[ 8] - + ((sp_int64)a[11]) * b[ 7] - + ((sp_int64)a[12]) * b[ 6] - + ((sp_int64)a[13]) * b[ 5] - + ((sp_int64)a[14]) * b[ 4]; - r[17] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 5]) * b[14] - + ((sp_int64)a[ 6]) * b[13] - + ((sp_int64)a[ 7]) * b[12] - + ((sp_int64)a[ 8]) * b[11] - + ((sp_int64)a[ 9]) * b[10] - + ((sp_int64)a[10]) * b[ 9] - + ((sp_int64)a[11]) * b[ 8] - + ((sp_int64)a[12]) * b[ 7] - + ((sp_int64)a[13]) * b[ 6] - + ((sp_int64)a[14]) * b[ 5]; - r[18] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 6]) * b[14] - + ((sp_int64)a[ 7]) * b[13] - + ((sp_int64)a[ 8]) * b[12] - + ((sp_int64)a[ 9]) * b[11] - + ((sp_int64)a[10]) * b[10] - + ((sp_int64)a[11]) * b[ 9] - + ((sp_int64)a[12]) * b[ 8] - + ((sp_int64)a[13]) * b[ 7] - + ((sp_int64)a[14]) * b[ 6]; - r[19] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 7]) * b[14] - + ((sp_int64)a[ 8]) * b[13] - + ((sp_int64)a[ 9]) * b[12] - + ((sp_int64)a[10]) * b[11] - + ((sp_int64)a[11]) * b[10] - + ((sp_int64)a[12]) * b[ 9] - + ((sp_int64)a[13]) * b[ 8] - + ((sp_int64)a[14]) * b[ 7]; - r[20] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[ 8]) * b[14] - + ((sp_int64)a[ 9]) * b[13] - + ((sp_int64)a[10]) * b[12] - + ((sp_int64)a[11]) * b[11] - + ((sp_int64)a[12]) * b[10] - + ((sp_int64)a[13]) * b[ 9] - + ((sp_int64)a[14]) * b[ 8]; - r[21] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[ 9]) * b[14] - + ((sp_int64)a[10]) * b[13] - + ((sp_int64)a[11]) * b[12] - + ((sp_int64)a[12]) * b[11] - + ((sp_int64)a[13]) * b[10] - + ((sp_int64)a[14]) * b[ 9]; - r[22] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[10]) * b[14] - + ((sp_int64)a[11]) * b[13] - + ((sp_int64)a[12]) * b[12] - + ((sp_int64)a[13]) * b[11] - + ((sp_int64)a[14]) * b[10]; - r[23] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[11]) * b[14] - + ((sp_int64)a[12]) * b[13] - + ((sp_int64)a[13]) * b[12] - + ((sp_int64)a[14]) * b[11]; - r[24] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[12]) * b[14] - + ((sp_int64)a[13]) * b[13] - + ((sp_int64)a[14]) * b[12]; - r[25] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = ((sp_int64)a[13]) * b[14] - + ((sp_int64)a[14]) * b[13]; - r[26] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[14]) * b[14]; - r[27] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - r[28] = (sp_digit)(t0 & 0x3ffffff); - r[29] = (sp_digit)(t0 >> 26); - XMEMCPY(r, t, sizeof(t)); -} - -#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 imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[14]) * a[14]; - r[29] = (sp_digit)(c >> 26); - c = (c & 0x3ffffff) << 26; - for (k = 27; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 14) { - imax = k; - } - else { - imax = 14; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - 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) -{ - sp_int64 t0; - sp_int64 t1; - sp_digit t[15]; - - t0 = ((sp_int64)a[ 0]) * a[ 0]; - t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[ 2]) * 2 - + ((sp_int64)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 0]) * a[ 3] - + ((sp_int64)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[ 4] - + ((sp_int64)a[ 1]) * a[ 3]) * 2 - + ((sp_int64)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 0]) * a[ 5] - + ((sp_int64)a[ 1]) * a[ 4] - + ((sp_int64)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[ 6] - + ((sp_int64)a[ 1]) * a[ 5] - + ((sp_int64)a[ 2]) * a[ 4]) * 2 - + ((sp_int64)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 0]) * a[ 7] - + ((sp_int64)a[ 1]) * a[ 6] - + ((sp_int64)a[ 2]) * a[ 5] - + ((sp_int64)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[ 8] - + ((sp_int64)a[ 1]) * a[ 7] - + ((sp_int64)a[ 2]) * a[ 6] - + ((sp_int64)a[ 3]) * a[ 5]) * 2 - + ((sp_int64)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 0]) * a[ 9] - + ((sp_int64)a[ 1]) * a[ 8] - + ((sp_int64)a[ 2]) * a[ 7] - + ((sp_int64)a[ 3]) * a[ 6] - + ((sp_int64)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[10] - + ((sp_int64)a[ 1]) * a[ 9] - + ((sp_int64)a[ 2]) * a[ 8] - + ((sp_int64)a[ 3]) * a[ 7] - + ((sp_int64)a[ 4]) * a[ 6]) * 2 - + ((sp_int64)a[ 5]) * a[ 5]; - t[ 9] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 0]) * a[11] - + ((sp_int64)a[ 1]) * a[10] - + ((sp_int64)a[ 2]) * a[ 9] - + ((sp_int64)a[ 3]) * a[ 8] - + ((sp_int64)a[ 4]) * a[ 7] - + ((sp_int64)a[ 5]) * a[ 6]) * 2; - t[10] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[12] - + ((sp_int64)a[ 1]) * a[11] - + ((sp_int64)a[ 2]) * a[10] - + ((sp_int64)a[ 3]) * a[ 9] - + ((sp_int64)a[ 4]) * a[ 8] - + ((sp_int64)a[ 5]) * a[ 7]) * 2 - + ((sp_int64)a[ 6]) * a[ 6]; - t[11] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 0]) * a[13] - + ((sp_int64)a[ 1]) * a[12] - + ((sp_int64)a[ 2]) * a[11] - + ((sp_int64)a[ 3]) * a[10] - + ((sp_int64)a[ 4]) * a[ 9] - + ((sp_int64)a[ 5]) * a[ 8] - + ((sp_int64)a[ 6]) * a[ 7]) * 2; - t[12] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 0]) * a[14] - + ((sp_int64)a[ 1]) * a[13] - + ((sp_int64)a[ 2]) * a[12] - + ((sp_int64)a[ 3]) * a[11] - + ((sp_int64)a[ 4]) * a[10] - + ((sp_int64)a[ 5]) * a[ 9] - + ((sp_int64)a[ 6]) * a[ 8]) * 2 - + ((sp_int64)a[ 7]) * a[ 7]; - t[13] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 1]) * a[14] - + ((sp_int64)a[ 2]) * a[13] - + ((sp_int64)a[ 3]) * a[12] - + ((sp_int64)a[ 4]) * a[11] - + ((sp_int64)a[ 5]) * a[10] - + ((sp_int64)a[ 6]) * a[ 9] - + ((sp_int64)a[ 7]) * a[ 8]) * 2; - t[14] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 2]) * a[14] - + ((sp_int64)a[ 3]) * a[13] - + ((sp_int64)a[ 4]) * a[12] - + ((sp_int64)a[ 5]) * a[11] - + ((sp_int64)a[ 6]) * a[10] - + ((sp_int64)a[ 7]) * a[ 9]) * 2 - + ((sp_int64)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 3]) * a[14] - + ((sp_int64)a[ 4]) * a[13] - + ((sp_int64)a[ 5]) * a[12] - + ((sp_int64)a[ 6]) * a[11] - + ((sp_int64)a[ 7]) * a[10] - + ((sp_int64)a[ 8]) * a[ 9]) * 2; - r[16] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 4]) * a[14] - + ((sp_int64)a[ 5]) * a[13] - + ((sp_int64)a[ 6]) * a[12] - + ((sp_int64)a[ 7]) * a[11] - + ((sp_int64)a[ 8]) * a[10]) * 2 - + ((sp_int64)a[ 9]) * a[ 9]; - r[17] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 5]) * a[14] - + ((sp_int64)a[ 6]) * a[13] - + ((sp_int64)a[ 7]) * a[12] - + ((sp_int64)a[ 8]) * a[11] - + ((sp_int64)a[ 9]) * a[10]) * 2; - r[18] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 6]) * a[14] - + ((sp_int64)a[ 7]) * a[13] - + ((sp_int64)a[ 8]) * a[12] - + ((sp_int64)a[ 9]) * a[11]) * 2 - + ((sp_int64)a[10]) * a[10]; - r[19] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 7]) * a[14] - + ((sp_int64)a[ 8]) * a[13] - + ((sp_int64)a[ 9]) * a[12] - + ((sp_int64)a[10]) * a[11]) * 2; - r[20] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[ 8]) * a[14] - + ((sp_int64)a[ 9]) * a[13] - + ((sp_int64)a[10]) * a[12]) * 2 - + ((sp_int64)a[11]) * a[11]; - r[21] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[ 9]) * a[14] - + ((sp_int64)a[10]) * a[13] - + ((sp_int64)a[11]) * a[12]) * 2; - r[22] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[10]) * a[14] - + ((sp_int64)a[11]) * a[13]) * 2 - + ((sp_int64)a[12]) * a[12]; - r[23] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[11]) * a[14] - + ((sp_int64)a[12]) * a[13]) * 2; - r[24] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = (((sp_int64)a[12]) * a[14]) * 2 - + ((sp_int64)a[13]) * a[13]; - r[25] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - t1 = (((sp_int64)a[13]) * a[14]) * 2; - r[26] = (sp_digit)(t0 & 0x3ffffff); t1 += t0 >> 26; - t0 = ((sp_int64)a[14]) * a[14]; - r[27] = (sp_digit)(t1 & 0x3ffffff); t0 += t1 >> 26; - r[28] = (sp_digit)(t0 & 0x3ffffff); - r[29] = (sp_digit)(t0 >> 26); - XMEMCPY(r, t, sizeof(t)); -} - -#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 i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 25); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 25); - } -#elif DIGIT_BIT > 26 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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; -} - -/* 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_384_cmp_15(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=14; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 25); - } -#else - r |= (a[14] - b[14]) & (0 - (sp_digit)1); - r |= (a[13] - b[13]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[12] - b[12]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[11] - b[11]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[10] - b[10]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 9] - b[ 9]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 8] - b[ 8]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 25); - r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 25); -#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_384_cond_sub_15(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 < 15; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - r[ 0] = a[ 0] - (b[ 0] & m); - r[ 1] = a[ 1] - (b[ 1] & m); - r[ 2] = a[ 2] - (b[ 2] & m); - r[ 3] = a[ 3] - (b[ 3] & m); - r[ 4] = a[ 4] - (b[ 4] & m); - r[ 5] = a[ 5] - (b[ 5] & m); - r[ 6] = a[ 6] - (b[ 6] & m); - r[ 7] = a[ 7] - (b[ 7] & m); - r[ 8] = a[ 8] - (b[ 8] & m); - r[ 9] = a[ 9] - (b[ 9] & m); - r[10] = a[10] - (b[10] & m); - r[11] = a[11] - (b[11] & m); - r[12] = a[12] - (b[12] & m); - r[13] = a[13] - (b[13] & m); - r[14] = a[14] - (b[14] & 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_384_mul_add_15(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 12; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x3ffffff); - t[1] += t[0] >> 26; - r[i+1] = (sp_digit)(t[1] & 0x3ffffff); - t[2] += t[1] >> 26; - r[i+2] = (sp_digit)(t[2] & 0x3ffffff); - t[3] += t[2] >> 26; - r[i+3] = (sp_digit)(t[3] & 0x3ffffff); - t[0] = t[3] >> 26; - } - t[0] += (tb * a[12]) + r[12]; - t[1] = (tb * a[13]) + r[13]; - t[2] = (tb * a[14]) + r[14]; - r[12] = (sp_digit)(t[0] & 0x3ffffff); - t[1] += t[0] >> 26; - r[13] = (sp_digit)(t[1] & 0x3ffffff); - t[2] += t[1] >> 26; - r[14] = (sp_digit)(t[2] & 0x3ffffff); - r[15] += (sp_digit)(t[2] >> 26); -#else - sp_int64 tb = b; - sp_int64 t[15]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - t[ 7] = tb * a[ 7]; - t[ 8] = tb * a[ 8]; - t[ 9] = tb * a[ 9]; - t[10] = tb * a[10]; - t[11] = tb * a[11]; - t[12] = tb * a[12]; - t[13] = tb * a[13]; - t[14] = tb * a[14]; - r[ 0] += (sp_digit) (t[ 0] & 0x3ffffff); - r[ 1] += (sp_digit)((t[ 0] >> 26) + (t[ 1] & 0x3ffffff)); - r[ 2] += (sp_digit)((t[ 1] >> 26) + (t[ 2] & 0x3ffffff)); - r[ 3] += (sp_digit)((t[ 2] >> 26) + (t[ 3] & 0x3ffffff)); - r[ 4] += (sp_digit)((t[ 3] >> 26) + (t[ 4] & 0x3ffffff)); - r[ 5] += (sp_digit)((t[ 4] >> 26) + (t[ 5] & 0x3ffffff)); - r[ 6] += (sp_digit)((t[ 5] >> 26) + (t[ 6] & 0x3ffffff)); - r[ 7] += (sp_digit)((t[ 6] >> 26) + (t[ 7] & 0x3ffffff)); - r[ 8] += (sp_digit)((t[ 7] >> 26) + (t[ 8] & 0x3ffffff)); - r[ 9] += (sp_digit)((t[ 8] >> 26) + (t[ 9] & 0x3ffffff)); - r[10] += (sp_digit)((t[ 9] >> 26) + (t[10] & 0x3ffffff)); - r[11] += (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff)); - r[12] += (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff)); - r[13] += (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff)); - r[14] += (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff)); - r[15] += (sp_digit) (t[14] >> 26); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Normalize the values in each word to 26 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_384_norm_15(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 14; i++) { - a[i+1] += a[i] >> 26; - a[i] &= 0x3ffffff; - } -#else - a[1] += a[0] >> 26; a[0] &= 0x3ffffff; - a[2] += a[1] >> 26; a[1] &= 0x3ffffff; - a[3] += a[2] >> 26; a[2] &= 0x3ffffff; - a[4] += a[3] >> 26; a[3] &= 0x3ffffff; - a[5] += a[4] >> 26; a[4] &= 0x3ffffff; - a[6] += a[5] >> 26; a[5] &= 0x3ffffff; - a[7] += a[6] >> 26; a[6] &= 0x3ffffff; - a[8] += a[7] >> 26; a[7] &= 0x3ffffff; - a[9] += a[8] >> 26; a[8] &= 0x3ffffff; - a[10] += a[9] >> 26; a[9] &= 0x3ffffff; - a[11] += a[10] >> 26; a[10] &= 0x3ffffff; - a[12] += a[11] >> 26; a[11] &= 0x3ffffff; - a[13] += a[12] >> 26; a[12] &= 0x3ffffff; - a[14] += a[13] >> 26; a[13] &= 0x3ffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Shift the result in the high 384 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_384_mont_shift_15(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_int64 n = a[14] >> 20; - n += ((sp_int64)a[15]) << 6; - - for (i = 0; i < 14; i++) { - r[i] = (sp_digit)(n & 0x3ffffff); - n >>= 26; - n += ((sp_int64)a[16 + i]) << 6; - } - r[14] = (sp_digit)n; -#else - sp_int64 n = a[14] >> 20; - n += ((sp_int64)a[15]) << 6; - r[ 0] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[16]) << 6; - r[ 1] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[17]) << 6; - r[ 2] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[18]) << 6; - r[ 3] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[19]) << 6; - r[ 4] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[20]) << 6; - r[ 5] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[21]) << 6; - r[ 6] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[22]) << 6; - r[ 7] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[23]) << 6; - r[ 8] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[24]) << 6; - r[ 9] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[25]) << 6; - r[10] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[26]) << 6; - r[11] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[27]) << 6; - r[12] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[28]) << 6; - r[13] = (sp_digit)(n & 0x3ffffff); n >>= 26; n += ((sp_int64)a[29]) << 6; - r[14] = (sp_digit)n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[15], 0, sizeof(*r) * 15U); -} - -/* 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. - */ -static void sp_384_mont_reduce_order_15(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_384_norm_15(a + 15); - - for (i=0; i<14; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff); - sp_384_mul_add_15(a+i, m, mu); - a[i+1] += a[i] >> 26; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL); - 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); - over = a[14] >> 20; - sp_384_cond_sub_15(a, a, m, ~((over - 1) >> 31)); - sp_384_norm_15(a); -} - -/* 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. - */ -static void sp_384_mont_reduce_15(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit am; - - (void)m; - (void)mp; - - for (i = 0; i < 14; i++) { - am = (sp_digit)((a[i] * 0x1) & 0x3ffffff); - a[i + 1] += (sp_digit)((am << 6) & 0x3ffffff); - a[i + 2] += am >> 20; - a[i + 3] -= (sp_digit)((am << 18) & 0x3ffffff); - a[i + 4] -= am >> 8; - a[i + 4] -= (sp_digit)((am << 24) & 0x3ffffff); - a[i + 5] -= am >> 2; - a[i + 14] += (sp_digit)((am << 20) & 0x3ffffff); - a[i + 15] += am >> 6; - - a[i + 1] += a[i] >> 26; - } - am = (sp_digit)((a[14] * 0x1) & 0xfffff); - a[14 + 1] += (sp_digit)((am << 6) & 0x3ffffff); - a[14 + 2] += am >> 20; - a[14 + 3] -= (sp_digit)((am << 18) & 0x3ffffff); - a[14 + 4] -= am >> 8; - a[14 + 4] -= (sp_digit)((am << 24) & 0x3ffffff); - a[14 + 5] -= am >> 2; - a[14 + 14] += (sp_digit)((am << 20) & 0x3ffffff); - a[14 + 15] += am >> 6; - - a[0] = (a[14] >> 20) + (sp_digit)((a[15] << 6) & 0x3ffffff); - a[1] = (a[15] >> 20) + (sp_digit)((a[16] << 6) & 0x3ffffff); - a[2] = (a[16] >> 20) + (sp_digit)((a[17] << 6) & 0x3ffffff); - a[3] = (a[17] >> 20) + (sp_digit)((a[18] << 6) & 0x3ffffff); - a[4] = (a[18] >> 20) + (sp_digit)((a[19] << 6) & 0x3ffffff); - a[5] = (a[19] >> 20) + (sp_digit)((a[20] << 6) & 0x3ffffff); - a[6] = (a[20] >> 20) + (sp_digit)((a[21] << 6) & 0x3ffffff); - a[7] = (a[21] >> 20) + (sp_digit)((a[22] << 6) & 0x3ffffff); - a[8] = (a[22] >> 20) + (sp_digit)((a[23] << 6) & 0x3ffffff); - a[9] = (a[23] >> 20) + (sp_digit)((a[24] << 6) & 0x3ffffff); - a[10] = (a[24] >> 20) + (sp_digit)((a[25] << 6) & 0x3ffffff); - a[11] = (a[25] >> 20) + (sp_digit)((a[26] << 6) & 0x3ffffff); - a[12] = (a[26] >> 20) + (sp_digit)((a[27] << 6) & 0x3ffffff); - a[13] = (a[27] >> 20) + (sp_digit)((a[28] << 6) & 0x3ffffff); - a[14] = (a[14 + 14] >> 20) + (a[29] << 6); - - a[1] += a[0] >> 26; a[0] &= 0x3ffffff; - a[2] += a[1] >> 26; a[1] &= 0x3ffffff; - a[3] += a[2] >> 26; a[2] &= 0x3ffffff; - a[4] += a[3] >> 26; a[3] &= 0x3ffffff; - a[5] += a[4] >> 26; a[4] &= 0x3ffffff; - a[6] += a[5] >> 26; a[5] &= 0x3ffffff; - a[7] += a[6] >> 26; a[6] &= 0x3ffffff; - a[8] += a[7] >> 26; a[7] &= 0x3ffffff; - a[9] += a[8] >> 26; a[8] &= 0x3ffffff; - a[10] += a[9] >> 26; a[9] &= 0x3ffffff; - a[11] += a[10] >> 26; a[10] &= 0x3ffffff; - a[12] += a[11] >> 26; a[11] &= 0x3ffffff; - a[13] += a[12] >> 26; a[12] &= 0x3ffffff; - a[14] += a[13] >> 26; a[13] &= 0x3ffffff; - - /* Get the bit over, if any. */ - am = a[14] >> 20; - /* Create mask. */ - am = 0 - am; - - a[0] -= (sp_digit)(0x03ffffff & am); - a[1] -= (sp_digit)(0x0000003f & am); - /* p384_mod[2] is zero */ - a[3] -= (sp_digit)(0x03fc0000 & am); - a[4] -= (sp_digit)(0x02ffffff & am); - a[5] -= (sp_digit)(0x03ffffff & am); - a[6] -= (sp_digit)(0x03ffffff & am); - a[7] -= (sp_digit)(0x03ffffff & am); - a[8] -= (sp_digit)(0x03ffffff & am); - a[9] -= (sp_digit)(0x03ffffff & am); - a[10] -= (sp_digit)(0x03ffffff & am); - a[11] -= (sp_digit)(0x03ffffff & am); - a[12] -= (sp_digit)(0x03ffffff & am); - a[13] -= (sp_digit)(0x03ffffff & am); - a[14] -= (sp_digit)(0x000fffff & am); - - a[1] += a[0] >> 26; a[0] &= 0x3ffffff; - a[2] += a[1] >> 26; a[1] &= 0x3ffffff; - a[3] += a[2] >> 26; a[2] &= 0x3ffffff; - a[4] += a[3] >> 26; a[3] &= 0x3ffffff; - a[5] += a[4] >> 26; a[4] &= 0x3ffffff; - a[6] += a[5] >> 26; a[5] &= 0x3ffffff; - a[7] += a[6] >> 26; a[6] &= 0x3ffffff; - a[8] += a[7] >> 26; a[7] &= 0x3ffffff; - a[9] += a[8] >> 26; a[8] &= 0x3ffffff; - a[10] += a[9] >> 26; a[9] &= 0x3ffffff; - a[11] += a[10] >> 26; a[10] &= 0x3ffffff; - a[12] += a[11] >> 26; a[11] &= 0x3ffffff; - a[13] += a[12] >> 26; a[12] &= 0x3ffffff; - a[14] += a[13] >> 26; a[13] &= 0x3ffffff; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) -/* Square the Montgomery form number a number of times. (r = a ^ n mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * n Number of times to square. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_384_mont_sqr_n_15(sp_digit* r, - const sp_digit* a, int n, const sp_digit* m, sp_digit mp) -{ - sp_384_mont_sqr_15(r, a, m, mp); - for (; n > 1; n--) { - sp_384_mont_sqr_15(r, r, m, mp); - } -} - -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ -#ifdef WOLFSSL_SP_SMALL -/* Mod-2 for the P384 curve. */ -static const word32 p384_mod_minus_2[12] = { - 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU, - 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU -}; -#endif /* !WOLFSSL_SP_SMALL */ - -/* Invert the number, in Montgomery form, modulo the modulus (prime) of the - * P384 curve. (r = 1 / a mod m) - * - * r Inverse result. - * a Number to invert. - * td Temporary data. - */ -static void sp_384_mont_inv_15(sp_digit* r, const sp_digit* a, sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 15); - for (i=382; i>=0; i--) { - sp_384_mont_sqr_15(t, t, p384_mod, p384_mp_mod); - if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) - sp_384_mont_mul_15(t, t, a, p384_mod, p384_mp_mod); - } - XMEMCPY(r, t, sizeof(sp_digit) * 15); -#else - sp_digit* t1 = td; - sp_digit* t2 = td + 2 * 15; - sp_digit* t3 = td + 4 * 15; - sp_digit* t4 = td + 6 * 15; - sp_digit* t5 = td + 8 * 15; - - /* 0x2 */ - sp_384_mont_sqr_15(t1, a, p384_mod, p384_mp_mod); - /* 0x3 */ - sp_384_mont_mul_15(t5, t1, a, p384_mod, p384_mp_mod); - /* 0xc */ - sp_384_mont_sqr_n_15(t1, t5, 2, p384_mod, p384_mp_mod); - /* 0xf */ - sp_384_mont_mul_15(t2, t5, t1, p384_mod, p384_mp_mod); - /* 0x1e */ - sp_384_mont_sqr_15(t1, t2, p384_mod, p384_mp_mod); - /* 0x1f */ - sp_384_mont_mul_15(t4, t1, a, p384_mod, p384_mp_mod); - /* 0x3e0 */ - sp_384_mont_sqr_n_15(t1, t4, 5, p384_mod, p384_mp_mod); - /* 0x3ff */ - sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod); - /* 0x7fe0 */ - sp_384_mont_sqr_n_15(t1, t2, 5, p384_mod, p384_mp_mod); - /* 0x7fff */ - sp_384_mont_mul_15(t4, t4, t1, p384_mod, p384_mp_mod); - /* 0x3fff8000 */ - sp_384_mont_sqr_n_15(t1, t4, 15, p384_mod, p384_mp_mod); - /* 0x3fffffff */ - sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod); - /* 0xfffffffc */ - sp_384_mont_sqr_n_15(t3, t2, 2, p384_mod, p384_mp_mod); - /* 0xfffffffd */ - sp_384_mont_mul_15(r, t3, a, p384_mod, p384_mp_mod); - /* 0xffffffff */ - sp_384_mont_mul_15(t3, t5, t3, p384_mod, p384_mp_mod); - /* 0xfffffffc0000000 */ - sp_384_mont_sqr_n_15(t1, t2, 30, p384_mod, p384_mp_mod); - /* 0xfffffffffffffff */ - sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod); - /* 0xfffffffffffffff000000000000000 */ - sp_384_mont_sqr_n_15(t1, t2, 60, p384_mod, p384_mp_mod); - /* 0xffffffffffffffffffffffffffffff */ - sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod); - /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ - sp_384_mont_sqr_n_15(t1, t2, 120, p384_mod, p384_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ - sp_384_mont_sqr_n_15(t1, t2, 15, p384_mod, p384_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ - sp_384_mont_sqr_n_15(t1, t2, 33, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ - sp_384_mont_mul_15(t2, t3, t1, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ - sp_384_mont_sqr_n_15(t1, t2, 96, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ - sp_384_mont_mul_15(r, r, t1, p384_mod, p384_mp_mod); - -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_15(sp_point_384* r, const sp_point_384* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*15; - sp_int32 n; - - sp_384_mont_inv_15(t1, p->z, t + 2*15); - - sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod); - - /* x /= z^2 */ - sp_384_mont_mul_15(r->x, p->x, t2, p384_mod, p384_mp_mod); - XMEMSET(r->x + 15, 0, sizeof(sp_digit) * 15U); - sp_384_mont_reduce_15(r->x, p384_mod, p384_mp_mod); - /* Reduce x to less than modulus */ - n = sp_384_cmp_15(r->x, p384_mod); - sp_384_cond_sub_15(r->x, r->x, p384_mod, (sp_digit)~(n >> 25)); - sp_384_norm_15(r->x); - - /* y /= z^3 */ - sp_384_mont_mul_15(r->y, p->y, t1, p384_mod, p384_mp_mod); - XMEMSET(r->y + 15, 0, sizeof(sp_digit) * 15U); - sp_384_mont_reduce_15(r->y, p384_mod, p384_mp_mod); - /* Reduce y to less than modulus */ - n = sp_384_cmp_15(r->y, p384_mod); - sp_384_cond_sub_15(r->y, r->y, p384_mod, (sp_digit)~(n >> 25)); - sp_384_norm_15(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_add_15(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - sp_digit over; - (void)sp_384_add_15(r, a, b); - sp_384_norm_15(r); - over = r[14] >> 20; - sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31)); - sp_384_norm_15(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_dbl_15(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_384_add_15(r, a, a); - sp_384_norm_15(r); - over = r[14] >> 20; - sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31)); - sp_384_norm_15(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_tpl_15(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_384_add_15(r, a, a); - sp_384_norm_15(r); - over = r[14] >> 20; - sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31)); - sp_384_norm_15(r); - (void)sp_384_add_15(r, r, a); - sp_384_norm_15(r); - over = r[14] >> 20; - sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31)); - sp_384_norm_15(r); -} - -#ifdef 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_384_cond_add_15(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 15; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_384_cond_add_15(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - r[ 0] = a[ 0] + (b[ 0] & m); - r[ 1] = a[ 1] + (b[ 1] & m); - r[ 2] = a[ 2] + (b[ 2] & m); - r[ 3] = a[ 3] + (b[ 3] & m); - r[ 4] = a[ 4] + (b[ 4] & m); - r[ 5] = a[ 5] + (b[ 5] & m); - r[ 6] = a[ 6] + (b[ 6] & m); - r[ 7] = a[ 7] + (b[ 7] & m); - r[ 8] = a[ 8] + (b[ 8] & m); - r[ 9] = a[ 9] + (b[ 9] & m); - r[10] = a[10] + (b[10] & m); - r[11] = a[11] + (b[11] & m); - r[12] = a[12] + (b[12] & m); - r[13] = a[13] + (b[13] & m); - r[14] = a[14] + (b[14] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_sub_15(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_384_sub_15(r, a, b); - sp_384_norm_15(r); - sp_384_cond_add_15(r, r, m, r[14] >> 20); - sp_384_norm_15(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -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) + (sp_digit)((a[i + 1] << 25) & 0x3ffffff); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 25) & 0x3ffffff); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 25) & 0x3ffffff); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 25) & 0x3ffffff); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 25) & 0x3ffffff); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 25) & 0x3ffffff); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 25) & 0x3ffffff); - r[6] = (a[6] >> 1) + (sp_digit)((a[7] << 25) & 0x3ffffff); - r[7] = (a[7] >> 1) + (sp_digit)((a[8] << 25) & 0x3ffffff); - r[8] = (a[8] >> 1) + (sp_digit)((a[9] << 25) & 0x3ffffff); - r[9] = (a[9] >> 1) + (sp_digit)((a[10] << 25) & 0x3ffffff); - r[10] = (a[10] >> 1) + (sp_digit)((a[11] << 25) & 0x3ffffff); - r[11] = (a[11] >> 1) + (sp_digit)((a[12] << 25) & 0x3ffffff); - r[12] = (a[12] >> 1) + (sp_digit)((a[13] << 25) & 0x3ffffff); - r[13] = (a[13] >> 1) + (sp_digit)((a[14] << 25) & 0x3ffffff); -#endif - r[14] = a[14] >> 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_384_mont_div2_15(sp_digit* r, const sp_digit* a, - const sp_digit* m) -{ - sp_384_cond_add_15(r, a, m, 0 - (a[0] & 1)); - sp_384_norm_15(r); - sp_384_rshift1_15(r, r); -} - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static void sp_384_proj_point_dbl_15(sp_point_384* r, const sp_point_384* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*15; - 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_384_mont_sqr_15(t1, p->z, p384_mod, p384_mp_mod); - /* Z = Y * Z */ - sp_384_mont_mul_15(z, p->y, p->z, p384_mod, p384_mp_mod); - /* Z = 2Z */ - sp_384_mont_dbl_15(z, z, p384_mod); - /* T2 = X - T1 */ - sp_384_mont_sub_15(t2, p->x, t1, p384_mod); - /* T1 = X + T1 */ - sp_384_mont_add_15(t1, p->x, t1, p384_mod); - /* T2 = T1 * T2 */ - sp_384_mont_mul_15(t2, t1, t2, p384_mod, p384_mp_mod); - /* T1 = 3T2 */ - sp_384_mont_tpl_15(t1, t2, p384_mod); - /* Y = 2Y */ - sp_384_mont_dbl_15(y, p->y, p384_mod); - /* Y = Y * Y */ - sp_384_mont_sqr_15(y, y, p384_mod, p384_mp_mod); - /* T2 = Y * Y */ - sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod); - /* T2 = T2/2 */ - sp_384_mont_div2_15(t2, t2, p384_mod); - /* Y = Y * X */ - sp_384_mont_mul_15(y, y, p->x, p384_mod, p384_mp_mod); - /* X = T1 * T1 */ - sp_384_mont_sqr_15(x, t1, p384_mod, p384_mp_mod); - /* X = X - Y */ - sp_384_mont_sub_15(x, x, y, p384_mod); - /* X = X - Y */ - sp_384_mont_sub_15(x, x, y, p384_mod); - /* Y = Y - X */ - sp_384_mont_sub_15(y, y, x, p384_mod); - /* Y = Y * T1 */ - sp_384_mont_mul_15(y, y, t1, p384_mod, p384_mp_mod); - /* Y = Y - T2 */ - sp_384_mont_sub_15(y, y, t2, p384_mod); -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_384_proj_point_dbl_15_ctx { - int state; - sp_digit* t1; - sp_digit* t2; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_384_proj_point_dbl_15_ctx; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static int sp_384_proj_point_dbl_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_point_384* p, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_384_proj_point_dbl_15_ctx* ctx = (sp_384_proj_point_dbl_15_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - ctx->t1 = t; - ctx->t2 = t + 2*15; - 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_384_mont_sqr_15(ctx->t1, p->z, p384_mod, p384_mp_mod); - ctx->state = 2; - break; - case 2: - /* Z = Y * Z */ - sp_384_mont_mul_15(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); - ctx->state = 3; - break; - case 3: - /* Z = 2Z */ - sp_384_mont_dbl_15(ctx->z, ctx->z, p384_mod); - ctx->state = 4; - break; - case 4: - /* T2 = X - T1 */ - sp_384_mont_sub_15(ctx->t2, p->x, ctx->t1, p384_mod); - ctx->state = 5; - break; - case 5: - /* T1 = X + T1 */ - sp_384_mont_add_15(ctx->t1, p->x, ctx->t1, p384_mod); - ctx->state = 6; - break; - case 6: - /* T2 = T1 * T2 */ - sp_384_mont_mul_15(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 7; - break; - case 7: - /* T1 = 3T2 */ - sp_384_mont_tpl_15(ctx->t1, ctx->t2, p384_mod); - ctx->state = 8; - break; - case 8: - /* Y = 2Y */ - sp_384_mont_dbl_15(ctx->y, p->y, p384_mod); - ctx->state = 9; - break; - case 9: - /* Y = Y * Y */ - sp_384_mont_sqr_15(ctx->y, ctx->y, p384_mod, p384_mp_mod); - ctx->state = 10; - break; - case 10: - /* T2 = Y * Y */ - sp_384_mont_sqr_15(ctx->t2, ctx->y, p384_mod, p384_mp_mod); - ctx->state = 11; - break; - case 11: - /* T2 = T2/2 */ - sp_384_mont_div2_15(ctx->t2, ctx->t2, p384_mod); - ctx->state = 12; - break; - case 12: - /* Y = Y * X */ - sp_384_mont_mul_15(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); - ctx->state = 13; - break; - case 13: - /* X = T1 * T1 */ - sp_384_mont_sqr_15(ctx->x, ctx->t1, p384_mod, p384_mp_mod); - ctx->state = 14; - break; - case 14: - /* X = X - Y */ - sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod); - ctx->state = 15; - break; - case 15: - /* X = X - Y */ - sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod); - ctx->state = 16; - break; - case 16: - /* Y = Y - X */ - sp_384_mont_sub_15(ctx->y, ctx->y, ctx->x, p384_mod); - ctx->state = 17; - break; - case 17: - /* Y = Y * T1 */ - sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); - ctx->state = 18; - break; - case 18: - /* Y = Y - T2 */ - sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t2, p384_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 */ -/* 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_384_cmp_equal_15(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])) == 0; -} - -/* 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_384_iszero_15(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]) == 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. - */ -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) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*15; - sp_digit* t2 = t + 4*15; - sp_digit* t3 = t + 6*15; - sp_digit* t4 = t + 8*15; - sp_digit* t5 = t + 10*15; - - /* U1 = X1*Z2^2 */ - sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t1, t1, p->x, p384_mod, p384_mp_mod); - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_15(t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t4, t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_384_mont_mul_15(t3, t3, p->y, p384_mod, p384_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_384_cmp_equal_15(t2, t1) & - sp_384_cmp_equal_15(t4, t3)) { - sp_384_proj_point_dbl_15(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* H = U2 - U1 */ - sp_384_mont_sub_15(t2, t2, t1, p384_mod); - /* R = S2 - S1 */ - sp_384_mont_sub_15(t4, t4, t3, p384_mod); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(y, t1, t5, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod); - /* Z3 = H*Z1*Z2 */ - sp_384_mont_mul_15(z, p->z, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(z, z, q->z, p384_mod, p384_mp_mod); - sp_384_mont_sqr_15(x, t4, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(x, x, t5, p384_mod); - sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod); - sp_384_mont_dbl_15(t3, y, p384_mod); - sp_384_mont_sub_15(x, x, t3, p384_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_384_mont_sub_15(y, y, x, p384_mod); - sp_384_mont_mul_15(y, y, t4, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(y, y, t5, p384_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 15; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 15; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 15; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_384_proj_point_add_15_ctx { - int state; - sp_384_proj_point_dbl_15_ctx dbl_ctx; - const sp_point_384* ap[2]; - sp_point_384* rp[2]; - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; - sp_digit* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_384_proj_point_add_15_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -static int sp_384_proj_point_add_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_point_384* p, const sp_point_384* q, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_384_proj_point_add_15_ctx* ctx = (sp_384_proj_point_add_15_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_384_proj_point_add_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_384* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*15; - ctx->t2 = t + 4*15; - ctx->t3 = t + 6*15; - ctx->t4 = t + 8*15; - ctx->t5 = t + 10*15; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_384_mont_sqr_15(ctx->t1, q->z, p384_mod, p384_mp_mod); - ctx->state = 2; - break; - case 2: - sp_384_mont_mul_15(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); - ctx->state = 3; - break; - case 3: - sp_384_mont_mul_15(ctx->t1, ctx->t1, p->x, p384_mod, p384_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_15(ctx->t2, p->z, p384_mod, p384_mp_mod); - ctx->state = 5; - break; - case 5: - sp_384_mont_mul_15(ctx->t4, ctx->t2, p->z, p384_mod, p384_mp_mod); - ctx->state = 6; - break; - case 6: - sp_384_mont_mul_15(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_384_mont_mul_15(ctx->t3, ctx->t3, p->y, p384_mod, p384_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_15(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_384_cmp_equal_15(ctx->t2, ctx->t1) & - sp_384_cmp_equal_15(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_384_proj_point_dbl_15(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_384_mont_sub_15(ctx->t2, ctx->t2, ctx->t1, p384_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_384_mont_sub_15(ctx->t4, ctx->t4, ctx->t3, p384_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_384_mont_sqr_15(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 13; - break; - case 13: - sp_384_mont_mul_15(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); - ctx->state = 14; - break; - case 14: - sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_384_mont_mul_15(ctx->z, p->z, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 16; - break; - case 16: - sp_384_mont_mul_15(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); - ctx->state = 17; - break; - case 17: - sp_384_mont_sqr_15(ctx->x, ctx->t4, p384_mod, p384_mp_mod); - ctx->state = 18; - break; - case 18: - sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t5, p384_mod); - ctx->state = 19; - break; - case 19: - sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); - ctx->state = 20; - break; - case 20: - sp_384_mont_dbl_15(ctx->t3, ctx->y, p384_mod); - sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t3, p384_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_384_mont_sub_15(ctx->y, ctx->y, ctx->x, p384_mod); - ctx->state = 22; - break; - case 22: - sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); - ctx->state = 23; - break; - case 23: - sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t5, p384_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 15; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 15; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 15; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -/* Multiply a number by Montgomery 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) -{ - SP_DECL_VAR(int64_t, t, 2 * 12); - int64_t* a32 = NULL; - int64_t o; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(int64_t, t, 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - a32 = t + 12; - - a32[0] = a[0]; - a32[0] |= (int64_t)a[1] << 26U; - a32[0] &= 0xffffffffL; - a32[1] = (a[1] >> 6); - a32[1] |= (int64_t)a[2] << 20U; - a32[1] &= 0xffffffffL; - a32[2] = (a[2] >> 12); - a32[2] |= (int64_t)a[3] << 14U; - a32[2] &= 0xffffffffL; - a32[3] = (a[3] >> 18); - a32[3] |= (int64_t)a[4] << 8U; - a32[3] &= 0xffffffffL; - a32[4] = (a[4] >> 24); - a32[4] |= (int64_t)a[5] << 2U; - a32[4] |= (int64_t)a[6] << 28U; - a32[4] &= 0xffffffffL; - a32[5] = (a[6] >> 4); - a32[5] |= (int64_t)a[7] << 22U; - a32[5] &= 0xffffffffL; - a32[6] = (a[7] >> 10); - a32[6] |= (int64_t)a[8] << 16U; - a32[6] &= 0xffffffffL; - a32[7] = (a[8] >> 16); - a32[7] |= (int64_t)a[9] << 10U; - a32[7] &= 0xffffffffL; - a32[8] = (a[9] >> 22); - a32[8] |= (int64_t)a[10] << 4U; - a32[8] |= (int64_t)a[11] << 30U; - a32[8] &= 0xffffffffL; - a32[9] = (a[11] >> 2); - a32[9] |= (int64_t)a[12] << 24U; - a32[9] &= 0xffffffffL; - a32[10] = (a[12] >> 8); - a32[10] |= (int64_t)a[13] << 18U; - a32[10] &= 0xffffffffL; - a32[11] = (a[13] >> 14); - a32[11] |= (int64_t)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); - } - - SP_FREE_VAR(t, NULL, DYNAMIC_TYPE_ECC); - - 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. - * 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_15(sp_point_384* r, const sp_point_384* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_384, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 15 * 6); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_384, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 15 * 6, heap, DYNAMIC_TYPE_ECC); - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_384) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod); - } - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); - - if (err == MP_OKAY) { - i = 14; - c = 20; - n = k[i--] << (26 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 26; - } - - y = (n >> 25) & 1; - n <<= 1; - - sp_384_proj_point_add_15(&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_384)); - sp_384_proj_point_dbl_15(&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_384)); - } - - if (map != 0) { - sp_384_map_15(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_384)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 15 * 6, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_384, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_384_ecc_mulmod_15_ctx { - int state; - union { - sp_384_proj_point_dbl_15_ctx dbl_ctx; - sp_384_proj_point_add_15_ctx add_ctx; - }; - sp_point_384 t[3]; - sp_digit tmp[2 * 15 * 6]; - sp_digit n; - int i; - int c; - int y; -} sp_384_ecc_mulmod_15_ctx; - -static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_384_ecc_mulmod_15_ctx* ctx = (sp_384_ecc_mulmod_15_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_15_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_384) * 3); - ctx->i = 14; - ctx->c = 20; - ctx->n = k[ctx->i--] << (26 - 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_384_mod_mul_norm_15(ctx->t[1].x, g->x, p384_mod); - ctx->state = 2; - break; - case 2: /* T1Y */ - err = sp_384_mod_mul_norm_15(ctx->t[1].y, g->y, p384_mod); - ctx->state = 3; - break; - case 3: /* T1Z */ - err = sp_384_mod_mul_norm_15(ctx->t[1].z, g->z, p384_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 = 26; - } - ctx->y = (ctx->n >> 25) & 1; - ctx->n <<= 1; - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 5; - break; - case 5: /* ADD */ - err = sp_384_proj_point_add_15_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_384)); - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 6; - } - break; - case 6: /* DBL */ - err = sp_384_proj_point_dbl_15_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_384)); - ctx->state = 4; - ctx->c--; - } - break; - case 7: /* MAP */ - if (map != 0) { - sp_384_map_15(r, &ctx->t[0], ctx->tmp); - } - else { - XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384)); - } - 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 */ - -#else -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_384 { - sp_digit x[15]; - sp_digit y[15]; -} sp_table_entry_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. - */ -static void sp_384_cond_copy_15(sp_digit* r, const sp_digit* a, const sp_digit m) -{ - sp_digit t[15]; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i = 0; i < 15; i++) { - t[i] = r[i] ^ a[i]; - } - for (i = 0; i < 15; 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]; - 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; -#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_384_proj_point_dbl_n_15(sp_point_384* p, int i, - sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*15; - sp_digit* b = t + 4*15; - sp_digit* t1 = t + 6*15; - sp_digit* t2 = t + 8*15; - sp_digit* x; - sp_digit* y; - sp_digit* z; - volatile int n = i - 1; - - x = p->x; - y = p->y; - z = p->z; - - /* Y = 2*Y */ - sp_384_mont_dbl_15(y, y, p384_mod); - /* 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); -#ifndef WOLFSSL_SP_SMALL - while (n > 0) -#else - while (n >= 0) -#endif - { - /* 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); - sp_384_mont_tpl_15(a, t1, p384_mod); - /* B = X*Y^2 */ - sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod); - /* X = A^2 - 2B */ - sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_15(t2, b, p384_mod); - sp_384_mont_sub_15(x, x, t2, p384_mod); - /* B = 2.(B - X) */ - sp_384_mont_sub_15(t2, b, x, p384_mod); - sp_384_mont_dbl_15(b, t2, p384_mod); - /* Z = Z*Y */ - sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod); - /* t1 = Y^4 */ - sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod); -#ifdef WOLFSSL_SP_SMALL - if (n != 0) -#endif - { - /* W = W*Y^4 */ - sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(y, y, t1, p384_mod); - n = n - 1; - } -#ifndef WOLFSSL_SP_SMALL - /* 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); - sp_384_mont_tpl_15(a, t1, p384_mod); - /* B = X*Y^2 */ - sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod); - /* X = A^2 - 2B */ - sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_15(t2, b, p384_mod); - sp_384_mont_sub_15(x, x, t2, p384_mod); - /* B = 2.(B - X) */ - sp_384_mont_sub_15(t2, b, x, p384_mod); - sp_384_mont_dbl_15(b, t2, p384_mod); - /* Z = Z*Y */ - sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod); - /* t1 = Y^4 */ - sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(y, y, t1, p384_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_384_mont_div2_15(y, y, p384_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_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; - sp_digit* b = t + 4*15; - sp_digit* t1 = t + 6*15; - sp_digit* t2 = t + 8*15; - sp_digit* x = r[2*m].x; - sp_digit* y = r[(1<x[i]; - } - for (i=0; i<15; i++) { - y[i] = p->y[i]; - } - for (i=0; i<15; i++) { - z[i] = p->z[i]; - } - - /* Y = 2*Y */ - sp_384_mont_dbl_15(y, y, p384_mod); - /* 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); - sp_384_mont_tpl_15(a, t1, p384_mod); - /* B = X*Y^2 */ - sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod); - x = r[j].x; - /* X = A^2 - 2B */ - sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_15(t2, b, p384_mod); - sp_384_mont_sub_15(x, x, t2, p384_mod); - /* B = 2.(B - X) */ - sp_384_mont_sub_15(t2, b, x, p384_mod); - sp_384_mont_dbl_15(b, t2, p384_mod); - /* Z = Z*Y */ - sp_384_mont_mul_15(r[j].z, z, y, p384_mod, p384_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod); - if (i != n) { - /* W = W*Y^4 */ - sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(y, y, t1, p384_mod); - /* Y = Y/2 */ - sp_384_mont_div2_15(r[j].y, y, p384_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_384_proj_point_add_sub_15(sp_point_384* ra, - sp_point_384* rs, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*15; - sp_digit* t3 = t + 4*15; - sp_digit* t4 = t + 6*15; - sp_digit* t5 = t + 8*15; - sp_digit* t6 = t + 10*15; - sp_digit* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, p->z, sizeof(p->z) / 2); - ra->infinity = 0; - rs->infinity = 0; - - /* U1 = X1*Z2^2 */ - sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t1, t1, xa, p384_mod, p384_mp_mod); - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_15(t2, za, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t4, t2, za, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_384_mont_mul_15(t3, t3, ya, p384_mod, p384_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod); - /* H = U2 - U1 */ - sp_384_mont_sub_15(t2, t2, t1, p384_mod); - /* RS = S2 + S1 */ - sp_384_mont_add_15(t6, t4, t3, p384_mod); - /* R = S2 - S1 */ - sp_384_mont_sub_15(t4, t4, t3, p384_mod); - /* Z3 = H*Z1*Z2 */ - /* ZS = H*Z1*Z2 */ - sp_384_mont_mul_15(za, za, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(za, za, t2, p384_mod, p384_mp_mod); - XMEMCPY(zs, za, sizeof(p->z)/2); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - /* XS = RS^2 - H^3 - 2*U1*H^2 */ - sp_384_mont_sqr_15(xa, t4, p384_mod, p384_mp_mod); - sp_384_mont_sqr_15(xs, t6, p384_mod, p384_mp_mod); - sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(ya, t1, t5, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(xa, xa, t5, p384_mod); - sp_384_mont_sub_15(xs, xs, t5, p384_mod); - sp_384_mont_dbl_15(t1, ya, p384_mod); - sp_384_mont_sub_15(xa, xa, t1, p384_mod); - sp_384_mont_sub_15(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_15(ys, ya, xs, p384_mod); - sp_384_mont_sub_15(ya, ya, xa, p384_mod); - sp_384_mont_mul_15(ya, ya, t4, p384_mod, p384_mp_mod); - sp_384_sub_15(t6, p384_mod, t6); - sp_384_mont_mul_15(ys, ys, t6, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(ya, ya, t5, p384_mod); - sp_384_mont_sub_15(ys, ys, t5, p384_mod); -} - -/* Structure used to describe recoding of scalar multiplication. */ -typedef struct ecc_recode_384 { - /* Index into pre-computation table. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_384; - -/* The index into pre-computation table to use. */ -static const word8 recode_index_15_6[66] = { - 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, 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 word8 recode_neg_15_6[66] = { - 0, 0, 0, 0, 0, 0, 0, 0, 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, - 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_6_15(const sp_digit* k, ecc_recode_384* v) -{ - int i; - int j; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<65; i++) { - y = (word8)(int8_t)n; - if (o + 6 < 26) { - y &= 0x3f; - n >>= 6; - o += 6; - } - else if (o + 6 == 26) { - n >>= 6; - if (++j < 15) - n = k[j]; - o = 0; - } - else if (++j < 15) { - n = k[j]; - y |= (word8)((n << (26 - o)) & 0x3f); - o -= 20; - n >>= o; - } - - y = (word8)(y + carry); - v[i].i = recode_index_15_6[y]; - v[i].neg = recode_neg_15_6[y]; - carry = (y >> 6) + v[i].neg; - } -} - -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible point that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_384_get_point_33_15(sp_point_384* r, const sp_point_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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 0; - r->x[9] = 0; - r->x[10] = 0; - r->x[11] = 0; - r->x[12] = 0; - r->x[13] = 0; - r->x[14] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - r->y[9] = 0; - r->y[10] = 0; - r->y[11] = 0; - r->y[12] = 0; - r->y[13] = 0; - r->y[14] = 0; - r->z[0] = 0; - r->z[1] = 0; - r->z[2] = 0; - r->z[3] = 0; - r->z[4] = 0; - r->z[5] = 0; - r->z[6] = 0; - r->z[7] = 0; - r->z[8] = 0; - r->z[9] = 0; - r->z[10] = 0; - r->z[11] = 0; - r->z[12] = 0; - r->z[13] = 0; - r->z[14] = 0; - for (i = 1; i < 33; i++) { - mask = (sp_digit)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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - r->x[9] |= mask & table[i].x[9]; - r->x[10] |= mask & table[i].x[10]; - r->x[11] |= mask & table[i].x[11]; - r->x[12] |= mask & table[i].x[12]; - r->x[13] |= mask & table[i].x[13]; - r->x[14] |= mask & table[i].x[14]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - r->y[9] |= mask & table[i].y[9]; - r->y[10] |= mask & table[i].y[10]; - r->y[11] |= mask & table[i].y[11]; - r->y[12] |= mask & table[i].y[12]; - r->y[13] |= mask & table[i].y[13]; - r->y[14] |= mask & table[i].y[14]; - r->z[0] |= mask & table[i].z[0]; - r->z[1] |= mask & table[i].z[1]; - r->z[2] |= mask & table[i].z[2]; - r->z[3] |= mask & table[i].z[3]; - r->z[4] |= mask & table[i].z[4]; - r->z[5] |= mask & table[i].z[5]; - r->z[6] |= mask & table[i].z[6]; - r->z[7] |= mask & table[i].z[7]; - r->z[8] |= mask & table[i].z[8]; - r->z[9] |= mask & table[i].z[9]; - r->z[10] |= mask & table[i].z[10]; - r->z[11] |= mask & table[i].z[11]; - r->z[12] |= mask & table[i].z[12]; - r->z[13] |= mask & table[i].z[13]; - r->z[14] |= mask & table[i].z[14]; - } -} -#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. - * - * Window technique of 6 bits. (Add-Sub variation.) - * Calculate 0..32 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_384_ecc_mulmod_win_add_sub_15(sp_point_384* r, const sp_point_384* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_384, t, 33+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 15 * 6); - sp_point_384* rt = NULL; - sp_point_384* p = NULL; - sp_digit* negy; - int i; - ecc_recode_384 v[65]; - int err = MP_OKAY; - - /* Constant time used for cache attack resistance implementation. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_384, t, 33+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 15 * 6, heap, DYNAMIC_TYPE_ECC); - 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_15(t[1].x, g->x, p384_mod); - } - if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); - } - if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); - } - - if (err == MP_OKAY) { - t[1].infinity = 0; - /* t[2] ... t[32] */ - sp_384_proj_point_dbl_n_store_15(t, &t[ 1], 5, 1, tmp); - sp_384_proj_point_add_15(&t[ 3], &t[ 2], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[ 6], &t[ 3], tmp); - sp_384_proj_point_add_sub_15(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[10], &t[ 5], tmp); - sp_384_proj_point_add_sub_15(&t[11], &t[ 9], &t[10], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[12], &t[ 6], tmp); - sp_384_proj_point_dbl_15(&t[14], &t[ 7], tmp); - sp_384_proj_point_add_sub_15(&t[15], &t[13], &t[14], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[18], &t[ 9], tmp); - sp_384_proj_point_add_sub_15(&t[19], &t[17], &t[18], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[20], &t[10], tmp); - sp_384_proj_point_dbl_15(&t[22], &t[11], tmp); - sp_384_proj_point_add_sub_15(&t[23], &t[21], &t[22], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[24], &t[12], tmp); - sp_384_proj_point_dbl_15(&t[26], &t[13], tmp); - sp_384_proj_point_add_sub_15(&t[27], &t[25], &t[26], &t[ 1], tmp); - sp_384_proj_point_dbl_15(&t[28], &t[14], tmp); - sp_384_proj_point_dbl_15(&t[30], &t[15], tmp); - sp_384_proj_point_add_sub_15(&t[31], &t[29], &t[30], &t[ 1], tmp); - - negy = t[0].y; - - sp_384_ecc_recode_6_15(k, v); - - i = 64; - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_point_33_15(rt, t, v[i].i); - rt->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384)); - } - for (--i; i>=0; i--) { - sp_384_proj_point_dbl_n_15(rt, 6, tmp); - - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_point_33_15(p, t, v[i].i); - p->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384)); - } - sp_384_sub_15(negy, p384_mod, p->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); - } - - if (map != 0) { - sp_384_map_15(r, rt, tmp); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_384)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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_384_proj_point_add_qz1_15(sp_point_384* r, - const sp_point_384* p, const sp_point_384* q, sp_digit* t) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*15; - sp_digit* t6 = t + 4*15; - sp_digit* t1 = t + 6*15; - sp_digit* t4 = t + 8*15; - sp_digit* t5 = t + 10*15; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_15(t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t4, t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod); - - if ((~p->infinity) & (~q->infinity) & - sp_384_cmp_equal_15(p->x, t2) & - sp_384_cmp_equal_15(p->y, t4)) { - sp_384_proj_point_dbl_15(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_384_mont_sub_15(t2, t2, p->x, p384_mod); - /* R = S2 - Y1 */ - sp_384_mont_sub_15(t4, t4, p->y, p384_mod); - /* Z3 = H*Z1 */ - sp_384_mont_mul_15(z, p->z, t2, p384_mod, p384_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_384_mont_sqr_15(t1, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t3, p->x, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod); - sp_384_mont_sqr_15(t2, t4, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(t2, t2, t1, p384_mod); - sp_384_mont_dbl_15(t5, t3, p384_mod); - sp_384_mont_sub_15(x, t2, t5, p384_mod); - /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_384_mont_sub_15(t3, t3, x, p384_mod); - sp_384_mont_mul_15(t3, t3, t4, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t1, t1, p->y, p384_mod, p384_mp_mod); - sp_384_mont_sub_15(y, t3, t1, p384_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 15; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 15; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 15; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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_15(sp_point_384* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 15; - sp_digit* tmp = t + 4 * 15; - - sp_384_mont_inv_15(t1, a->z, tmp); - - sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod); - - sp_384_mont_mul_15(a->x, a->x, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(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 = 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_15(const sp_point_384* a, - sp_table_entry_384* table, sp_digit* tmp, void* heap) -{ - SP_DECL_VAR(sp_point_384, t, 3); - sp_point_384* s1 = NULL; - sp_point_384* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_384, t, 3, heap, DYNAMIC_TYPE_ECC); - 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) { - err = sp_384_mod_mul_norm_15(t->y, a->y, p384_mod); - } - if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_15(t->z, a->z, p384_mod); - } - if (err == MP_OKAY) { - t->infinity = 0; - sp_384_proj_to_affine_15(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_15(t, 48, tmp); - sp_384_proj_to_affine_15(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_15(t, s1, s2, tmp); - sp_384_proj_to_affine_15(t, tmp); - XMEMCPY(table[j].x, t->x, sizeof(table->x)); - XMEMCPY(table[j].y, t->y, sizeof(table->y)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible entry that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_384_get_entry_256_15(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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 0; - r->x[9] = 0; - r->x[10] = 0; - r->x[11] = 0; - r->x[12] = 0; - r->x[13] = 0; - r->x[14] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - r->y[9] = 0; - r->y[10] = 0; - r->y[11] = 0; - r->y[12] = 0; - r->y[13] = 0; - r->y[14] = 0; - for (i = 1; i < 256; i++) { - sp_digit gte = (sp_digit)((((sp_uint32)i - (sp_uint32)idx) >> 31) - 1); - sp_digit lte = (sp_digit)((((sp_uint32)idx - (sp_uint32)i) >> 31) - 1); - mask = gte & lte; - 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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - r->x[9] |= mask & table[i].x[9]; - r->x[10] |= mask & table[i].x[10]; - r->x[11] |= mask & table[i].x[11]; - r->x[12] |= mask & table[i].x[12]; - r->x[13] |= mask & table[i].x[13]; - r->x[14] |= mask & table[i].x[14]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - r->y[9] |= mask & table[i].y[9]; - r->y[10] |= mask & table[i].y[10]; - r->y[11] |= mask & table[i].y[11]; - r->y[12] |= mask & table[i].y[12]; - r->y[13] |= mask & table[i].y[13]; - r->y[14] |= mask & table[i].y[14]; - } -} -#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_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) -{ - SP_DECL_VAR(sp_point_384, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 15 * 6); - 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; - - - SP_ALLOC_VAR(sp_point_384, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 15 * 6, heap, DYNAMIC_TYPE_ECC); - 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 / 26] >> (x % 26)) & 1) << j); - x += 48; - } - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_entry_256_15(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 / 26] >> (x % 26)) & 1) << j); - x += 48; - } - - sp_384_proj_point_dbl_15(rt, rt, t); - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_entry_256_15(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_15(rt, rt, p, t); - } - - if (map != 0) { - sp_384_map_15(r, rt, t); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_384)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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_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. */ - word32 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 - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_384 = 0; - #endif - static wolfSSL_Mutex sp_cache_384_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_384_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * 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; - word32 least; - - if (sp_cache_384_inited == 0) { - for (i=0; ix, sp_cache_384[i].x) & - sp_384_cmp_equal_15(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_15(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_15(r, g, k, map, ct, heap); -#else - SP_DECL_VAR(sp_digit, tmp, 2 * 15 * 7); - sp_cache_384_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 15 * 7, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_384 == 0) { - wc_InitMutex(&sp_cache_384_lock); - initCacheMutex_384 = 1; - } - #endif - 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_15(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_15(r, g, k, map, ct, heap); - } - else { - err = sp_384_ecc_mulmod_stripe_15(r, g, cache->table, k, - map, ct, heap); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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_384(const mp_int* km, const ecc_point* gm, ecc_point* r, - int map, void* heap) -{ - SP_DECL_VAR(sp_point_384, point, 1); - SP_DECL_VAR(sp_digit, k, 15); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 15, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_384_from_mp(k, 15, km); - sp_384_point_from_ecc_point_15(point, gm); - - err = sp_384_ecc_mulmod_15(point, point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_15(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_384, point, 2); - SP_DECL_VAR(sp_digit, k, 15 + 15 * 2 * 6); - sp_point_384* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 15 + 15 * 2 * 6, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef 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. - * - * 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_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, - int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_384_ecc_mulmod_15(r, &p384_base, k, map, ct, heap); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_384_ecc_mulmod_base_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_384_ecc_mulmod_15_nb(sp_ctx, r, &p384_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#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 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 } }, - /* 1 */ - { { 0x1c0b528,0x01d5992,0x0e383dd,0x38a835b,0x220e378,0x106d35b, - 0x1c3afc5,0x03bfe1e,0x28459a3,0x2d91521,0x214ede2,0x0bfdc8d, - 0x2151381,0x3708a67,0x004d3aa }, - { 0x303a4fe,0x10f6b52,0x29ac230,0x2fdeed2,0x0a1bfa8,0x3a0ec14, - 0x2de7562,0x3ff662e,0x21968f4,0x031b0d4,0x3969a84,0x2000898, - 0x1c5e9dd,0x2f09685,0x002b78a } }, - /* 2 */ - { { 0x30c535b,0x191d4ca,0x2296298,0x14dc141,0x090dd69,0x05aae6b, - 0x0cd6b42,0x35da80e,0x3b7be12,0x2cf7e6d,0x1f347bd,0x3d365e1, - 0x1448913,0x32704fa,0x00222c5 }, - { 0x280dc64,0x39e5bc9,0x24175f8,0x2dd60d4,0x0120e7c,0x041d02e, - 0x0b5d8ad,0x37b9895,0x2fb5337,0x1f0e2e3,0x14f0224,0x2230b86, - 0x1bc4cf6,0x17cdb09,0x007b5c7 } }, - /* 3 */ - { { 0x2dffea5,0x28f30e7,0x29fce26,0x070df5f,0x235bbfd,0x2f78fbd, - 0x27700d9,0x23d6bc3,0x3471a53,0x0c0e03a,0x05bf9eb,0x276a2ec, - 0x20c3e2e,0x31cc691,0x00dbb93 }, - { 0x126b605,0x2e8983d,0x153737d,0x23bf5e1,0x295d497,0x35ca812, - 0x2d793ae,0x16c6893,0x3777600,0x089a520,0x1e681f8,0x3d55ee6, - 0x154ef99,0x155f592,0x00ae5f9 } }, - /* 4 */ - { { 0x26feef9,0x20315fc,0x1240244,0x250e838,0x3c31a26,0x1cf8af1, - 0x1002c32,0x3b531cd,0x1c53ef1,0x22310ba,0x3f4948e,0x22eafd9, - 0x3863202,0x3d0e2a5,0x006a502 }, - { 0x34536fe,0x04e91ad,0x30ebf5f,0x2af62a7,0x01d218b,0x1c8c9da, - 0x336bcc3,0x23060c3,0x331576e,0x1b14c5e,0x1bbcb76,0x0755e9a, - 0x3d4dcef,0x24c2cf8,0x00917c4 } }, - /* 5 */ - { { 0x349ddd0,0x09b8bb8,0x0250114,0x3e66cbf,0x29f117e,0x3005d29, - 0x36b480e,0x2119bfc,0x2761845,0x253d2f7,0x0580604,0x0bb6db4, - 0x3ca922f,0x1744677,0x008adc7 }, - { 0x3d5a7ce,0x27425ed,0x11e9a61,0x3968d10,0x3874275,0x3692d3b, - 0x03e0470,0x0763d50,0x3d97790,0x3cbaeab,0x2747170,0x18faf3a, - 0x180365e,0x2511fe7,0x0012a36 } }, - /* 6 */ - { { 0x3c52870,0x2701e93,0x296128f,0x120694e,0x1ce0b37,0x3860a36, - 0x10fa180,0x0896b55,0x2f76adb,0x22892ae,0x2e58a34,0x07b4295, - 0x2cb62d1,0x079a522,0x00f3d81 }, - { 0x061ed22,0x2375dd3,0x3c9d861,0x3e602d1,0x10bb747,0x39ae156, - 0x3f796fd,0x087a48a,0x06d680a,0x37f7f47,0x2af2c9d,0x36c55dc, - 0x10f3dc0,0x279b07a,0x00a0937 } }, - /* 7 */ - { { 0x085c629,0x319bbf8,0x089a386,0x184256f,0x15fc2a4,0x00fd2d0, - 0x13d6312,0x363d44d,0x32b7e4b,0x25f2865,0x27df8ce,0x1dce02a, - 0x24ea3b0,0x0e27b9f,0x00d8a90 }, - { 0x3b14461,0x1d371f9,0x0f781bc,0x0503271,0x0dc2cb0,0x13bc284, - 0x34b3a68,0x1ff894a,0x25d2032,0x16f79ba,0x260f961,0x07b10d5, - 0x18173b7,0x2812e2b,0x00eede5 } }, - /* 8 */ - { { 0x13b9a2d,0x132ece2,0x0c5d558,0x02c0214,0x1820c66,0x37cb50f, - 0x26d8267,0x3a00504,0x3f00109,0x33756ee,0x38172f1,0x2e4bb8c, - 0x030d985,0x3e4fcc5,0x00609d4 }, - { 0x2daf9d6,0x16681fa,0x1fb01e0,0x1b03c49,0x370e653,0x183c839, - 0x2207515,0x0ea6b58,0x1ae7aaf,0x3a96522,0x24bae14,0x1c38bd9, - 0x082497b,0x1c05db4,0x000dd03 } }, - /* 9 */ - { { 0x110521f,0x04efa21,0x0c174cc,0x2a7dc93,0x387315b,0x14f7098, - 0x1d83bb3,0x2495ed2,0x2fe0c27,0x1e2d9df,0x093c953,0x0287073, - 0x02c9951,0x336291c,0x0033e30 }, - { 0x208353f,0x3f22748,0x2b2bf0f,0x2373b50,0x10170fa,0x1b8a97d, - 0x0851ed2,0x0b25824,0x055ecb5,0x12049d9,0x3fe1adf,0x11b1385, - 0x28eab06,0x11fac21,0x00513f0 } }, - /* 10 */ - { { 0x35bdf53,0x1847d37,0x1a6dc07,0x29d62c4,0x045d331,0x313b8e5, - 0x165daf1,0x1e34562,0x3e75a58,0x16ea2fa,0x02dd302,0x3302862, - 0x3eb8bae,0x2266a48,0x00cf2a3 }, - { 0x24fd048,0x324a074,0x025df98,0x1662eec,0x3841bfb,0x26ae754, - 0x1df8cec,0x0113ae3,0x0b67fef,0x094e293,0x2323666,0x0ab087c, - 0x2f06509,0x0e142d9,0x00a919d } }, - /* 11 */ - { { 0x1d480d8,0x00ed021,0x3a7d3db,0x1e46ca1,0x28cd9f4,0x2a3ceeb, - 0x24dc754,0x0624a3c,0x0003db4,0x1520bae,0x1c56e0f,0x2fe7ace, - 0x1dc6f38,0x0c826a4,0x008b977 }, - { 0x209cfc2,0x2c16c9c,0x1b70a31,0x21416cb,0x34c49bf,0x186549e, - 0x062498d,0x146e959,0x0391fac,0x08ff944,0x2b4b834,0x013d57a, - 0x2eabffb,0x0370131,0x00c07c1 } }, - /* 12 */ - { { 0x332f048,0x0bf9336,0x16dfad2,0x2451d7b,0x35f23bf,0x299adb2, - 0x0ce0c0a,0x0170294,0x289f034,0x2b7d89e,0x395e2d6,0x1d20df7, - 0x2e64e36,0x16dae90,0x00081c9 }, - { 0x31d6ceb,0x0f80db9,0x0271eba,0x33db1ac,0x1b45bcc,0x1a11c07, - 0x347e630,0x148fd9e,0x142e712,0x3183e3e,0x1cd47ad,0x108d1c9, - 0x09cbb82,0x35e61d9,0x0083027 } }, - /* 13 */ - { { 0x215b0b8,0x0a7a98d,0x2c41b39,0x3f69536,0x0b41441,0x16da8da, - 0x15d556b,0x3c17a26,0x129167e,0x3ea0351,0x2d25a27,0x2f2d285, - 0x15b68f6,0x2931ef5,0x00210d6 }, - { 0x1351130,0x012aec9,0x37ebf38,0x26640f8,0x01d2df6,0x2130972, - 0x201efc0,0x23a457c,0x087a1c6,0x14c68a3,0x163f62a,0x36b494d, - 0x015d481,0x39c35b1,0x005dd6d } }, - /* 14 */ - { { 0x06612ce,0x11c3f61,0x199729f,0x3b36863,0x2986f3e,0x3cd2be1, - 0x04c1612,0x2be2dae,0x00846dd,0x3d7bc29,0x249e795,0x1016803, - 0x37a3714,0x2c5aa8b,0x005f491 }, - { 0x341b38d,0x01eb936,0x3caac7f,0x27863ef,0x1ef7d11,0x1110ec6, - 0x18e0761,0x26498e8,0x01a79a1,0x390d5a1,0x22226fb,0x3d2a473, - 0x0872191,0x1230f32,0x00dc772 } }, - /* 15 */ - { { 0x0b1ec9d,0x03fc6b9,0x3706d57,0x03b9fbb,0x221d23e,0x2867821, - 0x1e40f4c,0x2c9c0f3,0x3c4cd4b,0x31f5948,0x3f13aa6,0x307c1b2, - 0x04b6016,0x116b453,0x005aa72 }, - { 0x0b74de8,0x20519d1,0x134e37f,0x05d882a,0x1839e7a,0x3a2c6a8, - 0x0d14e8d,0x1d78bdd,0x251f30d,0x3a1e27e,0x081c261,0x2c9014b, - 0x165ee09,0x19e0cf1,0x00654e2 } }, - /* 16 */ - { { 0x39fbe67,0x081778b,0x0e44378,0x20dfdca,0x1c4afcb,0x20b803c, - 0x0ec06c6,0x1508f6f,0x1c3114d,0x3bca851,0x3a52463,0x07661d1, - 0x17b0aa0,0x16c5f5c,0x00fc093 }, - { 0x0d01f95,0x0ef13f5,0x2d34965,0x2a25582,0x39aa83e,0x3e38fcf, - 0x3943dca,0x385bbdd,0x210e86f,0x3dc1dd2,0x3f9ffdc,0x18b9bc6, - 0x345c96b,0x0e79621,0x008a72f } }, - /* 17 */ - { { 0x341c342,0x3793688,0x042273a,0x153a9c1,0x3dd326e,0x1d073bc, - 0x2c7d983,0x05524cd,0x00d59e6,0x347abe8,0x3d9a3ef,0x0fb624a, - 0x2c7e4cd,0x09b3171,0x0003faf }, - { 0x045f8ac,0x38bf3cc,0x1e73087,0x0c85d3c,0x314a655,0x382be69, - 0x384f28f,0x24d6cb3,0x2842cdc,0x1777f5e,0x2929c89,0x03c45ed, - 0x3cfcc4c,0x0b59322,0x0035657 } }, - /* 18 */ - { { 0x18c1bba,0x2eb005f,0x33d57ec,0x30e42c3,0x36058f9,0x1865f43, - 0x2116e3f,0x2c4a2bb,0x0684033,0x0f1375c,0x0209b98,0x2136e9b, - 0x1bc4af0,0x0b3e0c7,0x0097c7c }, - { 0x16010e8,0x398777e,0x2a172f4,0x0814a7e,0x0d97e4e,0x274dfc8, - 0x2666606,0x1b5c93b,0x1ed3d36,0x3f3304e,0x13488e0,0x02dbb88, - 0x2d53369,0x3717ce9,0x007cad1 } }, - /* 19 */ - { { 0x257a41f,0x2a6a076,0x39b6660,0x04bb000,0x1e74a04,0x3876b45, - 0x343c6b5,0x0753108,0x3f54668,0x24a13cf,0x23749e8,0x0421fc5, - 0x32f13b5,0x0f31be7,0x00070f2 }, - { 0x1186e14,0x0847697,0x0dff542,0x0dff76c,0x084748f,0x2c7d060, - 0x23aab4d,0x0b43906,0x27ba640,0x1497b59,0x02f5835,0x0a492a4, - 0x0a6892f,0x39f3e91,0x005844e } }, - /* 20 */ - { { 0x33b236f,0x02181cf,0x21dafab,0x0760788,0x019e9d4,0x249ed0a, - 0x36571e3,0x3c7dbcf,0x1337550,0x010d22a,0x285e62f,0x19ee65a, - 0x052bf71,0x1d65fd5,0x0062d43 }, - { 0x2955926,0x3fae7bc,0x0353d85,0x07db7de,0x1440a56,0x328dad6, - 0x1668ec9,0x28058e2,0x1a1a22d,0x1014afc,0x3609325,0x3effdcb, - 0x209f3bd,0x3ca3888,0x0094e50 } }, - /* 21 */ - { { 0x062e8af,0x0b96ccc,0x136990b,0x1d7a28f,0x1a85723,0x0076dec, - 0x21b00b2,0x06a88ff,0x2f0ee65,0x1fa49b7,0x39b10ad,0x10b26fa, - 0x0be7465,0x026e8bf,0x00098e3 }, - { 0x3f1d63f,0x37bacff,0x1374779,0x02882ff,0x323d0e8,0x1da3de5, - 0x12bb3b8,0x0a15a11,0x34d1f95,0x2b3dd6e,0x29ea3fa,0x39ad000, - 0x33a538f,0x390204d,0x0012bd3 } }, - /* 22 */ - { { 0x04cbba5,0x0de0344,0x1d4cc02,0x11fe8d7,0x36207e7,0x32a6da8, - 0x0239281,0x1ec40d7,0x3e89798,0x213fc66,0x0022eee,0x11daefe, - 0x3e74db8,0x28534ee,0x00aa0a4 }, - { 0x07d4543,0x250cc46,0x206620f,0x1c1e7db,0x1321538,0x31fa0b8, - 0x30f74ea,0x01aae0e,0x3a2828f,0x3e9dd22,0x026ef35,0x3c0a62b, - 0x27dbdc5,0x01c23a6,0x000f0c5 } }, - /* 23 */ - { { 0x2f029dd,0x3091337,0x21b80c5,0x21e1419,0x13dabc6,0x3847660, - 0x12b865f,0x36eb666,0x38f6274,0x0ba6006,0x098da24,0x1398c64, - 0x13d08e5,0x246a469,0x009929a }, - { 0x1285887,0x3ff5c8d,0x010237b,0x097c506,0x0bc7594,0x34b9b88, - 0x00cc35f,0x0bb964a,0x00cfbc4,0x29cd718,0x0837619,0x2b4a192, - 0x0c57bb7,0x08c69de,0x00a3627 } }, - /* 24 */ - { { 0x1361ed8,0x266d724,0x366cae7,0x1d5b18c,0x247d71b,0x2c9969a, - 0x0dd5211,0x1edd153,0x25998d7,0x0380856,0x3ab29db,0x09366de, - 0x1e53644,0x2b31ff6,0x008b0ff }, - { 0x3b5d9ef,0x217448d,0x174746d,0x18afea4,0x15b106d,0x3e66e8b, - 0x0479f85,0x13793b4,0x1231d10,0x3c39bce,0x25e8983,0x2a13210, - 0x05a7083,0x382be04,0x00a9507 } }, - /* 25 */ - { { 0x0cf381c,0x1a29b85,0x31ccf6c,0x2f708b8,0x3af9d27,0x2a29732, - 0x168d4da,0x393488d,0x2c0e338,0x3f90c7b,0x0f52ad1,0x2a0a3fa, - 0x2cd80f1,0x15e7a1a,0x00db6a0 }, - { 0x107832a,0x159cb91,0x1289288,0x17e21f9,0x073fc27,0x1584342, - 0x3802780,0x3d6c197,0x154075f,0x16366d1,0x09f712b,0x23a3ec4, - 0x29cf23a,0x3218baf,0x0039f0a } }, - /* 26 */ - { { 0x052edf5,0x2afde13,0x2e53d8f,0x3969626,0x3dcd737,0x1e46ac5, - 0x118bf0d,0x01b2652,0x156bcff,0x16d7ef6,0x1ca46d4,0x34c0cbb, - 0x3e486f6,0x1f85068,0x002cdff }, - { 0x1f47ec8,0x12cee98,0x0608667,0x18fbbe1,0x08a8821,0x31a1fe4, - 0x17c7054,0x3c89e89,0x2edf6cd,0x1b8c32c,0x3f6ea84,0x1319329, - 0x3cd3c2c,0x05f331a,0x00186fa } }, - /* 27 */ - { { 0x1fcb91e,0x0fd4d87,0x358a48a,0x04d91b4,0x083595e,0x044a1e6, - 0x15827b9,0x1d5eaf4,0x2b82187,0x08f3984,0x21bd737,0x0c54285, - 0x2f56887,0x14c2d98,0x00f4684 }, - { 0x01896f6,0x0e542d0,0x2090883,0x269dfcf,0x1e11cb8,0x239fd29, - 0x312cac4,0x19dfacb,0x369f606,0x0cc4f75,0x16579f9,0x33c22cc, - 0x0f22bfd,0x3b251ae,0x006429c } }, - /* 28 */ - { { 0x375f9a4,0x137552e,0x3570498,0x2e4a74e,0x24aef06,0x35b9307, - 0x384ca23,0x3bcd6d7,0x011b083,0x3c93187,0x392ca9f,0x129ce48, - 0x0a800ce,0x145d9cc,0x00865d6 }, - { 0x22b4a2b,0x37f9d9c,0x3e0eca3,0x3e5ec20,0x112c04b,0x2e1ae29, - 0x3ce5b51,0x0f83200,0x32d6a7e,0x10ff1d8,0x081adbe,0x265c30b, - 0x216b1c8,0x0eb4483,0x003cbcd } }, - /* 29 */ - { { 0x030ce93,0x2d331fb,0x20a2fbf,0x1f6dc9c,0x010ed6c,0x1ed5540, - 0x275bf74,0x3df0fb1,0x103333f,0x0241c96,0x1075bfc,0x30e5cf9, - 0x0f31bc7,0x32c01eb,0x00b049e }, - { 0x358839c,0x1dbabd3,0x1e4fb40,0x36a8ac1,0x2101896,0x2d0319b, - 0x2033b0a,0x192e8fd,0x2ebc8d8,0x2867ba7,0x07bf6d2,0x1b3c555, - 0x2477deb,0x198fe09,0x008e5a9 } }, - /* 30 */ - { { 0x3fbd5e1,0x18bf77d,0x2b1d69e,0x151da44,0x338ecfe,0x0768efe, - 0x1a3d56d,0x3c35211,0x10e1c86,0x2012525,0x3bc36ce,0x32b6fe4, - 0x0c8d183,0x15c93f3,0x0041fce }, - { 0x332c144,0x24e70a0,0x246e05f,0x22c21c7,0x2b17f24,0x1ba2bfd, - 0x0534e26,0x318a4f6,0x1dc3b85,0x0c741bc,0x23131b7,0x01a8cba, - 0x364e5db,0x21362cf,0x00f2951 } }, - /* 31 */ - { { 0x2ddc103,0x14ffdcd,0x206fd96,0x0de57bd,0x025f43e,0x381b73a, - 0x2301fcf,0x3bafc27,0x34130b6,0x0216bc8,0x0ff56b2,0x2c4ad4c, - 0x23c6b79,0x1267fa6,0x009b4fb }, - { 0x1d27ac2,0x13e2494,0x1389015,0x38d5b29,0x2d33167,0x3f01969, - 0x28ec1fa,0x1b26de0,0x2587f74,0x1c25668,0x0c44f83,0x23c6f8c, - 0x32fdbb1,0x045f104,0x00a7946 } }, - /* 32 */ - { { 0x23c647b,0x09addd7,0x1348c04,0x0e633c1,0x1bfcbd9,0x1cb034f, - 0x1312e31,0x11cdcc7,0x1e6ee75,0x057d27f,0x2da7ee6,0x154c3c1, - 0x3a5fb89,0x2c2ba2c,0x00cf281 }, - { 0x1b8a543,0x125cd50,0x1d30fd1,0x29cc203,0x341a625,0x14e4233, - 0x3aae076,0x289e38a,0x036ba02,0x230f405,0x3b21b8f,0x34088b9, - 0x01297a0,0x03a75fb,0x00fdc27 } }, - /* 33 */ - { { 0x07f41d6,0x1cf032f,0x1641008,0x0f86deb,0x3d97611,0x0e110fe, - 0x136ff42,0x0b914a9,0x0e241e6,0x180c340,0x1f545fc,0x0ba619d, - 0x1208c53,0x04223a4,0x00cd033 }, - { 0x397612c,0x0132665,0x34e2d1a,0x00bba99,0x1d4393e,0x065d0a8, - 0x2fa69ee,0x1643b55,0x08085f0,0x3774aad,0x08a2243,0x33bf149, - 0x03f41a5,0x1ed950e,0x0048cc6 } }, - /* 34 */ - { { 0x014ab48,0x010c3bf,0x2a744e5,0x13c99c1,0x2195b7f,0x32207fd, - 0x28a228c,0x004f4bf,0x0e2d945,0x2ec6e5a,0x0b92162,0x1aa95e5, - 0x2754a93,0x1adcd93,0x004fb76 }, - { 0x1e1ff7f,0x24ef28c,0x269113f,0x32b393c,0x2696eb5,0x0ac2780, - 0x354bf8a,0x0ffe3fd,0x09ce58e,0x0163c4f,0x1678c0b,0x15cd1bc, - 0x292b3b7,0x036ea19,0x00d5420 } }, - /* 35 */ - { { 0x1da1265,0x0c2ef5b,0x18dd9a0,0x3f3a25c,0x0f7b4f3,0x0d8196e, - 0x24931f9,0x090729a,0x1875f72,0x1ef39cb,0x2577585,0x2ed472d, - 0x136756c,0x20553a6,0x00c7161 }, - { 0x2e32189,0x283de4b,0x00b2e81,0x0989df7,0x3ef2fab,0x1c7d1a7, - 0x24f6feb,0x3e16679,0x233dfda,0x06d1233,0x3e6b5df,0x1707132, - 0x05f7b3f,0x2c00779,0x00fb8df } }, - /* 36 */ - { { 0x15bb921,0x117e9d3,0x267ec73,0x2f934ad,0x25c7e04,0x20b5e8f, - 0x2d3a802,0x2ca911f,0x3f87e47,0x39709dd,0x08488e2,0x2cec400, - 0x35b4589,0x1f0acba,0x009aad7 }, - { 0x2ac34ae,0x06f29f6,0x3326d68,0x3949abe,0x02452e4,0x0687b85, - 0x0879244,0x1eb7832,0x0d4c240,0x31d0ec1,0x3c17a2a,0x17a666f, - 0x01a06cb,0x3e0929c,0x004dca2 } }, - /* 37 */ - { { 0x127bc1a,0x0c72984,0x13be68e,0x26c5fab,0x1a3edd5,0x097d685, - 0x36b645e,0x385799e,0x394a420,0x39d8885,0x0b1e872,0x13f60ed, - 0x2ce1b79,0x3c0ecb7,0x007cab3 }, - { 0x29b3586,0x26fc572,0x0bd7711,0x0913494,0x0a55459,0x31af3c9, - 0x3633eac,0x3e2105c,0x0c2b1b6,0x0e6f4c2,0x047d38c,0x2b81bd5, - 0x1fe1c3b,0x04d7cd0,0x0054dcc } }, - /* 38 */ - { { 0x03caf0d,0x0d66365,0x313356d,0x2a4897f,0x2ce044e,0x18feb7a, - 0x1f6a7c5,0x3709e7b,0x14473e8,0x2d8cbae,0x3190dca,0x12d19f8, - 0x31e3181,0x3cc5b6e,0x002d4f4 }, - { 0x143b7ca,0x2604728,0x39508d6,0x0cb79f3,0x24ec1ac,0x1ed7fa0, - 0x3ab5fd3,0x3c76488,0x2e49390,0x03a0985,0x3580461,0x3fd2c81, - 0x308f0ab,0x38561d6,0x0011b9b } }, - /* 39 */ - { { 0x3be682c,0x0c68f4e,0x32dd4ae,0x099d3bb,0x0bc7c5d,0x311f750, - 0x2fd10a3,0x2e7864a,0x23bc14a,0x13b1f82,0x32e495e,0x1b0f746, - 0x3cd856a,0x17a4c26,0x00085ee }, - { 0x02e67fd,0x06a4223,0x2af2f38,0x2038987,0x132083a,0x1b7bb85, - 0x0d6a499,0x131e43f,0x3035e52,0x278ee3e,0x1d5b08b,0x30d8364, - 0x2719f8d,0x0b21fc9,0x003a06e } }, - /* 40 */ - { { 0x237cac0,0x27d6a1c,0x27945cd,0x2750d61,0x293f0b5,0x253db13, - 0x04a764e,0x20b4d0e,0x12bb627,0x160c13b,0x0de0601,0x236e2cf, - 0x2190f0b,0x354d76f,0x004336d }, - { 0x2ab473a,0x10d54e4,0x1046574,0x1d6f97b,0x0031c72,0x06426a9, - 0x38678c2,0x0b76cf9,0x04f9920,0x152adf8,0x2977e63,0x1234819, - 0x198be26,0x061024c,0x00d427d } }, - /* 41 */ - { { 0x39b5a31,0x2123d43,0x362a822,0x1a2eab6,0x0bb0034,0x0d5d567, - 0x3a04723,0x3a10c8c,0x08079ae,0x0d27bda,0x2eb9e1e,0x2619e82, - 0x39a55a8,0x0c6c7db,0x00c1519 }, - { 0x174251e,0x13ac2eb,0x295ed26,0x18d2afc,0x037b9b2,0x1258344, - 0x00921b0,0x1f702d8,0x1bc4da7,0x1c3794f,0x12b1869,0x366eacf, - 0x16ddf01,0x31ebdc5,0x00ad54e } }, - /* 42 */ - { { 0x1efdc58,0x1370d5e,0x0ddb8e7,0x1a53fda,0x1456bd3,0x0c825a9, - 0x0e74ccd,0x20f41c9,0x3423867,0x139073f,0x3c70d8a,0x131fc85, - 0x219a2a0,0x34bf986,0x0041199 }, - { 0x1c05dd2,0x268f80a,0x3da9d38,0x1af9f8f,0x0535f2a,0x30ad37e, - 0x2cf72d7,0x14a509b,0x1f4fe74,0x259e09d,0x1d23f51,0x0672732, - 0x08fc463,0x00b6201,0x001e05a } }, - /* 43 */ - { { 0x0d5ffe8,0x3238bb5,0x17f275c,0x25b6fa8,0x2f8bb48,0x3b8f2d2, - 0x059790c,0x18594d4,0x285a47c,0x3d301bb,0x12935d2,0x23ffc96, - 0x3d7c7f9,0x15c8cbf,0x0034c4a }, - { 0x20376a2,0x05201ba,0x1e02c4b,0x1413c45,0x02ea5e7,0x39575f0, - 0x2d76e21,0x113694c,0x011f310,0x0da3725,0x31b7799,0x1cb9195, - 0x0cfd592,0x22ee4ea,0x00adaa3 } }, - /* 44 */ - { { 0x14ed72a,0x031c49f,0x39a34bf,0x192e87d,0x0da0e92,0x130e7a9, - 0x00258bf,0x144e123,0x2d82a71,0x0294e53,0x3f06c66,0x3d4473a, - 0x037cd4a,0x3bbfb17,0x00fcebc }, - { 0x39ae8c1,0x2dd6a9d,0x206ef23,0x332b479,0x2deff59,0x09d5720, - 0x3526fd2,0x33bf7cf,0x344bb32,0x359316a,0x115bdef,0x1b8468a, - 0x3813ea9,0x11a8450,0x00ab197 } }, - /* 45 */ - { { 0x0837d7d,0x1e1617b,0x0ba443c,0x2f2e3b8,0x2ca5b6f,0x176ed7b, - 0x2924d9d,0x07294d3,0x104bb4f,0x1cfd3e8,0x398640f,0x1162dc8, - 0x007ea15,0x2aa75fd,0x004231f }, - { 0x16e6896,0x01987be,0x0f9d53e,0x1a740ec,0x1554e4c,0x31e1634, - 0x3cb07b9,0x013eb53,0x39352cb,0x1dfa549,0x0974e7f,0x17c55d2, - 0x157c85f,0x1561adb,0x002e3fa } }, - /* 46 */ - { { 0x29951a8,0x35200da,0x2ad042c,0x22109e4,0x3a8b15b,0x2eca69c, - 0x28bcf9a,0x0cfa063,0x0924099,0x12ff668,0x2fb88dc,0x028d653, - 0x2445876,0x218d01c,0x0014418 }, - { 0x1caedc7,0x295bba6,0x01c9162,0x3364744,0x28fb12e,0x24c80b6, - 0x2719673,0x35e5ba9,0x04aa4cc,0x206ab23,0x1cf185a,0x2c140d8, - 0x1095a7d,0x1b3633f,0x000c9f8 } }, - /* 47 */ - { { 0x0b2a556,0x0a051c4,0x30b29a7,0x190c9ed,0x3767ca9,0x38de66d, - 0x2d9e125,0x3aca813,0x2dc22a3,0x319e074,0x0d9450a,0x3445bac, - 0x3e08a5b,0x07f29fa,0x00eccac }, - { 0x02d6e94,0x21113f7,0x321bde6,0x0a4d7b3,0x03621f4,0x2780e8b, - 0x22d5432,0x1fc2853,0x0d57d3e,0x254f90b,0x33ed00b,0x289b025, - 0x12272bb,0x30e715f,0x0000297 } }, - /* 48 */ - { { 0x0243a7d,0x2aac42e,0x0c5b3aa,0x0fa3e96,0x06eeef9,0x2b9fdd9, - 0x26fca39,0x0134fe1,0x22661ab,0x1990416,0x03945d6,0x15e3628, - 0x3848ca3,0x0f91e46,0x00b08cd }, - { 0x16d2411,0x3717e1d,0x128c45e,0x3669d54,0x0d4a790,0x2797da8, - 0x0f09634,0x2faab0b,0x27df649,0x3b19b49,0x0467039,0x39b65a2, - 0x3816f3c,0x31ad0bd,0x0050046 } }, - /* 49 */ - { { 0x2425043,0x3858099,0x389092a,0x3f7c236,0x11ff66a,0x3c58b39, - 0x2f5a7f8,0x1663ce1,0x2a0fcf5,0x38634b7,0x1a8ca18,0x0dcace8, - 0x0e6f778,0x03ae334,0x00df0d2 }, - { 0x1bb4045,0x357875d,0x14b77ed,0x33ae5b6,0x2252a47,0x31899dd, - 0x3293582,0x040c6f6,0x14340dd,0x3614f0e,0x3d5f47f,0x326fb3d, - 0x0044a9d,0x00beeb9,0x0027c23 } }, - /* 50 */ - { { 0x32d49ce,0x34822a3,0x30a22d1,0x00858b7,0x10d91aa,0x2681fd9, - 0x1cce870,0x2404a71,0x38b8433,0x377c1c8,0x019442c,0x0a38b21, - 0x22aba50,0x0d61c81,0x002dcbd }, - { 0x0680967,0x2f0f2f9,0x172cb5f,0x1167e4b,0x12a7bc6,0x05b0da7, - 0x2c76e11,0x3a36201,0x37a3177,0x1d71419,0x0569df5,0x0dce7ad, - 0x3f40b75,0x3bd8db0,0x002d481 } }, - /* 51 */ - { { 0x2a1103e,0x34e7f7f,0x1b171a2,0x24a57e0,0x2eaae55,0x166c992, - 0x10aa18f,0x0bb836f,0x01acb59,0x0e430e7,0x1750cca,0x18be036, - 0x3cc6cdf,0x0a0f7e5,0x00da4d8 }, - { 0x2201067,0x374d187,0x1f6b0a6,0x165a7ec,0x31531f8,0x3580487, - 0x15e5521,0x0724522,0x2b04c04,0x202c86a,0x3cc1ccf,0x225b11a, - 0x1bde79d,0x0eccc50,0x00d24da } }, - /* 52 */ - { { 0x3b0a354,0x2814dd4,0x1cd8575,0x3d031b7,0x0392ff2,0x1855ee5, - 0x0e8cff5,0x203442e,0x3bd3b1b,0x141cf95,0x3fedee1,0x1d783c0, - 0x26f192a,0x0392aa3,0x0075238 }, - { 0x158ffe9,0x3889f19,0x14151f4,0x06067b1,0x13a3486,0x1e65c21, - 0x382d5ef,0x1ab0aac,0x2ffddc4,0x3179b7a,0x3c8d094,0x05101e3, - 0x237c6e5,0x3947d83,0x00f674f } }, - /* 53 */ - { { 0x363408f,0x21eb96b,0x27376fb,0x2a735d6,0x1a39c36,0x3d31863, - 0x33313fc,0x32235e0,0x082f034,0x23ef351,0x39b3528,0x1a69d84, - 0x1d9c944,0x07159ad,0x0077a71 }, - { 0x04f8d65,0x25771e5,0x2ba84a6,0x194586a,0x1e6da5f,0x118059a, - 0x14e9c32,0x1d24619,0x3f528ae,0x22f22e4,0x0f5580d,0x0747a0e, - 0x32cc85f,0x286b3a8,0x008ccf9 } }, - /* 54 */ - { { 0x196fee2,0x2c4431c,0x094528a,0x18e1d32,0x175799d,0x26bb6b7, - 0x2293482,0x23fd289,0x07b2be8,0x1a5c533,0x158d60d,0x04a4f3f, - 0x164e9f7,0x32ccca9,0x00da6b6 }, - { 0x1d821c2,0x3f76c4f,0x323df43,0x17e4374,0x0f2f278,0x121227e, - 0x2464190,0x19d2644,0x326d24c,0x3185983,0x0803c15,0x0767a33, - 0x1c4c996,0x0563eab,0x00631c6 } }, - /* 55 */ - { { 0x1752366,0x0baf83f,0x288bacf,0x0384e6f,0x2b93c34,0x3c805e7, - 0x3664850,0x29e1663,0x254ff1d,0x3852080,0x0f85c16,0x1e389d9, - 0x3191352,0x3915eaa,0x00a246e }, - { 0x3763b33,0x187ad14,0x3c0d438,0x3f11702,0x1c49f03,0x35ac7a8, - 0x3f16bca,0x27266bf,0x08b6fd4,0x0f38ce4,0x37fde8c,0x147a6ff, - 0x02c5e5c,0x28e7fc5,0x00076a7 } }, - /* 56 */ - { { 0x2338d10,0x0e77fa7,0x011b046,0x1bfd0ad,0x28ee699,0x21d73bc, - 0x0461d1a,0x342ea58,0x2d695b4,0x30415ed,0x2906e0b,0x18e494a, - 0x20f8a27,0x026b870,0x002c19f }, - { 0x2f4c43d,0x3f0fc3b,0x0aa95b8,0x2a01ea1,0x3e2e1b1,0x0d74af6, - 0x0555288,0x0cb757d,0x24d2071,0x143d2bb,0x3907f67,0x3e0ce30, - 0x131f0e9,0x3724381,0x007a874 } }, - /* 57 */ - { { 0x3c27050,0x08b5165,0x0bf884b,0x3dd679c,0x3bd0b8d,0x25ce2e6, - 0x1674057,0x1f13ed3,0x1f5cd91,0x0d1fd35,0x13ce6e3,0x2671338, - 0x10f8b90,0x34e5487,0x00942bf }, - { 0x03b566d,0x23c3da9,0x37de502,0x1a486ff,0x1af6e86,0x1108cb3, - 0x36f856c,0x01a6a0f,0x179f915,0x1595a01,0x2cfecb8,0x082568b, - 0x1ba16d1,0x1abb6c0,0x00cf7f0 } }, - /* 58 */ - { { 0x2f96c80,0x1b8f123,0x209c0f5,0x2ccf76d,0x1d521f2,0x3705143, - 0x2941027,0x07f88af,0x07102a9,0x38b4868,0x1efa37d,0x1bdd3e8, - 0x028a12e,0x02e055b,0x009a9a9 }, - { 0x1c7dfcb,0x3aa7aa7,0x1d62c54,0x3f0b0b0,0x3c74e66,0x274f819, - 0x23f9674,0x0e2b67c,0x24654dd,0x0c71f0e,0x1946cee,0x0016211, - 0x0045dc7,0x0da1173,0x0089856 } }, - /* 59 */ - { { 0x0e73946,0x29f353f,0x056329d,0x2d48c5a,0x28f697d,0x2ea4bb1, - 0x235e9cc,0x34faa38,0x15f9f91,0x3557519,0x2a50a6c,0x1a27c8e, - 0x2a1a0f3,0x3098879,0x00dcf21 }, - { 0x1b818bf,0x2f20b98,0x2243cff,0x25b691e,0x3c74a2f,0x2f06833, - 0x0e980a8,0x32db48d,0x2b57929,0x33cd7f5,0x2fe17d6,0x11a384b, - 0x2dafb81,0x2b9562c,0x00ddea6 } }, - /* 60 */ - { { 0x2787b2e,0x37a21df,0x310d294,0x07ce6a4,0x1258acc,0x3050997, - 0x19714aa,0x122824b,0x11c708b,0x0462d56,0x21abbf7,0x331aec3, - 0x307b927,0x3e8d5a0,0x00c0581 }, - { 0x24d4d58,0x3d628fc,0x23279e0,0x2e38338,0x2febe9b,0x346f9c0, - 0x3d6a419,0x3264e47,0x245faca,0x3669f62,0x1e50d66,0x3028232, - 0x18201ab,0x0bdc192,0x0002c34 } }, - /* 61 */ - { { 0x17bdbc2,0x1c501c5,0x1605ccd,0x31ab438,0x372fa89,0x24a8057, - 0x13da2bb,0x3f95ac7,0x3cda0a3,0x1e2b679,0x24f0673,0x03b72f4, - 0x35be616,0x2ccd849,0x0079d4d }, - { 0x33497c4,0x0c7f657,0x2fb0d3d,0x3b81064,0x38cafea,0x0e942bc, - 0x3ca7451,0x2ab9784,0x1678c85,0x3c62098,0x1eb556f,0x01b3aa2, - 0x149f3ce,0x2656f6d,0x002eef1 } }, - /* 62 */ - { { 0x0596edc,0x1f4fad4,0x03a28ed,0x18a4149,0x3aa3593,0x12db40a, - 0x12c2c2a,0x3b1a288,0x327c4fb,0x35847f5,0x384f733,0x02e3fde, - 0x1af0e8a,0x2e417c3,0x00d85a6 }, - { 0x0091cf7,0x2267d75,0x276860e,0x19cbbfc,0x04fef2b,0x030ce59, - 0x3195cb1,0x1aa3f07,0x3699362,0x2a09d74,0x0d6c840,0x1e413d0, - 0x28acdc7,0x1ff5ea1,0x0088d8b } }, - /* 63 */ - { { 0x3d98425,0x08dc8de,0x154e85f,0x24b1c2c,0x2d44639,0x19a1e8b, - 0x300ee29,0x053f72e,0x3f7c832,0x12417f6,0x1359368,0x0674a4c, - 0x1218e20,0x0e4fbd4,0x000428c }, - { 0x01e909a,0x1d88fe6,0x12da40c,0x215ef86,0x2925133,0x004241f, - 0x3e480f4,0x2d16523,0x07c3120,0x3375e86,0x21fd8f3,0x35dc0b6, - 0x0efc5c9,0x14ef8d6,0x0066e47 } }, - /* 64 */ - { { 0x2973cf4,0x34d3845,0x34f7070,0x22df93c,0x120aee0,0x3ae2b4a, - 0x1af9b95,0x177689a,0x036a6a4,0x0377828,0x23df41e,0x22d4a39, - 0x0df2aa1,0x06ca898,0x0003cc7 }, - { 0x06b1dd7,0x19dc2a8,0x35d324a,0x0467499,0x25bfa9c,0x1a1110c, - 0x01e2a19,0x1b3c1cf,0x18d131a,0x10d9815,0x2ee7945,0x0a2720c, - 0x0ddcdb0,0x2c071b6,0x00a6aef } }, - /* 65 */ - { { 0x1ab5245,0x1192d00,0x13ffba1,0x1b71236,0x09b8d0b,0x0eb49cb, - 0x1867dc9,0x371de4e,0x05eae9f,0x36faf82,0x094ea8b,0x2b9440e, - 0x022e173,0x2268e6b,0x00740fc }, - { 0x0e23b23,0x22c28ca,0x04d05e2,0x0bb84c4,0x1235272,0x0289903, - 0x267a18b,0x0df0fd1,0x32e49bb,0x2ab1d29,0x281e183,0x3dcd3c3, - 0x1c0eb79,0x2db0ff6,0x00bffe5 } }, - /* 66 */ - { { 0x2a2123f,0x0d63d71,0x1f6db1a,0x257f8a3,0x1927b2d,0x06674be, - 0x302753f,0x20b7225,0x14c1a3f,0x0429cdd,0x377affe,0x0f40a75, - 0x2d34d06,0x05fb6b9,0x0054398 }, - { 0x38b83c4,0x1e7bbda,0x1682f79,0x0527651,0x2615cb2,0x1795fab, - 0x0e4facc,0x11f763c,0x1b81130,0x2010ae2,0x13f3650,0x20d5b72, - 0x1f32f88,0x34617f4,0x00bf008 } }, - /* 67 */ - { { 0x28068db,0x0aa8913,0x1a47801,0x10695ca,0x1c72cc6,0x0fc1a47, - 0x33df2c4,0x0517cf0,0x3471d92,0x1be815c,0x397f794,0x3f03cbe, - 0x121bfae,0x172cbe0,0x00813d7 }, - { 0x383bba6,0x04f1c90,0x0b3f056,0x1c29089,0x2a924ce,0x3c85e69, - 0x1cecbe5,0x0ad8796,0x0aa79f6,0x25e38ba,0x13ad807,0x30b30ed, - 0x0fa963a,0x35c763d,0x0055518 } }, - /* 68 */ - { { 0x0623f3b,0x3ca4880,0x2bff03c,0x0457ca7,0x3095c71,0x02a9a08, - 0x1722478,0x302c10b,0x3a17458,0x001131e,0x0959ec2,0x18bdfbc, - 0x2929fca,0x2adfe32,0x0040ae2 }, - { 0x127b102,0x14ddeaa,0x1771b8c,0x283700c,0x2398a86,0x085a901, - 0x108f9dc,0x0cc0012,0x33a918d,0x26d08e9,0x20b9473,0x12c3fc7, - 0x1f69763,0x1c94b5a,0x00e29de } }, - /* 69 */ - { { 0x035af04,0x3450021,0x12da744,0x077fb06,0x25f255b,0x0db7150, - 0x17dc123,0x1a2a07c,0x2a7636a,0x3972430,0x3704ca1,0x0327add, - 0x3d65a96,0x3c79bec,0x009de8c }, - { 0x11d3d06,0x3fb8354,0x12c7c60,0x04fe7ad,0x0466e23,0x01ac245, - 0x3c0f5f2,0x2a935d0,0x3ac2191,0x090bd56,0x3febdbc,0x3f1f23f, - 0x0ed1cce,0x02079ba,0x00d4fa6 } }, - /* 70 */ - { { 0x0ab9645,0x10174ec,0x3711b5e,0x26357c7,0x2aeec7f,0x2170a9b, - 0x1423115,0x1a5122b,0x39e512c,0x18116b2,0x290db1c,0x041b13a, - 0x26563ae,0x0f56263,0x00b89f3 }, - { 0x3ed2ce4,0x01f365f,0x1b2043b,0x05f7605,0x1f9934e,0x2a068d2, - 0x38d4d50,0x201859d,0x2de5291,0x0a7985a,0x17e6711,0x01b6c1b, - 0x08091fa,0x33c6212,0x001da23 } }, - /* 71 */ - { { 0x2f2c4b5,0x311acd0,0x1e47821,0x3bd9816,0x1931513,0x1bd4334, - 0x30ae436,0x2c49dc0,0x2c943e7,0x010ed4d,0x1fca536,0x189633d, - 0x17abf00,0x39e5ad5,0x00e4e3e }, - { 0x0c8b22f,0x2ce4009,0x1054bb6,0x307f2fc,0x32eb5e2,0x19d24ab, - 0x3b18c95,0x0e55e4d,0x2e4acf5,0x1bc250c,0x1dbf3a5,0x17d6a74, - 0x087cf58,0x07f6f82,0x00f8675 } }, - /* 72 */ - { { 0x110e0b2,0x0e672e7,0x11b7157,0x1598371,0x01c0d59,0x3d60c24, - 0x096b8a1,0x0121075,0x0268859,0x219962f,0x03213f2,0x3022adc, - 0x18de488,0x3dcdeb9,0x008d2e0 }, - { 0x06cfee6,0x26f2552,0x3c579b7,0x31fa796,0x2036a26,0x362ba5e, - 0x103601c,0x012506b,0x387ff3a,0x101a41f,0x2c7eb58,0x23d2efc, - 0x10a5a07,0x2fd5fa3,0x00e3731 } }, - /* 73 */ - { { 0x1cd0abe,0x08a0af8,0x2fa272f,0x17a1fbf,0x1d4f901,0x30e0d2f, - 0x1898066,0x273b674,0x0c1b8a2,0x3272337,0x3ee82eb,0x006e7d3, - 0x2a75606,0x0af1c81,0x0037105 }, - { 0x2f32562,0x2842491,0x1bb476f,0x1305cd4,0x1daad53,0x0d8daed, - 0x164c37b,0x138030f,0x05145d5,0x300e2a3,0x32c09e7,0x0798600, - 0x3515130,0x2b9e55c,0x009764e } }, - /* 74 */ - { { 0x3d5256a,0x06c67f2,0x3a3b879,0x3c9b284,0x04007e0,0x33c1a41, - 0x3794604,0x1d6240e,0x022b6c1,0x22c62a7,0x01d4590,0x32df5f6, - 0x368f1a1,0x2a7486e,0x006e13f }, - { 0x31e6e16,0x20f18a9,0x09ed471,0x23b861d,0x15cf0ef,0x397b502, - 0x1c7f9b2,0x05f84b2,0x2cce6e1,0x3c10bba,0x13fb5a7,0x1b52058, - 0x1feb1b8,0x03b7279,0x00ea1cf } }, - /* 75 */ - { { 0x2a4cc9b,0x15cf273,0x08f36e6,0x076bf3b,0x2541796,0x10e2dbd, - 0x0bf02aa,0x3aa2201,0x03cdcd4,0x3ee252c,0x3799571,0x3e01fa4, - 0x156e8d0,0x1fd6188,0x003466a }, - { 0x2515664,0x166b355,0x2b0b51e,0x0f28f17,0x355b0f9,0x2909e76, - 0x206b026,0x3823a12,0x179c5fa,0x0972141,0x2663a1a,0x01ee36e, - 0x3fc8dcf,0x2ef3d1b,0x0049a36 } }, - /* 76 */ - { { 0x2d93106,0x3d6b311,0x3c9ce47,0x382aa25,0x265b7ad,0x0b5f92f, - 0x0f4c941,0x32aa4df,0x380d4b2,0x0e8aba6,0x260357a,0x1f38273, - 0x0d5f95e,0x199f23b,0x0029f77 }, - { 0x0a0b1c5,0x21a3d6a,0x0ad8df6,0x33d8a5e,0x1240858,0x30000a8, - 0x3ac101d,0x2a8143d,0x1d7ffe9,0x1c74a2a,0x1b962c9,0x1261359, - 0x0c8b274,0x002cf4a,0x00a8a7c } }, - /* 77 */ - { { 0x211a338,0x22a14ab,0x16e77c5,0x3c746be,0x3a78613,0x0d5731c, - 0x1767d25,0x0b799fa,0x009792a,0x09ae8dc,0x124386b,0x183d860, - 0x176747d,0x14c4445,0x00ab09b }, - { 0x0eb9dd0,0x0121066,0x032895a,0x330541c,0x1e6c17a,0x2271b92, - 0x06da454,0x054c2bf,0x20abb21,0x0ead169,0x3d7ea93,0x2359649, - 0x242c6c5,0x3194255,0x00a3ef3 } }, - /* 78 */ - { { 0x3010879,0x1083a77,0x217989d,0x174e55d,0x29d2525,0x0e544ed, - 0x1efd50e,0x30c4e73,0x05bd5d1,0x0793bf9,0x3f7af77,0x052779c, - 0x2b06bc0,0x13d0d02,0x0055a6b }, - { 0x3eaf771,0x094947a,0x0288f13,0x0a21e35,0x22ab441,0x23816bf, - 0x15832e1,0x2d8aff3,0x348cc1f,0x2bbd4a8,0x01c4792,0x34209d3, - 0x06dc72b,0x211a1df,0x00345c5 } }, - /* 79 */ - { { 0x2a65e90,0x173ac2f,0x199cde1,0x0ac905b,0x00987f7,0x3618f7b, - 0x1b578df,0x0d5e113,0x34bac6a,0x27d85ed,0x1b48e99,0x18af5eb, - 0x1a1be9e,0x3987aac,0x00877ca }, - { 0x2358610,0x3776a8e,0x2b0723a,0x344c978,0x22fc4d6,0x1615d53, - 0x3198f51,0x2d61225,0x12cb392,0x07dd061,0x355f7de,0x09e0132, - 0x0efae99,0x13b46aa,0x00e9e6c } }, - /* 80 */ - { { 0x0683186,0x36d8e66,0x0ea9867,0x0937731,0x1fb5cf4,0x13c39ef, - 0x1a7ffed,0x27dfb32,0x31c7a77,0x09f15fd,0x16b25ef,0x1dd01e7, - 0x0168090,0x240ed02,0x0090eae }, - { 0x2e1fceb,0x2ab9783,0x1a1fdf2,0x093a1b0,0x33ff1da,0x2864fb7, - 0x3587d6c,0x275aa03,0x123dc9b,0x0e95a55,0x0592030,0x2102402, - 0x1bdef7b,0x37f2e9b,0x001efa4 } }, - /* 81 */ - { { 0x0540015,0x20e3e78,0x37dcfbd,0x11b0e41,0x02c3239,0x3586449, - 0x1fb9e6a,0x0baa22c,0x00c0ca6,0x3e58491,0x2dbe00f,0x366d4b0, - 0x176439a,0x2a86b86,0x00f52ab }, - { 0x0ac32ad,0x226250b,0x0f91d0e,0x1098aa6,0x3dfb79e,0x1dbd572, - 0x052ecf2,0x0f84995,0x0d27ad2,0x036c6b0,0x1e4986f,0x2317dab, - 0x2327df6,0x0dee0b3,0x00389ac } }, - /* 82 */ - { { 0x0e60f5b,0x0622d3e,0x2ada511,0x05522a8,0x27fe670,0x206af28, - 0x333cb83,0x3f25f6c,0x19ddaf3,0x0ec579b,0x36aabc0,0x093dbac, - 0x348b44b,0x277dca9,0x00c5978 }, - { 0x1cf5279,0x32e294a,0x1a6c26f,0x3f006b6,0x37a3c6b,0x2e2eb26, - 0x2cf88d4,0x3410619,0x1899c80,0x23d3226,0x30add14,0x2810905, - 0x01a41f0,0x11e5176,0x005a02f } }, - /* 83 */ - { { 0x1c90202,0x321df30,0x3570fa5,0x103e2b1,0x3d099d4,0x05e207d, - 0x0a5b1bd,0x0075d0a,0x3db5b25,0x2d87899,0x32e4465,0x226fc13, - 0x24cb8f8,0x3821daa,0x004da3a }, - { 0x3e66861,0x03f89b8,0x386d3ef,0x14ccc62,0x35e7729,0x11ce5b7, - 0x035fbc7,0x3f4df0f,0x29c439f,0x1144568,0x32d7037,0x312f65e, - 0x06b9dbf,0x03a9589,0x0008863 } }, - /* 84 */ - { { 0x0a9e8c9,0x1a19b6e,0x091ecd9,0x2e16ee0,0x2a11963,0x116cf34, - 0x390d530,0x194131f,0x2b580f3,0x31d569c,0x21d3751,0x3e2ce64, - 0x193de46,0x32454f0,0x004bffd }, - { 0x09554e7,0x170126e,0x2be6cd1,0x153de89,0x0353c67,0x350765c, - 0x202370b,0x1db01e5,0x30b12b1,0x3778591,0x00c8809,0x2e845d5, - 0x1fb1e56,0x170f90d,0x00e2db3 } }, - /* 85 */ - { { 0x328e33f,0x392aad8,0x36d1d71,0x0aebe04,0x1548678,0x1b55c8c, - 0x24995f8,0x2a5a01e,0x1bd1651,0x37c7c29,0x36803b6,0x3716c91, - 0x1a935a5,0x32f10b7,0x005c587 }, - { 0x2e8b4c0,0x336ccae,0x11382b6,0x22ec4cc,0x066d159,0x35fa585, - 0x23b2d25,0x3017528,0x2a674a8,0x3a4f900,0x1a7ce82,0x2b2539b, - 0x3d46545,0x0a07918,0x00eb9f8 } }, - /* 86 */ - { { 0x2cf5b9b,0x03e747f,0x166a34e,0x0afc81a,0x0a115b1,0x3aa814d, - 0x11cf3b1,0x163e556,0x3cbfb15,0x157c0a4,0x1bc703a,0x2141e90, - 0x01f811c,0x207218b,0x0092e6b }, - { 0x1af24e3,0x3af19b3,0x3c70cc9,0x335cbf3,0x068917e,0x055ee92, - 0x09a9308,0x2cac9b7,0x008b06a,0x1175097,0x36e929c,0x0be339c, - 0x0932436,0x15f18ba,0x0009f6f } }, - /* 87 */ - { { 0x29375fb,0x35ade34,0x11571c7,0x07b8d74,0x3fabd85,0x090fa91, - 0x362dcd4,0x02c3fdb,0x0608fe3,0x2477649,0x3fc6e70,0x059b7eb, - 0x1e6a708,0x1a4c220,0x00c6c4c }, - { 0x2a53fb0,0x1a3e1f5,0x11f9203,0x27e7ad3,0x038718e,0x3f5f9e4, - 0x308acda,0x0a8700f,0x34472fe,0x3420d7a,0x08076e5,0x014240e, - 0x0e7317e,0x197a98e,0x00538f7 } }, - /* 88 */ - { { 0x2663b4b,0x0927670,0x38dd0e0,0x16d1f34,0x3e700ab,0x3119567, - 0x12559d2,0x399b6c6,0x0a84bcd,0x163e7dd,0x3e2aced,0x058548c, - 0x03a5bad,0x011cf74,0x00c155c }, - { 0x3e454eb,0x2a1e64e,0x1ccd346,0x36e0edf,0x266ee94,0x2e74aaf, - 0x2d8378a,0x3cd547d,0x1d27733,0x0928e5b,0x353553c,0x26f502b, - 0x1d94341,0x2635cc7,0x00d0ead } }, - /* 89 */ - { { 0x0142408,0x382c3bb,0x3310908,0x2e50452,0x398943c,0x1d0ac75, - 0x1bf7d81,0x04bd00f,0x36b6934,0x3349c37,0x0f69e20,0x0195252, - 0x243a1c5,0x030da5f,0x00a76a9 }, - { 0x224825a,0x28ce111,0x34c2e0f,0x02e2b30,0x382e48c,0x26853ca, - 0x24bd14e,0x0200dec,0x1e24db3,0x0d3d775,0x132da0a,0x1dea79e, - 0x253dc0c,0x03c9d31,0x0020db9 } }, - /* 90 */ - { { 0x26c5fd9,0x05e6dc3,0x2eea261,0x08db260,0x2f8bec1,0x1255edf, - 0x283338d,0x3d9a91d,0x2640a72,0x03311f9,0x1bad935,0x152fda8, - 0x0e95abd,0x31abd15,0x00dfbf4 }, - { 0x107f4fa,0x29ebe9a,0x27353f7,0x3821972,0x27311fa,0x2925ab6, - 0x337ab82,0x2de6c91,0x1f115fe,0x044f909,0x21b93c2,0x3a5f142, - 0x13eb5e9,0x3ab1377,0x00b26b6 } }, - /* 91 */ - { { 0x22e5f2b,0x2ae7d4a,0x1ac481c,0x0a6fce1,0x2f93caf,0x242658e, - 0x3f35c3c,0x050f3d2,0x30074c9,0x142079c,0x0281b4c,0x295fea3, - 0x007413e,0x01726cd,0x00e4979 }, - { 0x1ab3cfb,0x1b76295,0x36adf55,0x1ad4636,0x1d444b9,0x3bd2e55, - 0x35425a5,0x1aa8cd3,0x3acecd2,0x1f769e8,0x1a655e9,0x1f6846f, - 0x24c70b5,0x3bff080,0x0002da3 } }, - /* 92 */ - { { 0x081d0d9,0x2c00d99,0x1fe2e24,0x396063f,0x03740db,0x243f680, - 0x3c1f451,0x1ff7b07,0x2803cf2,0x38ca724,0x2934f43,0x0d72d4d, - 0x0e8fe74,0x2975e21,0x002b505 }, - { 0x11adcc9,0x331a99c,0x21e16cf,0x1714c78,0x1f03432,0x2caa2a6, - 0x34a9679,0x2f7fe8b,0x0423c21,0x1a757ce,0x31b57d6,0x171e044, - 0x093b9b2,0x13602e0,0x00db534 } }, - /* 93 */ - { { 0x250a2f5,0x0b999eb,0x21d10d7,0x22b92a1,0x39b7f8d,0x0c37c72, - 0x29f70f3,0x3bf0e84,0x1d7e04f,0x07a42a9,0x272c3ae,0x1587b2f, - 0x155faff,0x10a336e,0x000d8fb }, - { 0x3663784,0x0d7dcf5,0x056ad22,0x319f8b1,0x0c05bae,0x2b6ff33, - 0x0292e42,0x0435797,0x188efb1,0x0d3f45e,0x119d49f,0x395dcd3, - 0x279fe27,0x133a13d,0x00188ac } }, - /* 94 */ - { { 0x396c53e,0x0d133e9,0x009b7ee,0x13421a0,0x1bbf607,0x1d284a5, - 0x1594f74,0x18cb47c,0x2dcac11,0x2999ddb,0x04e2fa5,0x1889e2c, - 0x0a89a18,0x33cb215,0x0052665 }, - { 0x104ab58,0x1d91920,0x3d6d7e3,0x04dc813,0x1167759,0x13a8466, - 0x0a06a54,0x103761b,0x25b1c92,0x26a8fdd,0x2474614,0x21406a4, - 0x251d75f,0x38c3734,0x007b982 } }, - /* 95 */ - { { 0x15f3060,0x3a7bf30,0x3be6e44,0x0baa1fa,0x05ad62f,0x1e54035, - 0x099d41c,0x2a744d9,0x1c0336f,0x3e99b5b,0x1afd3b1,0x2bf1255, - 0x1822bf8,0x2c93972,0x001d8cc }, - { 0x1d7584b,0x0508ade,0x20dd403,0x203a8fc,0x1c54a05,0x1611a31, - 0x037c8f9,0x1dcd4fe,0x110fbea,0x30f60bc,0x3dffe2f,0x26a1de1, - 0x0480367,0x18ec81c,0x0048eba } }, - /* 96 */ - { { 0x346e2f6,0x0435077,0x036789b,0x3e06545,0x313ab57,0x351a721, - 0x3372b91,0x15e6019,0x2fa4f6c,0x3c30656,0x272c9ac,0x10e84a8, - 0x2bdacea,0x232d9e2,0x009dadd }, - { 0x182579a,0x15b1af8,0x02d8cce,0x36cb49b,0x086feba,0x2911d17, - 0x268ee12,0x011e871,0x18698dc,0x35602b3,0x11b9ec2,0x0ade731, - 0x0f6a05a,0x1821015,0x00007da } }, - /* 97 */ - { { 0x3b00dd0,0x328d485,0x27a69e3,0x32c3a06,0x1046779,0x120b61c, - 0x19fef3d,0x0fef2e6,0x134d923,0x039bce0,0x348cd0e,0x0b0c007, - 0x066ae11,0x15d8f1b,0x00934e7 }, - { 0x33234dc,0x353f0f5,0x2fc1b44,0x18a193a,0x2fcae20,0x1afbc86, - 0x3afe252,0x17f7e10,0x107f3b7,0x2d84d54,0x394c2e6,0x19e96a9, - 0x0a37283,0x26c6152,0x003d262 } }, - /* 98 */ - { { 0x37cfaf8,0x01863d0,0x0299623,0x32c80cb,0x25b8742,0x0a4d90e, - 0x1f72472,0x13de652,0x31a0946,0x0ee0103,0x0f25414,0x2518b49, - 0x07e7604,0x1488d9b,0x00abd6b }, - { 0x1338f55,0x2ce4af5,0x1a0c119,0x3380525,0x21a80a9,0x235d4df, - 0x118ca7f,0x2dd8bcc,0x1c26bf4,0x32dc56b,0x28482b6,0x1418596, - 0x3c84d24,0x1f1a5a9,0x00d958d } }, - /* 99 */ - { { 0x1c21f31,0x22aa1ef,0x258c9ad,0x2d2018f,0x0adb3ca,0x01f75ee, - 0x186283b,0x31ad3bf,0x3621be7,0x3b1ee6d,0x015582d,0x3d61d04, - 0x2ddf32e,0x14b8a66,0x00c970c }, - { 0x2f24d66,0x00b8a88,0x100a78f,0x041d330,0x2efec1d,0x24c5b86, - 0x2a6a390,0x37526bc,0x2055849,0x3339f08,0x16bffc4,0x07f9d72, - 0x06ec09c,0x3f49ee8,0x00cad98 } }, - /* 100 */ - { { 0x248b73e,0x1b8b42d,0x285eed7,0x39473f4,0x1a9f92c,0x3b44f78, - 0x086c062,0x06a4ea3,0x34ea519,0x3c74e95,0x1ad1b8b,0x1737e2c, - 0x2cfe338,0x0a291f4,0x00bbecc }, - { 0x1cec548,0x0c9b01a,0x20b298d,0x377c902,0x24f5bc1,0x2415c8d, - 0x1a70622,0x2529090,0x1c5c682,0x283f1ba,0x2319f17,0x0120e2e, - 0x01c6f4d,0x33c67ff,0x008b612 } }, - /* 101 */ - { { 0x03830eb,0x02d4053,0x10c59bb,0x0f23b83,0x13d08f8,0x26ea4e2, - 0x2626427,0x0a45292,0x0449cbc,0x0175750,0x074c46f,0x27ae0f8, - 0x2d7d6ae,0x163dd3a,0x0063bb7 }, - { 0x2bb29e0,0x034bab1,0x341e1c4,0x21d2c0b,0x295aa2d,0x0f2c666, - 0x1891755,0x13db64a,0x2fe5158,0x337646e,0x31a1aae,0x057bee4, - 0x00f9e37,0x396d19e,0x00c1b6a } }, - /* 102 */ - { { 0x2772f41,0x34f92d0,0x39d1cde,0x174ef2d,0x03a700d,0x03fbb98, - 0x30d50e8,0x352ed10,0x1fcf5e5,0x3d113bc,0x26e358f,0x180653f, - 0x1b43cc6,0x3cc9aa4,0x00e68a2 }, - { 0x37fe4d2,0x09dd725,0x01eb584,0x171f8a9,0x278fdef,0x3e37c03, - 0x3bec02f,0x149757c,0x0cd5852,0x37d2e10,0x0e6988b,0x1c120e9, - 0x0b83708,0x38e7319,0x0039499 } }, - /* 103 */ - { { 0x08df5fe,0x177a02c,0x0362fc0,0x1f18ee8,0x00c1295,0x173c50a, - 0x379414d,0x1885ba8,0x32a54ef,0x2315644,0x39e65cf,0x357c4be, - 0x1d66333,0x09e05a5,0x0009c60 }, - { 0x1f7a2fb,0x073b518,0x2eb83ac,0x11353d7,0x1dd8384,0x0c63f2b, - 0x238c6c8,0x2a1920a,0x2e5e9f1,0x1cc56f8,0x042daf4,0x1ed5dc5, - 0x25f9e31,0x012a56a,0x0081b59 } }, - /* 104 */ - { { 0x321d232,0x2c71422,0x3a756b6,0x30230b2,0x387f3db,0x3a7c3eb, - 0x274b46a,0x201e69f,0x185bb7b,0x140da82,0x0d974a2,0x0616e42, - 0x35ec94f,0x3bc366b,0x005aa7c }, - { 0x3dcfffc,0x19a9c15,0x3225e05,0x36ae114,0x16ea311,0x0cda2aa, - 0x2a1a8d2,0x154b5cb,0x08348cd,0x17b66c8,0x080ea43,0x21e59f3, - 0x04173b9,0x31d5b04,0x00ad735 } }, - /* 105 */ - { { 0x2e76ef4,0x216acf3,0x2b93aea,0x112bc74,0x3449974,0x2b2e48f, - 0x11929be,0x2f03021,0x19051e3,0x0ac202d,0x19be68a,0x3b87619, - 0x26cdac4,0x086592c,0x00f00de }, - { 0x2e90d4d,0x3ed703c,0x2c648d7,0x29ddf67,0x000e219,0x3471247, - 0x26febd5,0x1161713,0x3541a8f,0x302038d,0x08d2af9,0x26e1b21, - 0x398514a,0x36dad99,0x002ed70 } }, - /* 106 */ - { { 0x06f25cb,0x1104596,0x370faee,0x07e83f3,0x0f7b686,0x228d43a, - 0x12cd201,0x0a1bd57,0x3e592dc,0x1e186fc,0x2226aba,0x2c63fe9, - 0x17b039a,0x1efaa61,0x00d1582 }, - { 0x2e6acef,0x07d51e4,0x3ac326c,0x322b07e,0x1422c63,0x32ff5c7, - 0x18760df,0x048928b,0x139b251,0x04d7da9,0x048d1a2,0x2a23e84, - 0x199dbba,0x2fa7afe,0x0049f1a } }, - /* 107 */ - { { 0x3492b73,0x27d3d3d,0x2b1a16f,0x07b2ce4,0x0cf28ec,0x2729bff, - 0x3130d46,0x3e96116,0x140b72e,0x14a2ea3,0x1ca066f,0x3a61f1d, - 0x022ebac,0x09192b4,0x003e399 }, - { 0x12555bb,0x0b6139d,0x239463a,0x12a70ab,0x2aaa93b,0x2254e72, - 0x00424ec,0x26a6736,0x26daa11,0x25b5ad6,0x379f262,0x140cd30, - 0x0c7d3bd,0x097bbcf,0x00899e9 } }, - /* 108 */ - { { 0x3825dc4,0x3cd946f,0x0462b7f,0x31102e7,0x30f741c,0x3313ed6, - 0x1ff5a95,0x15bf9dc,0x09b47fd,0x0f2e7a7,0x1626c0d,0x3c14f6d, - 0x14098bd,0x19d7df8,0x00a97ce }, - { 0x0934f5e,0x3f968db,0x046f68a,0x12333bf,0x26cd5e1,0x1ea2161, - 0x358570d,0x235031d,0x35edd55,0x05265e3,0x24ae00c,0x3542229, - 0x25bb2a1,0x1c83c75,0x0058f2a } }, - /* 109 */ - { { 0x24daedb,0x376928f,0x305266f,0x0499746,0x038318c,0x312efd7, - 0x1910a24,0x33450a3,0x1c478a9,0x39d8bf9,0x12cc0ae,0x397aeab, - 0x0654c08,0x095f283,0x00d2cdf }, - { 0x0b717d2,0x1f162c2,0x107a48f,0x128e1b3,0x2380718,0x39f4044, - 0x00f626a,0x05ec0c9,0x21bc439,0x200fa4d,0x20aea01,0x186a1d8, - 0x26372f2,0x1a91f87,0x0053f55 } }, - /* 110 */ - { { 0x3512a90,0x33b958b,0x29f1c84,0x0106c3a,0x224b3c0,0x09b307a, - 0x215d2de,0x3bdf43b,0x22cf0c9,0x176121d,0x1534143,0x09ba717, - 0x16b3110,0x0f73f6c,0x008f5b7 }, - { 0x2c75d95,0x26fbcb4,0x0dda1f6,0x206f819,0x28d33d5,0x1fb4d79, - 0x024c125,0x30a0630,0x1f9c309,0x0fe350d,0x1696019,0x0a54187, - 0x09541fd,0x35e3a79,0x0066618 } }, - /* 111 */ - { { 0x0e382de,0x33f5163,0x0dde571,0x3bb7a40,0x1175806,0x12ae8ed, - 0x0499653,0x3b25586,0x38ade7a,0x3fa265d,0x3f4aa97,0x3c03dbb, - 0x30c6de8,0x32d4042,0x00ae971 }, - { 0x2f788f1,0x1fbaf0e,0x3e2d182,0x3ff904f,0x0d46229,0x1d0726d, - 0x15455b4,0x093ae28,0x290f8e4,0x097c0b9,0x1ae8771,0x28480bb, - 0x04f6d40,0x3689925,0x0049b3b } }, - /* 112 */ - { { 0x35b2d69,0x31819c0,0x11b0d63,0x035afb6,0x2b50715,0x2bece6c, - 0x35f82f7,0x0ad987c,0x0011601,0x02e6f67,0x2d0a5f5,0x365e583, - 0x2f7c900,0x11449c5,0x00ed705 }, - { 0x27abdb4,0x1bbfd04,0x301c157,0x263c079,0x36850d6,0x3f21f8b, - 0x27d7493,0x0f9227e,0x06fb0ce,0x002daf3,0x37d8c1c,0x3ef87d7, - 0x19cc6f4,0x0c3809c,0x00cf752 } }, - /* 113 */ - { { 0x22d94ed,0x075b09c,0x020e676,0x084dc62,0x2d1ec3f,0x17439f1, - 0x240b702,0x33cc596,0x30ebaf3,0x0359fe0,0x393ea43,0x0ece01e, - 0x16c6963,0x03a82f2,0x0017faa }, - { 0x3866b98,0x3cd20b7,0x12d4e6b,0x3a6a76d,0x1205c1e,0x3e6ae1a, - 0x2f9bbdf,0x2e61547,0x2d175ee,0x28e18f6,0x13cf442,0x085b0ef, - 0x0e321ef,0x238fe72,0x003fb22 } }, - /* 114 */ - { { 0x360ac07,0x26dc301,0x3f4d94f,0x2ba75e6,0x1f3c9cc,0x17ff20f, - 0x0ea084c,0x30e39cf,0x143dc49,0x03bd43e,0x3c9e733,0x19e8aba, - 0x27fbaf4,0x12d913a,0x005ee53 }, - { 0x3609e7f,0x2d89c80,0x09f020c,0x1558bf7,0x3098443,0x3c515fd, - 0x1c8e580,0x16506bd,0x26cb4b2,0x1747d42,0x2ec8239,0x32c91f0, - 0x1ca3377,0x079768f,0x00a5f3e } }, - /* 115 */ - { { 0x185fa94,0x122759f,0x0e47023,0x0dcb6e7,0x10ba405,0x3b5eab4, - 0x1f7a1fa,0x32d003f,0x1739a4c,0x3295ec3,0x1b18967,0x3f3b265, - 0x34d2448,0x2dbadc9,0x00f30b5 }, - { 0x01c5338,0x2d1dcf2,0x2bd07cc,0x39a8fb5,0x2b85639,0x355bab6, - 0x1df95f1,0x01eb5f6,0x17f0a16,0x1b895b5,0x157574d,0x29fff72, - 0x3a8c46d,0x0118071,0x0065f84 } }, - /* 116 */ - { { 0x3a1e7f1,0x17432f2,0x1f648d4,0x3000ad5,0x2ef0a08,0x1f86624, - 0x1ca31b1,0x241f9dc,0x2cb4885,0x2b8610f,0x364ce16,0x1e5faf0, - 0x0b33867,0x2cb637d,0x00816d2 }, - { 0x1aa8671,0x02c394e,0x35f5e87,0x393040a,0x39f0db3,0x1c831a5, - 0x2966591,0x034a8d0,0x09e613c,0x042b532,0x018ddd6,0x3e402c9, - 0x2e20e1a,0x29cb4cd,0x00e087c } }, - /* 117 */ - { { 0x3a10079,0x20c7fea,0x3ff2222,0x1edb593,0x00dc5f8,0x3a32ccc, - 0x1479073,0x0cfed11,0x2a2702a,0x17a056a,0x1fba321,0x235acb9, - 0x149c833,0x172de7d,0x000f753 }, - { 0x2e95923,0x3b365cb,0x009f471,0x0df1b47,0x21e868b,0x199bbd3, - 0x07b8ecc,0x12ff0af,0x189808a,0x3bd5059,0x3fbc4d2,0x0fa7b88, - 0x1125bf2,0x0db0b5d,0x0043572 } }, - /* 118 */ - { { 0x29cdb1b,0x1db656e,0x391efe1,0x004be09,0x245a1ca,0x3793328, - 0x254af24,0x2f2e65d,0x10e5cc4,0x2af6fe7,0x2d97ac0,0x29f7d42, - 0x19fd6f6,0x0ac184d,0x00c5211 }, - { 0x305eae3,0x36738d3,0x2c2b696,0x00ba50e,0x3903adc,0x2122f85, - 0x0753470,0x1cf96a4,0x1702a39,0x247883c,0x2feb67e,0x2ab3071, - 0x3c6b9e1,0x30cb85a,0x002ca0a } }, - /* 119 */ - { { 0x3871eb5,0x284b93b,0x0a7affe,0x176a2fc,0x294c2f2,0x204d3aa, - 0x1e4c2a7,0x3ec4134,0x2fb0360,0x3847b45,0x05fc11b,0x0a6db6e, - 0x390fa40,0x2adfd34,0x005e9f7 }, - { 0x0646612,0x1b5cbcc,0x10d8507,0x0777687,0x3a0afed,0x1687440, - 0x0222578,0x1af34a4,0x2174e27,0x372d267,0x11246c3,0x34769c5, - 0x2044316,0x1b4d626,0x00c72d5 } }, - /* 120 */ - { { 0x2e5bb45,0x3ff1d36,0x16dcdf5,0x128986f,0x399068c,0x2a63b1e, - 0x0afa7aa,0x3a5b770,0x200f121,0x33b74bb,0x1414045,0x0f31ef8, - 0x2f50e16,0x2f38cd6,0x00b0b1b }, - { 0x1a06293,0x035e140,0x2644d44,0x1f1954b,0x2cdebab,0x31d5f91, - 0x0b8dbc8,0x38f2d23,0x3783cab,0x2a07e73,0x3123f59,0x3409846, - 0x3784ddd,0x223bbac,0x003dc7b } }, - /* 121 */ - { { 0x0741456,0x234e631,0x2121e1b,0x00980ca,0x3a9dfa9,0x098c916, - 0x3fc86d1,0x1c63072,0x3625244,0x13d0471,0x05b0fc5,0x1487550, - 0x2498596,0x11bb6ea,0x001afab }, - { 0x274b4ad,0x240aea1,0x3d12a75,0x2b56b61,0x1486b43,0x1b83426, - 0x31c7363,0x35b59ca,0x207bb6c,0x38e6243,0x19bace4,0x0a26671, - 0x35e3381,0x0c2ded4,0x00d8da4 } }, - /* 122 */ - { { 0x2b75791,0x19590b1,0x2bfb39f,0x2988601,0x0050947,0x0d8bbe1, - 0x23e3701,0x08e4432,0x2ed8c3d,0x326f182,0x332e1dd,0x12219c5, - 0x2e0779b,0x367aa63,0x0012d10 }, - { 0x251b7dc,0x0a08b4d,0x1138b6f,0x2ea02af,0x06345a5,0x1cb4f21, - 0x0332624,0x1d49d88,0x140acc5,0x2f55287,0x024447c,0x291ace9, - 0x1a4966e,0x015cbec,0x005bc41 } }, - /* 123 */ - { { 0x351cd0e,0x315e8e9,0x07d6e70,0x067ae8f,0x2190d84,0x351f556, - 0x03bee79,0x31b62c7,0x266f912,0x1b6a504,0x007a6ad,0x3a6ab31, - 0x3891112,0x3c45ba0,0x00d6ce5 }, - { 0x0e1f2ce,0x32a5edc,0x1434063,0x1ca084f,0x2a3e47c,0x137e042, - 0x16e2418,0x2069280,0x3b0dfd8,0x35a22b5,0x289bf0a,0x1f667f2, - 0x02d23a3,0x0ce688f,0x00d8e3f } }, - /* 124 */ - { { 0x10bed6f,0x14c58dd,0x0b0abdf,0x0ca0f9a,0x3808abc,0x2ec228c, - 0x2366275,0x12afa16,0x20f6b0e,0x37dca8e,0x3af0c6a,0x1c5b467, - 0x1b25ff7,0x00814de,0x0022dcc }, - { 0x1a56e11,0x02fe37e,0x3f21740,0x35d5a91,0x06cb8ba,0x29bad91, - 0x17176f7,0x2d919f2,0x0f7d1f5,0x13a3f61,0x04ddb05,0x0c82a51, - 0x286f598,0x2e8c777,0x0007071 } }, - /* 125 */ - { { 0x0f8fcb9,0x3e83966,0x170c6fd,0x3825343,0x089cec8,0x01b482a, - 0x0993971,0x3327282,0x39aba8a,0x32456fe,0x1507e01,0x1c3252d, - 0x21ffb13,0x29822a0,0x0083246 }, - { 0x23c378f,0x1cea7ef,0x1be9a82,0x224d689,0x37e5447,0x3764a75, - 0x3a49724,0x361e1b3,0x19d365b,0x3a61ffb,0x1c29a7a,0x20ab251, - 0x17ec549,0x175d777,0x004589a } }, - /* 126 */ - { { 0x15540a9,0x2ec5d2a,0x05b09fa,0x1bc058b,0x07cfb88,0x28f7b86, - 0x3e766be,0x189305e,0x01fe88e,0x23fdf69,0x0b919c3,0x02dc7ae, - 0x3f9a9ad,0x0b83cc7,0x0086a52 }, - { 0x28bc259,0x39bdca1,0x39e4bc8,0x0e0f33b,0x16130c6,0x2919955, - 0x31f4549,0x2fed027,0x30919b2,0x0a39b03,0x0ca7bb2,0x1711b24, - 0x3b67b94,0x05a136b,0x00acd87 } }, - /* 127 */ - { { 0x0c53841,0x31cb284,0x3ced090,0x06d5693,0x1c20ae0,0x0408d2b, - 0x37ebd5e,0x081900f,0x26a8589,0x0acfd0a,0x34a1472,0x2f0c302, - 0x124ccbd,0x10de328,0x00971bc }, - { 0x17ff2ff,0x27d1b54,0x147b6f7,0x38bb2ea,0x26a9c96,0x0a49448, - 0x39f2f46,0x247c579,0x3b16a4e,0x28c2a5a,0x2d4c72d,0x11f248c, - 0x1e4df11,0x047d604,0x0065bc3 } }, - /* 128 */ - { { 0x39b3239,0x1f75f44,0x3bae87c,0x139360c,0x18b5782,0x3ffc005, - 0x3c48789,0x2bc6af2,0x38b909e,0x223ff3b,0x31443a7,0x017d3bb, - 0x0bfed99,0x128b857,0x00020dd }, - { 0x306d695,0x25a7b28,0x2f60ca2,0x2b6e4f2,0x1df940c,0x1fa9b8e, - 0x37fab78,0x13f959f,0x10ff98c,0x38343b8,0x019cb91,0x11a1e6b, - 0x17ab4c6,0x1431f47,0x004b4ea } }, - /* 129 */ - { { 0x20db57e,0x102515e,0x170219e,0x2b66a32,0x1e6017c,0x2f973fe, - 0x3739e51,0x0e28b6f,0x3cda7a9,0x30d91ac,0x28350df,0x1444215, - 0x098b504,0x1bcd5b8,0x00ad3bd }, - { 0x22e3e3e,0x3aeaffb,0x26cb935,0x0091ce4,0x2fbd017,0x3a7ed6a, - 0x335b029,0x3bfc1f1,0x3852e3f,0x2b14a86,0x046b405,0x266af4c, - 0x3997191,0x33b0e40,0x00e306f } }, - /* 130 */ - { { 0x3e4712c,0x26bb208,0x18eed6d,0x1b30f06,0x27ca837,0x06faf62, - 0x1831873,0x3fbcf9b,0x3f3d88b,0x1fb55eb,0x0f44edc,0x29917bb, - 0x3151772,0x342d72e,0x00d4e63 }, - { 0x2ee0ecf,0x39e8733,0x2e8e98c,0x0cd4e0f,0x08f0126,0x1ad157a, - 0x079078a,0x23018ee,0x196c765,0x2b2f34f,0x0783336,0x075bf9c, - 0x3713672,0x098d699,0x00f21a7 } }, - /* 131 */ - { { 0x186ba11,0x22cf365,0x048019d,0x2ca2970,0x0d9e0ae,0x08c3bd7, - 0x261dbf2,0x2fc2790,0x1ee02e6,0x10256a7,0x00dc778,0x18dc8f2, - 0x157b189,0x2ebc514,0x005c97d }, - { 0x3c4503e,0x1d10d12,0x337097e,0x0c6169a,0x30fb1cb,0x3481752, - 0x0df2bec,0x19768fa,0x1bcf8f7,0x2925f74,0x2c988a1,0x3be571d, - 0x04cfa92,0x2ea9937,0x003f924 } }, - /* 132 */ - { { 0x268b448,0x06e375c,0x1b946bf,0x287bf5e,0x3d4c28b,0x138d547, - 0x21f8c8e,0x21ea4be,0x2d45c91,0x35da78e,0x00326c0,0x210ed35, - 0x1d66928,0x0251435,0x00fefc8 }, - { 0x0339366,0x216ff64,0x2c3a30c,0x3c5733d,0x04eeb56,0x2333477, - 0x32b1492,0x25e3839,0x1b5f2ce,0x0dcfba1,0x3165bb2,0x3acafcc, - 0x10abfcd,0x248d390,0x008106c } }, - /* 133 */ - { { 0x102f4ee,0x3c0585f,0x1225c8d,0x11c6388,0x08a7815,0x2b3e790, - 0x2895eb6,0x18cf53a,0x0b56e5a,0x2e2c003,0x3e981ff,0x0761b55, - 0x1bc32f3,0x0a7111d,0x00f5c80 }, - { 0x3568973,0x1587386,0x16ec764,0x20698a6,0x02f809b,0x2821502, - 0x113d64d,0x38c2679,0x15de61c,0x0309f60,0x272999e,0x29bfe64, - 0x173f70d,0x1de7fab,0x00bd284 } }, - /* 134 */ - { { 0x31cdf2b,0x0f0be66,0x2151603,0x01af17e,0x32a99cf,0x085dece, - 0x27d2591,0x1520df4,0x273c448,0x1ec7c54,0x102e229,0x355f604, - 0x2acb75f,0x005f1fd,0x003d43e }, - { 0x270eb28,0x22ec2ce,0x306b41a,0x238fa02,0x167de2d,0x030a379, - 0x245a417,0x1808c24,0x0b1a7b2,0x3ab5f6f,0x2cbc6c1,0x2c228d4, - 0x3041f70,0x2d9a6cc,0x00b504f } }, - /* 135 */ - { { 0x17a27c2,0x216ad7e,0x011ba8e,0x22f0428,0x16ac5ec,0x3ef3c58, - 0x345533f,0x0298155,0x2856579,0x0005e03,0x19ee75b,0x146fe16, - 0x29881e4,0x18ece70,0x008907a }, - { 0x20189ed,0x119ce09,0x35cb76d,0x0d91ef4,0x2284a44,0x032ad87, - 0x0e8c402,0x3c82b5d,0x38c416c,0x398992f,0x1fd820c,0x169b255, - 0x3b5fcfa,0x1343c92,0x00fa715 } }, - /* 136 */ - { { 0x33f5034,0x20b3b26,0x28fd184,0x16b3679,0x3962d44,0x15d1bc8, - 0x2fb1d69,0x1292c99,0x25a58c9,0x1b19ab7,0x2d68a5b,0x2f6a09b, - 0x0d6aedb,0x2935eac,0x0005664 }, - { 0x25e32fc,0x13f9440,0x3252bcd,0x2fea5b7,0x161a5ae,0x0564a8c, - 0x0a07e23,0x1545f62,0x0de9890,0x1d76765,0x1fd440e,0x2ed0041, - 0x3db4c96,0x1e8ba01,0x001b0c4 } }, - /* 137 */ - { { 0x0223878,0x29ab202,0x15585c2,0x1a79969,0x1ba08c2,0x2ef09ff, - 0x2b1b9b9,0x181f748,0x1bf72b9,0x224645c,0x2588dc5,0x2d157e7, - 0x22d939a,0x05b88d9,0x006d549 }, - { 0x31de0c1,0x23a4e0e,0x278f8da,0x1aa013c,0x1a84d18,0x0d185a5, - 0x0988ccd,0x2c32efd,0x3bee10e,0x37d7ab8,0x3f2a66e,0x3e2da3e, - 0x1b5701f,0x3d9f0c1,0x00a68da } }, - /* 138 */ - { { 0x0b2e045,0x0133fd1,0x05d4c10,0x0d92c70,0x391b5e1,0x2292281, - 0x2e40908,0x2ec694e,0x195ea11,0x29cfeca,0x3d93a4e,0x01215c0, - 0x08a5f32,0x37a0eff,0x00cce45 }, - { 0x2b3106e,0x12a5fb0,0x0b4faff,0x0c2da12,0x09069c6,0x35d8907, - 0x2837a6e,0x3db3fb6,0x3136cc3,0x222836b,0x3da018a,0x2741274, - 0x13ba319,0x1ac7642,0x00f867c } }, - /* 139 */ - { { 0x2527296,0x10a9595,0x178de4d,0x0f739c4,0x0ae26c7,0x3094599, - 0x20adac6,0x2b875c2,0x3ae5dc0,0x3e04d20,0x1aab2da,0x1d3ab37, - 0x15f4f75,0x0b730b5,0x00c56b5 }, - { 0x1f32923,0x2f059e5,0x2a89872,0x2056f74,0x04be175,0x1da67c0, - 0x17f1e7a,0x3780a6d,0x0723ac2,0x257f367,0x1237773,0x2bcee86, - 0x0b97f83,0x38aff14,0x00a64d4 } }, - /* 140 */ - { { 0x2552b40,0x0b6b883,0x12e8217,0x0974d35,0x062f497,0x1e563e6, - 0x30ee400,0x375d1e4,0x290751f,0x0d5b68a,0x353e48c,0x064a0d3, - 0x3c343f1,0x309a394,0x0034d2a }, - { 0x3111286,0x0f08604,0x1827107,0x0536a76,0x0201dac,0x3a574de, - 0x2c29dbe,0x382c7b0,0x1191f3e,0x324c5bc,0x144ce71,0x24327c1, - 0x1212778,0x22bc9d8,0x00d7713 } }, - /* 141 */ - { { 0x34ad1cd,0x1179b4e,0x1bc1780,0x1392a92,0x2cd86b9,0x359de85, - 0x251f1df,0x0da5d5f,0x135fa61,0x0f64a42,0x34f4d89,0x0fe564c, - 0x3cf9b7a,0x122d757,0x008c9c2 }, - { 0x370d4e9,0x0e9209b,0x0ae99f2,0x1518c64,0x0172734,0x2c20692, - 0x1d7c135,0x149c52f,0x38928d6,0x3c78b78,0x25841d1,0x2eaa897, - 0x372e50b,0x29e5d19,0x00c4c18 } }, - /* 142 */ - { { 0x13375ac,0x389a056,0x211310e,0x2f9f757,0x04f3288,0x103cd4e, - 0x17b2fb2,0x2c78a6a,0x09f1de6,0x23e8442,0x1351bc5,0x1b69588, - 0x285b551,0x0464b7e,0x00573b6 }, - { 0x0ba7df5,0x259a0db,0x2b4089e,0x05630a2,0x3f299be,0x350ff2f, - 0x1c9348a,0x3becfa4,0x3cc9a1c,0x17a6ef1,0x338b277,0x2b761d9, - 0x2aa01c8,0x3cb9dd7,0x006e3b1 } }, - /* 143 */ - { { 0x277788b,0x16a222d,0x173c036,0x310ff58,0x2634ae8,0x392636f, - 0x0987619,0x1e6acc1,0x26dc8f7,0x242310f,0x0c09aca,0x22b8e11, - 0x0d17006,0x1c2c806,0x002380c }, - { 0x297c5ec,0x1fef0e8,0x3948cf7,0x14f2915,0x2dacbc8,0x0dafb1f, - 0x10de043,0x31184da,0x06414ee,0x3c9aeeb,0x1f713ab,0x308f1f8, - 0x1569ed1,0x3f379bf,0x00f08bb } }, - /* 144 */ - { { 0x0770ee3,0x058fd21,0x17065f8,0x251d128,0x10e0c7f,0x06cb51b, - 0x0f05f7e,0x3666a72,0x3e7d01f,0x2d05fab,0x11440e5,0x28577d4, - 0x2fbcf2b,0x14aa469,0x00dc5c5 }, - { 0x270f721,0x1c75d28,0x085b862,0x1d68011,0x132c0a0,0x37be81d, - 0x1a87e38,0x083fa74,0x3acbf0d,0x16d6429,0x0feda1f,0x031070a, - 0x2ec2443,0x21e563d,0x00454d2 } }, - /* 145 */ - { { 0x0525435,0x1e98d5f,0x3dbc52b,0x1fcdf12,0x13d9ef5,0x3ff311d, - 0x393e9ed,0x3cef8ae,0x2987710,0x3bdee2e,0x21b727d,0x3ba1b68, - 0x10d0142,0x3c64b92,0x0055ac3 }, - { 0x0c1c390,0x38e9bb0,0x1e7b487,0x11511b3,0x1036fb3,0x25aba54, - 0x1eb2764,0x048d022,0x0d971ed,0x1bb7fb5,0x100f0b4,0x06c3756, - 0x2f0d366,0x3c6e160,0x0011bd6 } }, - /* 146 */ - { { 0x36bc9d1,0x24d43c1,0x12c35cf,0x2fb3cf3,0x015d903,0x16bc0c7, - 0x0fc8c22,0x3195c87,0x2488b1c,0x1f82b4c,0x30014e8,0x27ee58d, - 0x31658dd,0x1684a5f,0x00f0f3a }, - { 0x1f703aa,0x023eebc,0x20babb9,0x080bd9d,0x12f9cc4,0x1a8e2d4, - 0x0eec666,0x1176803,0x33005d6,0x1137b68,0x37de339,0x33d71cb, - 0x0c906b9,0x14086b5,0x00aeef6 } }, - /* 147 */ - { { 0x219045d,0x0f22c5e,0x024c058,0x00b414a,0x0ae7c31,0x3db3e96, - 0x234979f,0x0cf00a8,0x3c962c7,0x27fa77f,0x1c0c4b0,0x1fe8942, - 0x218053a,0x1eed3f8,0x0051643 }, - { 0x2a23ddb,0x138f570,0x104e945,0x21ca270,0x30726d8,0x3f45490, - 0x37d9184,0x242ea25,0x33f6d77,0x3f15679,0x065af85,0x34fa1f5, - 0x2e46b8f,0x31d17fb,0x00a2615 } }, - /* 148 */ - { { 0x335167d,0x181ea10,0x0887c8d,0x01383d7,0x18b42d8,0x263447e, - 0x1f13df3,0x0319d7e,0x0872074,0x2d6aa94,0x23d9234,0x36a69aa, - 0x0bad183,0x3138a95,0x00bd3a5 }, - { 0x1b0f658,0x0e4530b,0x373add1,0x1b968fc,0x329dcb6,0x09169ca, - 0x162df55,0x0211eff,0x02391e4,0x3867460,0x3136b1a,0x37dd36e, - 0x3bc5bd9,0x2dacfe4,0x0072a06 } }, - /* 149 */ - { { 0x119d96f,0x067b0eb,0x00996da,0x293eca9,0x2b342da,0x1889c7a, - 0x21633a6,0x0152c39,0x281ce8c,0x18ef3b3,0x0bd62dc,0x3238186, - 0x38d8b7c,0x3867b95,0x00ae189 }, - { 0x0ed1eed,0x1e89777,0x13ab73e,0x029e1d7,0x2c1257f,0x33fbc09, - 0x32d5a21,0x3d870b2,0x39bb1fd,0x33663bc,0x24e83e6,0x239bda4, - 0x3088bcd,0x01db1ed,0x00d71e7 } }, - /* 150 */ - { { 0x14245bf,0x0da0c27,0x153b339,0x05cab0a,0x122d962,0x1b0f0f3, - 0x3f5a825,0x267a2ce,0x2910d06,0x254326f,0x0f36645,0x025118e, - 0x37c35ec,0x36e944e,0x006c056 }, - { 0x05ab0e3,0x29aa0c1,0x1295687,0x1fd1172,0x08d40b5,0x05bd655, - 0x345048a,0x02a1c3c,0x2393d8f,0x0992d71,0x1f71c5e,0x18d4e8a, - 0x30dd410,0x11d61d3,0x00dd58b } }, - /* 151 */ - { { 0x2230c72,0x30213d8,0x05e367e,0x329204e,0x0f14f6c,0x3369ddd, - 0x0bb4074,0x2edafd6,0x1b1aa2d,0x0785404,0x0c035ab,0x220da74, - 0x1f2fdd4,0x092a091,0x00ef83c }, - { 0x3dc2538,0x1cca3e7,0x246afb5,0x24c647f,0x0798082,0x0bb7952, - 0x0f5c443,0x008b38a,0x299ea1a,0x3c6cf36,0x3df2ec7,0x398e6dc, - 0x29a1839,0x1cadd83,0x0077b62 } }, - /* 152 */ - { { 0x25d56d5,0x3546f69,0x16e02b1,0x3e5fa9a,0x03a9b71,0x2413d31, - 0x250ecc9,0x1d2de54,0x2ebe757,0x2a2f135,0x2aeeb9a,0x0d0fe2b, - 0x204cb0e,0x07464c3,0x00c473c }, - { 0x24cd8ae,0x0c86c41,0x221c282,0x0795588,0x1f4b437,0x06fc488, - 0x0c81ecd,0x020bf07,0x3a9e2c8,0x2294a81,0x3a64a95,0x0363966, - 0x32c9a35,0x0f79bec,0x0029e4f } }, - /* 153 */ - { { 0x289aaa5,0x2755b2e,0x059e0aa,0x3031318,0x0f0208a,0x35b7729, - 0x00d9c6b,0x3dd29d0,0x075f2c2,0x0ece139,0x31562dd,0x04187f2, - 0x13b8d4c,0x0920b85,0x003924e }, - { 0x09808ab,0x2e36621,0x2a36f38,0x1829246,0x229bf32,0x20883b7, - 0x159ada8,0x3108a14,0x15bbe5b,0x1e2d1e4,0x1730096,0x0d35cbb, - 0x15d0da9,0x0e60b94,0x00c4f30 } }, - /* 154 */ - { { 0x31de38b,0x27b9086,0x2760e3e,0x169098d,0x2a124e2,0x00596c6, - 0x3f73c09,0x0d31642,0x2341464,0x248600a,0x2e1fa10,0x2aa0fc8, - 0x051e954,0x00f3b67,0x001d4bd }, - { 0x18751e6,0x25a8e1e,0x07f5c2d,0x17e30d4,0x0ed2723,0x23093e2, - 0x3b80e2c,0x13de2d7,0x2fad37f,0x1be1cfb,0x3224ba9,0x0a7f5d3, - 0x1714972,0x06667b7,0x009dcd9 } }, - /* 155 */ - { { 0x294f22a,0x3e06993,0x0341ee9,0x24bdc7b,0x2e56098,0x2660a13, - 0x018ddda,0x2c261b2,0x2953b54,0x267f51c,0x0e8a7cc,0x29ab00c, - 0x3a38247,0x397ac81,0x00de684 }, - { 0x36b956b,0x347b34a,0x35834bd,0x053c06c,0x0090844,0x148cec5, - 0x380b325,0x2f17b8b,0x054ef5e,0x09683fb,0x3f8b29a,0x33c979a, - 0x1e01474,0x3e81fca,0x001c757 } }, - /* 156 */ - { { 0x30fdfe4,0x2d712ba,0x13671bc,0x2cfc226,0x3d7c649,0x16f020e, - 0x368e3f0,0x2981ebb,0x246a78a,0x115e81b,0x21223a4,0x04dbb30, - 0x1a50ba2,0x12114bd,0x0089bd6 }, - { 0x055f15a,0x1046e51,0x00fd724,0x1c022a7,0x323dfa9,0x36d8efb, - 0x0da4d16,0x0910dec,0x2c1fb16,0x2dbe29f,0x298284f,0x2b273bb, - 0x26022c1,0x20accd5,0x00085a5 } }, - /* 157 */ - { { 0x01f138a,0x2d87e7b,0x0c2815c,0x0c19a3c,0x311c9a2,0x3e4fce3, - 0x029729d,0x21236b2,0x2984048,0x3f3bc95,0x2bba8fb,0x1a1b680, - 0x0619a3f,0x29e0447,0x00ed5fe }, - { 0x2d1c833,0x3dcef35,0x3f809b4,0x01a1b9e,0x1509516,0x10ac754, - 0x2735080,0x27b0a8a,0x2495fb8,0x0a7bdba,0x1ef8b89,0x00233a5, - 0x0568bf1,0x1a126ba,0x0078a7e } }, - /* 158 */ - { { 0x0470cd8,0x20e9f04,0x30003fe,0x20be1b7,0x1927346,0x2a5026d, - 0x1ac06bd,0x2717ed7,0x2609493,0x3079ea5,0x1cc116d,0x31b0541, - 0x2c8ccde,0x10219ae,0x001a52b }, - { 0x2864045,0x0e8d95b,0x2fc1530,0x0aa44e7,0x345eae7,0x3cc7553, - 0x3ec6466,0x229b60e,0x06f6e95,0x00bed2a,0x0ff4403,0x181c639, - 0x2e0df67,0x1f8fa46,0x0000811 } }, - /* 159 */ - { { 0x04310a2,0x20cee8e,0x09fc5d5,0x3707f5b,0x0bdfb4e,0x12713ee, - 0x24f1028,0x0787ee6,0x39a581c,0x3797ec8,0x10a9746,0x112cb9f, - 0x142b9ba,0x1da0ef6,0x0078f7b }, - { 0x07607ae,0x3232872,0x2a7e076,0x0bb572a,0x182b23c,0x1d8f918, - 0x181f392,0x37c45a9,0x24a3886,0x0b2a297,0x264e7f2,0x1fa433c, - 0x0fcfcc8,0x21c0857,0x0004f74 } }, - /* 160 */ - { { 0x01d161c,0x1744585,0x2d17528,0x03a4f13,0x267cd2e,0x30d861f, - 0x062a647,0x213284b,0x139ed25,0x27d4ca5,0x02fbbd6,0x31ddf11, - 0x3c50ac4,0x1dd86f7,0x00107de }, - { 0x16beebd,0x1b7317a,0x2151997,0x256a196,0x3be2aff,0x3621cab, - 0x0a9da19,0x05f3038,0x23da63c,0x3178d5e,0x215cc67,0x07f7f63, - 0x0c6d8d3,0x3bf5e5c,0x00c44bb } }, - /* 161 */ - { { 0x00c62f1,0x3e0f893,0x1572703,0x3b93865,0x19b1e28,0x389b33b, - 0x02858bf,0x0e3e9aa,0x04bc436,0x234e072,0x25ba43d,0x3dca19e, - 0x0274394,0x20f442e,0x003b4a7 }, - { 0x176451e,0x2b5ed5d,0x35c8ee1,0x25c52da,0x0c3d0b5,0x32b306e, - 0x030954f,0x275ecf7,0x10e472c,0x21577c4,0x02f8a32,0x321bb5c, - 0x0098f97,0x104e237,0x00d0433 } }, - /* 162 */ - { { 0x0a8f2fe,0x034548b,0x141f1a6,0x121246f,0x1616409,0x237f80d, - 0x2e29a55,0x1218db6,0x3ea278e,0x1669856,0x1ad7c8e,0x36d11de, - 0x2c2fcbb,0x18c0b3a,0x001c706 }, - { 0x1699b4b,0x2d531a6,0x17e85e2,0x1b48e78,0x2b509ca,0x2818ea0, - 0x0165fee,0x0b809ca,0x09db6a2,0x3dad798,0x326ee1d,0x204e416, - 0x091fa12,0x1c890e5,0x0007b9f } }, - /* 163 */ - { { 0x0ff4e49,0x0bb0512,0x0129159,0x05db591,0x03e4e9f,0x055ab30, - 0x0f82881,0x0ac2deb,0x3a8bb09,0x356a8d2,0x3d38393,0x03e4089, - 0x38187cd,0x1377a93,0x0041672 }, - { 0x0139e73,0x3990730,0x187d3c4,0x33e4793,0x2e0fe46,0x2ad87e2, - 0x33c792c,0x21d4fb6,0x1e4d386,0x2932d1b,0x20f1098,0x1270874, - 0x0ea6ee4,0x0167d6e,0x005e5fd } }, - /* 164 */ - { { 0x1856031,0x2b7519d,0x3bd07fc,0x337abcb,0x089c7a4,0x2a1f120, - 0x3523ce7,0x2ba406b,0x09561d9,0x1797f04,0x3cdb95f,0x2d6193e, - 0x32c7d3f,0x223aed6,0x00beb51 }, - { 0x2e65825,0x158f0ce,0x16413d1,0x310395f,0x3116854,0x250baf4, - 0x373d341,0x156cc47,0x104c069,0x0893716,0x195a0a6,0x035320e, - 0x37b7d8a,0x21b5755,0x00fb26b } }, - /* 165 */ - { { 0x286ae17,0x04239f1,0x1a56c53,0x0e74707,0x29090d7,0x2bb142b, - 0x03b0139,0x1aac916,0x08ba49a,0x0376682,0x3382f85,0x064bbab, - 0x2910e28,0x1d5bd7f,0x00cc8df }, - { 0x0ab7630,0x208e8e7,0x3fc1877,0x26bee39,0x264984a,0x192ff05, - 0x08ef9c3,0x0aa6951,0x071c44e,0x26eed3e,0x035c95e,0x06906ad, - 0x10a0690,0x397eaa9,0x00c6c23 } }, - /* 166 */ - { { 0x034d8dd,0x005b064,0x279bb78,0x12c2c4f,0x1856bb4,0x0c90681, - 0x06409ab,0x3b48617,0x19a2d78,0x0a34bf8,0x326eddf,0x31f09b5, - 0x04f04dc,0x3d7c944,0x003ccaf }, - { 0x321f843,0x35fb71a,0x1e4c397,0x377a5d7,0x2da88e4,0x3d6ada7, - 0x33d3964,0x1b30149,0x0e39aae,0x054dda0,0x3e6f946,0x1273394, - 0x3ffd3f7,0x2f6655e,0x00021dd } }, - /* 167 */ - { { 0x37233cf,0x11617dd,0x26f07b6,0x3d8250a,0x0fe6771,0x3f9bbbc, - 0x2aba7ad,0x200a58d,0x3568603,0x198eefa,0x1e8fcf3,0x3b9610b, - 0x20524ac,0x2a67528,0x0048d9a }, - { 0x1a5e57a,0x1e9d303,0x16c9cff,0x0f39527,0x3c23259,0x03c8a1e, - 0x104bccf,0x182d5a1,0x18dbc83,0x05b5f42,0x1b402f4,0x317c525, - 0x11bf1ea,0x3c46e1f,0x0061936 } }, - /* 168 */ - { { 0x0153a9d,0x36859ee,0x2cf0aa9,0x2b27a0f,0x0a49fe3,0x2d984e1, - 0x018f8e1,0x1378453,0x1ab3843,0x1987093,0x283dae9,0x25cf0e8, - 0x14fc93d,0x280609d,0x00c99ba }, - { 0x026b1e3,0x34663d3,0x2202477,0x21a9d45,0x212e8e1,0x18ab77e, - 0x2e52f63,0x0a14ce1,0x295c396,0x00c7a3d,0x2aaedb6,0x30abc4d, - 0x374acde,0x1318a73,0x00fcfdb } }, - /* 169 */ - { { 0x0a40298,0x3ba5633,0x11956b3,0x14fcbd7,0x3c38781,0x34bab96, - 0x165630e,0x1f3c831,0x37e3a69,0x2b4226c,0x2d5029e,0x3b4ab1e, - 0x1da6ac2,0x3eb43c3,0x007e5cd }, - { 0x1b86202,0x109b7f6,0x2054f98,0x2c50cd7,0x2ed1960,0x3c518e7, - 0x1b02463,0x319c07f,0x1c30db6,0x045fdc2,0x373421e,0x31a1eb9, - 0x1a8acbf,0x31289b0,0x0013fef } }, - /* 170 */ - { { 0x3fa0a5f,0x068661f,0x2109e36,0x00b18ff,0x1f4b261,0x31d3844, - 0x0acbc56,0x3aebc99,0x1fa77ab,0x152bd11,0x24cddb7,0x2313f74, - 0x06eea44,0x15f5114,0x000b131 }, - { 0x2e9993d,0x1ac565c,0x2cbe22a,0x3921797,0x12c3c57,0x360f868, - 0x33560bf,0x320ee99,0x382c3b8,0x39af88f,0x00bbe38,0x2c4ea59, - 0x3399b40,0x00ceb45,0x0066eea } }, - /* 171 */ - { { 0x0c6c693,0x31ba56d,0x3d3849f,0x378dabd,0x0efc735,0x17f90bf, - 0x13343d3,0x2df0f81,0x27c6a9a,0x13c2a90,0x0a0fcb2,0x27c10d9, - 0x3bc50c7,0x090e4fa,0x0016287 }, - { 0x2927e1e,0x35af405,0x184c5c3,0x3499cee,0x240158e,0x33522e6, - 0x386fc84,0x0a0b69f,0x1a660ea,0x34590fb,0x22a1bee,0x2ce4fab, - 0x31a9445,0x0e78655,0x00664c8 } }, - /* 172 */ - { { 0x3eeaf94,0x115d409,0x21e7577,0x097aa67,0x22875c9,0x021ab7a, - 0x27e7ba5,0x1093f04,0x2a086fe,0x05d9494,0x2b6c028,0x10f31b0, - 0x1312d11,0x262759c,0x00c9bb2 }, - { 0x1acb0a5,0x30cdf14,0x0f78880,0x0574f18,0x1a37109,0x098adbb, - 0x2113c09,0x2060925,0x1f89ce4,0x1974976,0x3381358,0x2dab5ca, - 0x2159c53,0x3af1303,0x000ea3b } }, - /* 173 */ - { { 0x1e49bea,0x29142b1,0x1a59cab,0x055f017,0x0684e54,0x39eb0db, - 0x29cab9d,0x255ee8b,0x35f2e6f,0x05329e6,0x09b817b,0x1ec091c, - 0x1df0fef,0x2641f62,0x00eb304 }, - { 0x2fe5096,0x3dcc1d1,0x2aaf508,0x3a0b813,0x0695810,0x144bddb, - 0x2f1bd93,0x281ae23,0x3513ebc,0x1ddd984,0x0cf158b,0x35218eb, - 0x257daf7,0x391253b,0x00b2a81 } }, - /* 174 */ - { { 0x153e6ba,0x22396db,0x0ea2ff2,0x2a45121,0x0a90de1,0x34cf23b, - 0x2db60ce,0x1a900be,0x2f328b6,0x355e75b,0x2c24372,0x0b75b77, - 0x2ec7d4f,0x3f24759,0x00e9e33 }, - { 0x39eab6e,0x2267480,0x3b5e110,0x1e8fa5e,0x2a31a66,0x3f739a3, - 0x00166dc,0x3552d88,0x3ae5137,0x3efa0fa,0x0800acd,0x17df61d, - 0x38c8608,0x04cc31b,0x00cf4ab } }, - /* 175 */ - { { 0x31e08fb,0x1961164,0x22c003f,0x078541b,0x3643855,0x30da587, - 0x11f0dc9,0x324595e,0x329e3dc,0x29a041e,0x3495d2c,0x0908dd3, - 0x1895b83,0x198dbb9,0x00d8cfb }, - { 0x0349b1b,0x383c5a8,0x2b86525,0x1b1283e,0x133cd2c,0x2be376a, - 0x012ee82,0x1eb4d1b,0x0ba71e9,0x01f3109,0x37621eb,0x1d9b77c, - 0x0d39069,0x3d5a97c,0x0095565 } }, - /* 176 */ - { { 0x20f5e94,0x1eefc86,0x1327e0e,0x054760b,0x2f771e1,0x3ac447e, - 0x033e3dc,0x198e040,0x04dd342,0x1b49a5d,0x00d01ef,0x3cb6768, - 0x1ceafbd,0x31c6812,0x001cb80 }, - { 0x221c677,0x060ca27,0x398b17f,0x0146723,0x36452af,0x02d9e65, - 0x39c5f78,0x3cf50d6,0x0be40f8,0x2970b87,0x26d667c,0x3e45959, - 0x16e7943,0x01673e7,0x009faaa } }, - /* 177 */ - { { 0x2078fe6,0x0918602,0x11dd8ad,0x399193f,0x0f6cc73,0x0f8dd12, - 0x2ce34dc,0x06d7d34,0x0c5e327,0x0989254,0x2fc5af7,0x2443d7b, - 0x32bc662,0x2fe2a84,0x008b585 }, - { 0x039327f,0x08e616a,0x252f117,0x1f52ab0,0x234e2d2,0x0a5b313, - 0x2f59ef6,0x0f7a500,0x15c4705,0x2c02b81,0x28b4f09,0x08aa5c8, - 0x0180efc,0x0993e83,0x00a9e86 } }, - /* 178 */ - { { 0x0310ecc,0x2d8892f,0x14ed0b7,0x3c59fe8,0x08a1a74,0x0850e57, - 0x1d09607,0x044a21f,0x109f5c9,0x237c6cf,0x06b264a,0x3fc8f1a, - 0x0d4c539,0x2740f96,0x00dc2d4 }, - { 0x1d6f501,0x0adf4ea,0x14f7215,0x0930102,0x3f4c32e,0x24e2643, - 0x366596d,0x081ff18,0x38f94fb,0x2c21341,0x328594c,0x267c75c, - 0x196b3fd,0x29932cb,0x0036def } }, - /* 179 */ - { { 0x3ed7cbe,0x26de044,0x3d0e461,0x0565e12,0x295e500,0x31dc17f, - 0x32251c2,0x3420ca8,0x3995f0d,0x2e8ddab,0x0361a45,0x10971b0, - 0x11e7b55,0x33bc7ca,0x00812d2 }, - { 0x3d94972,0x1606817,0x0383ccf,0x0e795b7,0x026e20e,0x0f6fefc, - 0x13685d6,0x315d402,0x0cc36b8,0x1c7f059,0x390ef5e,0x316ae04, - 0x08c66b9,0x2fac9a4,0x0040086 } }, - /* 180 */ - { { 0x3e3c115,0x153de4d,0x1a8ae5e,0x2330511,0x169b8ee,0x1d965c2, - 0x2edff2b,0x3ef99e6,0x1631b46,0x1f8a238,0x118d7bb,0x12113c3, - 0x26424db,0x0f4122a,0x00e0ea2 }, - { 0x3d80a73,0x30393bc,0x0f98714,0x278ef59,0x087a0aa,0x3b18c20, - 0x04b8a82,0x2068e21,0x030255d,0x3382b27,0x055397f,0x05448dd, - 0x2015586,0x1190be0,0x000b979 } }, - /* 181 */ - { { 0x2e03080,0x2895692,0x09fb127,0x2d1602a,0x1232306,0x105bd4e, - 0x28cd6a6,0x0a83813,0x1ee13b0,0x2abadc3,0x0c09684,0x00e33e1, - 0x033eea3,0x30f0a39,0x00a710e }, - { 0x01b1f7d,0x1c959da,0x017077a,0x254bf0a,0x086fbce,0x15cd6b2, - 0x008683f,0x23a4f4d,0x22a6bd6,0x14e8c93,0x0027d15,0x31d0d4f, - 0x271777e,0x1533510,0x00ab603 } }, - /* 182 */ - { { 0x34c209d,0x14d0abb,0x270432a,0x1d02358,0x22ba752,0x209757f, - 0x34af6fc,0x1ffc52e,0x1ced28e,0x1870e46,0x1e0340f,0x3f0bf73, - 0x33ba91d,0x2ebca7c,0x00c6580 }, - { 0x1d442cb,0x0879d50,0x24e4ae1,0x3f4e91c,0x04c7727,0x093cd1d, - 0x16d6a45,0x10a8b95,0x0c77856,0x361f84f,0x217845f,0x0bbeec6, - 0x0485718,0x33c5385,0x00dcec0 } }, - /* 183 */ - { { 0x1539819,0x225507a,0x1bf11cb,0x13e7653,0x0c8cb3b,0x05f695e, - 0x353f634,0x2827874,0x3fb8053,0x22de9a5,0x035d8b7,0x2105cc7, - 0x2a7a98d,0x35bed95,0x0085748 }, - { 0x1859c5d,0x00e51f0,0x22a21fd,0x3054d74,0x06ce965,0x328eab7, - 0x26a13e0,0x13bfc65,0x01d4fb1,0x36600b9,0x36dd3fc,0x01232ed, - 0x15bbaa9,0x0ad7a51,0x0089b18 } }, - /* 184 */ - { { 0x3360710,0x1eb5a90,0x136bd77,0x3bd57a6,0x0841287,0x12886c9, - 0x35c6700,0x21bc6eb,0x25f35ad,0x3bcb01c,0x0707e72,0x23e9943, - 0x03e5233,0x34bb622,0x002bf8e }, - { 0x16e0d6a,0x04b3d2d,0x290cb02,0x049a10c,0x350537e,0x22cf71b, - 0x3184a19,0x2dc8b62,0x2350210,0x3b4afa6,0x159781e,0x1d01b6d, - 0x1853440,0x16442f0,0x005a78d } }, - /* 185 */ - { { 0x348b02c,0x1ea8ab5,0x3b954d5,0x14684ac,0x0be5b34,0x11c4496, - 0x0a7a456,0x14f6eb7,0x11a3221,0x2d65f82,0x32eb1ea,0x09c4018, - 0x3f301f3,0x32e8a1c,0x00bd9ad }, - { 0x0543f7f,0x31e744e,0x1fefd1d,0x24a486c,0x1000220,0x3977e3b, - 0x1b3ef51,0x2512a1b,0x2049e6b,0x122232b,0x391a32b,0x2f4a7b1, - 0x1c13e71,0x081a9b4,0x00d3516 } }, - /* 186 */ - { { 0x1924f43,0x1ae5495,0x28d52ef,0x2b93e77,0x2d2f401,0x371a010, - 0x33e8d7a,0x06ed3f1,0x30c0d9d,0x2589fa9,0x3bf3567,0x2ecf8fa, - 0x2dee4c3,0x152b620,0x007e8a2 }, - { 0x1924407,0x01bd42d,0x044a089,0x18686b5,0x2f14a0e,0x17cdce3, - 0x0efa216,0x3c586a8,0x1d6ae71,0x375831f,0x3175894,0x20e43eb, - 0x34c009e,0x3480527,0x00d115c } }, - /* 187 */ - { { 0x12abf77,0x38b0769,0x25682f2,0x295508c,0x0c2a0dc,0x1259b73, - 0x023ea25,0x340e7b5,0x3c7cd0d,0x1f92324,0x176405c,0x1528894, - 0x18f2e1e,0x2c59c35,0x001efb5 }, - { 0x0fb1471,0x07e7665,0x141da75,0x07d9f4a,0x0fdb31e,0x0dccda6, - 0x074eb25,0x3d92a9b,0x11189a0,0x1b4c557,0x24b8d2b,0x0533f92, - 0x0e9e344,0x2fa3dea,0x008d5a4 } }, - /* 188 */ - { { 0x2669e98,0x1ad3514,0x2a035c9,0x08a3f50,0x24547f9,0x0a145d3, - 0x1c1319d,0x3fe833d,0x1ae064b,0x1e01734,0x246d27e,0x3a2f13c, - 0x01e1150,0x263f55e,0x00f89ef }, - { 0x2e0b63f,0x3e57db7,0x23a4b4f,0x11c8899,0x0ad8500,0x348f3a7, - 0x2918604,0x27d6409,0x1ce5001,0x38f94c2,0x29a508a,0x39bdc89, - 0x3a52c27,0x194899e,0x00e9376 } }, - /* 189 */ - { { 0x0368708,0x34a2730,0x2e1da04,0x0bd78c1,0x2c45887,0x0c44bfa, - 0x3a23de3,0x390b9db,0x1746efd,0x05c638e,0x1d20609,0x3263370, - 0x31987f0,0x2988529,0x005fa3c }, - { 0x0aa9f2a,0x20622f7,0x060deee,0x0c9626a,0x3312cc7,0x18ebac7, - 0x008dd6c,0x0ad4fe6,0x3db4ea6,0x1dc3f50,0x090b6e9,0x0aff8d2, - 0x26aa62c,0x18f3e90,0x00105f8 } }, - /* 190 */ - { { 0x38059ad,0x25e576c,0x3ea00b2,0x1fa4191,0x25686b7,0x2d1ce8f, - 0x30470ed,0x3478bbf,0x340f9b6,0x1c9e348,0x3d594ec,0x2ffe56e, - 0x3f23deb,0x0cd34e9,0x00f4b72 }, - { 0x1a83f0b,0x2166029,0x28b32a2,0x06a5c5a,0x20786c4,0x0944604, - 0x0901bd2,0x379b84e,0x221e2fe,0x0346d54,0x1f4eb59,0x01b8993, - 0x2462e08,0x25f9d8b,0x006c4c8 } }, - /* 191 */ - { { 0x0b41d9d,0x2e417ed,0x265bd10,0x199148e,0x3826ca4,0x1a67e8d, - 0x1bbd13b,0x23e414d,0x3d773bc,0x356e64c,0x0d2118a,0x0cb587f, - 0x25fd093,0x24fb529,0x00158c6 }, - { 0x2806e63,0x3ecaa39,0x251b4dd,0x3b2d779,0x2e31ed3,0x066f1a6, - 0x060e518,0x2c7e3e5,0x0d62c76,0x0d88a70,0x101970a,0x1e3c8c6, - 0x272b8bb,0x083e73b,0x0031f38 } }, - /* 192 */ - { { 0x09e1c72,0x072bcb0,0x0cf4e93,0x2604a64,0x00715f2,0x10c98b6, - 0x2ad81d9,0x234fcce,0x37a7304,0x1974a4a,0x1c7415f,0x14aaa93, - 0x19587b1,0x3f643f4,0x00c3d10 }, - { 0x1ddadd0,0x2cd715d,0x294cf76,0x14479ed,0x19f5f4a,0x0198c09, - 0x1ab7ebc,0x182c0bc,0x0879202,0x1807273,0x05d39da,0x2c7d868, - 0x29c4ec4,0x1b13ad2,0x006dcd7 } }, - /* 193 */ - { { 0x1c83f01,0x0245bff,0x24f90ba,0x112554f,0x2354c8b,0x3f17988, - 0x0c511af,0x39e1e9b,0x26ae95b,0x0ae551c,0x35b41a6,0x0120455, - 0x1e989cb,0x1b37aff,0x00fa2ae }, - { 0x324659a,0x1aef1c3,0x1c43637,0x3f530a2,0x313a999,0x326af62, - 0x134184e,0x2ac131c,0x3f6a789,0x30a300a,0x13e526e,0x2107af3, - 0x093a8ff,0x2479902,0x00442b1 } }, - /* 194 */ - { { 0x22b6e20,0x31b18be,0x18614ca,0x26fdb5a,0x197f29e,0x325b44b, - 0x0ab1dbb,0x042348a,0x3275e8e,0x15bae44,0x0077124,0x2cf5345, - 0x2803ad4,0x188f2a2,0x0061b20 }, - { 0x2a560b1,0x3ced069,0x3cf42c2,0x100e167,0x3879e1d,0x0936ff0, - 0x1b51450,0x14c55f3,0x3153bfa,0x2957423,0x2a93823,0x15f5dce, - 0x2c9a22f,0x16731a8,0x00a97f2 } }, - /* 195 */ - { { 0x18edbbb,0x18c5ef9,0x1f13c30,0x071e77f,0x225ade5,0x1b60f75, - 0x1beaf11,0x3e495ad,0x2441dd8,0x2fa00e2,0x32a87b6,0x00050f2, - 0x038de7f,0x0037d6d,0x00a885d }, - { 0x39e48bd,0x1d9e433,0x2768e9f,0x3c29458,0x3f0bdf9,0x35ed5f2, - 0x36709fa,0x176dc10,0x012f7c1,0x2df8547,0x1d90ee3,0x053c089, - 0x21a8d35,0x200cb0d,0x002e84e } }, - /* 196 */ - { { 0x23ec8d8,0x1d81f55,0x0cb7227,0x07f8e4d,0x2a66181,0x163f577, - 0x272e7af,0x131a8f2,0x2046229,0x25e6276,0x36bbefe,0x2cdc22f, - 0x17c8288,0x33dd4fb,0x000d524 }, - { 0x330c073,0x1a6728b,0x1cf369f,0x12e7707,0x2f0fa26,0x17c2abd, - 0x0a45680,0x26ebd13,0x3c7d19b,0x1c3d6c8,0x2abd110,0x064fd07, - 0x09b8339,0x02b4a9f,0x009e3e1 } }, - /* 197 */ - { { 0x0ae972f,0x2093c35,0x06e7a90,0x0af1ba1,0x243eef0,0x2748582, - 0x0606122,0x13a45f9,0x0acfe60,0x08a685e,0x0eb184b,0x015bc11, - 0x0cdf423,0x157fad5,0x004fcad }, - { 0x2728d15,0x3e5bceb,0x0331a0f,0x31b1a80,0x28a2680,0x3b94955, - 0x04cae07,0x176b57e,0x03ac5a6,0x3d7918b,0x22d23f4,0x0ae077f, - 0x1eb075d,0x006f16c,0x006e473 } }, - /* 198 */ - { { 0x38219b9,0x0475a2b,0x107a774,0x39946c6,0x1cb883c,0x004e0ed, - 0x087e571,0x25c3497,0x059982f,0x0a71f66,0x118305d,0x1aaf294, - 0x3a5dbaa,0x34be404,0x00725fe }, - { 0x3abd109,0x336ebea,0x2528487,0x15a1d61,0x0c0f8cf,0x2b56095, - 0x2591e68,0x3549a80,0x1d1debb,0x0701c6c,0x161e7e3,0x1f7fa2e, - 0x3dfe192,0x17e6498,0x0055f89 } }, - /* 199 */ - { { 0x175645b,0x26c036c,0x0b92f89,0x09ed96d,0x351f3a6,0x19ce67b, - 0x33ac8db,0x2f0828b,0x27fe400,0x0b9c5e1,0x1967b95,0x3324080, - 0x11de142,0x1d44fb3,0x003d596 }, - { 0x3979775,0x3af37b6,0x3e88d41,0x2f1a8b9,0x299ba61,0x085413c, - 0x1149a53,0x0beb40e,0x31427ba,0x239f708,0x357d836,0x1558c22, - 0x280a79f,0x1b255f6,0x002b6d1 } }, - /* 200 */ - { { 0x39ad982,0x3d79d89,0x01a684a,0x0b6722e,0x39bb4c9,0x39a6399, - 0x1ad44e0,0x3059f5e,0x048265f,0x33a2fa4,0x0c3a4cc,0x0d7df98, - 0x23a33f1,0x34e2e21,0x00a0a10 }, - { 0x386efd9,0x1c91f34,0x06c2e19,0x3e6d48d,0x00eefd3,0x2181ef2, - 0x2415f97,0x1d33b08,0x0625086,0x1e8aa3e,0x08c9d60,0x0ab427b, - 0x2764fa7,0x3b7943e,0x00cd9f0 } }, - /* 201 */ - { { 0x1a46d4d,0x0e471f4,0x1693063,0x0467ac0,0x22df51c,0x127a0f7, - 0x0498008,0x20e0b16,0x1aa8ad0,0x1923f42,0x2a74273,0x01761ce, - 0x1600ca4,0x187b87e,0x00ee49e }, - { 0x0c76f73,0x19daf92,0x0b2ad76,0x3d8049d,0x1d9c100,0x0fe1c63, - 0x0bb67c8,0x035cc44,0x02002fc,0x37b2169,0x344656a,0x1127879, - 0x1939bc0,0x0dd8df6,0x0028ce7 } }, - /* 202 */ - { { 0x0544ac7,0x26bdc91,0x042697e,0x356e804,0x1f2c658,0x2ceb7ef, - 0x2dec39f,0x02c1dcc,0x391a2df,0x2344beb,0x2171e20,0x3099c94, - 0x0fa548a,0x37216c9,0x00f820c }, - { 0x0f4cf77,0x29bbaa5,0x33c6307,0x34a5128,0x118c783,0x2dd06b1, - 0x139d4c0,0x2db912e,0x1153ffb,0x1075eb3,0x3a255e4,0x2892161, - 0x36d5006,0x125338c,0x0014fbc } }, - /* 203 */ - { { 0x1584e3c,0x0830314,0x00279b9,0x167df95,0x2c7733c,0x2108aef, - 0x0ce1398,0x35aaf89,0x012523b,0x3c46b6a,0x388e6de,0x01a2002, - 0x0582dde,0x19c7fa3,0x007b872 }, - { 0x1e53510,0x11bca1f,0x19684e7,0x267de5c,0x2492f8b,0x364a2b0, - 0x080bc77,0x2c6d47b,0x248432e,0x3ace44f,0x32028f6,0x0212198, - 0x2f38bad,0x20d63f0,0x00122bb } }, - /* 204 */ - { { 0x30b29c3,0x3cec78e,0x01510a9,0x0c93e91,0x3837b64,0x1eca3a9, - 0x105c921,0x05d42e6,0x1379845,0x07ce6f2,0x0e8b6da,0x0e0f093, - 0x220b2cd,0x1f6c041,0x00299f5 }, - { 0x0afdce3,0x2b0e596,0x2f477b6,0x2ccf417,0x3a15206,0x26ec0bf, - 0x2e37e2b,0x2593282,0x0ab9db3,0x2841dd8,0x27954be,0x277a681, - 0x03f82e2,0x2b610c7,0x00446a1 } }, - /* 205 */ - { { 0x06b8195,0x3b3a817,0x31b9c6f,0x317d279,0x3d744a7,0x1de9eb9, - 0x296acc1,0x1ce9ea3,0x06c3587,0x246815d,0x3756736,0x0588518, - 0x1c971a4,0x1fde1f4,0x00aa021 }, - { 0x3fd3226,0x274561d,0x00be61e,0x01393d8,0x30f6f23,0x29b7fc1, - 0x04cebc7,0x0a892a7,0x20109f1,0x27456be,0x0c863ee,0x2eb6c8a, - 0x38c782b,0x039397a,0x00a2829 } }, - /* 206 */ - { { 0x29de330,0x21fe80f,0x145b55b,0x1986570,0x012b260,0x2482fbc, - 0x0536e0a,0x16b7382,0x32c4d19,0x1deffdb,0x145f418,0x0c67a76, - 0x2ce477f,0x218fe24,0x00f9848 }, - { 0x3e37657,0x3f074d3,0x245ad0e,0x20973c3,0x23c58de,0x2c332ef, - 0x2ad21a8,0x0bf1589,0x208af95,0x1f4a8c4,0x2b43735,0x1e46657, - 0x15d4f81,0x0c3e63a,0x005f19d } }, - /* 207 */ - { { 0x26865bb,0x20f6683,0x16a672e,0x0efd8d1,0x222f5af,0x18f2367, - 0x1e9c734,0x25c3902,0x178dfe6,0x2903a79,0x311b91c,0x1adbbe9, - 0x225a387,0x0b3e509,0x0089551 }, - { 0x34e462b,0x23b6a32,0x27c884c,0x129104b,0x384c015,0x3adedc7, - 0x325db1c,0x021dc10,0x1e366f7,0x3054df7,0x1992b9a,0x2824e64, - 0x0ae77f3,0x181b526,0x00a7316 } }, - /* 208 */ - { { 0x2d260f5,0x2434bf2,0x28c0139,0x0a7bb03,0x176c3be,0x3def5f5, - 0x05bee00,0x3692df7,0x3d2efeb,0x3a6f859,0x1122b87,0x38f779a, - 0x1415ccc,0x2c260ad,0x0075a28 }, - { 0x04607a6,0x042f37a,0x3f0df68,0x0a1bd36,0x3c6d581,0x2d36bfa, - 0x2d577d1,0x0a3affa,0x0b2066b,0x2e6f110,0x0b17e84,0x3c76a5e, - 0x1a57553,0x012f36a,0x0004595 } }, - /* 209 */ - { { 0x29e5836,0x0e6808c,0x269d13e,0x147dc5c,0x32c9e7d,0x09b258e, - 0x2c58d6f,0x1efd716,0x0437996,0x34ec31b,0x15908d9,0x2efa8fd, - 0x09ad160,0x079fc1f,0x00d8481 }, - { 0x3d20e4a,0x18269d6,0x3aa8fe7,0x34829c2,0x2e4325d,0x0d800e1, - 0x11f370b,0x10c08dc,0x22fd092,0x1a5fe55,0x0acc443,0x037030d, - 0x1cdd404,0x097379e,0x00fd6d7 } }, - /* 210 */ - { { 0x313eafb,0x3f438f3,0x2e5fb3e,0x2ed6a82,0x121009c,0x240889e, - 0x00c5537,0x269b792,0x334b2fc,0x1dd573c,0x07096ae,0x19296fc, - 0x3813985,0x2742f48,0x00ddd64 }, - { 0x2045041,0x3842c62,0x1572d0d,0x04f255f,0x06e05b4,0x383ec97, - 0x1ff8064,0x18bed71,0x39b6411,0x2764cc5,0x257439f,0x3521217, - 0x172aa42,0x342a2a3,0x0070c5b } }, - /* 211 */ - { { 0x3bdf646,0x1c5ce25,0x1f7ca76,0x2d2acca,0x3aa1485,0x23c97f7, - 0x3e11d6f,0x0609338,0x07ec622,0x01da8ff,0x3392474,0x17ca07f, - 0x13a9a04,0x353a5b4,0x0024557 }, - { 0x14c27cd,0x32012f7,0x3fea875,0x3d03d71,0x211c5f0,0x3157fdf, - 0x0c880bd,0x3c406b2,0x2c51103,0x24ab377,0x399faa8,0x0d06887, - 0x16b5738,0x28b33a7,0x00c7b67 } }, - /* 212 */ - { { 0x2357586,0x35c93e3,0x0da09a0,0x3d77d92,0x11d7f4f,0x37b98a9, - 0x3e6c9bf,0x2cdca70,0x2f00389,0x2412673,0x18eab87,0x0101436, - 0x11617e9,0x06d9b01,0x00e8eef }, - { 0x37e3ca9,0x16ffaf0,0x391debf,0x1b69382,0x07c5e94,0x312fa8a, - 0x0973142,0x2cadde4,0x109ee67,0x3a07db0,0x1afc5ed,0x08df66f, - 0x304c7af,0x0804aae,0x00d2e60 } }, - /* 213 */ - { { 0x24f57bf,0x1818322,0x182a615,0x25bfc44,0x0f97586,0x0a5bbc0, - 0x36773c6,0x1a2660c,0x3ceff66,0x3270152,0x319cd11,0x2845845, - 0x1acfad6,0x19076f8,0x009824a }, - { 0x289fd01,0x2de97ee,0x39d80b7,0x026227d,0x0f8d3b8,0x15e0a17, - 0x21ea08f,0x20a2317,0x136ae6d,0x3deb1d1,0x3521ef5,0x0de8801, - 0x0a25d5d,0x0612c98,0x005ecc4 } }, - /* 214 */ - { { 0x308c8d3,0x3aec669,0x01ecddc,0x13f18fe,0x1e63ed0,0x061cfe5, - 0x05f5a01,0x1db5741,0x14479f2,0x0ced6b5,0x025ae5b,0x09ca8f5, - 0x2160581,0x1404433,0x008bfeb }, - { 0x08228bf,0x0e02722,0x37df423,0x33ecabf,0x34bd82a,0x32f529f, - 0x28f1800,0x0c8f671,0x1246b44,0x1ff35dc,0x091db95,0x303f3da, - 0x28f7f60,0x3624136,0x00cfbb4 } }, - /* 215 */ - { { 0x326139a,0x2977e4e,0x3eb89a6,0x20ecb31,0x13e076a,0x2a592f3, - 0x28e82d5,0x235ad1e,0x239b927,0x262938a,0x2444354,0x141b263, - 0x0d56693,0x2a3fc78,0x0006497 }, - { 0x31efa05,0x3a3664a,0x3e333de,0x2a114e4,0x12da63c,0x3c15e6b, - 0x2f7277c,0x363aa92,0x2393236,0x16bd2d1,0x32b617f,0x32b656c, - 0x3b1246c,0x22e2e22,0x00ce76d } }, - /* 216 */ - { { 0x03843dc,0x094de82,0x13b463d,0x0507905,0x089eb35,0x2a6bf25, - 0x35ebc4e,0x2bb5d45,0x1808ed1,0x1de9949,0x185e829,0x0a55847, - 0x0b73d67,0x1a2ed61,0x008dd2d }, - { 0x133c3a4,0x04e7980,0x38ea237,0x2ad2f49,0x19de838,0x018bf36, - 0x29b072c,0x21c1ba0,0x14f63ba,0x31c1cc3,0x13cd05e,0x20120ff, - 0x1f84d60,0x16e0321,0x00872ab } }, - /* 217 */ - { { 0x19d4d49,0x1ddb4e6,0x05e7fc0,0x37bb0fd,0x1a3eb59,0x36b87f0, - 0x190e440,0x1c7fef2,0x31ea153,0x14cd65a,0x1bc7ab2,0x11f72ca, - 0x39582d4,0x0fa4d65,0x00cd5b6 }, - { 0x3d1ff11,0x0d9be9d,0x2903ae3,0x017b7b9,0x259f28f,0x110cefc, - 0x03fed1a,0x38039bd,0x09bdf9c,0x3055027,0x2ca9c5d,0x2d737b6, - 0x3bdb421,0x16560b5,0x00f9f33 } }, - /* 218 */ - { { 0x022c792,0x110de25,0x38bf959,0x08f2562,0x1239ea9,0x3c1d950, - 0x21a247d,0x315112d,0x285bb9f,0x2534a73,0x0b42455,0x1a4a99c, - 0x069009a,0x1680392,0x006e0ca }, - { 0x1b3bece,0x269e0a1,0x18926b7,0x0e7187e,0x241f35e,0x39d1fe0, - 0x02099aa,0x1675bfe,0x23fd0ca,0x3d6322b,0x19406b5,0x324c38a, - 0x242434a,0x3ae677c,0x002ce04 } }, - /* 219 */ - { { 0x2c37b82,0x1ae6506,0x0d83436,0x23496c1,0x0ff0c72,0x2711edf, - 0x1513611,0x04f9c7d,0x1edbeff,0x376fcb5,0x212a683,0x23bf547, - 0x0f9c4f7,0x16e6627,0x0082cd8 }, - { 0x0cb5d37,0x31b6db8,0x1a15e23,0x2f5cbb8,0x0818aee,0x21dc6c5, - 0x12aafd2,0x205f608,0x1d91def,0x3def088,0x1445c51,0x3100e8a, - 0x3746bda,0x145c4b0,0x00711b0 } }, - /* 220 */ - { { 0x2a99ecc,0x27b5217,0x35e10ed,0x036e32a,0x0f79950,0x15c32f7, - 0x2c87dcb,0x3ebb2a3,0x2c2d35d,0x114b3ec,0x2e4d80a,0x0c7eb89, - 0x2abe58d,0x3727737,0x00e6a37 }, - { 0x1eca452,0x1968d07,0x344e5d3,0x29435a2,0x109a5f8,0x181d12c, - 0x238ea5a,0x127a564,0x00dbb42,0x0fcbfb7,0x2909b2e,0x2571d3a, - 0x08250e3,0x0694e4e,0x00e156d } }, - /* 221 */ - { { 0x3181ae9,0x1acf411,0x3808d79,0x2a11065,0x0baf44b,0x133cfeb, - 0x1330943,0x1711b9a,0x2dec3bd,0x1906a9a,0x2ed947c,0x369d763, - 0x1a5254f,0x104a7a9,0x00acd9d }, - { 0x030301b,0x31568f5,0x2a4965c,0x33ded4b,0x03c9a5b,0x16541fc, - 0x1319cf1,0x2a3748b,0x1b5de74,0x18bb82e,0x077ac2b,0x309a87a, - 0x3c31420,0x0f6a4b9,0x00387d7 } }, - /* 222 */ - { { 0x0d3fdac,0x120cfa3,0x1b8e13c,0x1ccccb9,0x376fcd4,0x0bf87f4, - 0x271b4be,0x363b3fd,0x28b5d98,0x0535cd3,0x114bbc1,0x3ab4f19, - 0x10494b1,0x2161ece,0x00d14ca }, - { 0x12d37e9,0x110ebd7,0x062295a,0x1cc0119,0x073c6ea,0x15d5411, - 0x0aeb4b1,0x23fba91,0x175fab5,0x3ee8fe1,0x1c680a6,0x1e76f27, - 0x3ddfc97,0x3d69ecd,0x00e1ee5 } }, - /* 223 */ - { { 0x2d29f46,0x2d19204,0x3137cd0,0x02c3b54,0x193295b,0x02fbdb2, - 0x2260948,0x22c02ff,0x3885424,0x1299595,0x00e7f9c,0x310ff2a, - 0x01ea169,0x0deef85,0x0021908 }, - { 0x1b26cfb,0x38566a8,0x2852875,0x21debff,0x290ca9f,0x0b29663, - 0x26550d9,0x2b44457,0x05d1938,0x1f8f825,0x366ef93,0x1d8daec, - 0x069e5ef,0x342ece6,0x00b6034 } }, - /* 224 */ - { { 0x2d8356e,0x1578c09,0x226f4d2,0x3b74c51,0x0f83666,0x0323b59, - 0x1ddf61d,0x1ed8508,0x3c52667,0x0e5b91c,0x1e9b18b,0x352bdfa, - 0x13f75da,0x352aa4e,0x00fceff }, - { 0x1c731d5,0x04e2844,0x01d9843,0x286cbc5,0x105bcb3,0x05edd9c, - 0x21fa956,0x3b1ec83,0x01288cc,0x22fbf3a,0x10f1b56,0x081cf72, - 0x15cb758,0x18687c1,0x00f5722 } }, - /* 225 */ - { { 0x2973088,0x1209dcd,0x3980f31,0x0221aa7,0x1c008e7,0x011b098, - 0x395947e,0x2f2806d,0x27dca76,0x037c79a,0x31acddf,0x2bf6219, - 0x0d8f4ab,0x13644d9,0x00ff705 }, - { 0x2260594,0x18d51f8,0x277e2cf,0x1cb5cec,0x2468a53,0x3e6f4d7, - 0x019e24e,0x0f30f1d,0x0202404,0x34ad287,0x090b39c,0x23c11ea, - 0x1a2e3a2,0x3a851be,0x00dca2c } }, - /* 226 */ - { { 0x3277538,0x221cd94,0x3738ab7,0x0973da5,0x1a734e2,0x2c8b8b0, - 0x2e1d1e6,0x348499b,0x389ebe1,0x18b1854,0x02bb076,0x1b2b500, - 0x0f207f3,0x170cf99,0x0012088 }, - { 0x0fbfec2,0x1df55a4,0x34ae59e,0x2ab5e95,0x3f9e781,0x3411794, - 0x1410b05,0x17c3a00,0x0aaa91b,0x074ed7c,0x3fbb352,0x3477c01, - 0x3ee9ab3,0x0cfb1ca,0x0011c4b } }, - /* 227 */ - { { 0x3c3a7f3,0x2e60ca0,0x2354d32,0x33e2362,0x28083ab,0x03d3b16, - 0x3164045,0x0a41f7a,0x3f0641e,0x38635d1,0x31bbf03,0x225e2bb, - 0x0cd894e,0x1f72228,0x0093244 }, - { 0x33d5897,0x383faf3,0x0e6d561,0x0bc4d80,0x3fc3a68,0x05a9adc, - 0x0b9d73d,0x3d6031e,0x2ded29b,0x339c4ff,0x08d69e5,0x089488c, - 0x3fda40a,0x295c7fd,0x003a924 } }, - /* 228 */ - { { 0x0093bee,0x115532d,0x2ec0fb6,0x0969631,0x3a6d65a,0x0f43b4d, - 0x26994d4,0x0b51104,0x2515515,0x3695a26,0x284caa8,0x397aa30, - 0x25538b8,0x353f47c,0x0033f05 }, - { 0x3615d6e,0x37f8246,0x07dae0f,0x23dc154,0x02ded7e,0x1eef320, - 0x1631e51,0x3447f75,0x13e267f,0x353e1d1,0x3f89d62,0x369c8ff, - 0x1a21dc6,0x2b8b8f3,0x0055cbc } }, - /* 229 */ - { { 0x34e84f3,0x2f2539a,0x2c35336,0x0c53bdc,0x1728630,0x3ad5fe6, - 0x05fdeee,0x3386db6,0x272a42e,0x29fd38c,0x36f0320,0x21b2ed4, - 0x331e67f,0x28ae48c,0x00f09b6 }, - { 0x2778435,0x0fb3c55,0x32d221d,0x2660c8e,0x32977ba,0x1c12f03, - 0x1b57fb1,0x01229a8,0x38b389f,0x375ddf3,0x2c6b42c,0x3885d3e, - 0x2c55a9c,0x2ffc279,0x00404e2 } }, - /* 230 */ - { { 0x04c5ddb,0x2c4d788,0x150e9b9,0x110fbfd,0x29dbfe0,0x30ef83d, - 0x2ab4bfe,0x395bcd7,0x30d0a43,0x0e2d30f,0x0e73f9b,0x07199cc, - 0x0c9054c,0x22f4b1e,0x0092ed3 }, - { 0x386e27c,0x00fdaa8,0x0507c70,0x1beb3b6,0x0b9c4f4,0x277d519, - 0x024ec85,0x1cbaba8,0x1524295,0x112be58,0x21fc119,0x273578b, - 0x2358c27,0x280ca07,0x00aa376 } }, - /* 231 */ - { { 0x0dbc95c,0x16488cf,0x337a078,0x1abbcb8,0x0aae1aa,0x1caa151, - 0x00108d4,0x1edf701,0x3e68d03,0x1203214,0x0c7eee2,0x084c572, - 0x07752d2,0x215a3b9,0x00195d3 }, - { 0x2cd7fbe,0x06e80f6,0x052bd4b,0x07b4f83,0x24b5ac6,0x2aaded4, - 0x13c0526,0x0ffa9a3,0x08c660e,0x13c35c9,0x3145efb,0x36cfe24, - 0x0936daf,0x268e3d0,0x00a73fd } }, - /* 232 */ - { { 0x31b17ce,0x2e7bcee,0x3f31891,0x19f1849,0x1140236,0x015487f, - 0x32e58d3,0x202204a,0x049e350,0x1ce91f9,0x3f75150,0x27f212f, - 0x0d16ee4,0x1c894c4,0x004023f }, - { 0x33399fa,0x2397b6d,0x2a3ea60,0x36354ca,0x1f12632,0x117a105, - 0x22758e8,0x361844e,0x3851fc2,0x0ab92db,0x339d02f,0x1e7d6c4, - 0x19ebd38,0x0a9a036,0x00446d2 } }, - /* 233 */ - { { 0x3e164f1,0x008c092,0x19200f5,0x35a22e0,0x38d09d2,0x212b3bf, - 0x0056f19,0x3a03545,0x1f075e9,0x0e97137,0x1f496a9,0x32d1f9b, - 0x36bf738,0x35ace37,0x00899e1 }, - { 0x19eb2a6,0x21fa22d,0x338b69e,0x18e6d1f,0x1280d9d,0x1953a55, - 0x1411ea3,0x2960566,0x0fd969a,0x1f3e375,0x130742a,0x170aebd, - 0x33085ff,0x14d868d,0x00a4391 } }, - /* 234 */ - { { 0x0a4bdd2,0x39ca8ea,0x37026ac,0x346da3b,0x0c656cd,0x03136b6, - 0x233e7e9,0x0714352,0x08a9d95,0x192bb38,0x085d68e,0x20016b8, - 0x102b8ea,0x1f5dbdd,0x00fdd7a }, - { 0x0d6fa45,0x3ec29a6,0x2b8cce6,0x1c84413,0x0228f86,0x28275f7, - 0x3d8787d,0x0c19748,0x28b2ae9,0x1954850,0x2a56c36,0x3eae8f7, - 0x0aca595,0x00e42a2,0x00edbe5 } }, - /* 235 */ - { { 0x3b26c82,0x3682b6f,0x2f9cd64,0x0f254b0,0x0e5d70b,0x1f9dfda, - 0x28f365f,0x35a57d7,0x00208f2,0x19c8d38,0x112e7be,0x3e403bb, - 0x3734efa,0x24d12b3,0x0027dc6 }, - { 0x260a46a,0x13fd7b0,0x1c2880e,0x338b70c,0x27da5eb,0x29a7d54, - 0x1c5d73c,0x2130921,0x32969cc,0x2b37eda,0x2d6d4ec,0x0716bfb, - 0x0763703,0x1320889,0x00c7bbf } }, - /* 236 */ - { { 0x1fe01b2,0x2dcb1d2,0x11b89d5,0x219e4ea,0x0347851,0x3d1810e, - 0x3a3c54c,0x06dbe8e,0x03d3ab2,0x2dcfa39,0x3e57b8a,0x337a382, - 0x0426450,0x0e9f748,0x006488b }, - { 0x1dc4582,0x0e62cf7,0x06fea9e,0x2a56fb1,0x31698c1,0x15b4e10, - 0x1446ef1,0x0a689fc,0x1d87703,0x20ff497,0x2c71066,0x2c48868, - 0x2e6cf05,0x30aa9cb,0x0065b2d } }, - /* 237 */ - { { 0x1021d63,0x2217df3,0x1f0821a,0x057fa98,0x23f344b,0x173dcf9, - 0x1ba6ddc,0x22c8eb5,0x18f227a,0x0455343,0x1c55931,0x1d0dcf3, - 0x20fa19b,0x1c56618,0x004feab }, - { 0x19ec924,0x224e39f,0x2550509,0x179b51f,0x284d54a,0x2d85d41, - 0x2d1bdc1,0x1a29068,0x3826158,0x1267f85,0x3005a92,0x0769e00, - 0x379b617,0x17b5f63,0x00a70bf } }, - /* 238 */ - { { 0x22216c5,0x049437f,0x33510bc,0x141d806,0x22c37e2,0x1bc1adf, - 0x300175d,0x2e6ded8,0x0a18bfe,0x35377a3,0x382f843,0x08410ca, - 0x00afd4f,0x0be6c6b,0x008d70e }, - { 0x2e91abb,0x1cede2a,0x28f225c,0x28e18c0,0x30230dc,0x173cc2d, - 0x123ecfe,0x3c9962e,0x2c25506,0x27b5d53,0x329a5e3,0x106e231, - 0x3889b8e,0x3b0aeaf,0x00ee67c } }, - /* 239 */ - { { 0x3e46c65,0x0eb3d46,0x1d7ae18,0x23f9d59,0x2978953,0x2589ed3, - 0x073391d,0x2461e1e,0x0c19f1d,0x22fd2b1,0x0691f5c,0x2e67d8d, - 0x1fb985d,0x200dd28,0x00a68df }, - { 0x392b5fa,0x123b46f,0x1c323c4,0x104f82f,0x0a098c8,0x26fc05b, - 0x34cd557,0x0913639,0x09c115e,0x3977c34,0x3410b66,0x062b404, - 0x0213094,0x132c5e8,0x008b612 } }, - /* 240 */ - { { 0x26e3392,0x3b0ebf0,0x2e00425,0x1c285c8,0x3c07f84,0x08d5ad0, - 0x028190e,0x1669b73,0x1ffb1ef,0x053b65f,0x063028c,0x0aceb47, - 0x18988c2,0x0f09a30,0x0007072 }, - { 0x0f49e7d,0x28c0bd3,0x252270d,0x24cfc4a,0x0c5e87c,0x2165052, - 0x2cdd1d1,0x04931d2,0x3abca74,0x22b57dc,0x169fd47,0x0b928fb, - 0x17cc3e7,0x21a1ec4,0x0061593 } }, - /* 241 */ - { { 0x1aa0486,0x2e55dea,0x15577b7,0x0d6818f,0x36e41fb,0x2a411f5, - 0x17d5c7d,0x1eea6c0,0x28068a8,0x0e31d20,0x1f08ad9,0x117e973, - 0x08a28ab,0x085d30a,0x00cd9fb }, - { 0x347843d,0x1119095,0x11e3595,0x1b29584,0x134d64c,0x2ff3a35, - 0x247ea14,0x099fc4b,0x2056169,0x145dd03,0x2ed03fb,0x1250e3b, - 0x3f5135c,0x2b753f0,0x009da30 } }, - /* 242 */ - { { 0x0fa5200,0x214a0b3,0x313dc4e,0x23da866,0x3270760,0x15c9b8b, - 0x39a53df,0x1f79772,0x3c9e942,0x2984901,0x154d582,0x1685f87, - 0x2e1183e,0x1f79956,0x00b9987 }, - { 0x15254de,0x3a5cac0,0x37c56f0,0x2c7c29b,0x292a56d,0x195be2c, - 0x17e4e1a,0x0660f4a,0x052ad98,0x1267f80,0x07cfed8,0x194b4bc, - 0x01738d3,0x14ba10f,0x00c7843 } }, - /* 243 */ - { { 0x29b2d8a,0x242bc1f,0x19646ee,0x0615f3c,0x0ac8d70,0x07ca3bf, - 0x2d90317,0x2c83bdb,0x1a96812,0x39fdc35,0x31c61ee,0x2d55fd3, - 0x2375827,0x355f189,0x00f1c9b }, - { 0x21a6194,0x1f4050a,0x2b845cf,0x02c6242,0x2dd614e,0x3a4f0a9, - 0x39de100,0x24714fb,0x175e0cd,0x0be633d,0x14befc3,0x13b0318, - 0x1d68c50,0x299989e,0x00d0513 } }, - /* 244 */ - { { 0x059fb6a,0x2b6eb6a,0x3666a8e,0x39f6ca0,0x1cf8346,0x388b8d5, - 0x35e61a3,0x271adec,0x22c9963,0x20a4fb3,0x16f241c,0x0058b89, - 0x21ddafa,0x1ee6fde,0x00d2e6c }, - { 0x0075e63,0x39894d0,0x0286d0d,0x187e7b2,0x02405aa,0x3f91525, - 0x37830a8,0x2723088,0x2c7364e,0x013f406,0x104ba75,0x270f486, - 0x3520b4d,0x3852bc6,0x00d589b } }, - /* 245 */ - { { 0x262e53b,0x1da93d1,0x3676135,0x147e41d,0x335ec2f,0x1f02be5, - 0x297d139,0x22d6198,0x1fe9e59,0x13b4c80,0x1e70f60,0x2f1d4a9, - 0x2d95149,0x14d6ec4,0x00b54af }, - { 0x12c1c76,0x2930ac8,0x0dfd36e,0x31fac94,0x218f5bb,0x2828691, - 0x1466cc9,0x3645e83,0x1a4dac2,0x1549593,0x0e95fab,0x19567d2, - 0x27a3320,0x0642729,0x007487c } }, - /* 246 */ - { { 0x1e98e9c,0x2ff8df7,0x119975a,0x098a904,0x099b90b,0x336c7df, - 0x010996d,0x159d46d,0x3118b3b,0x3aacd1b,0x31f8ae1,0x214864f, - 0x398c104,0x089dae2,0x001ec4d }, - { 0x1452baa,0x2f24991,0x2572ba3,0x162b312,0x2387d18,0x147c5c7, - 0x38eff6e,0x0700251,0x37d931e,0x23cd5c1,0x254c8ca,0x3b9df37, - 0x1c9a4ff,0x0bfd547,0x00fb489 } }, - /* 247 */ - { { 0x1b8dff8,0x2f6b40b,0x05a25b1,0x3f5688a,0x1d462f4,0x2802d18, - 0x2aad8ed,0x1b46c75,0x3cf4130,0x250fefb,0x2a13fe1,0x23a1bcd, - 0x0940442,0x04605fe,0x00c8b2f }, - { 0x0d51afb,0x14a2abc,0x1d06762,0x291526c,0x2a3e2fe,0x28f77d9, - 0x3ad8f2e,0x3481a1b,0x04b4fbd,0x2836733,0x0189ff5,0x3a5f533, - 0x319a6cd,0x0f58667,0x00c3679 } }, - /* 248 */ - { { 0x1b85197,0x22426d4,0x2895ea3,0x342d324,0x3ffb17d,0x376cfcf, - 0x30878b1,0x3c3c83a,0x0ffc57c,0x0ac174a,0x1abd57e,0x2f78b9c, - 0x01b20d8,0x0a37103,0x007f2be }, - { 0x19a2d48,0x137288a,0x182d655,0x0ba0dde,0x25130ba,0x01c65c6, - 0x23205f1,0x2097621,0x2827cf2,0x2c57b98,0x03748f2,0x2db15fc, - 0x385a0d4,0x13690c0,0x00a9e3f } }, - /* 249 */ - { { 0x3fbc9c6,0x2df3b20,0x377e33e,0x31d1505,0x024a311,0x3c1d9ff, - 0x1377f74,0x00b6b20,0x2364ab7,0x184ab6b,0x2a77969,0x3f2db6c, - 0x2a6adb7,0x0a10073,0x004a6fb }, - { 0x1fc73de,0x2c74ab3,0x3d325e8,0x2346c0b,0x1d0efae,0x2076146, - 0x19c190d,0x225c4fe,0x3fafc80,0x2cf063d,0x11b7ae7,0x3dc4f9d, - 0x3c3f841,0x10d7c1f,0x000a4b3 } }, - /* 250 */ - { { 0x19b7d2e,0x28f1300,0x0b897dd,0x06b5371,0x0631c8d,0x336cc4f, - 0x09cd6e1,0x2ec1952,0x1104c07,0x07512bb,0x35f000d,0x25f84e9, - 0x1df4d8f,0x193f769,0x000e9ee }, - { 0x2346910,0x267cecf,0x0ad7eaa,0x087e8a5,0x1622f69,0x342cbfa, - 0x2aa20d0,0x206e88a,0x3991e58,0x093fb4b,0x0157180,0x3cecb5b, - 0x2e17c9a,0x1ea371f,0x00919e6 } }, - /* 251 */ - { { 0x2250533,0x13f931d,0x3ef8c72,0x395f605,0x18a2080,0x1cb25d4, - 0x2fb0f41,0x1c0ba8a,0x1eb17c0,0x266c433,0x09b7e3e,0x0e5d78f, - 0x0cdc5bf,0x1f7c734,0x0020611 }, - { 0x205ebd5,0x127986f,0x02c0fb0,0x1705b1e,0x1eb0bb5,0x2dffb42, - 0x2331b8a,0x18fc04e,0x31d6328,0x17db162,0x0d3b619,0x193bdb9, - 0x3f11662,0x2d8e694,0x0092c51 } }, - /* 252 */ - { { 0x08b364d,0x31ef20a,0x25c4a57,0x021ed07,0x14a562e,0x262a684, - 0x1d21c66,0x126e5a6,0x181f3f8,0x2a93b65,0x1eb726b,0x08fbbce, - 0x084f9a2,0x308f30a,0x0013159 }, - { 0x23f4963,0x0c7960e,0x2a81739,0x2242b69,0x3965003,0x2aca542, - 0x28a1c65,0x2ad48fb,0x149775f,0x1bbb7d2,0x0f2671b,0x3594b85, - 0x22f5563,0x2470f13,0x00fed44 } }, - /* 253 */ - { { 0x0eb453e,0x3ab70fd,0x1a5b335,0x18f2b74,0x25ff74b,0x3612a46, - 0x33d0d75,0x28cdda4,0x2b9b49b,0x22728fb,0x004c15b,0x1beb33b, - 0x1a7e41f,0x0c9b702,0x004ef19 }, - { 0x1ca3233,0x0b4c90f,0x1d4b53d,0x2428896,0x20ee405,0x151bc00, - 0x022edb5,0x1adc463,0x00109ea,0x06490a6,0x30e91e6,0x3682b76, - 0x23c50aa,0x3bd2665,0x005fe53 } }, - /* 254 */ - { { 0x0c28c65,0x3741ae4,0x247d372,0x0b04673,0x2176524,0x2c8bf20, - 0x01fb806,0x3330701,0x307b0a7,0x3999fb7,0x1261bec,0x256679c, - 0x3f22ac7,0x26e8673,0x00bc69d }, - { 0x3c06819,0x35df344,0x379d009,0x2bb8a0a,0x0635a66,0x096c6fa, - 0x1ac4a62,0x023e53b,0x0e45240,0x115f53d,0x3056af8,0x0a66b16, - 0x3c386ee,0x1130e82,0x00cc384 } }, - /* 255 */ - { { 0x14c2356,0x190ec73,0x07be490,0x145d415,0x0740a48,0x1251301, - 0x3eaf29d,0x2628190,0x079299a,0x26e95c9,0x2e05fdf,0x2ca7c5b, - 0x32d7b48,0x3d84226,0x0033fb4 }, - { 0x150f955,0x01240aa,0x3ddf867,0x137fb70,0x297e103,0x17eeda8, - 0x1320b60,0x266ec84,0x13f4322,0x0c8f5ee,0x0590e4a,0x386815e, - 0x00ce61f,0x161bd63,0x008e1d0 } }, -}; - -/* 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. - * 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_15(sp_point_384* r, const sp_digit* k, - int map, int ct, void* heap) -{ - return sp_384_ecc_mulmod_stripe_15(r, &p384_base, p384_table, - k, map, ct, heap); -} - -#endif - -/* Multiply the base point of P384 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_384(const mp_int* km, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_384, point, 1); - SP_DECL_VAR(sp_digit, k, 15); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 15, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_384_from_mp(k, 15, km); - - err = sp_384_ecc_mulmod_base_15(point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_15(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_384, point, 2); - SP_DECL_VAR(sp_digit, k, 15 + 15 * 2 * 6); - sp_point_384* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 15 + 15 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ -#ifndef WC_NO_RNG -/* Add 1 to a. (a = a + 1) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_add_one_15(sp_digit* a) -{ - a[0]++; - sp_384_norm_15(a); -} - -#endif -/* 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_384_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 >= 18U) { - r[j] &= 0x3ffffff; - s = 26U - 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; - } -} - -/* Generates a scalar that is in the range 1..order-1. - * - * rng Random number generator. - * k Scalar value. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. - */ -static int sp_384_ecc_gen_k_15(WC_RNG* rng, sp_digit* k) -{ -#ifndef WC_NO_RNG - int err; - byte buf[48]; - - do { - err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); - if (err == 0) { - sp_384_from_bin(k, 15, buf, (int)sizeof(buf)); - if (sp_384_cmp_15(k, p384_order2) <= 0) { - sp_384_add_one_15(k); - break; - } - } - } - while (err == 0); - - return err; -#else - (void)rng; - (void)k; - return NOT_COMPILED_IN; -#endif -} - -/* Makes a random EC key pair. - * - * rng Random number generator. - * priv Generated private value. - * pub Generated public point. - * heap Heap to use for allocation. - * returns ECC_INF_E when the point does not have the correct order, RNG - * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) -{ -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_DECL_VAR(sp_point_384, point, 2); -#else - SP_DECL_VAR(sp_point_384, point, 1); -#endif - SP_DECL_VAR(sp_digit, k, 15); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384* infinity = NULL; -#endif - int err = MP_OKAY; - - - (void)heap; - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_ALLOC_VAR(sp_point_384, point, 2, heap, DYNAMIC_TYPE_ECC); -#else - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); -#endif - SP_ALLOC_VAR(sp_digit, k, 15, heap, DYNAMIC_TYPE_ECC); - 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) { - err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, NULL); - } - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_15(infinity, point, p384_order, 1, 1, NULL); - } - if (err == MP_OKAY) { - if (sp_384_iszero_15(point->x) || sp_384_iszero_15(point->y)) { - err = ECC_INF_E; - } - } -#endif - - if (err == MP_OKAY) { - err = sp_384_to_mp(k, priv); - } - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_15(point, pub); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - /* point is not sensitive, so no need to zeroize */ - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_key_gen_384_ctx { - int state; - sp_384_ecc_mulmod_15_ctx mulmod_ctx; - sp_digit k[15]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 point[2]; -#else - sp_point_384 point[1]; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ -} sp_ecc_key_gen_384_ctx; - -int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, - ecc_point* pub, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384* infinity = ctx->point + 1; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - - typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) - >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - err = sp_384_ecc_gen_k_15(rng, ctx->k); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - ctx->state = 1; - } - break; - case 1: - err = sp_384_ecc_mulmod_base_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - #else - ctx->state = 3; - #endif - } - break; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - case 2: - err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p384_order, 1, 1); - if (err == MP_OKAY) { - if (sp_384_iszero_15(ctx->point->x) || - sp_384_iszero_15(ctx->point->y)) { - err = ECC_INF_E; - } - else { - err = FP_WOULDBLOCK; - ctx->state = 3; - } - } - break; - #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - case 3: - err = sp_384_to_mp(ctx->k, priv); - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_15(ctx->point, pub); - } - break; - } - - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#ifdef HAVE_ECC_DHE -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 48 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_384_to_bin_15(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<14; i++) { - r[i+1] += r[i] >> 26; - r[i] &= 0x3ffffff; - } - j = 391 / 8 - 1; - a[j] = 0; - for (i=0; i<15 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 26) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 26); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Multiply the point by the scalar and serialize the X ordinate. - * The number is 0 padded to maximum size on output. - * - * priv Scalar to multiply the point by. - * pub Point to multiply. - * out Buffer to hold X ordinate. - * outLen On entry, size of the buffer in bytes. - * On exit, length of data in buffer in bytes. - * heap Heap to use for allocation. - * 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(const mp_int* priv, const ecc_point* pub, byte* out, - word32* outLen, void* heap) -{ - SP_DECL_VAR(sp_point_384, point, 1); - SP_DECL_VAR(sp_digit, k, 15); - int err = MP_OKAY; - - if (*outLen < 48U) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 15, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_384_from_mp(k, 15, priv); - sp_384_point_from_ecc_point_15(point, pub); - err = sp_384_ecc_mulmod_15(point, point, k, 1, 1, heap); - } - if (err == MP_OKAY) { - sp_384_to_bin_15(point->x, out); - *outLen = 48; - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sec_gen_384_ctx { - int state; - union { - sp_384_ecc_mulmod_15_ctx mulmod_ctx; - }; - sp_digit k[15]; - sp_point_384 point; -} sp_ecc_sec_gen_384_ctx; - -int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, - const ecc_point* pub, byte* out, word32* outLen, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - if (*outLen < 32U) { - err = BUFFER_E; - } - - switch (ctx->state) { - case 0: - sp_384_from_mp(ctx->k, 15, priv); - sp_384_point_from_ecc_point_15(&ctx->point, pub); - ctx->state = 1; - break; - case 1: - err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - sp_384_to_bin_15(ctx->point.x, out); - *outLen = 48; - } - break; - } - - if (err == MP_OKAY && ctx->state != 1) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_DHE */ - -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -SP_NOINLINE static void sp_384_rshift_15(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<14; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (26 - n))) & 0x3ffffff); - } -#else - for (i=0; i<8; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (26 - n)) & 0x3ffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (26 - n)) & 0x3ffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (26 - n)) & 0x3ffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (26 - n)) & 0x3ffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (26 - n)) & 0x3ffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (26 - n)) & 0x3ffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (26 - n)) & 0x3ffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (26 - n)) & 0x3ffffff); - } - r[8] = (a[8] >> n) | (sp_digit)((a[9] << (26 - n)) & 0x3ffffff); - r[9] = (a[9] >> n) | (sp_digit)((a[10] << (26 - n)) & 0x3ffffff); - r[10] = (a[10] >> n) | (sp_digit)((a[11] << (26 - n)) & 0x3ffffff); - r[11] = (a[11] >> n) | (sp_digit)((a[12] << (26 - n)) & 0x3ffffff); - r[12] = (a[12] >> n) | (sp_digit)((a[13] << (26 - n)) & 0x3ffffff); - r[13] = (a[13] >> n) | (sp_digit)((a[14] << (26 - n)) & 0x3ffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[14] = a[14] >> n; -} - -/* 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_384_mul_d_15(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 15; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x3ffffff); - t >>= 26; - } - r[15] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t[15]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - t[ 7] = tb * a[ 7]; - t[ 8] = tb * a[ 8]; - t[ 9] = tb * a[ 9]; - t[10] = tb * a[10]; - t[11] = tb * a[11]; - t[12] = tb * a[12]; - t[13] = tb * a[13]; - t[14] = tb * a[14]; - r[ 0] = (sp_digit) (t[ 0] & 0x3ffffff); - r[ 1] = (sp_digit)((t[ 0] >> 26) + (t[ 1] & 0x3ffffff)); - r[ 2] = (sp_digit)((t[ 1] >> 26) + (t[ 2] & 0x3ffffff)); - r[ 3] = (sp_digit)((t[ 2] >> 26) + (t[ 3] & 0x3ffffff)); - r[ 4] = (sp_digit)((t[ 3] >> 26) + (t[ 4] & 0x3ffffff)); - r[ 5] = (sp_digit)((t[ 4] >> 26) + (t[ 5] & 0x3ffffff)); - r[ 6] = (sp_digit)((t[ 5] >> 26) + (t[ 6] & 0x3ffffff)); - r[ 7] = (sp_digit)((t[ 6] >> 26) + (t[ 7] & 0x3ffffff)); - r[ 8] = (sp_digit)((t[ 7] >> 26) + (t[ 8] & 0x3ffffff)); - r[ 9] = (sp_digit)((t[ 8] >> 26) + (t[ 9] & 0x3ffffff)); - r[10] = (sp_digit)((t[ 9] >> 26) + (t[10] & 0x3ffffff)); - r[11] = (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff)); - r[12] = (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff)); - r[13] = (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff)); - r[14] = (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff)); - r[15] = (sp_digit) (t[14] >> 26); -#endif /* WOLFSSL_SP_SMALL */ -} - -SP_NOINLINE static void sp_384_lshift_30(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[30] = a[29] >> (26 - n); - for (i=29; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (26 - n))) & 0x3ffffff); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[29]; - r[30] = s >> (26U - n); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (26U - n))) & 0x3ffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0x3ffffff); -} - -/* 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. - * - * Simplified based on top word of divisor being (1 << 26) - 1 - * - * 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, - const sp_digit* m, sp_digit* r) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 15 + 3); - int i; - sp_digit r1; - sp_digit mask; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 15 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 30 + 1; - sd = t2 + 15 + 1; - - sp_384_mul_d_15(sd, d, (sp_digit)1 << 6); - sp_384_lshift_30(t1, a, 6); - t1[15 + 15] += t1[15 + 15 - 1] >> 26; - t1[15 + 15 - 1] &= 0x3ffffff; - for (i=14; i>=0; i--) { - r1 = t1[15 + i]; - sp_384_mul_d_15(t2, sd, r1); - (void)sp_384_sub_15(&t1[i], &t1[i], t2); - t1[15 + i] -= t2[15]; - sp_384_norm_15(&t1[i + 1]); - - mask = ~((t1[15 + i] - 1) >> 31); - sp_384_cond_sub_15(t1 + i, t1 + i, sd, mask); - sp_384_norm_15(&t1[i + 1]); - } - sp_384_norm_15(t1); - sp_384_rshift_15(r, t1, 6); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_384_mod_15(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_384_div_15(a, m, NULL, r); -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply two number mod the order of P384 curve. (r = a * b mod order) - * - * r Result of the multiplication. - * a First operand of the multiplication. - * b Second operand of the multiplication. - */ -static void sp_384_mont_mul_order_15(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_384_mul_15(r, a, b); - sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order); -} - -#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL)) -#ifdef WOLFSSL_SP_SMALL -/* Order-2 for the P384 curve. */ -static const word32 p384_order_minus_2[12] = { - 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U, - 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU -}; -#else -/* The low half of the order-2 of the P384 curve. */ -static const word32 p384_order_low[6] = { - 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U -}; -#endif /* WOLFSSL_SP_SMALL */ - -/* Square number mod the order of P384 curve. (r = a * a mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_384_mont_sqr_order_15(sp_digit* r, const sp_digit* a) -{ - sp_384_sqr_15(r, a); - sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square number mod the order of P384 curve a number of times. - * (r = a ^ n mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_384_mont_sqr_n_order_15(sp_digit* r, const sp_digit* a, int n) -{ - int i; - - sp_384_mont_sqr_order_15(r, a); - for (i=1; i= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - XMEMCPY(t, a, sizeof(sp_digit) * 15); - ctx->i = 382; - ctx->state = 1; - break; - case 1: - sp_384_mont_sqr_order_15(t, t); - ctx->state = 2; - break; - case 2: - if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { - sp_384_mont_mul_order_15(t, t, a); - } - ctx->i--; - ctx->state = (ctx->i >= 0) ? 1 : 3; - break; - case 3: - XMEMCPY(r, t, sizeof(sp_digit) * 15U); - err = MP_OKAY; - break; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, - sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 15); - for (i=382; i>=0; i--) { - sp_384_mont_sqr_order_15(t, t); - if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_384_mont_mul_order_15(t, t, a); - } - } - XMEMCPY(r, t, sizeof(sp_digit) * 15U); -#else - sp_digit* t = td; - sp_digit* t2 = td + 2 * 15; - sp_digit* t3 = td + 4 * 15; - int i; - - /* t = a^2 */ - sp_384_mont_sqr_order_15(t, a); - /* t = a^3 = t * a */ - sp_384_mont_mul_order_15(t, t, a); - /* t2= a^c = t ^ 2 ^ 2 */ - sp_384_mont_sqr_n_order_15(t2, t, 2); - /* t = a^f = t2 * t */ - sp_384_mont_mul_order_15(t, t2, t); - /* t2= a^f0 = t ^ 2 ^ 4 */ - sp_384_mont_sqr_n_order_15(t2, t, 4); - /* t = a^ff = t2 * t */ - sp_384_mont_mul_order_15(t, t2, t); - /* t2= a^ff00 = t ^ 2 ^ 8 */ - sp_384_mont_sqr_n_order_15(t2, t, 8); - /* t3= a^ffff = t2 * t */ - sp_384_mont_mul_order_15(t3, t2, t); - /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ - sp_384_mont_sqr_n_order_15(t2, t3, 16); - /* t = a^ffffffff = t2 * t3 */ - sp_384_mont_mul_order_15(t, t2, t3); - /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ - sp_384_mont_sqr_n_order_15(t2, t, 16); - /* t = a^ffffffffffff = t2 * t3 */ - sp_384_mont_mul_order_15(t, t2, t3); - /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ - sp_384_mont_sqr_n_order_15(t2, t, 48); - /* t= a^fffffffffffffffffffffffff = t2 * t */ - sp_384_mont_mul_order_15(t, t2, t); - /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ - sp_384_mont_sqr_n_order_15(t2, t, 96); - /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ - sp_384_mont_mul_order_15(t2, t2, t); - for (i=191; i>=1; i--) { - sp_384_mont_sqr_order_15(t2, t2); - if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_384_mont_mul_order_15(t2, t2, a); - } - } - sp_384_mont_sqr_order_15(t2, t2); - sp_384_mont_mul_order_15(r, t2, a); -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */ -#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; - sp_int32 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, - (sp_digit)0 - (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 - * s = (r * x + e) / k mod order - * The hash is truncated to the first 384 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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. - */ -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) -{ - SP_DECL_VAR(sp_digit, e, 7 * 2 * 15); - SP_DECL_VAR(sp_point_384, point, 1); - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, e, 7 * 2 * 15, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - x = e + 2 * 15; - k = e + 4 * 15; - r = e + 6 * 15; - tmp = e + 8 * 15; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_15(rng, k); - } - else { - sp_384_from_mp(k, 15, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 15U); - sp_384_norm_15(r); - c = sp_384_cmp_15(r, p384_order); - sp_384_cond_sub_15(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_15(r); - - if (!sp_384_iszero_15(r)) { - /* x is modified in calculation of s. */ - sp_384_from_mp(x, 15, priv); - /* s ptr == e ptr, e is modified in calculation of s. */ - sp_384_from_bin(e, 15, hash, (int)hashLen); - - err = sp_384_calc_s_15(s, r, k, x, e, tmp); - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (!sp_384_iszero_15(s))) { - break; - } - } - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - - SP_ZEROFREE_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_digit, e, 7 * 2 * 15, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sign_384_ctx { - int state; - union { - sp_384_ecc_mulmod_15_ctx mulmod_ctx; - sp_384_mont_inv_order_15_ctx mont_inv_order_ctx; - }; - sp_digit e[2*15]; - sp_digit x[2*15]; - sp_digit k[2*15]; - sp_digit r[2*15]; - sp_digit tmp[3 * 2*15]; - sp_point_384 point; - sp_digit* s; - sp_digit* kInv; - 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 err = FP_WOULDBLOCK; - sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - ctx->s = ctx->e; - ctx->kInv = ctx->k; - - ctx->i = SP_ECC_MAX_SIG_GEN; - ctx->state = 1; - break; - case 1: /* GEN */ - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_15(rng, ctx->k); - } - else { - sp_384_from_mp(ctx->k, 15, km); - mp_zero(km); - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - break; - case 2: /* MULMOD */ - err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &p384_base, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - ctx->state = 3; - } - break; - case 3: /* MODORDER */ - { - sp_int32 c; - /* r = point->x mod order */ - XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 15U); - sp_384_norm_15(ctx->r); - c = sp_384_cmp_15(ctx->r, p384_order); - sp_384_cond_sub_15(ctx->r, ctx->r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_15(ctx->r); - - if (hashLen > 48U) { - hashLen = 48U; - } - sp_384_from_mp(ctx->x, 15, priv); - sp_384_from_bin(ctx->e, 15, hash, (int)hashLen); - ctx->state = 4; - break; - } - case 4: /* KMODORDER */ - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_15(ctx->k, ctx->k, p384_norm_order); - err = sp_384_mod_15(ctx->k, ctx->k, p384_order); - if (err == MP_OKAY) { - sp_384_norm_15(ctx->k); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 5; - } - break; - case 5: /* KINV */ - /* kInv = 1/k mod order */ - err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); - if (err == MP_OKAY) { - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 6; - } - break; - case 6: /* KINVNORM */ - sp_384_norm_15(ctx->kInv); - ctx->state = 7; - break; - case 7: /* R */ - /* s = r * x + e */ - sp_384_mul_15(ctx->x, ctx->x, ctx->r); - ctx->state = 8; - break; - case 8: /* S1 */ - err = sp_384_mod_15(ctx->x, ctx->x, p384_order); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* S2 */ - { - sp_digit carry; - sp_int32 c; - sp_384_norm_15(ctx->x); - carry = sp_384_add_15(ctx->s, ctx->e, ctx->x); - sp_384_cond_sub_15(ctx->s, ctx->s, - p384_order, 0 - carry); - sp_384_norm_15(ctx->s); - c = sp_384_cmp_15(ctx->s, p384_order); - sp_384_cond_sub_15(ctx->s, ctx->s, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_15(ctx->s); - - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_15(ctx->s, ctx->s, ctx->kInv); - sp_384_norm_15(ctx->s); - - /* Check that signature is usable. */ - if (sp_384_iszero_15(ctx->s) == 0) { - ctx->state = 10; - break; - } - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - ctx->i = 1; - #endif - - /* not usable gen, try again */ - ctx->i--; - if (ctx->i == 0) { - err = RNG_FAILURE_E; - } - ctx->state = 1; - break; - } - case 10: /* RES */ - err = sp_384_to_mp(ctx->r, rm); - if (err == MP_OKAY) { - err = sp_384_to_mp(ctx->s, sm); - } - break; - } - - if (err == MP_OKAY && ctx->state != 10) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_SIGN */ - -#ifndef WOLFSSL_SP_SMALL -static const char sp_384_tab32_15[32] = { - 1, 10, 2, 11, 14, 22, 3, 30, - 12, 15, 17, 19, 23, 26, 4, 31, - 9, 13, 21, 29, 16, 18, 25, 8, - 20, 28, 24, 7, 27, 6, 5, 32}; - -static int sp_384_num_bits_26_15(sp_digit v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return sp_384_tab32_15[(word32)(v*0x07C4ACDD) >> 27]; -} - -static int sp_384_num_bits_15(const sp_digit* a) -{ - int i; - int r = 0; - - for (i = 14; i >= 0; i--) { - if (a[i] != 0) { - r = sp_384_num_bits_26_15(a[i]); - r += i * 26; - break; - } - } - - return r; -} - -/* 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. - * @return MEMEORY_E when dynamic memory allocation fails. - */ -static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int err = MP_OKAY; - SP_DECL_VAR(sp_digit, u, 15 * 4); - sp_digit* v = NULL; - sp_digit* b = NULL; - sp_digit* d = NULL; - int ut; - int vt; - - SP_ALLOC_VAR(sp_digit, u, 15 * 4, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - v = u + 15; - b = u + 2 * 15; - d = u + 3 * 15; - - XMEMCPY(u, m, sizeof(sp_digit) * 15); - XMEMCPY(v, a, sizeof(sp_digit) * 15); - - ut = sp_384_num_bits_15(u); - vt = sp_384_num_bits_15(v); - - XMEMSET(b, 0, sizeof(sp_digit) * 15); - if ((v[0] & 1) == 0) { - sp_384_rshift1_15(v, v); - XMEMCPY(d, m, sizeof(sp_digit) * 15); - d[0]++; - sp_384_rshift1_15(d, d); - vt--; - - while ((v[0] & 1) == 0) { - sp_384_rshift1_15(v, v); - if (d[0] & 1) - sp_384_add_15(d, d, m); - sp_384_rshift1_15(d, d); - vt--; - } - } - else { - XMEMSET(d+1, 0, sizeof(sp_digit) * (15 - 1)); - d[0] = 1; - } - - while (ut > 1 && vt > 1) { - if ((ut > vt) || ((ut == vt) && - (sp_384_cmp_15(u, v) >= 0))) { - sp_384_sub_15(u, u, v); - sp_384_norm_15(u); - - sp_384_sub_15(b, b, d); - sp_384_norm_15(b); - if (b[14] < 0) - sp_384_add_15(b, b, m); - sp_384_norm_15(b); - ut = sp_384_num_bits_15(u); - - do { - sp_384_rshift1_15(u, u); - if (b[0] & 1) - sp_384_add_15(b, b, m); - sp_384_rshift1_15(b, b); - ut--; - } - while (ut > 0 && (u[0] & 1) == 0); - } - else { - sp_384_sub_15(v, v, u); - sp_384_norm_15(v); - - sp_384_sub_15(d, d, b); - sp_384_norm_15(d); - if (d[14] < 0) - sp_384_add_15(d, d, m); - sp_384_norm_15(d); - vt = sp_384_num_bits_15(v); - - do { - sp_384_rshift1_15(v, v); - if (d[0] & 1) - sp_384_add_15(d, d, m); - sp_384_rshift1_15(d, d); - vt--; - } - while (vt > 0 && (v[0] & 1) == 0); - } - } - - if (ut == 1) - XMEMCPY(r, b, sizeof(sp_digit) * 15); - else - XMEMCPY(r, d, sizeof(sp_digit) * 15); - } - SP_FREE_VAR(u, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#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 Temporary 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 - err = sp_384_mod_inv_15(s, s, p384_order); - if (err == MP_OKAY) -#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) - * u1 = e/s mod order - * u2 = r/s mod order - * r == (u1.G + u2.Q)->x mod order - * Optimization: Leave point in projective form. - * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') - * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' - * The hash is truncated to the first 384 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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 MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -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) -{ - SP_DECL_VAR(sp_digit, u1, 18 * 15); - SP_DECL_VAR(sp_point_384, p1, 2); - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, u1, 18 * 15, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p1, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - 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, 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); - - err = sp_384_calc_vfy_point_15(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (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, rm); - err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_15(p1->z, p1->z, p384_mod, p384_mp_mod); - 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) { - /* Reload r and add order. */ - 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) { - sp_384_norm_15(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_15(u2, p384_mod); - } - } - 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); - } - } - } - - SP_FREE_VAR(p1, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(u1, heap, DYNAMIC_TYPE_ECC); - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_verify_384_ctx { - int state; - union { - sp_384_ecc_mulmod_15_ctx mulmod_ctx; - sp_384_mont_inv_order_15_ctx mont_inv_order_ctx; - sp_384_proj_point_dbl_15_ctx dbl_ctx; - sp_384_proj_point_add_15_ctx add_ctx; - }; - sp_digit u1[2*15]; - sp_digit u2[2*15]; - sp_digit s[2*15]; - sp_digit tmp[2*15 * 6]; - sp_point_384 p1; - 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, 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; - - typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(ctx->u1, 15, hash, (int)hashLen); - 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); - sp_384_from_mp(ctx->p2.z, 15, pZ); - ctx->state = 1; - break; - case 1: /* NORMS0 */ - sp_384_mul_15(ctx->s, ctx->s, p384_norm_order); - err = sp_384_mod_15(ctx->s, ctx->s, p384_order); - if (err == MP_OKAY) - ctx->state = 2; - break; - case 2: /* NORMS1 */ - sp_384_norm_15(ctx->s); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 3; - break; - case 3: /* NORMS2 */ - err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 4; - } - break; - case 4: /* NORMS3 */ - sp_384_mont_mul_order_15(ctx->u1, ctx->u1, ctx->s); - ctx->state = 5; - break; - case 5: /* NORMS4 */ - sp_384_mont_mul_order_15(ctx->u2, ctx->u2, ctx->s); - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 6; - break; - case 6: /* MULBASE */ - err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_384_iszero_15(ctx->p1.z)) { - ctx->p1.infinity = 1; - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 7; - } - break; - case 7: /* MULMOD */ - err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_384_iszero_15(ctx->p2.z)) { - ctx->p2.infinity = 1; - } - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 8; - } - break; - case 8: /* ADD */ - err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); - if (err == MP_OKAY) - ctx->state = 9; - break; - 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, rm); - err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) - ctx->state = 10; - break; - 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 = 11; - break; - case 11: /* MUL */ - sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 12; - break; - case 12: /* RES */ - { - sp_int32 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; - - /* Reload r and add order. */ - 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) { - sp_384_norm_15(ctx->u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_15(ctx->u2, p384_mod); - } - } - 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 != 12) { - err = FP_WOULDBLOCK; - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_VERIFY */ - -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* Check that the x and y ordinates 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_384_ecc_is_point_15(const sp_point_384* point, - void* heap) -{ - SP_DECL_VAR(sp_digit, t1, 15 * 4); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 15 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 15; - - /* y^2 - x^3 - a.x = b */ - sp_384_sqr_15(t1, point->y); - (void)sp_384_mod_15(t1, t1, p384_mod); - sp_384_sqr_15(t2, point->x); - (void)sp_384_mod_15(t2, t2, p384_mod); - sp_384_mul_15(t2, t2, point->x); - (void)sp_384_mod_15(t2, t2, p384_mod); - sp_384_mont_sub_15(t1, t1, t2, p384_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - sp_384_mont_add_15(t1, t1, point->x, p384_mod); - sp_384_mont_add_15(t1, t1, point->x, p384_mod); - sp_384_mont_add_15(t1, t1, point->x, p384_mod); - - - if (sp_384_cmp_15(t1, p384_b) != 0) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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_384(const mp_int* pX, const mp_int* pY) -{ - SP_DECL_VAR(sp_point_384, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, pub, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - 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)); - - err = sp_384_ecc_is_point_15(pub, NULL); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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_384(const mp_int* pX, const mp_int* pY, - const mp_int* privm, void* heap) -{ - SP_DECL_VAR(sp_digit, priv, 15); - SP_DECL_VAR(sp_point_384, pub, 2); - 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 (((mp_count_bits(pX) > 384) || - (mp_count_bits(pY) > 384) || - ((privm != NULL) && (mp_count_bits(privm) > 384)))) { - err = ECC_OUT_OF_RANGE_E; - } - - SP_ALLOC_VAR(sp_digit, priv, 15, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, pub, 2, heap, DYNAMIC_TYPE_ECC); - 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)); - if (privm) - sp_384_from_mp(priv, 15, privm); - - /* Check point at infinitiy. */ - if ((sp_384_iszero_15(pub->x) != 0) && - (sp_384_iszero_15(pub->y) != 0)) { - err = ECC_INF_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) { - /* Check point is on curve */ - err = sp_384_ecc_is_point_15(pub, heap); - } - - if (err == MP_OKAY) { - /* Point * order = infinity */ - err = sp_384_ecc_mulmod_15(p, pub, p384_order, 1, 1, heap); - } - /* 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) { - if (err == MP_OKAY) { - /* Base * private = point */ - err = sp_384_ecc_mulmod_base_15(p, priv, 1, 1, heap); - } - /* 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; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL -/* Add two projective EC points together. - * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) - * - * pX First EC point's X ordinate. - * pY First EC point's Y ordinate. - * pZ First EC point's Z ordinate. - * qX Second EC point's X ordinate. - * qY Second EC point's Y ordinate. - * qZ Second EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 15 * 6); - SP_DECL_VAR(sp_point_384, p, 2); - sp_point_384* q = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 15 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p, 2, NULL, DYNAMIC_TYPE_ECC); - 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); - sp_384_from_mp(q->x, 15, qX); - sp_384_from_mp(q->y, 15, qY); - sp_384_from_mp(q->z, 15, qZ); - p->infinity = sp_384_iszero_15(p->x) & - sp_384_iszero_15(p->y); - q->infinity = sp_384_iszero_15(q->x) & - sp_384_iszero_15(q->y); - - sp_384_proj_point_add_15(p, p, q, tmp); - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Double a projective EC point. - * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 15 * 2); - SP_DECL_VAR(sp_point_384, p, 1); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 15 * 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - p->infinity = sp_384_iszero_15(p->x) & - sp_384_iszero_15(p->y); - - sp_384_proj_point_dbl_15(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Map a projective EC point to affine in place. - * pZ will be one. - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 15 * 6); - SP_DECL_VAR(sp_point_384, p, 1); - int err = MP_OKAY; - - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 15 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - p->infinity = sp_384_iszero_15(p->x) & - sp_384_iszero_15(p->y); - - sp_384_map_15(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(p->x, pX); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pY); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifdef HAVE_COMP_KEY -/* Find the square root of a number mod the prime of the curve. - * - * y The number to operate on and the result. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mont_sqrt_15(sp_digit* y) -{ - SP_DECL_VAR(sp_digit, t1, 5 * 2 * 15); - sp_digit* t2 = NULL; - sp_digit* t3 = NULL; - sp_digit* t4 = NULL; - sp_digit* t5 = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, t1, 5 * 2 * 15, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 15; - t3 = t1 + 4 * 15; - t4 = t1 + 6 * 15; - t5 = t1 + 8 * 15; - - { - /* t2 = y ^ 0x2 */ - sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3 */ - sp_384_mont_mul_15(t1, t2, y, p384_mod, p384_mp_mod); - /* t5 = y ^ 0xc */ - sp_384_mont_sqr_n_15(t5, t1, 2, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xf */ - sp_384_mont_mul_15(t1, t1, t5, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x1e */ - sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod); - /* t3 = y ^ 0x1f */ - sp_384_mont_mul_15(t3, t2, y, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3e0 */ - sp_384_mont_sqr_n_15(t2, t3, 5, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3ff */ - sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x7fe0 */ - sp_384_mont_sqr_n_15(t2, t1, 5, p384_mod, p384_mp_mod); - /* t3 = y ^ 0x7fff */ - sp_384_mont_mul_15(t3, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fff800 */ - sp_384_mont_sqr_n_15(t2, t3, 15, p384_mod, p384_mp_mod); - /* t4 = y ^ 0x3ffffff */ - sp_384_mont_mul_15(t4, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xffffffc000000 */ - sp_384_mont_sqr_n_15(t2, t4, 30, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xfffffffffffff */ - sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xfffffffffffffff000000000000000 */ - sp_384_mont_sqr_n_15(t2, t1, 60, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ - sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ - sp_384_mont_sqr_n_15(t2, t1, 120, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ - sp_384_mont_sqr_n_15(t2, t1, 15, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ - sp_384_mont_sqr_n_15(t2, t1, 31, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ - sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ - sp_384_mont_sqr_n_15(t2, t1, 4, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ - sp_384_mont_mul_15(t1, t5, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ - sp_384_mont_sqr_n_15(t2, t1, 62, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ - sp_384_mont_mul_15(t1, y, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ - sp_384_mont_sqr_n_15(y, t1, 30, p384_mod, p384_mp_mod); - } - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - - -/* Uncompress the point given the X ordinate. - * - * xm X ordinate. - * odd Whether the Y ordinate is odd. - * ym Calculated Y ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) -{ - SP_DECL_VAR(sp_digit, x, 4 * 15); - sp_digit* y = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, x, 4 * 15, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - y = x + 2 * 15; - - sp_384_from_mp(x, 15, xm); - err = sp_384_mod_mul_norm_15(x, x, p384_mod); - } - if (err == MP_OKAY) { - /* y = x^3 */ - { - sp_384_mont_sqr_15(y, x, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(y, y, x, p384_mod, p384_mp_mod); - } - /* y = x^3 - 3x */ - sp_384_mont_sub_15(y, y, x, p384_mod); - sp_384_mont_sub_15(y, y, x, p384_mod); - sp_384_mont_sub_15(y, y, x, p384_mod); - /* y = x^3 - 3x + b */ - err = sp_384_mod_mul_norm_15(x, p384_b, p384_mod); - } - if (err == MP_OKAY) { - sp_384_mont_add_15(y, y, x, p384_mod); - /* y = sqrt(x^3 - 3x + b) */ - err = sp_384_mont_sqrt_15(y); - } - if (err == MP_OKAY) { - XMEMSET(y + 15, 0, 15U * sizeof(sp_digit)); - sp_384_mont_reduce_15(y, p384_mod, p384_mp_mod); - if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { - sp_384_mont_sub_15(y, p384_mod, y, p384_mod); - } - - err = sp_384_to_mp(y, ym); - } - - SP_FREE_VAR(x, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* WOLFSSL_SP_384 */ -#ifdef WOLFSSL_SP_521 - -/* Point structure to use. */ -typedef struct sp_point_521 { - /* X ordinate of point. */ - sp_digit x[2 * 21]; - /* Y ordinate of point. */ - sp_digit y[2 * 21]; - /* Z ordinate of point. */ - sp_digit z[2 * 21]; - /* Indicates point is at infinity. */ - int infinity; -} sp_point_521; - -/* The modulus (prime) of the curve P521. */ -static const sp_digit p521_mod[21] = { - 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff, - 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff, - 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff -}; -/* The Montgomery normalizer for modulus of the curve P521. */ -static const sp_digit p521_norm_mod[21] = { - 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000 -}; -/* The Montgomery multiplier for modulus of the curve P521. */ -static const sp_digit p521_mp_mod = 0x000001; -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -/* The order of the curve P521. */ -static const sp_digit p521_order[21] = { - 0x1386409,0x1db8f48,0x1ebaedb,0x1113388,0x1bb5c9b,0x04d2e81,0x00523dc, - 0x0d6ff98,0x1bf2f96,0x0c343c1,0x1fffe94,0x1ffffff,0x1ffffff,0x1ffffff, - 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff -}; -#endif -#ifndef WC_NO_RNG -/* The order of the curve P521 minus 2. */ -static const sp_digit p521_order2[21] = { - 0x1386407,0x1db8f48,0x1ebaedb,0x1113388,0x1bb5c9b,0x04d2e81,0x00523dc, - 0x0d6ff98,0x1bf2f96,0x0c343c1,0x1fffe94,0x1ffffff,0x1ffffff,0x1ffffff, - 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery normalizer for order of the curve P521. */ -static const sp_digit p521_norm_order[21] = { - 0x0c79bf7,0x02470b7,0x0145124,0x0eecc77,0x044a364,0x1b2d17e,0x1fadc23, - 0x1290067,0x040d069,0x13cbc3e,0x000016b,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000 -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery multiplier for order of the curve P521. */ -static const sp_digit p521_mp_order = 0x1a995c7; -#endif -/* The base point of curve P521. */ -static const sp_point_521 p521_base = { - /* X ordinate */ - { - 0x0e5bd66,0x13f18e1,0x0a6fe5f,0x030ad48,0x1348b3c,0x1fd46f1,0x1049e8b, - 0x051fc3b,0x1efe759,0x0a5af3b,0x14f6ea8,0x1ec0d69,0x01f828a,0x029fda9, - 0x19204e4,0x1688538,0x1662395,0x0cf1f65,0x1013a73,0x1c0d6e0,0x00c6858, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0 - }, - /* Y ordinate */ - { - 0x1d16650,0x14a3b4f,0x090222f,0x0d44e58,0x153c708,0x1683b09,0x0e404fe, - 0x0818aa1,0x15ef426,0x1f7394c,0x1998b25,0x1a2e4e7,0x0817afb,0x0bcda23, - 0x1d51125,0x037b331,0x1b42c7d,0x02e452f,0x08ef001,0x12d4f13,0x0118392, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0 - }, - /* Z ordinate */ - { - 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0 - }, - /* infinity */ - 0 -}; -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) || \ - defined(HAVE_COMP_KEY) -static const sp_digit p521_b[21] = { - 0x1503f00,0x08fea35,0x13c7bd1,0x107a586,0x1573df8,0x18df839,0x102f4ee, - 0x0f62ca5,0x1ec7e93,0x10c9ca8,0x0427855,0x13231de,0x13b8b48,0x0cd98af, - 0x169c96e,0x081dd45,0x1a0b685,0x1c94d10,0x1872687,0x1d72c31,0x0051953 -}; -#endif - -#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. - */ -SP_NOINLINE static void sp_521_mul_21(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[20]) * b[20]; - r[41] = (sp_digit)(c >> 25); - c &= 0x1ffffff; - for (k = 39; k >= 0; k--) { - if (k >= 21) { - i = k - 20; - imax = 20; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 25; - r[k + 2] += (sp_digit)(c >> 25); - r[k + 1] = (sp_digit)(c & 0x1ffffff); - c = lo & 0x1ffffff; - } - r[0] = (sp_digit)c; -} - -#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_521_mul_21(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int j; - sp_int64 t[42]; - - XMEMSET(t, 0, sizeof(t)); - for (i=0; i<21; i++) { - for (j=0; j<21; j++) { - t[i+j] += ((sp_int64)a[i]) * b[j]; - } - } - for (i=0; i<41; i++) { - r[i] = (sp_digit)(t[i] & 0x1ffffff); - t[i+1] += t[i] >> 25; - } - r[41] = (sp_digit)t[41]; -} - -#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_521_sqr_21(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[20]) * a[20]; - r[41] = (sp_digit)(c >> 25); - c = (c & 0x1ffffff) << 25; - for (k = 39; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 20) { - imax = k; - } - else { - imax = 20; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - 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); -} - -#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_521_sqr_21(sp_digit* r, const sp_digit* a) -{ - int i; - int j; - sp_int64 t[42]; - - XMEMSET(t, 0, sizeof(t)); - for (i=0; i<21; i++) { - for (j=0; j> 25; - } - r[41] = (sp_digit)t[41]; -} - -#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_521_add_21(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 21; 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_521_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; -} - -#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_521_sub_21(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 21; 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_521_sub_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; -} - -#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_521_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 25 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 24); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 24); - } -#elif DIGIT_BIT > 25 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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_521. - * - * p Point of type sp_point_521 (result). - * pm Point of type ecc_point. - */ -static void sp_521_point_from_ecc_point_21(sp_point_521* 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_521_from_mp(p->x, 21, pm->x); - sp_521_from_mp(p->y, 21, pm->y); - sp_521_from_mp(p->z, 21, 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_521_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (521 + 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) * 21); - r->used = 21; - mp_clamp(r); -#elif DIGIT_BIT < 25 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 21; 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 = (521 + 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 < 21; 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 = (521 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_521 to type ecc_point. - * - * p Point of type sp_point_521. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_521_point_to_ecc_point_21(const sp_point_521* p, ecc_point* pm) -{ - int err; - - err = sp_521_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, pm->z); - } - - return err; -} - -/* Normalize the values in each word to 25 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_521_norm_21(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 20; i++) { - a[i+1] += a[i] >> 25; - a[i] &= 0x1ffffff; - } -#else - int i; - for (i = 0; i < 16; 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[17] += a[16] >> 25; a[16] &= 0x1ffffff; - a[18] += a[17] >> 25; a[17] &= 0x1ffffff; - a[19] += a[18] >> 25; a[18] &= 0x1ffffff; - a[20] += a[19] >> 25; a[19] &= 0x1ffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Reduce the number back to 521 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_521_mont_reduce_21(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - - (void)m; - (void)mp; - - for (i = 0; i < 20; i++) { - a[i] += (sp_digit)(((a[20 + i] >> 21) + (a[20 + i + 1] << 4)) & 0x1ffffff); - } - a[20] &= 0x1fffff; - a[20] += (sp_digit)(((a[40] >> 21) + (a[41] << 4)) & 0x1ffffff); - - sp_521_norm_21(a); - - a[0] += a[20] >> 21; - a[20] &= 0x1fffff; -} - -/* 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_521_cmp_21(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=20; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 24); - } -#else - int i; - - r |= (a[20] - b[20]) & (0 - (sp_digit)1); - r |= (a[19] - b[19]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[18] - b[18]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[17] - b[17]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[16] - b[16]) & ~(((sp_digit)0 - r) >> 24); - for (i = 8; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 24); - } -#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_521_cond_sub_21(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 < 21; 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); - r[18] = a[18] - (b[18] & m); - r[19] = a[19] - (b[19] & m); - r[20] = a[20] - (b[20] & 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_521_mul_add_21(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 20; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1ffffff); - t[1] += t[0] >> 25; - r[i+1] = (sp_digit)(t[1] & 0x1ffffff); - t[2] += t[1] >> 25; - r[i+2] = (sp_digit)(t[2] & 0x1ffffff); - t[3] += t[2] >> 25; - r[i+3] = (sp_digit)(t[3] & 0x1ffffff); - t[0] = t[3] >> 25; - } - t[0] += (tb * a[20]) + r[20]; - r[20] = (sp_digit)(t[0] & 0x1ffffff); - r[21] += (sp_digit)(t[0] >> 25); -#else - sp_int64 tb = b; - sp_int64 t[8]; - int i; - - t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffff); - for (i = 0; i < 16; 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[17]; - r[17] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff)); - t[2] = tb * a[18]; - r[18] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff)); - t[3] = tb * a[19]; - r[19] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff)); - t[4] = tb * a[20]; - r[20] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff)); - r[21] += (sp_digit)(t[4] >> 25); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Shift the result in the high 521 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_521_mont_shift_21(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_digit n; - sp_digit s; - - s = a[21]; - n = a[20] >> 21; - for (i = 0; i < 20; i++) { - n += (sp_digit)((s & 0x1ffffff) << 4); - r[i] = (sp_digit)(n & 0x1ffffff); - n >>= 25; - s = a[22 + i] + (s >> 25); - } - n += s << 4; - r[20] = n; -#else - sp_digit n; - sp_digit s; - int i; - - s = a[21]; n = a[20] >> 21; - for (i = 0; i < 16; i += 8) { - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+0] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+22] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+1] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+23] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+2] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+24] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+3] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+25] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+4] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+26] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+5] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+27] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+6] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+28] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[i+7] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[i+29] + (s >> 25); - } - n += (sp_digit)((s & 0x1ffffff) << 4); r[16] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[38] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[17] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[39] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[18] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[40] + (s >> 25); - n += (sp_digit)((s & 0x1ffffff) << 4); r[19] = (sp_digit)(n & 0x1ffffff); - n >>= 25; s = a[41] + (s >> 25); - n += s << 4; r[20] = n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[21], 0, sizeof(*r) * 21U); -} - -/* Reduce the number back to 521 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_521_mont_reduce_order_21(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_521_norm_21(a + 21); - - for (i=0; i<20; i++) { - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1ffffff); - sp_521_mul_add_21(a+i, m, mu); - a[i+1] += a[i] >> 25; - } - mu = (sp_digit)(((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffL); - sp_521_mul_add_21(a+i, m, mu); - a[i+1] += a[i] >> 25; - a[i] &= 0x1ffffff; - sp_521_mont_shift_21(a, a); - over = a[20] >> 21; - sp_521_cond_sub_21(a, a, m, ~((over - 1) >> 31)); - sp_521_norm_21(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_521_mont_mul_21(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_521_mul_21(r, a, b); - sp_521_mont_reduce_21(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_521_mont_sqr_21(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_521_sqr_21(r, a); - sp_521_mont_reduce_21(r, m, mp); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square the Montgomery form number a number of times. (r = a ^ n mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * n Number of times to square. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_521_mont_sqr_n_21(sp_digit* r, - const sp_digit* a, int n, const sp_digit* m, sp_digit mp) -{ - sp_521_mont_sqr_21(r, a, m, mp); - for (; n > 1; n--) { - sp_521_mont_sqr_21(r, r, m, mp); - } -} - -#endif /* !WOLFSSL_SP_SMALL */ -#ifdef WOLFSSL_SP_SMALL -/* Mod-2 for the P521 curve. */ -static const word32 p521_mod_minus_2[17] = { - 0xfffffffdU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU, - 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU, - 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU -}; -#endif /* !WOLFSSL_SP_SMALL */ - -/* Invert the number, in Montgomery form, modulo the modulus (prime) of the - * P521 curve. (r = 1 / a mod m) - * - * r Inverse result. - * a Number to invert. - * td Temporary data. - */ -static void sp_521_mont_inv_21(sp_digit* r, const sp_digit* a, sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 21); - for (i=519; i>=0; i--) { - sp_521_mont_sqr_21(t, t, p521_mod, p521_mp_mod); - if (p521_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) - sp_521_mont_mul_21(t, t, a, p521_mod, p521_mp_mod); - } - XMEMCPY(r, t, sizeof(sp_digit) * 21); -#else - sp_digit* t1 = td; - sp_digit* t2 = td + 2 * 21; - sp_digit* t3 = td + 4 * 21; - - /* 0x2 */ - sp_521_mont_sqr_21(t1, a, p521_mod, p521_mp_mod); - /* 0x3 */ - sp_521_mont_mul_21(t2, t1, a, p521_mod, p521_mp_mod); - /* 0x6 */ - sp_521_mont_sqr_21(t1, t2, p521_mod, p521_mp_mod); - /* 0x7 */ - sp_521_mont_mul_21(t3, t1, a, p521_mod, p521_mp_mod); - /* 0xc */ - sp_521_mont_sqr_n_21(t1, t2, 2, p521_mod, p521_mp_mod); - /* 0xf */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0x78 */ - sp_521_mont_sqr_n_21(t1, t2, 3, p521_mod, p521_mp_mod); - /* 0x7f */ - sp_521_mont_mul_21(t3, t3, t1, p521_mod, p521_mp_mod); - /* 0xf0 */ - sp_521_mont_sqr_n_21(t1, t2, 4, p521_mod, p521_mp_mod); - /* 0xff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xff00 */ - sp_521_mont_sqr_n_21(t1, t2, 8, p521_mod, p521_mp_mod); - /* 0xffff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffff0000 */ - sp_521_mont_sqr_n_21(t1, t2, 16, p521_mod, p521_mp_mod); - /* 0xffffffff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffff00000000 */ - sp_521_mont_sqr_n_21(t1, t2, 32, p521_mod, p521_mp_mod); - /* 0xffffffffffffffff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffffffffffff0000000000000000 */ - sp_521_mont_sqr_n_21(t1, t2, 64, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 */ - sp_521_mont_sqr_n_21(t1, t2, 128, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000 */ - sp_521_mont_sqr_n_21(t1, t2, 256, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 */ - sp_521_mont_sqr_n_21(t1, t2, 7, p521_mod, p521_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_21(t2, t3, t1, p521_mod, p521_mp_mod); - /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc */ - sp_521_mont_sqr_n_21(t1, t2, 2, p521_mod, p521_mp_mod); - /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd */ - sp_521_mont_mul_21(r, t1, a, p521_mod, p521_mp_mod); - -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_521_map_21(sp_point_521* r, const sp_point_521* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*21; - sp_int32 n; - - sp_521_mont_inv_21(t1, p->z, t + 2*21); - - sp_521_mont_sqr_21(t2, t1, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t1, t2, t1, p521_mod, p521_mp_mod); - - /* x /= z^2 */ - sp_521_mont_mul_21(r->x, p->x, t2, p521_mod, p521_mp_mod); - XMEMSET(r->x + 21, 0, sizeof(sp_digit) * 21U); - sp_521_mont_reduce_21(r->x, p521_mod, p521_mp_mod); - /* Reduce x to less than modulus */ - n = sp_521_cmp_21(r->x, p521_mod); - sp_521_cond_sub_21(r->x, r->x, p521_mod, (sp_digit)~(n >> 24)); - sp_521_norm_21(r->x); - - /* y /= z^3 */ - sp_521_mont_mul_21(r->y, p->y, t1, p521_mod, p521_mp_mod); - XMEMSET(r->y + 21, 0, sizeof(sp_digit) * 21U); - sp_521_mont_reduce_21(r->y, p521_mod, p521_mp_mod); - /* Reduce y to less than modulus */ - n = sp_521_cmp_21(r->y, p521_mod); - sp_521_cond_sub_21(r->y, r->y, p521_mod, (sp_digit)~(n >> 24)); - sp_521_norm_21(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_add_21(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - sp_digit over; - (void)sp_521_add_21(r, a, b); - sp_521_norm_21(r); - over = r[20] >> 21; - sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31)); - sp_521_norm_21(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_dbl_21(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_521_add_21(r, a, a); - sp_521_norm_21(r); - over = r[20] >> 21; - sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31)); - sp_521_norm_21(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_tpl_21(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_521_add_21(r, a, a); - sp_521_norm_21(r); - over = r[20] >> 21; - sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31)); - sp_521_norm_21(r); - (void)sp_521_add_21(r, r, a); - sp_521_norm_21(r); - over = r[20] >> 21; - sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31)); - sp_521_norm_21(r); -} - -#ifdef 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_521_cond_add_21(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 21; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_521_cond_add_21(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - 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); - r[18] = a[18] + (b[18] & m); - r[19] = a[19] + (b[19] & m); - r[20] = a[20] + (b[20] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_sub_21(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_521_sub_21(r, a, b); - sp_521_norm_21(r); - sp_521_cond_add_21(r, r, m, r[20] >> 21); - sp_521_norm_21(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -SP_NOINLINE static void sp_521_rshift1_21(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=0; i<20; i++) { - r[i] = (a[i] >> 1) + (sp_digit)((a[i + 1] << 24) & 0x1ffffff); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 24) & 0x1ffffff); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 24) & 0x1ffffff); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 24) & 0x1ffffff); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 24) & 0x1ffffff); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 24) & 0x1ffffff); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 24) & 0x1ffffff); - r[6] = (a[6] >> 1) + (sp_digit)((a[7] << 24) & 0x1ffffff); - r[7] = (a[7] >> 1) + (sp_digit)((a[8] << 24) & 0x1ffffff); - r[8] = (a[8] >> 1) + (sp_digit)((a[9] << 24) & 0x1ffffff); - r[9] = (a[9] >> 1) + (sp_digit)((a[10] << 24) & 0x1ffffff); - r[10] = (a[10] >> 1) + (sp_digit)((a[11] << 24) & 0x1ffffff); - r[11] = (a[11] >> 1) + (sp_digit)((a[12] << 24) & 0x1ffffff); - r[12] = (a[12] >> 1) + (sp_digit)((a[13] << 24) & 0x1ffffff); - r[13] = (a[13] >> 1) + (sp_digit)((a[14] << 24) & 0x1ffffff); - r[14] = (a[14] >> 1) + (sp_digit)((a[15] << 24) & 0x1ffffff); - r[15] = (a[15] >> 1) + (sp_digit)((a[16] << 24) & 0x1ffffff); - r[16] = (a[16] >> 1) + (sp_digit)((a[17] << 24) & 0x1ffffff); - r[17] = (a[17] >> 1) + (sp_digit)((a[18] << 24) & 0x1ffffff); - r[18] = (a[18] >> 1) + (sp_digit)((a[19] << 24) & 0x1ffffff); - r[19] = (a[19] >> 1) + (sp_digit)((a[20] << 24) & 0x1ffffff); -#endif - r[20] = a[20] >> 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_521_mont_div2_21(sp_digit* r, const sp_digit* a, - const sp_digit* m) -{ - sp_521_cond_add_21(r, a, m, 0 - (a[0] & 1)); - sp_521_norm_21(r); - sp_521_rshift1_21(r, r); -} - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static void sp_521_proj_point_dbl_21(sp_point_521* r, const sp_point_521* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*21; - 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_521_mont_sqr_21(t1, p->z, p521_mod, p521_mp_mod); - /* Z = Y * Z */ - sp_521_mont_mul_21(z, p->y, p->z, p521_mod, p521_mp_mod); - /* Z = 2Z */ - sp_521_mont_dbl_21(z, z, p521_mod); - /* T2 = X - T1 */ - sp_521_mont_sub_21(t2, p->x, t1, p521_mod); - /* T1 = X + T1 */ - sp_521_mont_add_21(t1, p->x, t1, p521_mod); - /* T2 = T1 * T2 */ - sp_521_mont_mul_21(t2, t1, t2, p521_mod, p521_mp_mod); - /* T1 = 3T2 */ - sp_521_mont_tpl_21(t1, t2, p521_mod); - /* Y = 2Y */ - sp_521_mont_dbl_21(y, p->y, p521_mod); - /* Y = Y * Y */ - sp_521_mont_sqr_21(y, y, p521_mod, p521_mp_mod); - /* T2 = Y * Y */ - sp_521_mont_sqr_21(t2, y, p521_mod, p521_mp_mod); - /* T2 = T2/2 */ - sp_521_mont_div2_21(t2, t2, p521_mod); - /* Y = Y * X */ - sp_521_mont_mul_21(y, y, p->x, p521_mod, p521_mp_mod); - /* X = T1 * T1 */ - sp_521_mont_sqr_21(x, t1, p521_mod, p521_mp_mod); - /* X = X - Y */ - sp_521_mont_sub_21(x, x, y, p521_mod); - /* X = X - Y */ - sp_521_mont_sub_21(x, x, y, p521_mod); - /* Y = Y - X */ - sp_521_mont_sub_21(y, y, x, p521_mod); - /* Y = Y * T1 */ - sp_521_mont_mul_21(y, y, t1, p521_mod, p521_mp_mod); - /* Y = Y - T2 */ - sp_521_mont_sub_21(y, y, t2, p521_mod); -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_521_proj_point_dbl_21_ctx { - int state; - sp_digit* t1; - sp_digit* t2; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_521_proj_point_dbl_21_ctx; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static int sp_521_proj_point_dbl_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_point_521* p, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_521_proj_point_dbl_21_ctx* ctx = (sp_521_proj_point_dbl_21_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_521_proj_point_dbl_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - ctx->t1 = t; - ctx->t2 = t + 2*21; - 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_521_mont_sqr_21(ctx->t1, p->z, p521_mod, p521_mp_mod); - ctx->state = 2; - break; - case 2: - /* Z = Y * Z */ - sp_521_mont_mul_21(ctx->z, p->y, p->z, p521_mod, p521_mp_mod); - ctx->state = 3; - break; - case 3: - /* Z = 2Z */ - sp_521_mont_dbl_21(ctx->z, ctx->z, p521_mod); - ctx->state = 4; - break; - case 4: - /* T2 = X - T1 */ - sp_521_mont_sub_21(ctx->t2, p->x, ctx->t1, p521_mod); - ctx->state = 5; - break; - case 5: - /* T1 = X + T1 */ - sp_521_mont_add_21(ctx->t1, p->x, ctx->t1, p521_mod); - ctx->state = 6; - break; - case 6: - /* T2 = T1 * T2 */ - sp_521_mont_mul_21(ctx->t2, ctx->t1, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 7; - break; - case 7: - /* T1 = 3T2 */ - sp_521_mont_tpl_21(ctx->t1, ctx->t2, p521_mod); - ctx->state = 8; - break; - case 8: - /* Y = 2Y */ - sp_521_mont_dbl_21(ctx->y, p->y, p521_mod); - ctx->state = 9; - break; - case 9: - /* Y = Y * Y */ - sp_521_mont_sqr_21(ctx->y, ctx->y, p521_mod, p521_mp_mod); - ctx->state = 10; - break; - case 10: - /* T2 = Y * Y */ - sp_521_mont_sqr_21(ctx->t2, ctx->y, p521_mod, p521_mp_mod); - ctx->state = 11; - break; - case 11: - /* T2 = T2/2 */ - sp_521_mont_div2_21(ctx->t2, ctx->t2, p521_mod); - ctx->state = 12; - break; - case 12: - /* Y = Y * X */ - sp_521_mont_mul_21(ctx->y, ctx->y, p->x, p521_mod, p521_mp_mod); - ctx->state = 13; - break; - case 13: - /* X = T1 * T1 */ - sp_521_mont_sqr_21(ctx->x, ctx->t1, p521_mod, p521_mp_mod); - ctx->state = 14; - break; - case 14: - /* X = X - Y */ - sp_521_mont_sub_21(ctx->x, ctx->x, ctx->y, p521_mod); - ctx->state = 15; - break; - case 15: - /* X = X - Y */ - sp_521_mont_sub_21(ctx->x, ctx->x, ctx->y, p521_mod); - ctx->state = 16; - break; - case 16: - /* Y = Y - X */ - sp_521_mont_sub_21(ctx->y, ctx->y, ctx->x, p521_mod); - ctx->state = 17; - break; - case 17: - /* Y = Y * T1 */ - sp_521_mont_mul_21(ctx->y, ctx->y, ctx->t1, p521_mod, p521_mp_mod); - ctx->state = 18; - break; - case 18: - /* Y = Y - T2 */ - sp_521_mont_sub_21(ctx->y, ctx->y, ctx->t2, p521_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 */ -/* 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_521_cmp_equal_21(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])) == 0; -} - -/* 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_521_iszero_21(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]) == 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. - */ -static void sp_521_proj_point_add_21(sp_point_521* r, - const sp_point_521* p, const sp_point_521* q, sp_digit* t) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*21; - sp_digit* t2 = t + 4*21; - sp_digit* t3 = t + 6*21; - sp_digit* t4 = t + 8*21; - sp_digit* t5 = t + 10*21; - - /* U1 = X1*Z2^2 */ - sp_521_mont_sqr_21(t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t3, t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t1, t1, p->x, p521_mod, p521_mp_mod); - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_21(t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t4, t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_521_mont_mul_21(t3, t3, p->y, p521_mod, p521_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_521_cmp_equal_21(t2, t1) & - sp_521_cmp_equal_21(t4, t3)) { - sp_521_proj_point_dbl_21(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* H = U2 - U1 */ - sp_521_mont_sub_21(t2, t2, t1, p521_mod); - /* R = S2 - S1 */ - sp_521_mont_sub_21(t4, t4, t3, p521_mod); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(y, t1, t5, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod); - /* Z3 = H*Z1*Z2 */ - sp_521_mont_mul_21(z, p->z, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(z, z, q->z, p521_mod, p521_mp_mod); - sp_521_mont_sqr_21(x, t4, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(x, x, t5, p521_mod); - sp_521_mont_mul_21(t5, t5, t3, p521_mod, p521_mp_mod); - sp_521_mont_dbl_21(t3, y, p521_mod); - sp_521_mont_sub_21(x, x, t3, p521_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_521_mont_sub_21(y, y, x, p521_mod); - sp_521_mont_mul_21(y, y, t4, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(y, y, t5, p521_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 21; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 21; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 21; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_521_proj_point_add_21_ctx { - int state; - sp_521_proj_point_dbl_21_ctx dbl_ctx; - const sp_point_521* ap[2]; - sp_point_521* rp[2]; - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; - sp_digit* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_521_proj_point_add_21_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -static int sp_521_proj_point_add_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_point_521* p, const sp_point_521* q, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_521_proj_point_add_21_ctx* ctx = (sp_521_proj_point_add_21_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_521_proj_point_add_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_521* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*21; - ctx->t2 = t + 4*21; - ctx->t3 = t + 6*21; - ctx->t4 = t + 8*21; - ctx->t5 = t + 10*21; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_521_mont_sqr_21(ctx->t1, q->z, p521_mod, p521_mp_mod); - ctx->state = 2; - break; - case 2: - sp_521_mont_mul_21(ctx->t3, ctx->t1, q->z, p521_mod, p521_mp_mod); - ctx->state = 3; - break; - case 3: - sp_521_mont_mul_21(ctx->t1, ctx->t1, p->x, p521_mod, p521_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_21(ctx->t2, p->z, p521_mod, p521_mp_mod); - ctx->state = 5; - break; - case 5: - sp_521_mont_mul_21(ctx->t4, ctx->t2, p->z, p521_mod, p521_mp_mod); - ctx->state = 6; - break; - case 6: - sp_521_mont_mul_21(ctx->t2, ctx->t2, q->x, p521_mod, p521_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_521_mont_mul_21(ctx->t3, ctx->t3, p->y, p521_mod, p521_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_21(ctx->t4, ctx->t4, q->y, p521_mod, p521_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_521_cmp_equal_21(ctx->t2, ctx->t1) & - sp_521_cmp_equal_21(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_521_proj_point_dbl_21(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_521_mont_sub_21(ctx->t2, ctx->t2, ctx->t1, p521_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_521_mont_sub_21(ctx->t4, ctx->t4, ctx->t3, p521_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_521_mont_sqr_21(ctx->t5, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 13; - break; - case 13: - sp_521_mont_mul_21(ctx->y, ctx->t1, ctx->t5, p521_mod, p521_mp_mod); - ctx->state = 14; - break; - case 14: - sp_521_mont_mul_21(ctx->t5, ctx->t5, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_521_mont_mul_21(ctx->z, p->z, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 16; - break; - case 16: - sp_521_mont_mul_21(ctx->z, ctx->z, q->z, p521_mod, p521_mp_mod); - ctx->state = 17; - break; - case 17: - sp_521_mont_sqr_21(ctx->x, ctx->t4, p521_mod, p521_mp_mod); - ctx->state = 18; - break; - case 18: - sp_521_mont_sub_21(ctx->x, ctx->x, ctx->t5, p521_mod); - ctx->state = 19; - break; - case 19: - sp_521_mont_mul_21(ctx->t5, ctx->t5, ctx->t3, p521_mod, p521_mp_mod); - ctx->state = 20; - break; - case 20: - sp_521_mont_dbl_21(ctx->t3, ctx->y, p521_mod); - sp_521_mont_sub_21(ctx->x, ctx->x, ctx->t3, p521_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_521_mont_sub_21(ctx->y, ctx->y, ctx->x, p521_mod); - ctx->state = 22; - break; - case 22: - sp_521_mont_mul_21(ctx->y, ctx->y, ctx->t4, p521_mod, p521_mp_mod); - ctx->state = 23; - break; - case 23: - sp_521_mont_sub_21(ctx->y, ctx->y, ctx->t5, p521_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 21; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 21; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 21; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -/* Multiply a number by Montgomery 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_521_mod_mul_norm_21(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - (void)m; - - if (r != a) { - XMEMCPY(r, a, 21 * sizeof(sp_digit)); - } - - return MP_OKAY; -} - -#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. - * 521 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. - */ -static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_521, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 21 * 6); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_521, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 21 * 6, heap, DYNAMIC_TYPE_ECC); - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_521) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod); - } - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod); - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod); - - if (err == MP_OKAY) { - i = 20; - c = 21; - 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_521_proj_point_add_21(&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_521)); - sp_521_proj_point_dbl_21(&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_521)); - } - - if (map != 0) { - sp_521_map_21(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_521)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 21 * 6, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_521, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_521_ecc_mulmod_21_ctx { - int state; - union { - sp_521_proj_point_dbl_21_ctx dbl_ctx; - sp_521_proj_point_add_21_ctx add_ctx; - }; - sp_point_521 t[3]; - sp_digit tmp[2 * 21 * 6]; - sp_digit n; - int i; - int c; - int y; -} sp_521_ecc_mulmod_21_ctx; - -static int sp_521_ecc_mulmod_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_point_521* g, const sp_digit* k, int map, int ct, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_521_ecc_mulmod_21_ctx* ctx = (sp_521_ecc_mulmod_21_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_521_ecc_mulmod_21_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_521) * 3); - ctx->i = 20; - ctx->c = 21; - 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_521_mod_mul_norm_21(ctx->t[1].x, g->x, p521_mod); - ctx->state = 2; - break; - case 2: /* T1Y */ - err = sp_521_mod_mul_norm_21(ctx->t[1].y, g->y, p521_mod); - ctx->state = 3; - break; - case 3: /* T1Z */ - err = sp_521_mod_mul_norm_21(ctx->t[1].z, g->z, p521_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_521_proj_point_add_21_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_521)); - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 6; - } - break; - case 6: /* DBL */ - err = sp_521_proj_point_dbl_21_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_521)); - ctx->state = 4; - ctx->c--; - } - break; - case 7: /* MAP */ - if (map != 0) { - sp_521_map_21(r, &ctx->t[0], ctx->tmp); - } - else { - XMEMCPY(r, &ctx->t[0], sizeof(sp_point_521)); - } - 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 */ - -#else -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_521 { - sp_digit x[21]; - sp_digit y[21]; -} sp_table_entry_521; - -/* 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_521_cond_copy_21(sp_digit* r, const sp_digit* a, const sp_digit m) -{ - sp_digit t[21]; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i = 0; i < 21; i++) { - t[i] = r[i] ^ a[i]; - } - for (i = 0; i < 21; 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]; - 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; -#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_521_proj_point_dbl_n_21(sp_point_521* p, int i, - sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*21; - sp_digit* b = t + 4*21; - sp_digit* t1 = t + 6*21; - sp_digit* t2 = t + 8*21; - sp_digit* x; - sp_digit* y; - sp_digit* z; - volatile int n = i - 1; - - x = p->x; - y = p->y; - z = p->z; - - /* Y = 2*Y */ - sp_521_mont_dbl_21(y, y, p521_mod); - /* W = Z^4 */ - sp_521_mont_sqr_21(w, z, p521_mod, p521_mp_mod); - sp_521_mont_sqr_21(w, w, p521_mod, p521_mp_mod); -#ifndef WOLFSSL_SP_SMALL - while (n > 0) -#else - while (n >= 0) -#endif - { - /* A = 3*(X^2 - W) */ - sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(t1, t1, w, p521_mod); - sp_521_mont_tpl_21(a, t1, p521_mod); - /* B = X*Y^2 */ - sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod); - /* X = A^2 - 2B */ - sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod); - sp_521_mont_dbl_21(t2, b, p521_mod); - sp_521_mont_sub_21(x, x, t2, p521_mod); - /* B = 2.(B - X) */ - sp_521_mont_sub_21(t2, b, x, p521_mod); - sp_521_mont_dbl_21(b, t2, p521_mod); - /* Z = Z*Y */ - sp_521_mont_mul_21(z, z, y, p521_mod, p521_mp_mod); - /* t1 = Y^4 */ - sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod); -#ifdef WOLFSSL_SP_SMALL - if (n != 0) -#endif - { - /* W = W*Y^4 */ - sp_521_mont_mul_21(w, w, t1, p521_mod, p521_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(y, y, t1, p521_mod); - n = n - 1; - } -#ifndef WOLFSSL_SP_SMALL - /* A = 3*(X^2 - W) */ - sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(t1, t1, w, p521_mod); - sp_521_mont_tpl_21(a, t1, p521_mod); - /* B = X*Y^2 */ - sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod); - /* X = A^2 - 2B */ - sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod); - sp_521_mont_dbl_21(t2, b, p521_mod); - sp_521_mont_sub_21(x, x, t2, p521_mod); - /* B = 2.(B - X) */ - sp_521_mont_sub_21(t2, b, x, p521_mod); - sp_521_mont_dbl_21(b, t2, p521_mod); - /* Z = Z*Y */ - sp_521_mont_mul_21(z, z, y, p521_mod, p521_mp_mod); - /* t1 = Y^4 */ - sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(y, y, t1, p521_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_521_mont_div2_21(y, y, p521_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_521_proj_point_dbl_n_store_21(sp_point_521* r, - const sp_point_521* p, int n, int m, sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*21; - sp_digit* b = t + 4*21; - sp_digit* t1 = t + 6*21; - sp_digit* t2 = t + 8*21; - sp_digit* x = r[2*m].x; - sp_digit* y = r[(1<x[i]; - } - for (i=0; i<21; i++) { - y[i] = p->y[i]; - } - for (i=0; i<21; i++) { - z[i] = p->z[i]; - } - - /* Y = 2*Y */ - sp_521_mont_dbl_21(y, y, p521_mod); - /* W = Z^4 */ - sp_521_mont_sqr_21(w, z, p521_mod, p521_mp_mod); - sp_521_mont_sqr_21(w, w, p521_mod, p521_mp_mod); - j = m; - for (i=1; i<=n; i++) { - j *= 2; - - /* A = 3*(X^2 - W) */ - sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(t1, t1, w, p521_mod); - sp_521_mont_tpl_21(a, t1, p521_mod); - /* B = X*Y^2 */ - sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod); - x = r[j].x; - /* X = A^2 - 2B */ - sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod); - sp_521_mont_dbl_21(t2, b, p521_mod); - sp_521_mont_sub_21(x, x, t2, p521_mod); - /* B = 2.(B - X) */ - sp_521_mont_sub_21(t2, b, x, p521_mod); - sp_521_mont_dbl_21(b, t2, p521_mod); - /* Z = Z*Y */ - sp_521_mont_mul_21(r[j].z, z, y, p521_mod, p521_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod); - if (i != n) { - /* W = W*Y^4 */ - sp_521_mont_mul_21(w, w, t1, p521_mod, p521_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(y, y, t1, p521_mod); - /* Y = Y/2 */ - sp_521_mont_div2_21(r[j].y, y, p521_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_521_proj_point_add_sub_21(sp_point_521* ra, - sp_point_521* rs, const sp_point_521* p, const sp_point_521* q, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*21; - sp_digit* t3 = t + 4*21; - sp_digit* t4 = t + 6*21; - sp_digit* t5 = t + 8*21; - sp_digit* t6 = t + 10*21; - sp_digit* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, p->z, sizeof(p->z) / 2); - ra->infinity = 0; - rs->infinity = 0; - - /* U1 = X1*Z2^2 */ - sp_521_mont_sqr_21(t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t3, t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t1, t1, xa, p521_mod, p521_mp_mod); - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_21(t2, za, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t4, t2, za, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_521_mont_mul_21(t3, t3, ya, p521_mod, p521_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod); - /* H = U2 - U1 */ - sp_521_mont_sub_21(t2, t2, t1, p521_mod); - /* RS = S2 + S1 */ - sp_521_mont_add_21(t6, t4, t3, p521_mod); - /* R = S2 - S1 */ - sp_521_mont_sub_21(t4, t4, t3, p521_mod); - /* Z3 = H*Z1*Z2 */ - /* ZS = H*Z1*Z2 */ - sp_521_mont_mul_21(za, za, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(za, za, t2, p521_mod, p521_mp_mod); - XMEMCPY(zs, za, sizeof(p->z)/2); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - /* XS = RS^2 - H^3 - 2*U1*H^2 */ - sp_521_mont_sqr_21(xa, t4, p521_mod, p521_mp_mod); - sp_521_mont_sqr_21(xs, t6, p521_mod, p521_mp_mod); - sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(ya, t1, t5, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(xa, xa, t5, p521_mod); - sp_521_mont_sub_21(xs, xs, t5, p521_mod); - sp_521_mont_dbl_21(t1, ya, p521_mod); - sp_521_mont_sub_21(xa, xa, t1, p521_mod); - sp_521_mont_sub_21(xs, xs, t1, p521_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ - sp_521_mont_sub_21(ys, ya, xs, p521_mod); - sp_521_mont_sub_21(ya, ya, xa, p521_mod); - sp_521_mont_mul_21(ya, ya, t4, p521_mod, p521_mp_mod); - sp_521_sub_21(t6, p521_mod, t6); - sp_521_mont_mul_21(ys, ys, t6, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t5, t5, t3, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(ya, ya, t5, p521_mod); - sp_521_mont_sub_21(ys, ys, t5, p521_mod); -} - -/* Structure used to describe recoding of scalar multiplication. */ -typedef struct ecc_recode_521 { - /* Index into pre-computation table. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_521; - -/* The index into pre-computation table to use. */ -static const word8 recode_index_21_6[66] = { - 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, 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 word8 recode_neg_21_6[66] = { - 0, 0, 0, 0, 0, 0, 0, 0, 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, - 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_521_ecc_recode_6_21(const sp_digit* k, ecc_recode_521* v) -{ - int i; - int j; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<87; i++) { - y = (word8)(int8_t)n; - if (o + 6 < 25) { - y &= 0x3f; - n >>= 6; - o += 6; - } - else if (o + 6 == 25) { - n >>= 6; - if (++j < 21) - n = k[j]; - o = 0; - } - else if (++j < 21) { - n = k[j]; - y |= (word8)((n << (25 - o)) & 0x3f); - o -= 19; - n >>= o; - } - - y = (word8)(y + carry); - v[i].i = recode_index_21_6[y]; - v[i].neg = recode_neg_21_6[y]; - carry = (y >> 6) + v[i].neg; - } -} - -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible point that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_521_get_point_33_21(sp_point_521* r, const sp_point_521* 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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 0; - r->x[9] = 0; - r->x[10] = 0; - r->x[11] = 0; - r->x[12] = 0; - r->x[13] = 0; - r->x[14] = 0; - r->x[15] = 0; - r->x[16] = 0; - r->x[17] = 0; - r->x[18] = 0; - r->x[19] = 0; - r->x[20] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - r->y[9] = 0; - r->y[10] = 0; - r->y[11] = 0; - r->y[12] = 0; - r->y[13] = 0; - r->y[14] = 0; - r->y[15] = 0; - r->y[16] = 0; - r->y[17] = 0; - r->y[18] = 0; - r->y[19] = 0; - r->y[20] = 0; - r->z[0] = 0; - r->z[1] = 0; - r->z[2] = 0; - r->z[3] = 0; - r->z[4] = 0; - r->z[5] = 0; - r->z[6] = 0; - r->z[7] = 0; - r->z[8] = 0; - r->z[9] = 0; - r->z[10] = 0; - r->z[11] = 0; - r->z[12] = 0; - r->z[13] = 0; - r->z[14] = 0; - r->z[15] = 0; - r->z[16] = 0; - r->z[17] = 0; - r->z[18] = 0; - r->z[19] = 0; - r->z[20] = 0; - for (i = 1; i < 33; i++) { - mask = (sp_digit)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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - r->x[9] |= mask & table[i].x[9]; - r->x[10] |= mask & table[i].x[10]; - r->x[11] |= mask & table[i].x[11]; - r->x[12] |= mask & table[i].x[12]; - r->x[13] |= mask & table[i].x[13]; - r->x[14] |= mask & table[i].x[14]; - r->x[15] |= mask & table[i].x[15]; - r->x[16] |= mask & table[i].x[16]; - r->x[17] |= mask & table[i].x[17]; - r->x[18] |= mask & table[i].x[18]; - r->x[19] |= mask & table[i].x[19]; - r->x[20] |= mask & table[i].x[20]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - r->y[9] |= mask & table[i].y[9]; - r->y[10] |= mask & table[i].y[10]; - r->y[11] |= mask & table[i].y[11]; - r->y[12] |= mask & table[i].y[12]; - r->y[13] |= mask & table[i].y[13]; - r->y[14] |= mask & table[i].y[14]; - r->y[15] |= mask & table[i].y[15]; - r->y[16] |= mask & table[i].y[16]; - r->y[17] |= mask & table[i].y[17]; - r->y[18] |= mask & table[i].y[18]; - r->y[19] |= mask & table[i].y[19]; - r->y[20] |= mask & table[i].y[20]; - r->z[0] |= mask & table[i].z[0]; - r->z[1] |= mask & table[i].z[1]; - r->z[2] |= mask & table[i].z[2]; - r->z[3] |= mask & table[i].z[3]; - r->z[4] |= mask & table[i].z[4]; - r->z[5] |= mask & table[i].z[5]; - r->z[6] |= mask & table[i].z[6]; - r->z[7] |= mask & table[i].z[7]; - r->z[8] |= mask & table[i].z[8]; - r->z[9] |= mask & table[i].z[9]; - r->z[10] |= mask & table[i].z[10]; - r->z[11] |= mask & table[i].z[11]; - r->z[12] |= mask & table[i].z[12]; - r->z[13] |= mask & table[i].z[13]; - r->z[14] |= mask & table[i].z[14]; - r->z[15] |= mask & table[i].z[15]; - r->z[16] |= mask & table[i].z[16]; - r->z[17] |= mask & table[i].z[17]; - r->z[18] |= mask & table[i].z[18]; - r->z[19] |= mask & table[i].z[19]; - r->z[20] |= mask & table[i].z[20]; - } -} -#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. - * - * Window technique of 6 bits. (Add-Sub variation.) - * Calculate 0..32 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_521_ecc_mulmod_win_add_sub_21(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_521, t, 33+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 21 * 6); - sp_point_521* rt = NULL; - sp_point_521* p = NULL; - sp_digit* negy; - int i; - ecc_recode_521 v[87]; - int err = MP_OKAY; - - /* Constant time used for cache attack resistance implementation. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_521, t, 33+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 21 * 6, heap, DYNAMIC_TYPE_ECC); - 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_521_mod_mul_norm_21(t[1].x, g->x, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod); - } - - if (err == MP_OKAY) { - t[1].infinity = 0; - /* t[2] ... t[32] */ - sp_521_proj_point_dbl_n_store_21(t, &t[ 1], 5, 1, tmp); - sp_521_proj_point_add_21(&t[ 3], &t[ 2], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[ 6], &t[ 3], tmp); - sp_521_proj_point_add_sub_21(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[10], &t[ 5], tmp); - sp_521_proj_point_add_sub_21(&t[11], &t[ 9], &t[10], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[12], &t[ 6], tmp); - sp_521_proj_point_dbl_21(&t[14], &t[ 7], tmp); - sp_521_proj_point_add_sub_21(&t[15], &t[13], &t[14], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[18], &t[ 9], tmp); - sp_521_proj_point_add_sub_21(&t[19], &t[17], &t[18], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[20], &t[10], tmp); - sp_521_proj_point_dbl_21(&t[22], &t[11], tmp); - sp_521_proj_point_add_sub_21(&t[23], &t[21], &t[22], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[24], &t[12], tmp); - sp_521_proj_point_dbl_21(&t[26], &t[13], tmp); - sp_521_proj_point_add_sub_21(&t[27], &t[25], &t[26], &t[ 1], tmp); - sp_521_proj_point_dbl_21(&t[28], &t[14], tmp); - sp_521_proj_point_dbl_21(&t[30], &t[15], tmp); - sp_521_proj_point_add_sub_21(&t[31], &t[29], &t[30], &t[ 1], tmp); - - negy = t[0].y; - - sp_521_ecc_recode_6_21(k, v); - - i = 86; - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_point_33_21(rt, t, v[i].i); - rt->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_521)); - } - for (--i; i>=0; i--) { - sp_521_proj_point_dbl_n_21(rt, 6, tmp); - - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_point_33_21(p, t, v[i].i); - p->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(p, &t[v[i].i], sizeof(sp_point_521)); - } - sp_521_sub_21(negy, p521_mod, p->y); - sp_521_norm_21(negy); - sp_521_cond_copy_21(p->y, negy, (sp_digit)0 - v[i].neg); - sp_521_proj_point_add_21(rt, rt, p, tmp); - } - - if (map != 0) { - sp_521_map_21(r, rt, tmp); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_521)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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_521_proj_point_add_qz1_21(sp_point_521* r, - const sp_point_521* p, const sp_point_521* q, sp_digit* t) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*21; - sp_digit* t6 = t + 4*21; - sp_digit* t1 = t + 6*21; - sp_digit* t4 = t + 8*21; - sp_digit* t5 = t + 10*21; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_21(t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t4, t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod); - - if ((~p->infinity) & (~q->infinity) & - sp_521_cmp_equal_21(p->x, t2) & - sp_521_cmp_equal_21(p->y, t4)) { - sp_521_proj_point_dbl_21(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_521_mont_sub_21(t2, t2, p->x, p521_mod); - /* R = S2 - Y1 */ - sp_521_mont_sub_21(t4, t4, p->y, p521_mod); - /* Z3 = H*Z1 */ - sp_521_mont_mul_21(z, p->z, t2, p521_mod, p521_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_521_mont_sqr_21(t1, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t3, p->x, t1, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t1, t1, t2, p521_mod, p521_mp_mod); - sp_521_mont_sqr_21(t2, t4, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(t2, t2, t1, p521_mod); - sp_521_mont_dbl_21(t5, t3, p521_mod); - sp_521_mont_sub_21(x, t2, t5, p521_mod); - /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_521_mont_sub_21(t3, t3, x, p521_mod); - sp_521_mont_mul_21(t3, t3, t4, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t1, t1, p->y, p521_mod, p521_mp_mod); - sp_521_mont_sub_21(y, t3, t1, p521_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 21; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 21; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 21; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef FP_ECC -/* Convert the projective point to affine. - * Ordinates are in Montgomery form. - * - * a Point to convert. - * t Temporary data. - */ -static void sp_521_proj_to_affine_21(sp_point_521* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 21; - sp_digit* tmp = t + 4 * 21; - - sp_521_mont_inv_21(t1, a->z, tmp); - - sp_521_mont_sqr_21(t2, t1, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(t1, t2, t1, p521_mod, p521_mp_mod); - - sp_521_mont_mul_21(a->x, a->x, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(a->y, a->y, t1, p521_mod, p521_mp_mod); - XMEMCPY(a->z, p521_norm_mod, sizeof(p521_norm_mod)); -} - -/* Generate the pre-computed table of points for the base point. - * - * width = 8 - * 256 entries - * 65 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_521_gen_stripe_table_21(const sp_point_521* a, - sp_table_entry_521* table, sp_digit* tmp, void* heap) -{ - SP_DECL_VAR(sp_point_521, t, 3); - sp_point_521* s1 = NULL; - sp_point_521* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_521, t, 3, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - s1 = t + 1; - s2 = t + 2; - - err = sp_521_mod_mul_norm_21(t->x, a->x, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_21(t->y, a->y, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_21(t->z, a->z, p521_mod); - } - if (err == MP_OKAY) { - t->infinity = 0; - sp_521_proj_to_affine_21(t, tmp); - - XMEMCPY(s1->z, p521_norm_mod, sizeof(p521_norm_mod)); - s1->infinity = 0; - XMEMCPY(s2->z, p521_norm_mod, sizeof(p521_norm_mod)); - s2->infinity = 0; - - /* table[0] = {0, 0, infinity} */ - XMEMSET(&table[0], 0, sizeof(sp_table_entry_521)); - /* 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_521_proj_point_dbl_n_21(t, 66, tmp); - sp_521_proj_to_affine_21(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_521_proj_point_add_qz1_21(t, s1, s2, tmp); - sp_521_proj_to_affine_21(t, tmp); - XMEMCPY(table[j].x, t->x, sizeof(table->x)); - XMEMCPY(table[j].y, t->y, sizeof(table->y)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible entry that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_521_get_entry_256_21(sp_point_521* r, - const sp_table_entry_521* 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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 0; - r->x[9] = 0; - r->x[10] = 0; - r->x[11] = 0; - r->x[12] = 0; - r->x[13] = 0; - r->x[14] = 0; - r->x[15] = 0; - r->x[16] = 0; - r->x[17] = 0; - r->x[18] = 0; - r->x[19] = 0; - r->x[20] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - r->y[9] = 0; - r->y[10] = 0; - r->y[11] = 0; - r->y[12] = 0; - r->y[13] = 0; - r->y[14] = 0; - r->y[15] = 0; - r->y[16] = 0; - r->y[17] = 0; - r->y[18] = 0; - r->y[19] = 0; - r->y[20] = 0; - for (i = 1; i < 256; i++) { - sp_digit gte = (sp_digit)((((sp_uint32)i - (sp_uint32)idx) >> 31) - 1); - sp_digit lte = (sp_digit)((((sp_uint32)idx - (sp_uint32)i) >> 31) - 1); - mask = gte & lte; - 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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - r->x[9] |= mask & table[i].x[9]; - r->x[10] |= mask & table[i].x[10]; - r->x[11] |= mask & table[i].x[11]; - r->x[12] |= mask & table[i].x[12]; - r->x[13] |= mask & table[i].x[13]; - r->x[14] |= mask & table[i].x[14]; - r->x[15] |= mask & table[i].x[15]; - r->x[16] |= mask & table[i].x[16]; - r->x[17] |= mask & table[i].x[17]; - r->x[18] |= mask & table[i].x[18]; - r->x[19] |= mask & table[i].x[19]; - r->x[20] |= mask & table[i].x[20]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - r->y[9] |= mask & table[i].y[9]; - r->y[10] |= mask & table[i].y[10]; - r->y[11] |= mask & table[i].y[11]; - r->y[12] |= mask & table[i].y[12]; - r->y[13] |= mask & table[i].y[13]; - r->y[14] |= mask & table[i].y[14]; - r->y[15] |= mask & table[i].y[15]; - r->y[16] |= mask & table[i].y[16]; - r->y[17] |= mask & table[i].y[17]; - r->y[18] |= mask & table[i].y[18]; - r->y[19] |= mask & table[i].y[19]; - r->y[20] |= mask & table[i].y[20]; - } -} -#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^65, ... - * 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_521_ecc_mulmod_stripe_21(sp_point_521* r, const sp_point_521* g, - const sp_table_entry_521* table, const sp_digit* k, int map, - int ct, void* heap) -{ - SP_DECL_VAR(sp_point_521, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 21 * 6); - sp_point_521* 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; - - - SP_ALLOC_VAR(sp_point_521, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 21 * 6, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - p = rt + 1; - - XMEMCPY(p->z, p521_norm_mod, sizeof(p521_norm_mod)); - XMEMCPY(rt->z, p521_norm_mod, sizeof(p521_norm_mod)); - - y = 0; - x = 65; - for (j=0; j<8 && x<521; j++) { - y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j); - x += 66; - } - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_entry_256_21(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=64; i>=0; i--) { - y = 0; - x = i; - for (j=0; j<8 && x<521; j++) { - y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j); - x += 66; - } - - sp_521_proj_point_dbl_21(rt, rt, t); - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_entry_256_21(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_521_proj_point_add_qz1_21(rt, rt, p, t); - } - - if (map != 0) { - sp_521_map_21(r, rt, t); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_521)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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_521_t { - /* X ordinate of point that table was generated from. */ - sp_digit x[21]; - /* Y ordinate of point that table was generated from. */ - sp_digit y[21]; - /* Precomputation table for point. */ - sp_table_entry_521 table[256]; - /* Count of entries in table. */ - word32 cnt; - /* Point and table set in entry. */ - int set; -} sp_cache_521_t; - -/* Cache of tables. */ -static THREAD_LS_T sp_cache_521_t sp_cache_521[FP_ENTRIES]; -/* Index of last entry in cache. */ -static THREAD_LS_T int sp_cache_521_last = -1; -/* Cache has been initialized. */ -static THREAD_LS_T int sp_cache_521_inited = 0; - -#ifndef HAVE_THREAD_LS - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_521 = 0; - #endif - static wolfSSL_Mutex sp_cache_521_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_521_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * cache [out] Cache table to use. - */ -static void sp_ecc_get_cache_521(const sp_point_521* g, sp_cache_521_t** cache) -{ - int i; - int j; - word32 least; - - if (sp_cache_521_inited == 0) { - for (i=0; ix, sp_cache_521[i].x) & - sp_521_cmp_equal_21(g->y, sp_cache_521[i].y)) { - sp_cache_521[i].cnt++; - break; - } - } - - /* No match. */ - if (i == FP_ENTRIES) { - /* Find empty entry. */ - i = (sp_cache_521_last + 1) % FP_ENTRIES; - for (; i != sp_cache_521_last; i=(i+1)%FP_ENTRIES) { - if (!sp_cache_521[i].set) { - break; - } - } - - /* Evict least used. */ - if (i == sp_cache_521_last) { - least = sp_cache_521[0].cnt; - for (j=1; jx, sizeof(sp_cache_521[i].x)); - XMEMCPY(sp_cache_521[i].y, g->y, sizeof(sp_cache_521[i].y)); - sp_cache_521[i].set = 1; - sp_cache_521[i].cnt = 1; - } - - *cache = &sp_cache_521[i]; - sp_cache_521_last = i; -} -#endif /* FP_ECC */ - -/* Multiply the base point of P521 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_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#ifndef FP_ECC - return sp_521_ecc_mulmod_win_add_sub_21(r, g, k, map, ct, heap); -#else - SP_DECL_VAR(sp_digit, tmp, 2 * 21 * 6); - sp_cache_521_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 21 * 6, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_521 == 0) { - wc_InitMutex(&sp_cache_521_lock); - initCacheMutex_521 = 1; - } - #endif - if (wc_LockMutex(&sp_cache_521_lock) != 0) { - err = BAD_MUTEX_E; - } - } -#endif /* HAVE_THREAD_LS */ - - if (err == MP_OKAY) { - sp_ecc_get_cache_521(g, &cache); - if (cache->cnt == 2) - sp_521_gen_stripe_table_21(g, cache->table, tmp, heap); - -#ifndef HAVE_THREAD_LS - wc_UnLockMutex(&sp_cache_521_lock); -#endif /* HAVE_THREAD_LS */ - - if (cache->cnt < 2) { - err = sp_521_ecc_mulmod_win_add_sub_21(r, g, k, map, ct, heap); - } - else { - err = sp_521_ecc_mulmod_stripe_21(r, g, cache->table, k, - map, ct, heap); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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_521(const mp_int* km, const ecc_point* gm, ecc_point* r, - int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 1); - SP_DECL_VAR(sp_digit, k, 21); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 21, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(k, 21, km); - sp_521_point_from_ecc_point_21(point, gm); - - err = sp_521_ecc_mulmod_21(point, point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_21(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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_521(const mp_int* km, const ecc_point* gm, - const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 2); - SP_DECL_VAR(sp_digit, k, 21 + 21 * 2 * 6); - sp_point_521* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 21 + 21 * 2 * 6, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - addP = point + 1; - tmp = k + 21; - - sp_521_from_mp(k, 21, km); - sp_521_point_from_ecc_point_21(point, gm); - sp_521_point_from_ecc_point_21(addP, am); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_21(addP->x, addP->x, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_21(addP->y, addP->y, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_21(addP->z, addP->z, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_21(point, point, k, 0, 0, heap); - } - if (err == MP_OKAY) { - sp_521_proj_point_add_21(point, point, addP, tmp); - - if (map) { - sp_521_map_21(point, point, tmp); - } - - err = sp_521_point_to_ecc_point_21(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_SMALL -/* Multiply the base point of P521 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_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k, - int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_521_ecc_mulmod_21(r, &p521_base, k, map, ct, heap); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_521_ecc_mulmod_base_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_521_ecc_mulmod_21_nb(sp_ctx, r, &p521_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#else -/* Striping precomputation table. - * 8 points combined into a table of 256 points. - * Distance of 66 between points. - */ -static const sp_table_entry_521 p521_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 } }, - /* 1 */ - { { 0x0e5bd66,0x13f18e1,0x0a6fe5f,0x030ad48,0x1348b3c,0x1fd46f1, - 0x1049e8b,0x051fc3b,0x1efe759,0x0a5af3b,0x14f6ea8,0x1ec0d69, - 0x01f828a,0x029fda9,0x19204e4,0x1688538,0x1662395,0x0cf1f65, - 0x1013a73,0x1c0d6e0,0x00c6858 }, - { 0x1d16650,0x14a3b4f,0x090222f,0x0d44e58,0x153c708,0x1683b09, - 0x0e404fe,0x0818aa1,0x15ef426,0x1f7394c,0x1998b25,0x1a2e4e7, - 0x0817afb,0x0bcda23,0x1d51125,0x037b331,0x1b42c7d,0x02e452f, - 0x08ef001,0x12d4f13,0x0118392 } }, - /* 2 */ - { { 0x10ccb51,0x0c33387,0x1d2a00e,0x026ca92,0x187e1d0,0x194f6cd, - 0x13c86ca,0x06efeb1,0x0a3add3,0x16074d5,0x023fec1,0x0ba1d3a, - 0x07f13b3,0x0b3b0b1,0x02fd132,0x07de9bb,0x014758a,0x1d250c6, - 0x0010eb6,0x0aedbb4,0x013e96a }, - { 0x12d95a3,0x1127c31,0x00a4af7,0x0298a49,0x19f15ef,0x0d5d0cb, - 0x018fa6f,0x00f55bb,0x0a962b7,0x0f029fa,0x1636637,0x05bc284, - 0x1cc598a,0x030e11a,0x0968674,0x1a6593f,0x110e8ff,0x0076a32, - 0x1de33ab,0x153ba3d,0x01852ae } }, - /* 3 */ - { { 0x0af1fe3,0x08eec75,0x14af42a,0x0488016,0x0db3866,0x15f8690, - 0x01aa486,0x081fed4,0x0a768c9,0x00943cd,0x1bb0de5,0x1579343, - 0x1cf3791,0x139c1a1,0x04fef98,0x1578392,0x0abe222,0x1b945a1, - 0x0e7bcc4,0x18150c5,0x0157874 }, - { 0x0f03d49,0x078c273,0x180c2b2,0x083c917,0x09c357e,0x0e5ef7d, - 0x17bce05,0x078059c,0x15fd8dc,0x120e3d5,0x0c4275e,0x0f93f5d, - 0x184bef6,0x1427a69,0x0633286,0x0155c5f,0x07d672f,0x1bf01ea, - 0x15625a2,0x0356b03,0x000724b } }, - /* 4 */ - { { 0x19314e0,0x196a5ef,0x0ab2413,0x1bcf401,0x1aae850,0x177d81e, - 0x0420d60,0x1a4f246,0x1ec7fe6,0x078e141,0x15d2a20,0x132c333, - 0x072d5b3,0x1ca803f,0x0482e6c,0x1e07cbe,0x1734773,0x118691b, - 0x0de2da1,0x0324e67,0x0121f4c }, - { 0x08b51f0,0x1ffb6fd,0x17c3c40,0x0281c57,0x0e7afb5,0x12a0b8d, - 0x0e03a0c,0x12a2260,0x0cda10d,0x01a80dc,0x0a3007a,0x0e3c9e7, - 0x0910577,0x1640383,0x14865aa,0x070431e,0x0aaa562,0x09b04d8, - 0x12829fc,0x0af20d2,0x01db8c2 } }, - /* 5 */ - { { 0x0c0958d,0x1b86659,0x0e1cc00,0x0cd34f6,0x09aef16,0x064d9c4, - 0x1cf3d20,0x0924f25,0x0fab3e1,0x194c279,0x12259c2,0x086ca0e, - 0x0a9751e,0x1699ed9,0x0ae6756,0x09b5539,0x132b44a,0x0a6ca2e, - 0x1b1dcc9,0x1994a42,0x000aa26 }, - { 0x1e66d18,0x10ea0fc,0x19eb36f,0x0d5422f,0x00aeef9,0x186925c, - 0x0528b76,0x17e0a64,0x15c98b7,0x0e7d913,0x0f2121b,0x086dbfa, - 0x0c613e7,0x1e526a9,0x1c0fe84,0x03cc8dc,0x1771855,0x0864714, - 0x1ea149f,0x121d597,0x01c6f5e } }, - /* 6 */ - { { 0x0b2d58f,0x178f3a5,0x000a8b0,0x185412f,0x01bbf82,0x05dbb56, - 0x1ac91dc,0x17acb07,0x15667f7,0x1276cf6,0x1a25fa3,0x1b0dfb2, - 0x15d8c01,0x1fdf078,0x0e5684c,0x1b962cc,0x19dd99c,0x0a8f279, - 0x0837ac9,0x108494e,0x0082de0 }, - { 0x0ea91af,0x129d930,0x1f765ea,0x0ef463b,0x04384af,0x084ddf5, - 0x1c8e573,0x1c39b05,0x0f30058,0x0be0ced,0x1e3a5e6,0x018dcb8, - 0x05443b6,0x0bad8c2,0x0ba6d7d,0x19c2df5,0x13308c2,0x12e7437, - 0x1d8fea1,0x19cb1e9,0x0073983 } }, - /* 7 */ - { { 0x017609d,0x09898c1,0x1002bba,0x084825f,0x1f8a9dd,0x163194b, - 0x19930a1,0x0bdc22f,0x07bf1c6,0x01bc16b,0x0fbb973,0x09b71a0, - 0x19e8c14,0x0d5c9bc,0x0b2b2ca,0x1098e03,0x1b5b077,0x190af58, - 0x0bff361,0x013f503,0x00f82c4 }, - { 0x18139a4,0x09bb31b,0x0a4c01f,0x176ab7d,0x06d969e,0x045e4ee, - 0x035bda3,0x0858f8c,0x15f93f2,0x0274230,0x1c5f661,0x1454e82, - 0x0e8461c,0x185f890,0x04c39e7,0x133af1d,0x0026b56,0x170aaa5, - 0x093edb7,0x18ee04d,0x007de69 } }, - /* 8 */ - { { 0x1ee80d7,0x08dd825,0x19a586d,0x1eed25b,0x0e1f6a1,0x15e1de8, - 0x191b283,0x1e106f3,0x1930644,0x005ffd3,0x16c1dc7,0x170e721, - 0x0997c67,0x1d6d0e7,0x170cf87,0x16a2412,0x0ddac54,0x11e2805, - 0x0c46195,0x03a6c1a,0x00b0c23 }, - { 0x1bcab2f,0x0494c1c,0x082818a,0x00c9ba4,0x00c0678,0x1ee1506, - 0x18211d8,0x1c60c5e,0x11938c3,0x074ed39,0x11bae62,0x1e5aa5c, - 0x1d69be8,0x152ef07,0x17234b5,0x01c4dca,0x163db2c,0x1f9d1fe, - 0x192ffd5,0x18db3e3,0x014a899 } }, - /* 9 */ - { { 0x005ce88,0x171d0f6,0x080a7fd,0x0d6d5fa,0x18fc249,0x1f5803f, - 0x081ddbe,0x080173a,0x1eebded,0x087605e,0x1c03ded,0x0e84d26, - 0x0eaef97,0x1fbd818,0x1b8de84,0x03eef00,0x1171b90,0x1ae78be, - 0x0a56b83,0x0dcbbf9,0x0159903 }, - { 0x00e8e0c,0x1b25a80,0x17e402b,0x080df69,0x13f2ae0,0x0f91dd6, - 0x1699d12,0x152bec3,0x0255b25,0x0548c21,0x0f19403,0x07cd1c6, - 0x01fa6af,0x016013e,0x0dcf003,0x0814a28,0x1a19728,0x04cf9e6, - 0x03a1090,0x0c56f3a,0x00e798c } }, - /* 10 */ - { { 0x04d0f28,0x1e25457,0x01bba31,0x1eacda0,0x1a8a55e,0x1720119, - 0x17d9419,0x0ec6f30,0x15d321b,0x0f6655a,0x146c1e3,0x0dad706, - 0x0b38b96,0x0beaa45,0x022794d,0x156165d,0x02fe631,0x1bd4f47, - 0x1d714de,0x0c1f2bc,0x005945c }, - { 0x067d79c,0x13e9a3c,0x0602f28,0x0b03903,0x1f460b1,0x15c628b, - 0x166ae5d,0x1b2fd85,0x061b91e,0x0682243,0x07457ff,0x144bb38, - 0x19730a7,0x1ca64ed,0x0b3c967,0x0b47714,0x1875dec,0x1473c25, - 0x1944c7b,0x0a4c0e7,0x0004062 } }, - /* 11 */ - { { 0x1631bba,0x0272e78,0x14937b8,0x1e2ade8,0x00e6c1d,0x0184c82, - 0x0fcc393,0x18e0cc0,0x16b6abe,0x1b24d21,0x053dbb6,0x0139ed7, - 0x15354f5,0x1b5bf05,0x1b3d1a4,0x0dba4ff,0x07eba1e,0x153d388, - 0x0251432,0x1db58ad,0x0022889 }, - { 0x05596f2,0x148b768,0x0e2e404,0x1960479,0x03901da,0x0a55f0f, - 0x14fb39f,0x0264a03,0x0a9c903,0x140a820,0x051b42c,0x07e38da, - 0x169dbcd,0x1a770c4,0x08756c5,0x04df6df,0x161a912,0x024d750, - 0x02a0261,0x19ddbf7,0x0154754 } }, - /* 12 */ - { { 0x070b2f0,0x113d821,0x135ed93,0x117e9ae,0x04b34e4,0x13915d4, - 0x0fa2c30,0x039630d,0x19ff9b7,0x0a52c4e,0x15af13d,0x09be69f, - 0x1d9887e,0x1a097a4,0x119a7f5,0x13a2d6f,0x1bb77f8,0x020046c, - 0x040b81d,0x1284d79,0x01cfafb }, - { 0x02935ca,0x07968b3,0x111b329,0x0732fb9,0x0847c70,0x1e3cfc1, - 0x1a794d4,0x1e98113,0x15215f0,0x16c6cc4,0x046e767,0x1179012, - 0x0359cf0,0x16f13d5,0x00d5039,0x0641a96,0x03ef69e,0x1a97a6b, - 0x13bc64e,0x02ffad2,0x00e6a02 } }, - /* 13 */ - { { 0x0214780,0x0f313ba,0x07aaddf,0x0e40e8b,0x0a06681,0x03fd80e, - 0x1e6dfa7,0x18fef0a,0x1d6d4b7,0x0aaa460,0x12a8e79,0x03214cd, - 0x0f45756,0x0c282d2,0x0506c0e,0x0c9d7f0,0x17c4c88,0x1d2e506, - 0x184a74f,0x15f2a13,0x0053bf8 }, - { 0x1285092,0x194ec42,0x197ef26,0x151ddab,0x02f31da,0x0c555cc, - 0x1a43bd8,0x1a33866,0x0d2626e,0x1770a7a,0x1638243,0x0e160fd, - 0x0042295,0x039b682,0x1de483a,0x1a03a32,0x1ffede7,0x1a3f712, - 0x11eadce,0x0438757,0x01b93c9 } }, - /* 14 */ - { { 0x08b2b14,0x103e650,0x11fc2da,0x177e2e9,0x0a978de,0x0659525, - 0x0e0a310,0x0705239,0x090adc8,0x0e3c139,0x1b779a5,0x1655183, - 0x0008da8,0x087de91,0x073acbe,0x1729ce8,0x1e5322d,0x12fc4e4, - 0x1cf1523,0x0cc10b6,0x007d182 }, - { 0x1efd012,0x1fc1516,0x1fbda7a,0x08b42a6,0x01ecb09,0x18408e8, - 0x1d4d4fb,0x1d478aa,0x1b2bd4d,0x0e44153,0x05a7216,0x12e4f7f, - 0x1b00a1f,0x0592d68,0x0eb7d78,0x0c00a0c,0x106f253,0x0260ff9, - 0x044bf86,0x02b7d88,0x01178e5 } }, - /* 15 */ - { { 0x1e3d3d5,0x03c3ff7,0x089e4c5,0x0b3b12e,0x09e76f6,0x1b567a9, - 0x1fb4782,0x1b22b8e,0x01c5e8d,0x015bd90,0x199ebe7,0x11e2bea, - 0x1478803,0x19abb77,0x031d9bf,0x02a95e7,0x1c80040,0x1cf8311, - 0x1a20ed4,0x078897b,0x009647d }, - { 0x01b21a4,0x1ab1c6f,0x0704c81,0x02ae210,0x1b6399c,0x001accd, - 0x1819dd7,0x1ea645c,0x1ade60c,0x03fef3f,0x0641657,0x0881df8, - 0x001b195,0x0ebd9cb,0x1c2b233,0x14e7cfc,0x03d6a6f,0x02552d4, - 0x0c201d9,0x119f58c,0x004234f } }, - /* 16 */ - { { 0x06492ad,0x0f38d14,0x0b13b8c,0x08cbf0d,0x08f3de4,0x189e5a0, - 0x0035369,0x009d12e,0x1a86b71,0x1687af4,0x0b0585e,0x1c9e4ae, - 0x19d9a62,0x12e60e4,0x1488fbc,0x05c18ef,0x1613b96,0x0f6ffb4, - 0x0762c81,0x1a51e70,0x008e818 }, - { 0x0df1f60,0x118e7c6,0x183dc84,0x16ce2ee,0x0b640f2,0x02d201c, - 0x1be3381,0x13f7ce4,0x0037068,0x11142ee,0x08372d0,0x1f1ee5d, - 0x037196b,0x0404331,0x1bde157,0x1fc9142,0x1c7c326,0x06a70cf, - 0x1da2fd1,0x190add1,0x013efdb } }, - /* 17 */ - { { 0x0a3ace5,0x06827f3,0x070778d,0x1d12c32,0x0dbb603,0x0f687a0, - 0x0001fdd,0x16b69b8,0x095b259,0x0f0735e,0x17c0805,0x14cc4c2, - 0x18dfbcb,0x098f51f,0x1b150cf,0x1f04965,0x0e4103f,0x1215858, - 0x1200ccb,0x02a0c18,0x0111193 }, - { 0x05452f1,0x1f51402,0x1cee665,0x1ee3e7e,0x00b678c,0x1499474, - 0x0f77107,0x04694a5,0x0e6af1c,0x1f932b7,0x08579ed,0x0b73688, - 0x0bc4380,0x1852014,0x09cd3cb,0x0edc475,0x0794224,0x1f1e392, - 0x031833d,0x05d160d,0x01f16dc } }, - /* 18 */ - { { 0x1fc0de5,0x1d737ff,0x1c92f37,0x1f5694b,0x0801814,0x15546ed, - 0x0d963a8,0x0823202,0x1da4f04,0x1d8e57a,0x001847c,0x19b6682, - 0x08f24b9,0x0b7067c,0x10c93b6,0x0b90491,0x1342305,0x0a5bf51, - 0x0424b8a,0x06b6c91,0x01d36e8 }, - { 0x1372f27,0x1bd7383,0x0669fad,0x150775c,0x0779b4f,0x014f5da, - 0x16b8595,0x07f42eb,0x0fc03ef,0x0176133,0x071f125,0x0d52d32, - 0x1c0e5fc,0x0b129e9,0x1d8793d,0x1ce7141,0x158de74,0x0bd08ff, - 0x0937a46,0x0499a8c,0x0002605 } }, - /* 19 */ - { { 0x1342e08,0x0e86500,0x02bd16d,0x016e93e,0x109ed4f,0x14ec022, - 0x00b6594,0x139d6aa,0x16d8035,0x15843ed,0x0120017,0x150e987, - 0x04eaa66,0x03ad43c,0x1cb1e83,0x062fdd2,0x0216874,0x0460b4f, - 0x1727efd,0x0aadc1c,0x014f81c }, - { 0x120674d,0x05895f0,0x02b09ac,0x12433e0,0x06bf09b,0x0c65536, - 0x1ccb759,0x13c3c3c,0x18292d9,0x1b8e2d7,0x16fe031,0x0a524bf, - 0x1d5d813,0x1b3361b,0x06f5e60,0x1ed01cc,0x06a1d0d,0x1c6d64a, - 0x0e7c260,0x19ed098,0x009f58d } }, - /* 20 */ - { { 0x17dc837,0x148813d,0x0710505,0x096a1d6,0x0d71975,0x133a0d9, - 0x024ab5f,0x07009e8,0x1bc824a,0x0853f8e,0x082f3c7,0x00ad91c, - 0x10570b2,0x0d0c0ed,0x0cb8ee7,0x0a114ce,0x16e0a7b,0x13c4031, - 0x07dc124,0x1ea0599,0x004511a }, - { 0x16f4ffa,0x106ca62,0x03e82e0,0x0589e18,0x1c6205a,0x1030350, - 0x0f53a86,0x1f733e6,0x079b316,0x1d5b233,0x0903f06,0x10a5c9e, - 0x0305aa0,0x096bee2,0x14e6de2,0x180e644,0x11206e3,0x181b2bf, - 0x1b6d98c,0x00a5019,0x0059284 } }, - /* 21 */ - { { 0x197760c,0x04388a1,0x141a434,0x0c393f9,0x19020b7,0x1f127bd, - 0x11fea61,0x1418ffd,0x0522335,0x119dc50,0x0728403,0x15fb5c4, - 0x0073dbe,0x1d81911,0x0301828,0x0bb4c8b,0x1b8ee14,0x1cdce39, - 0x1ffd8bb,0x0cc3ca4,0x00aa31c }, - { 0x1430b5e,0x0c75840,0x15a6bd4,0x14a1dc1,0x132f9ce,0x175f45d, - 0x0c2d6a9,0x1121d9b,0x09fe1d6,0x18afbf9,0x0732687,0x11e634b, - 0x03ce5d6,0x0455953,0x159e650,0x19ca9e9,0x0ef4347,0x1742d8e, - 0x01b41dd,0x0847805,0x01768ff } }, - /* 22 */ - { { 0x1dcec23,0x0082619,0x1466159,0x179ba0e,0x1af0d61,0x07984d5, - 0x0bd4531,0x02a90db,0x1de4887,0x00de47a,0x0e6e8fc,0x15e3a6a, - 0x0cddd6b,0x1d1df47,0x1f99974,0x10cbf76,0x0c3cb5d,0x07c8ced, - 0x0485268,0x007b47e,0x0173fe2 }, - { 0x0d4a3d1,0x174d0bc,0x1b6010e,0x110ca62,0x04d5cf5,0x0bb231d, - 0x09b0104,0x089d5e0,0x1f84afa,0x0b631c7,0x0908b4c,0x072fffd, - 0x13512f2,0x13115b0,0x07aa811,0x00d1ad2,0x0a397e7,0x02442b7, - 0x1286ccf,0x0365c7e,0x01b542d } }, - /* 23 */ - { { 0x1487402,0x196af0f,0x1757d46,0x0cf55e3,0x036016e,0x14e1057, - 0x1c7d5b6,0x1fa3d67,0x1ece45b,0x0dbe9b0,0x0a78609,0x0c6604f, - 0x0942db0,0x14208b2,0x08a1ddf,0x0e7a17e,0x0c44587,0x07afe70, - 0x175e97c,0x062a3a5,0x001fb2b }, - { 0x1aa096a,0x1b9f47d,0x01e0409,0x17c1275,0x152726e,0x1f8bc08, - 0x1341cb1,0x0ecb8a7,0x0ab5dca,0x069efe8,0x1cb528e,0x1b0b0fd, - 0x02bb4a7,0x1bf588e,0x070804e,0x1445eb9,0x0340b6d,0x0af1a9e, - 0x0c97b2b,0x1aa14b4,0x0039846 } }, - /* 24 */ - { { 0x077df58,0x13b9b0b,0x15b1db6,0x0e396a1,0x164bd56,0x0407f91, - 0x11f5c28,0x0600887,0x1865324,0x0542a14,0x04079e8,0x1ba586a, - 0x1682002,0x0462e6b,0x0f1850d,0x1e27f7d,0x1aeca6c,0x07f8ac8, - 0x02fe370,0x0f85cd3,0x00fb91c }, - { 0x0de14d5,0x02e5689,0x0089a9f,0x1ecac39,0x1c448c5,0x0dd9ed5, - 0x190c1f3,0x1af3f1b,0x1c76811,0x02c7808,0x1881267,0x00dcea8, - 0x091e898,0x04d3a72,0x0ab428b,0x06f87ca,0x05cb2be,0x0901a34, - 0x082f1cb,0x0c648a1,0x00ec7a8 } }, - /* 25 */ - { { 0x086786e,0x0c610c5,0x0b20ce0,0x08426fc,0x0d537f7,0x1375907, - 0x043469f,0x006bb2d,0x05cdc48,0x1c87638,0x1ef5d65,0x059049e, - 0x1446916,0x070f878,0x19fbe75,0x02b9413,0x08bce99,0x1e98609, - 0x11c489b,0x028becd,0x002d810 }, - { 0x11d87e5,0x1a4fadb,0x1b68c49,0x02f6059,0x05f3b14,0x1d7f8b1, - 0x1b4bb82,0x04e048a,0x1fcae66,0x1fbd9d4,0x16617e5,0x1f1e6f7, - 0x010d6eb,0x1fd3686,0x0aa06e5,0x1e26e41,0x00121f2,0x0d94f8d, - 0x130376c,0x0d45f0b,0x003de32 } }, - /* 26 */ - { { 0x0c2ee78,0x19cc59c,0x0fb89bc,0x034eb41,0x00c3d10,0x0d3fc72, - 0x05c1959,0x0ba6b46,0x104019e,0x094c2f1,0x1d2dbb4,0x0c85702, - 0x0a21e2a,0x17c0529,0x0857ba2,0x1b01c4b,0x1e68518,0x12e8f07, - 0x13dbaa6,0x1782700,0x00848cb }, - { 0x1d45169,0x143486f,0x0341da0,0x10b3a7d,0x18d7e09,0x1c5fe11, - 0x0204736,0x09046eb,0x0162cf6,0x04caa3d,0x056e321,0x167769a, - 0x06494ba,0x03024cd,0x0b2f15f,0x19fdb04,0x04ea8a1,0x1d62191, - 0x1f19662,0x0c68d2a,0x00d9435 } }, - /* 27 */ - { { 0x0271323,0x14929b4,0x135cac1,0x10939a0,0x04d9e0a,0x18e63e9, - 0x17efcac,0x0c355c6,0x157a3e3,0x07b25a7,0x13a1591,0x0d0c052, - 0x0e14904,0x01e76a5,0x120bb9d,0x1b48fbb,0x0a57e2c,0x065c953, - 0x1f07e5a,0x1885df7,0x013f989 }, - { 0x0651600,0x0c5efdc,0x0bbafb6,0x08f479f,0x0c36343,0x18d1134, - 0x0950cd6,0x00f2742,0x1d58255,0x0c6d3ee,0x1ac7a55,0x16470a5, - 0x05a5173,0x114afaa,0x16b9614,0x1a203be,0x0ef6646,0x172a371, - 0x1627e18,0x02d458b,0x01faf7e } }, - /* 28 */ - { { 0x1ec136d,0x0364763,0x146c35d,0x0f9a226,0x18e1d82,0x03d08b7, - 0x0eb4fc6,0x0caec94,0x1136e84,0x18dcb47,0x060f08b,0x05290a1, - 0x19d41aa,0x1f38b92,0x08fb312,0x0293842,0x152763c,0x0ee6e55, - 0x008ae0b,0x0a16302,0x016da7f }, - { 0x0a5e258,0x1299686,0x09efe67,0x0f2f6c5,0x0148ad1,0x1feef7d, - 0x090bb1d,0x1891a14,0x174f9b6,0x028c5e6,0x048b516,0x0170ffa, - 0x17c53b3,0x1da8596,0x033464f,0x155d377,0x0eebc01,0x08d0b4d, - 0x1789b82,0x1362143,0x01c57e4 } }, - /* 29 */ - { { 0x1210716,0x1f33a90,0x1000b2a,0x060fc04,0x01a296a,0x01bcadc, - 0x1047632,0x0d5295f,0x0dd9efa,0x079019a,0x15a1bda,0x13d6cef, - 0x155be2f,0x1fae713,0x04fc9de,0x0f8b8d4,0x041b975,0x07bec91, - 0x1d3d2e3,0x07a5e98,0x013270c }, - { 0x1209aa4,0x0304e46,0x10dbe72,0x05b656a,0x06f413a,0x091a2ea, - 0x0b468a6,0x09f2d6e,0x19487c3,0x0379575,0x028dd46,0x02ed688, - 0x0e4fa72,0x1ed29ac,0x10824d9,0x1662074,0x1e3ff25,0x0788f56, - 0x017582e,0x0e02a6a,0x01a99a5 } }, - /* 30 */ - { { 0x07495bb,0x089c9b7,0x0746b85,0x109210f,0x0bd2fd2,0x1ebb7e7, - 0x0ac2ca7,0x0393846,0x1c60e72,0x0d06a4d,0x08278a8,0x1706a2f, - 0x189f582,0x0ec5d6f,0x0de027a,0x1176958,0x09e0ad4,0x1a5526f, - 0x0db3121,0x0826259,0x0027fd0 }, - { 0x0d4fb6d,0x0817775,0x12fb015,0x1a14c05,0x160c25e,0x1fa503b, - 0x1a106f5,0x028b174,0x054edce,0x145b019,0x1d85330,0x1c72072, - 0x13b9d41,0x0c0f76c,0x086dc74,0x0961684,0x1c2332d,0x0e80871, - 0x0ac3906,0x0b144fb,0x0096dfe } }, - /* 31 */ - { { 0x1ebd24e,0x17e6b3e,0x01d5335,0x0135c56,0x1e3fca6,0x0be1365, - 0x108bbc8,0x07f4fb1,0x0b9620e,0x01681f0,0x07e1f75,0x042d8ff, - 0x0e634bf,0x04b97ff,0x0c7b14e,0x07cee45,0x1c1d60d,0x141d4ab, - 0x1da94df,0x1cbf0c1,0x0162edf }, - { 0x0ea20b8,0x02a0078,0x0401028,0x1c3af2d,0x0872ac7,0x0d86561, - 0x097243b,0x14eeecb,0x0b62939,0x0fadc98,0x12dc227,0x0edd5e5, - 0x12f78a6,0x097f5e0,0x01ccafd,0x015a606,0x0deba19,0x09d3320, - 0x0f9f8d0,0x15c2bf2,0x00d536e } }, - /* 32 */ - { { 0x1c88f3c,0x08cfb50,0x1129b18,0x185d8d2,0x124e5fe,0x017f954, - 0x0b1815d,0x0f89915,0x0ddb22c,0x056ef0f,0x1496ed8,0x0719f4b, - 0x0097289,0x1608bef,0x16b13df,0x05383f4,0x0b74829,0x0a0f9ad, - 0x0bf657d,0x09d1f21,0x0180d1c }, - { 0x1cd8358,0x0739ed3,0x0480bf1,0x0fe5439,0x19361a5,0x0a69441, - 0x1c4c2b6,0x1c5ede5,0x02b6a78,0x1bf1233,0x098b378,0x1f16f38, - 0x190babf,0x10dacbd,0x0b807bd,0x09cc8d9,0x1f0a60d,0x0ce0f19, - 0x1407e11,0x084501b,0x000e52a } }, - /* 33 */ - { { 0x1013755,0x1205207,0x03a5cb5,0x0ff7070,0x0b6dce7,0x1b25988, - 0x139e5fa,0x06c4f13,0x193ca5a,0x1382585,0x17ff263,0x01feb17, - 0x1218c36,0x191861b,0x0c7cc8e,0x10ba2a7,0x0885a73,0x1eb59c8, - 0x1ae4efd,0x0261eaa,0x004a071 }, - { 0x0ef3f88,0x104b5ff,0x0514a68,0x1370567,0x02eba86,0x1332539, - 0x0612a1c,0x084ffc4,0x1858ff9,0x06e05d0,0x03276a8,0x1d6ae92, - 0x0833799,0x00ac467,0x0d5bd8a,0x19dc43a,0x07fa7b2,0x0beecde, - 0x0f3ebba,0x0349d14,0x00d21e6 } }, - /* 34 */ - { { 0x1068656,0x0db14f4,0x137fb17,0x193fdbc,0x023bd70,0x0a2aa33, - 0x156f7f3,0x0838f15,0x06291a7,0x1cc0ee9,0x19a23bd,0x1b24ec3, - 0x0f3ac53,0x0adc939,0x05a24a9,0x0dfd8d5,0x1b80654,0x1210bf3, - 0x0e78bd5,0x1807975,0x015e793 }, - { 0x0ff39be,0x0caa1b7,0x1da023f,0x1db7fe9,0x1a1af07,0x120b0b2, - 0x1eaf6c0,0x05307a8,0x1d47980,0x1e2e97e,0x0b9becd,0x12f0c16, - 0x189d86d,0x0746dcc,0x18ca13b,0x17377c7,0x0b5d868,0x1cf824f, - 0x16b462c,0x1d14f13,0x018e3b3 } }, - /* 35 */ - { { 0x11e61f0,0x1362b72,0x1d5d5c0,0x0660fe4,0x1ddbcaa,0x1757a0e, - 0x09baec6,0x1752540,0x0e2d7f5,0x19f49be,0x1ab6468,0x003d78b, - 0x1d1f7cc,0x1723403,0x0ad9974,0x12a3321,0x1555341,0x0e15227, - 0x0599012,0x18394cf,0x00aa099 }, - { 0x197e387,0x0d484c7,0x15a6d58,0x108bc3b,0x1605177,0x18eb55f, - 0x144adff,0x1123ff4,0x0d09a9c,0x16d2ad2,0x00b8ad0,0x18e3a45, - 0x0d5e5a7,0x13a0c2d,0x096880f,0x15dffbf,0x09dea0b,0x10cd89b, - 0x1b30285,0x1df2283,0x01a3a5e } }, - /* 36 */ - { { 0x0573b81,0x106853d,0x13bcabc,0x10cc329,0x1eac1ca,0x188e1a3, - 0x0b6342d,0x085de1a,0x0ba099d,0x17500b6,0x1ea329a,0x1a50a0c, - 0x0fa6609,0x1d09a8f,0x14b1801,0x04c68d4,0x018b11c,0x06d5c2c, - 0x0c700cf,0x1f48bb7,0x0121f17 }, - { 0x03279d6,0x05c3d7e,0x07867ee,0x178403e,0x030e76a,0x1610eef, - 0x1aa0e01,0x09e055e,0x1c63f82,0x17ebf15,0x14694fa,0x1c4c8d7, - 0x047b074,0x1109c8b,0x1bd24c6,0x1b37f9a,0x139c172,0x0d5967e, - 0x16d673c,0x07d6969,0x010a62f } }, - /* 37 */ - { { 0x0689a1b,0x16f1b70,0x19cb900,0x1afb95f,0x1dccc9f,0x0e85fdc, - 0x0b5f895,0x1b3c9bd,0x04ada04,0x1f743f7,0x0b9dd35,0x073d7fa, - 0x1b5a850,0x1b8595c,0x0b1995d,0x0777450,0x026ba10,0x0d3d654, - 0x1f3541c,0x0051758,0x011aac7 }, - { 0x00c8f04,0x0e9ce34,0x0d78b98,0x1969167,0x0f09c4c,0x1a279e1, - 0x026f655,0x126262c,0x0aaccb5,0x0b9725a,0x1ec825b,0x0194b5b, - 0x0fdb706,0x0fe9f66,0x1f6790c,0x054e78c,0x06fe175,0x00a43d1, - 0x134215f,0x0a6cc6c,0x01e33d9 } }, - /* 38 */ - { { 0x0ec9e7f,0x02835a6,0x063f999,0x0861557,0x044564b,0x1fd1425, - 0x1407c5c,0x0e4bc36,0x015c974,0x1dbdebf,0x1b00cf9,0x0f5105b, - 0x02d6cc6,0x0531dbb,0x18ba4d0,0x05f9a3f,0x01b3f8e,0x11d0427, - 0x0b9b9d4,0x1c9b513,0x00fdccc }, - { 0x12fd820,0x1fc7760,0x1ccc1e5,0x152db48,0x125f892,0x0cbdfa1, - 0x0907556,0x19eb2fa,0x002b753,0x1779ad6,0x1f3ae8e,0x12bbece, - 0x0c8a73f,0x08ddd63,0x0a24adf,0x0f160b6,0x183cc52,0x1483a8a, - 0x11fd17d,0x1daa7f4,0x001c2f5 } }, - /* 39 */ - { { 0x140b79c,0x00b2f55,0x06a0e45,0x104b691,0x1fb6eed,0x16083fd, - 0x1adf629,0x117b426,0x18e01f2,0x018edc5,0x1e641f5,0x01bb49a, - 0x0584e5d,0x1238f34,0x0a451ca,0x0dff0d3,0x1699837,0x0ac6834, - 0x118c47f,0x0d36e98,0x0006ce3 }, - { 0x0dd1452,0x1b9e88d,0x08a9b01,0x0bdb1d3,0x0e4e9c9,0x0ad2061, - 0x038cb28,0x11fd1ff,0x0af62f1,0x1e5be9b,0x05212cf,0x0ddddd9, - 0x1b2ca33,0x1d90202,0x15b9ea4,0x106a549,0x031956d,0x1b6c868, - 0x07280f9,0x0eac07b,0x00e5dd3 } }, - /* 40 */ - { { 0x1481bf7,0x194bec5,0x00f3317,0x0854267,0x06a2a3e,0x005cb60, - 0x14a3371,0x0793c28,0x11189da,0x115f9af,0x15fe9e6,0x1312d9a, - 0x0bb8adb,0x09abe99,0x0924d72,0x0df5b83,0x180c2d7,0x0a8fd92, - 0x13c8f78,0x043d684,0x01ba987 }, - { 0x0a4b397,0x16d57a9,0x1952300,0x181a169,0x03c5f4c,0x1f3ce6e, - 0x136cded,0x16c537c,0x0b33970,0x1a19b76,0x0231ffc,0x16f9250, - 0x11ed3dc,0x011446d,0x0a43bfc,0x1ab35d8,0x151e96e,0x19523ce, - 0x1b63e97,0x1db0e0e,0x00929d7 } }, - /* 41 */ - { { 0x060043c,0x0d785f3,0x1d3763b,0x1602dc0,0x04aa2cc,0x061d9ec, - 0x1a39f8b,0x1893a46,0x05c269f,0x1da8098,0x0cf8d91,0x1dc27bc, - 0x04d0194,0x1c4e528,0x0cd86e5,0x1623bb6,0x033984d,0x0466a8c, - 0x03b24bc,0x1003d99,0x00c6d5b }, - { 0x1ab9887,0x08e0aa3,0x0044cfe,0x14d6b56,0x0f285e2,0x1fe40c1, - 0x139684c,0x05936e6,0x038d869,0x021ad3a,0x00ba057,0x08f8865, - 0x0a3c92b,0x0e3de6d,0x048c7d6,0x1190c32,0x1c34d15,0x11d7212, - 0x1688f32,0x0d1fd78,0x00117f5 } }, - /* 42 */ - { { 0x15caa87,0x1eceadf,0x1276332,0x1ed1bb1,0x17bfc60,0x0a6f6f0, - 0x136ef1f,0x17ec7d6,0x18270b5,0x1b72ca2,0x063f9ef,0x0f4b981, - 0x1588713,0x02ebdc7,0x17ada1c,0x14a6794,0x0ee4b25,0x025bef7, - 0x09c029b,0x08b8649,0x00ef8e0 }, - { 0x0cf52bc,0x00e4938,0x0a60583,0x152198c,0x0bf3f63,0x18147da, - 0x10872fc,0x1e2bffe,0x1523bef,0x140816b,0x1384142,0x1347173, - 0x1eff330,0x03310d8,0x0769340,0x0f00f1d,0x09fcc0a,0x14bbafc, - 0x005e184,0x0890ca0,0x00eb590 } }, - /* 43 */ - { { 0x1bd33ec,0x1327ef5,0x15e6299,0x019cb5a,0x0cf9a66,0x1dab768, - 0x1b01543,0x0ddd9a0,0x11d5aaa,0x0652fd6,0x09fc1ed,0x1cb7291, - 0x1a36dae,0x17f0e08,0x18de21f,0x0a897a5,0x0c491d2,0x120fb0d, - 0x0fff63a,0x1ee0e25,0x00be49d }, - { 0x1acdb56,0x178fab2,0x0f79838,0x08bcbcb,0x12f13c8,0x1d02097, - 0x14d5385,0x1df72ff,0x1d9c93b,0x11433e7,0x055f922,0x02d64b5, - 0x1f9ca9d,0x050c31a,0x157066d,0x15ce23e,0x0f58d26,0x0cd9c34, - 0x1251507,0x0900829,0x0000ac4 } }, - /* 44 */ - { { 0x0ad38db,0x1e7c4ea,0x1445b06,0x027ae28,0x1180f38,0x18121d0, - 0x09d672d,0x0d8b698,0x1163a71,0x0eb26b1,0x122f6d7,0x1fd426c, - 0x09bbd2e,0x126f4cb,0x1c61fe7,0x1188b48,0x112e2de,0x1b2ef34, - 0x0f6b429,0x0be5389,0x0048e07 }, - { 0x04dd88d,0x1aa3a2f,0x0bf000c,0x1100aef,0x1828363,0x19447b8, - 0x1700489,0x1bdc966,0x1e68989,0x0047ec8,0x1dc6eb4,0x062b9a7, - 0x0242142,0x1f26d0f,0x0c08ffc,0x05762b9,0x035b566,0x0bf35ce, - 0x1ec13f9,0x1e82caf,0x0072143 } }, - /* 45 */ - { { 0x0f40f2c,0x1823613,0x0c76c1a,0x18d9af8,0x1d5d246,0x09d4dbd, - 0x189c065,0x0df554a,0x08f0043,0x16494dc,0x0198356,0x125843a, - 0x0619373,0x0deb6df,0x1e7b456,0x087f3a4,0x15ad17c,0x09bbe26, - 0x03f3409,0x1db4a17,0x0179800 }, - { 0x0132f31,0x0ee059b,0x0e8ee23,0x0255bce,0x0f8f4f0,0x1ef15cb, - 0x07b0c80,0x066710b,0x0231b65,0x0d81c0a,0x024f2bb,0x1a41428, - 0x19ad08c,0x0e15f17,0x1e1b511,0x1813f73,0x132f6eb,0x0fe9eca, - 0x0bbd1e3,0x16b1323,0x013d757 } }, - /* 46 */ - { { 0x00f894b,0x168802c,0x11bdf66,0x15b24bc,0x1612488,0x0d3432d, - 0x1f850b9,0x0268a92,0x117f9a8,0x0370829,0x0cd5072,0x0415f14, - 0x18d8aa8,0x1d336ab,0x1e41981,0x11c474c,0x0ae5f75,0x023efb0, - 0x1fe2ad7,0x1a99214,0x0107cad }, - { 0x164ad0e,0x18227b3,0x06ccd5a,0x024a031,0x169fe0e,0x0a6db57, - 0x129897c,0x0a85bd5,0x11bd77d,0x0f93bcf,0x0a2573a,0x03e4b9f, - 0x0397991,0x1b78cd6,0x1a533b6,0x08963a9,0x01701af,0x0e1a99a, - 0x031c9fd,0x087ffea,0x003bcac } }, - /* 47 */ - { { 0x1c1d4cf,0x14a8e41,0x0d3c5d0,0x01648b8,0x003791d,0x16e638f, - 0x03bda70,0x0cfd51f,0x12a3107,0x152bd14,0x0522f4b,0x0d77625, - 0x03255b4,0x07f575c,0x1707824,0x17eb255,0x18c449a,0x0d06968, - 0x12a29a2,0x193feb8,0x00199e8 }, - { 0x128171a,0x1dce6f5,0x01ef27d,0x07aaed3,0x0fd7840,0x1fc1267, - 0x1cefc8b,0x18ab169,0x1bf333c,0x104d9c9,0x13adcbb,0x0745603, - 0x0debff8,0x11014ce,0x0cd3114,0x1eea2b7,0x0a066eb,0x1d1e1f4, - 0x074173c,0x1c0f769,0x01a65de } }, - /* 48 */ - { { 0x114257b,0x0ac6b58,0x18c026a,0x03a92eb,0x129afd4,0x173d88b, - 0x1e6d4ea,0x1060e50,0x1edd1ac,0x1c8d849,0x19e5d41,0x0fa23d6, - 0x0acfefc,0x1133ada,0x152f4df,0x0a2fe1c,0x17e8d69,0x1c4d316, - 0x0084268,0x100bb04,0x006b96f }, - { 0x1b5f9f4,0x0ea8bab,0x1345205,0x0c80b68,0x05c9e43,0x0380b07, - 0x1778392,0x1f06885,0x11ef6b3,0x09ff7ca,0x05febe5,0x19ebee9, - 0x17919e4,0x00b7785,0x18f3134,0x1ddda49,0x0872512,0x1fe2e55, - 0x0ef45c0,0x1480534,0x01b6f1b } }, - /* 49 */ - { { 0x09252ac,0x1421aa9,0x0360a99,0x00e9cf6,0x1da626c,0x1f43559, - 0x0330782,0x0a6aa10,0x14ed5dc,0x1a529fb,0x107f414,0x028019a, - 0x1ca9eff,0x0b3a448,0x1f25171,0x16b5a1c,0x095ec53,0x06f525c, - 0x1454262,0x0cf7de2,0x01ffefc }, - { 0x06033fd,0x0e08498,0x1766623,0x13e6d0e,0x1b28797,0x019ae28, - 0x0bc9b8f,0x1ac9a73,0x1124e29,0x0392cfe,0x16f7f29,0x0ae1883, - 0x155d60c,0x06606c4,0x0892d84,0x1ff0c0c,0x0e5eea8,0x1d020ea, - 0x19361c1,0x01c2b95,0x01fd292 } }, - /* 50 */ - { { 0x167da85,0x0af8666,0x08559b4,0x08b58a9,0x0e98b6f,0x1638e1d, - 0x18087c6,0x0485e0b,0x0475592,0x1f59113,0x015b707,0x0ac2cdd, - 0x072a2f1,0x17da5d2,0x1ac5159,0x12416cb,0x1d2a29d,0x19a3445, - 0x07532e6,0x19d0ddf,0x0061943 }, - { 0x0c91174,0x0b10c55,0x08d2d1a,0x1883bb2,0x05b519e,0x03b1d24, - 0x0b7ca7c,0x0676fdf,0x1712c8b,0x028bf93,0x0e18c26,0x1d8760a, - 0x04a02e7,0x0ff9f1f,0x0f116ec,0x0c90c8d,0x16f2949,0x1a35744, - 0x0f4ae4f,0x162c93d,0x01462ae } }, - /* 51 */ - { { 0x0e4d3c3,0x07a0ff4,0x076c7cd,0x1eb76fd,0x080d87f,0x085abce, - 0x1b02b64,0x15de042,0x1b87349,0x1125bb0,0x09b300a,0x0a50561, - 0x17054bc,0x17968ca,0x131c0a6,0x0d9ba76,0x0e2adbe,0x00725c8, - 0x181828d,0x0e9f024,0x00cf8e7 }, - { 0x0229950,0x1cede17,0x0dc0f1f,0x0db3f05,0x0b11f84,0x0602f9d, - 0x1668fc4,0x19456f5,0x10f1820,0x01f56a7,0x1eccc88,0x1791997, - 0x1151dbc,0x0333837,0x1672bc0,0x13abc77,0x0250605,0x12d1cdf, - 0x12bf993,0x070f91b,0x014c984 } }, - /* 52 */ - { { 0x0011531,0x13abfc7,0x15f1c22,0x0587b9a,0x1f45b17,0x0ccf14b, - 0x127f70b,0x02b51d5,0x1b93b64,0x0a7740f,0x023a1a7,0x16a94a9, - 0x10a5833,0x05dbd5b,0x155870c,0x1e753bb,0x184b3bd,0x1daded1, - 0x177ccca,0x13f1c03,0x0124f90 }, - { 0x141e782,0x0554255,0x0e1f16e,0x0d0a3bb,0x1de2012,0x0415e90, - 0x0a9f665,0x077e937,0x1f4b641,0x0cb1ef5,0x0788901,0x1f76f9a, - 0x0eed369,0x0dd6b07,0x1d25774,0x061dbb9,0x093892e,0x0f5a3ab, - 0x1c2884b,0x0237b15,0x010baaf } }, - /* 53 */ - { { 0x0ec64e2,0x100ba0b,0x1af9c51,0x1efaf8d,0x1fd14ac,0x05b8bb5, - 0x0128d9a,0x0383c6a,0x1741b04,0x171f9f9,0x0d9ec1c,0x0a945a7, - 0x0d651fa,0x12bec94,0x0fb728f,0x1e832c4,0x08b72c8,0x194dba7, - 0x09eaebb,0x13968e6,0x00383d9 }, - { 0x0342a3f,0x0e859ed,0x0552023,0x05bde95,0x1200246,0x1ad4300, - 0x190bbaa,0x0da3638,0x106e54b,0x10f1502,0x1b3c697,0x021e218, - 0x109ba17,0x07c81e6,0x13f0d98,0x0cdea66,0x0011341,0x1cb4f00, - 0x15710d4,0x04c0e82,0x00fafaa } }, - /* 54 */ - { { 0x12de285,0x0687338,0x1717217,0x010d3eb,0x0d2ff8b,0x0769c4e, - 0x0ae4b7d,0x1086e54,0x055b99c,0x1a92698,0x0800cd8,0x0b45c0f, - 0x1346fef,0x0b704a4,0x0b20b6b,0x12a5614,0x02172a8,0x159b133, - 0x1c85fad,0x1963115,0x002c9af }, - { 0x064c5b5,0x0ea3b4d,0x1f874ee,0x1c89899,0x00d8d5d,0x036dffd, - 0x163bc47,0x1daac10,0x141c14a,0x10ecbc7,0x1fa1533,0x1ce46bd, - 0x1d251f9,0x023a2ba,0x1430530,0x13807f3,0x18ebda8,0x0069641, - 0x1b32770,0x1e08166,0x016fa25 } }, - /* 55 */ - { { 0x0ad682d,0x0cef54e,0x0e46c8f,0x068c6d2,0x07acb1b,0x07926bc, - 0x0662170,0x19d3eb8,0x1d41883,0x1fb17e3,0x15791b7,0x13bea6a, - 0x05d1ab2,0x048e6d0,0x06c72ca,0x067daad,0x1c452c6,0x06d8a6d, - 0x08d150a,0x1770d85,0x01941ac }, - { 0x0db8127,0x1386412,0x1d6f61a,0x1e836f9,0x04a6563,0x046cda4, - 0x16afae4,0x0151b09,0x1899c26,0x1755731,0x0da55ea,0x1656888, - 0x0d13ed6,0x0854964,0x1253e67,0x1972e77,0x02bd04b,0x1cbc797, - 0x05a9597,0x0711dee,0x007456a } }, - /* 56 */ - { { 0x0fc1f77,0x16ff24b,0x15a9820,0x1e268f5,0x104c435,0x15f22bd, - 0x0537097,0x155e84d,0x1b6f764,0x050b834,0x00f6859,0x07aa09b, - 0x10e0387,0x1064119,0x0e76d4b,0x1367d61,0x14ed423,0x14c4359, - 0x0620536,0x10fe54b,0x016a765 }, - { 0x1c71a5d,0x07c7475,0x08cda46,0x050a80a,0x09141a4,0x0165e62, - 0x0273306,0x14fac7e,0x1e09057,0x17f2ce9,0x0763ad2,0x161bc47, - 0x12e633d,0x1eca4a5,0x12160b7,0x1fac375,0x0414704,0x0c5c8ad, - 0x13abbf6,0x0cd53bf,0x010ee08 } }, - /* 57 */ - { { 0x0e07a4d,0x0623829,0x1740ad4,0x11cbae8,0x1f6d38b,0x1789133, - 0x111f386,0x1ef6829,0x139c505,0x1f25a25,0x1ce6f80,0x0f2b0de, - 0x1c59f3d,0x13e178d,0x066f29f,0x1f5a994,0x01ec063,0x18e28e0, - 0x1d0a2be,0x126f4af,0x0080da3 }, - { 0x02369fa,0x0654e88,0x18d7a76,0x16e0d81,0x0009bff,0x1aaec07, - 0x0669e5a,0x0985c14,0x0ac0d09,0x107216f,0x1061eb6,0x058af0f, - 0x166c1be,0x0e7d025,0x12b8b32,0x0e680da,0x0607657,0x0ad8675, - 0x1f258a1,0x04a48b8,0x00d82d5 } }, - /* 58 */ - { { 0x093de69,0x191c657,0x1a6db72,0x0677fb5,0x0963c83,0x1bcc1b2, - 0x07d37a2,0x15c6790,0x0ae8bf8,0x09d1122,0x1aeb338,0x0f0c987, - 0x160bc6e,0x0aad2d6,0x0de94f1,0x128b350,0x135bc7e,0x0c3aec6, - 0x07d1bf3,0x00aa69f,0x001fb37 }, - { 0x1b974a1,0x093863f,0x1205e3a,0x01d3da4,0x03448fa,0x1ffdea1, - 0x1b0f592,0x078282c,0x1d79f4b,0x02d5221,0x1cca828,0x09e2773, - 0x1ed855a,0x164811a,0x1af3e36,0x0569097,0x1878db5,0x0b2c24c, - 0x1234274,0x1ab3e3c,0x0183aa4 } }, - /* 59 */ - { { 0x1ffad9f,0x02ebaed,0x03f3b96,0x09e833b,0x04df617,0x0349a2b, - 0x0fd679b,0x018dee7,0x183d59b,0x003c9e8,0x122542e,0x1f87253, - 0x0b6baf4,0x14cb15d,0x1116a54,0x024e77a,0x145eaa9,0x1a95b0c, - 0x1471e16,0x19bffe7,0x01be4fc }, - { 0x0b2857f,0x1c26cbe,0x0fd0170,0x100d6f5,0x0cf8305,0x1673592, - 0x1745d0e,0x16dea51,0x0bc43d6,0x03dc7d1,0x1592e4b,0x117e29c, - 0x1a8f0e2,0x095cf80,0x1a6f1cf,0x107cc36,0x1403dd3,0x1d5c5f5, - 0x1e4651a,0x1d418b2,0x00aeacc } }, - /* 60 */ - { { 0x163c2de,0x05d7700,0x029269a,0x17d64ed,0x042d0b2,0x0d73b3e, - 0x1c493ff,0x086ad0d,0x10aaca9,0x136d2ea,0x02473e4,0x099dc02, - 0x0d699c3,0x09925f6,0x0951501,0x141527a,0x0f14193,0x08db5ac, - 0x1847327,0x0924bda,0x014ff14 }, - { 0x1ed9259,0x0d30660,0x09fdfd8,0x065e3ab,0x1be37aa,0x177a188, - 0x1c4f41e,0x1740708,0x14e6fa7,0x0f99ea4,0x0dcc326,0x182d17a, - 0x1c43928,0x0dcaabe,0x13e333d,0x17dcae7,0x060d1a2,0x005e36a, - 0x0ec5584,0x1a32870,0x014527c } }, - /* 61 */ - { { 0x027af4e,0x1289a9a,0x0df52f9,0x02621b2,0x0e6c0bb,0x1338e19, - 0x09dab2a,0x0ed7b1d,0x0d3a9c3,0x0bd9fea,0x1c26aa7,0x10c68e2, - 0x00124ce,0x00c028e,0x1739074,0x1dc3844,0x04ff9e8,0x02a4494, - 0x0d713b2,0x105392a,0x013d22d }, - { 0x1b15e02,0x0f6ced0,0x01a1ac0,0x18603cb,0x1d092ba,0x1209ad8, - 0x0860d5d,0x1497f4f,0x16f7159,0x0772cdb,0x0434370,0x00a2301, - 0x169171a,0x1c0290c,0x054c6ee,0x0f208b8,0x0fc2092,0x0ba0498, - 0x18cdda1,0x169198e,0x0008963 } }, - /* 62 */ - { { 0x0aaaed5,0x05b107a,0x1ba03fa,0x1bfd0e3,0x1068de7,0x1fe5a58, - 0x00c3ffa,0x0b65644,0x1c3a215,0x06fdf73,0x06e0175,0x15184ed, - 0x10a7a26,0x169cf57,0x1f79dc1,0x1e0646e,0x047f615,0x0f8d492, - 0x0b66dcc,0x1035088,0x012aa1b }, - { 0x1152e8f,0x133e858,0x0530a67,0x0f256bc,0x0e773d9,0x05abd11, - 0x041cfc7,0x145c1b0,0x0bf1da4,0x1d7854e,0x0d12680,0x0c1d845, - 0x1d169b1,0x0e96be8,0x0b06b23,0x11dc970,0x0a6bfc9,0x0ba8456, - 0x0f2fa85,0x124881c,0x0150549 } }, - /* 63 */ - { { 0x13a4602,0x0250550,0x1839c00,0x07a1a58,0x105c71a,0x0bcde2a, - 0x0918e9b,0x1e949fc,0x0d54d9d,0x03c759d,0x0f1ee3a,0x120ee7a, - 0x057ecca,0x122767d,0x0eec9e0,0x1a2f2b6,0x01fb124,0x045187b, - 0x1d8cabc,0x1ca0029,0x01155b7 }, - { 0x0f0021a,0x017664f,0x07518b1,0x0ff0ad9,0x18017fd,0x123c5e2, - 0x10ee0b9,0x1b621c4,0x11505a4,0x183a334,0x1fba96b,0x143899a, - 0x0ad9bb0,0x0a95768,0x0e8e68b,0x1e13bd1,0x09ab549,0x003a3a2, - 0x195fe99,0x11ef7b3,0x013fd5c } }, - /* 64 */ - { { 0x053c22b,0x0673dad,0x11a86f6,0x1af9568,0x18733fc,0x1659ca3, - 0x0938922,0x01f8899,0x0a38c79,0x0c4458f,0x0d08dea,0x0dd62b8, - 0x0336afb,0x1db8103,0x04ee2a3,0x011f572,0x0c59175,0x19a5bbe, - 0x0791cca,0x03af4ff,0x0050a93 }, - { 0x0d21d18,0x121482b,0x0286a42,0x0eab682,0x0266630,0x053582c, - 0x12a2e25,0x0b968d0,0x1828cf7,0x10d6f31,0x1c0a8e2,0x10b424e, - 0x094fb2f,0x16fbdb8,0x1fdf416,0x03b6d07,0x092a68d,0x00e9fad, - 0x024f357,0x19c3b78,0x00f5243 } }, - /* 65 */ - { { 0x17d7891,0x0c1e1e9,0x1b2a3f0,0x13fb0cb,0x17b5014,0x10c2208, - 0x10f5a3c,0x0b01edc,0x15a07f6,0x1a8f612,0x00c80ab,0x0d975a6, - 0x158fe5a,0x0833b77,0x179a3cc,0x000192b,0x11fca4e,0x03a8471, - 0x1dcd495,0x1cb52ae,0x0159783 }, - { 0x0537ad9,0x0dab897,0x13def07,0x1a6b7d3,0x1e87112,0x1fcde5a, - 0x0ad2355,0x18f76a4,0x0a8b3cb,0x17fbc48,0x136d707,0x1c23cbd, - 0x0d4f306,0x19c3f3f,0x16a0e48,0x03c7a61,0x0f47232,0x026c8fe, - 0x104a99f,0x0f76c5c,0x009f848 } }, - /* 66 */ - { { 0x0b8e08e,0x0fc07c6,0x1b5a1bd,0x02492df,0x1cfd2c4,0x1bee6fb, - 0x0dd0d82,0x0be00c3,0x157f4d0,0x0dd7fef,0x0187c93,0x18548b0, - 0x04b1993,0x0ef4ca6,0x1b2a342,0x1c0c4d8,0x04d2747,0x077b869, - 0x066572f,0x0ba9c77,0x00ffd4e }, - { 0x0f40077,0x0f122e3,0x1418c5c,0x0a0e47c,0x1592e04,0x15fec40, - 0x1bdf9a9,0x1c06b90,0x16d9d9c,0x104ace8,0x15dc32e,0x1fd07d6, - 0x1d2e7f8,0x0206b1e,0x1ac2207,0x08832b1,0x1daeb9e,0x0ab199d, - 0x0bf47d3,0x072fbe7,0x0034fb0 } }, - /* 67 */ - { { 0x158815c,0x0702f59,0x1f65ee1,0x09c8210,0x1abcb2d,0x182ebd1, - 0x162241f,0x0390f4e,0x17a9d48,0x083bc6a,0x1932f4d,0x1ff085a, - 0x1e9d34c,0x067944f,0x167356b,0x058dc10,0x191dd2b,0x141b96a, - 0x02d02d8,0x1a905c3,0x006bc06 }, - { 0x04ed375,0x14ad06d,0x0bab441,0x10531b5,0x11baf58,0x1b84962, - 0x086d3d2,0x06b6051,0x07a335b,0x15c3ed7,0x1fbf622,0x06c40ac, - 0x14a7359,0x199061b,0x127f040,0x11660f4,0x0c4a355,0x1b9bd65, - 0x103f3a6,0x0d2d469,0x001ed30 } }, - /* 68 */ - { { 0x13902fe,0x085585e,0x0ecf655,0x170d53a,0x1bba4b4,0x0e561bc, - 0x182a65d,0x1b874b3,0x1333605,0x02f4398,0x10b1601,0x118435f, - 0x11f2c59,0x177ce5f,0x1fe35bf,0x0788503,0x1d09bf8,0x0c15f6a, - 0x0a04c75,0x1b3ab6a,0x01579d1 }, - { 0x119258e,0x0d182aa,0x0aa1a1f,0x1204fbc,0x13f539f,0x11186b3, - 0x05d1f5a,0x108d3f5,0x15f5d16,0x18d7591,0x1907d6a,0x128ebef, - 0x135bbfe,0x0b53ff5,0x151aaec,0x0a30f7a,0x0e8e16d,0x0957dea, - 0x13254f7,0x0f7c277,0x0160743 } }, - /* 69 */ - { { 0x09755a3,0x0b2d4f7,0x0ac557c,0x1570593,0x0c8d5a1,0x15cbf30, - 0x1916aad,0x0e2cb43,0x0ab05e2,0x00266d8,0x020c3cc,0x16a4db6, - 0x0b9e0c3,0x1ad65ef,0x187b069,0x1093155,0x084761e,0x1209ea2, - 0x06e718b,0x1c13776,0x01e9589 }, - { 0x072258d,0x09040ce,0x0f519d4,0x08b82b2,0x01dcd73,0x008fedb, - 0x1e9ee47,0x11cd8c4,0x1885790,0x0e9f4df,0x0f1a3b4,0x0dfca61, - 0x1f9aac0,0x15ada27,0x1705aed,0x1dbaa24,0x1b6db90,0x01c4305, - 0x0efb6d7,0x1d1611f,0x01aa96f } }, - /* 70 */ - { { 0x057c0f8,0x12eec79,0x0364c8e,0x05ba742,0x0884dc9,0x1c6701a, - 0x1e73aee,0x15207e6,0x1a47262,0x10bd6a9,0x01b1b58,0x002ea5c, - 0x0da1df2,0x0192146,0x0dc8f83,0x18c59eb,0x0892c30,0x00f2e9c, - 0x1dfe0b3,0x121e3e8,0x01fdd9a }, - { 0x163ab59,0x093dd0b,0x0fa60c3,0x1ce46f0,0x0f27d93,0x0cb4556, - 0x0099251,0x1ab02ab,0x01700d5,0x1928d19,0x11b67d8,0x1ce6062, - 0x12cf6bb,0x132df87,0x173d157,0x047f6d9,0x0ce6323,0x0405500, - 0x05a91d1,0x13cc59b,0x01496e4 } }, - /* 71 */ - { { 0x0574c09,0x185bf20,0x1a5afbf,0x067fd01,0x176f264,0x11bec8d, - 0x14d4bac,0x0041677,0x17edc31,0x006315b,0x08db70f,0x1296849, - 0x1ef9893,0x1e3621a,0x1a99309,0x1a0edd3,0x1c4e388,0x196fe10, - 0x139a792,0x10a5ed4,0x0139cc3 }, - { 0x1096b91,0x051ffdd,0x10f948e,0x0ae7b1a,0x0e72c9e,0x0bbaac7, - 0x16c4631,0x169822d,0x0dc47d4,0x07644e9,0x06557d5,0x1a6a85c, - 0x1c2006d,0x1a1ba3a,0x12bb5a9,0x1208200,0x12a2bee,0x0e0eee1, - 0x164ccb2,0x082f45d,0x01fb597 } }, - /* 72 */ - { { 0x19bae66,0x18cc0c2,0x106cf03,0x0308baf,0x0b48e9b,0x151e0f5, - 0x0700d14,0x0738d9d,0x0ff8103,0x1c25006,0x035bf88,0x1c22bf3, - 0x1bcd7ed,0x1c506ea,0x08038f4,0x0380def,0x08a3c7e,0x1ab6eca, - 0x194e987,0x034fa31,0x00d09d2 }, - { 0x00eb3fb,0x1edd7c4,0x1f27e73,0x0ebd07e,0x04cfd29,0x053a5a3, - 0x1f5be8a,0x006c374,0x1dfb13e,0x01006af,0x0984a2e,0x1e96465, - 0x0e03bc8,0x00d46c3,0x1ee4b0a,0x0dd4fa3,0x1ae706d,0x13433af, - 0x1eac630,0x10c115d,0x011d9b0 } }, - /* 73 */ - { { 0x1d2f539,0x1b0a35d,0x0e885f3,0x00edc4d,0x16052fc,0x1f2533c, - 0x0746352,0x1506d04,0x09f3f39,0x1c11a11,0x1e1cea3,0x0d72867, - 0x0868b84,0x18b7a2b,0x074fcd9,0x0eea0f4,0x0282fd4,0x16fb01f, - 0x05d7889,0x16058ad,0x000377c }, - { 0x001dd59,0x0d6e9c6,0x0debc9d,0x1d73834,0x1c213a9,0x1e2a01c, - 0x1441137,0x10cd215,0x007ee0d,0x0177103,0x1f10388,0x1d2acc3, - 0x16896ed,0x085817a,0x135ce63,0x03448d6,0x191e5af,0x0e65cb4, - 0x04fdc49,0x05035f8,0x009fd5c } }, - /* 74 */ - { { 0x1073a5a,0x062a5eb,0x11f7216,0x190c3d5,0x07c81a5,0x10100d4, - 0x128e79c,0x19ca3f0,0x040e003,0x0954fc7,0x06677a5,0x0956b1e, - 0x0b76bdc,0x0ab6601,0x1c48c8b,0x0c5e639,0x06383f1,0x0db31a7, - 0x1e5a784,0x002fdd1,0x016984c }, - { 0x089f1fa,0x019b12e,0x01e3c7d,0x016d2f6,0x0a02a63,0x02dbfa2, - 0x079712c,0x1986662,0x14fede4,0x1e65728,0x096a929,0x10e8960, - 0x0d0d26e,0x1c26dbd,0x16ddeef,0x183fcfa,0x0a8f571,0x01cf78d, - 0x0633348,0x1752508,0x018d65e } }, - /* 75 */ - { { 0x0bb2537,0x03355c5,0x05be8de,0x16cb661,0x14ac4cb,0x0145698, - 0x09fb4a9,0x12d04ff,0x010e9e1,0x0e8cfb1,0x006d3a5,0x0f41130, - 0x0331eb9,0x15745c1,0x19de98a,0x12c8555,0x02a5f5c,0x04b49eb, - 0x18da2e1,0x17fd2e7,0x00adff5 }, - { 0x12b0dee,0x1d710a4,0x0b3a8fb,0x1d2c058,0x0143e9e,0x1dccf29, - 0x1f265bc,0x0b2426c,0x0e93b8f,0x0bc5958,0x1304fb7,0x187020c, - 0x1a8d541,0x1ab9c73,0x0e5c36b,0x16349cd,0x0168373,0x1d7b766, - 0x12b8823,0x147e9ee,0x0180dbf } }, - /* 76 */ - { { 0x07a6aa0,0x0310d48,0x07dac09,0x1080f0f,0x0f56cb6,0x14549a7, - 0x02da205,0x0908987,0x19b9a90,0x06b1c69,0x107c81c,0x154104a, - 0x106968c,0x0fe445a,0x165c14c,0x0af0818,0x0d5af63,0x1aab26f, - 0x1352533,0x11318f8,0x0097e7e }, - { 0x16ebb2f,0x04c6cb5,0x049b877,0x18f553c,0x092a17f,0x1516341, - 0x03f6fe8,0x0376c1e,0x0b2e185,0x0319386,0x0933fa7,0x04cb039, - 0x15898db,0x188cace,0x02098e2,0x11a3328,0x08ea54b,0x0722798, - 0x1398c25,0x133d708,0x00d6963 } }, - /* 77 */ - { { 0x03769ee,0x079b15c,0x12cfe80,0x187df89,0x12d040a,0x15eb43b, - 0x0e2255e,0x0518726,0x1940a71,0x1132212,0x10a8c58,0x191fd84, - 0x11909c4,0x12d0d2a,0x1923c79,0x042e5a3,0x0f1049c,0x0345eb8, - 0x026dff5,0x125a56e,0x0041c86 }, - { 0x1816784,0x04550ef,0x173938e,0x0a037ce,0x0a58c8a,0x133c092, - 0x17fec0a,0x1c13693,0x0eda721,0x1994cf0,0x0997b29,0x03ebccf, - 0x168a0bd,0x02b638d,0x07a47a2,0x15461b0,0x0f4c005,0x11bd771, - 0x1656efc,0x000ea00,0x0073d94 } }, - /* 78 */ - { { 0x10c0ef3,0x1562500,0x0682a44,0x109d036,0x0e654bd,0x1a9a848, - 0x18f713c,0x1351e0a,0x1b47d18,0x06e20f9,0x0302704,0x1a0de47, - 0x07122ed,0x020d67b,0x1305abf,0x10a4044,0x1348375,0x18e65c9, - 0x09d6b9b,0x16be524,0x01271a4 }, - { 0x0e688b5,0x1ea399e,0x1a2de4b,0x0fb9538,0x14566d3,0x0b88e80, - 0x0c9b950,0x151f9d2,0x03cc341,0x1dd0a77,0x0b047f8,0x0998424, - 0x156b8ab,0x1ae9bcd,0x1e9d8ef,0x05f2381,0x0aef152,0x0caf169, - 0x073e569,0x04367a6,0x00acd4e } }, - /* 79 */ - { { 0x18e061a,0x1d3bc8e,0x08c1004,0x0159909,0x02707e7,0x17b1b53, - 0x0099bac,0x13ad581,0x177b25c,0x08bf510,0x1cd73fa,0x177ae1f, - 0x1eddb78,0x020c4c5,0x0236cac,0x1c88aa0,0x0fcce0a,0x187ac52, - 0x095f439,0x12472e4,0x0043ed0 }, - { 0x0e129e6,0x0bbd9f1,0x135cb2b,0x0e1e37c,0x1b8c4a8,0x02b199f, - 0x037fc80,0x0875dca,0x12a6915,0x0132c60,0x189902f,0x199571f, - 0x0f95dc0,0x0cb2d05,0x13ad610,0x1b33cd2,0x053edd1,0x1be9dd5, - 0x087b721,0x0276411,0x00832df } }, - /* 80 */ - { { 0x181c3f2,0x09123e8,0x08fffab,0x1de66f6,0x115d35b,0x0483394, - 0x1f2e9d2,0x143b699,0x1fda7a3,0x07b86c7,0x1d5a1b9,0x0832f24, - 0x1e226b6,0x17f8fbc,0x010218d,0x149d1d0,0x139cf5f,0x04c7425, - 0x02827d8,0x1417d3b,0x00da57a }, - { 0x0fcea66,0x0767aa7,0x1ebb503,0x195f8ed,0x18df2ae,0x0ac2d44, - 0x0692324,0x14ac7e3,0x113f00a,0x088ded3,0x172e7ec,0x1f56896, - 0x116687a,0x1293106,0x157ec49,0x06b578d,0x11bbacb,0x157ca9f, - 0x1e53134,0x0126e1f,0x00ed997 } }, - /* 81 */ - { { 0x0b54c89,0x1ab7034,0x108ab27,0x1b9ce6f,0x08ecc17,0x044da98, - 0x1a0feac,0x036411d,0x1543fbd,0x079d094,0x175c1ac,0x19f1089, - 0x0d1b204,0x0f61720,0x05d7227,0x1229501,0x1ae9399,0x1845808, - 0x119d37d,0x1742e0e,0x00176b4 }, - { 0x1dfc175,0x0b754c7,0x0c31c48,0x06fc1eb,0x17b7fc6,0x199d1a3, - 0x0a17f3a,0x16f11a0,0x10223ea,0x13cc0a7,0x1b648ad,0x0416a38, - 0x1d90787,0x0e09fa8,0x1675692,0x0c16ab0,0x10bfaed,0x1734fc2, - 0x14332ac,0x135088d,0x005c249 } }, - /* 82 */ - { { 0x1e7bcf1,0x0c0fdb9,0x1ef9075,0x19ba782,0x16dde61,0x0ccfec8, - 0x05fb3e8,0x12f8c53,0x1c159db,0x13ac439,0x0ca0c06,0x112cc82, - 0x184ed77,0x14a1548,0x1cb3a24,0x149772c,0x187816b,0x1f9f722, - 0x195375f,0x0f42919,0x01234fb }, - { 0x009be8c,0x0c057f8,0x0e87c17,0x0ef1be3,0x02e938d,0x16f3103, - 0x0ba10c4,0x1734fc4,0x16070c4,0x0694f3f,0x1768dd2,0x07d7436, - 0x135cd9c,0x1238ba2,0x146f4be,0x13cce3c,0x0b056ab,0x0ca04c5, - 0x07df1a8,0x1095789,0x0049bb5 } }, - /* 83 */ - { { 0x0a470f7,0x12a980f,0x18c2a7c,0x11d24a9,0x001bf80,0x1001c6d, - 0x1a7a9c6,0x10e130a,0x15913ca,0x0959770,0x007f6c3,0x0097705, - 0x0aae170,0x08c72e1,0x171bac0,0x08757b6,0x04c1fa9,0x0d2b563, - 0x0a4b540,0x1ec8ee3,0x00531aa }, - { 0x0345730,0x0f7a483,0x1f0a59e,0x1d08de6,0x146aaa4,0x1e1d55c, - 0x09ac069,0x09df02e,0x08166df,0x1c046d1,0x1370fb2,0x1f849c0, - 0x14e9fb3,0x1b760cd,0x02d876d,0x1a27d3c,0x05eeed6,0x0373fb3, - 0x1a9d4e1,0x1b180f0,0x00e570e } }, - /* 84 */ - { { 0x08ce13f,0x0b72c08,0x004d991,0x1a1c72f,0x15bfc58,0x1ca4f4d, - 0x0a12fa8,0x0fa096d,0x075af66,0x14db35e,0x0559afa,0x0db9512, - 0x1a7cb4d,0x1fb0aca,0x0f3b3c2,0x04a4036,0x13d002e,0x1218963, - 0x04d697e,0x0ed130c,0x014b81d }, - { 0x01078ec,0x1de12c2,0x1535011,0x0c2f388,0x15aa9c9,0x08fc7e3, - 0x0182521,0x03ed42c,0x0ce3409,0x0c6a71f,0x15040a6,0x0e0911c, - 0x1e9a9f6,0x0ed4562,0x0a03e21,0x046197e,0x0a08fec,0x0e32656, - 0x0252ddd,0x10c960a,0x002b0ac } }, - /* 85 */ - { { 0x15daf7f,0x0371cc7,0x1419ad8,0x122124e,0x0838548,0x02c5392, - 0x1717023,0x1c7444a,0x0c90f3e,0x19b17e8,0x057c08b,0x15e810f, - 0x0ac9633,0x0212fad,0x1c42f44,0x1b7f6e2,0x005ec06,0x0e100bf, - 0x06e2ef3,0x0fb9058,0x01c8d9c }, - { 0x0b8bed9,0x00fef8c,0x0495f6d,0x11c7446,0x0948330,0x08e25df, - 0x0779dca,0x15f79f2,0x141448a,0x185cb95,0x16918a6,0x0c67889, - 0x0295dfc,0x00dfa85,0x0e7118c,0x0626321,0x177869e,0x08c5b37, - 0x086eab6,0x09c5f42,0x00f5a8a } }, - /* 86 */ - { { 0x00251ea,0x0a884e5,0x06c2329,0x164f4d9,0x12aeed8,0x107a947, - 0x02fad58,0x0ad2035,0x0ae13fc,0x14210f4,0x04f01e6,0x03890b3, - 0x171349f,0x068d586,0x1820d64,0x1b21253,0x09baeb5,0x1cb7149, - 0x166699b,0x05e3f1e,0x00ce96c }, - { 0x0be8bd7,0x025a889,0x066f92f,0x1e78cfd,0x14846a0,0x1d1c327, - 0x11f4d34,0x103b139,0x073f439,0x1b23889,0x13959c7,0x06484db, - 0x0bc32bc,0x181584b,0x04d3aff,0x1056fee,0x00b0d06,0x0ab0278, - 0x0f3a2d6,0x07afd5c,0x011cfd2 } }, - /* 87 */ - { { 0x07689a6,0x1236651,0x1cafe25,0x06aac82,0x16a7dc4,0x1e5fe66, - 0x0923ad5,0x1ca617b,0x15b1adf,0x188fffd,0x162fd26,0x01b6e23, - 0x1b9f2d8,0x1b872d2,0x1e7f7c2,0x1143bd0,0x1836bd1,0x04ba9a0, - 0x12ff541,0x0a4d7b1,0x0114c8c }, - { 0x17388bd,0x1392df7,0x1a9f57f,0x1fcfff5,0x11c3dbd,0x16f1567, - 0x16e25f9,0x1f6f072,0x09ebf1b,0x0d3964d,0x01451a0,0x0e0ed2f, - 0x0f65265,0x1a93385,0x097b367,0x0fa9072,0x1d283d5,0x121bde6, - 0x003b2c0,0x0e654f9,0x01ceb5d } }, - /* 88 */ - { { 0x1d376d7,0x0fe6767,0x01369fe,0x1d4cd61,0x0b4eab3,0x1c8dec3, - 0x0342356,0x1b0d592,0x08aa304,0x11eadbf,0x19a93ea,0x0856ff0, - 0x0127f3d,0x1dc09d7,0x1467ea2,0x1240d2b,0x0d7e34a,0x0e9c3cc, - 0x0cb0737,0x1814d34,0x0073df7 }, - { 0x0315b16,0x000dd9c,0x03e6f8b,0x133c319,0x1daa7c8,0x1b5c298, - 0x0fed022,0x10347a8,0x068092a,0x0acf246,0x1eab52c,0x1b3d06d, - 0x1077e93,0x1234cb9,0x1b58d86,0x1c8eda9,0x1f66297,0x12b4e59, - 0x1e047e9,0x1b0307c,0x0185b69 } }, - /* 89 */ - { { 0x19cb764,0x13f59d5,0x15b463c,0x031d783,0x1bbefc2,0x1cd53cd, - 0x0376c11,0x1ea8eec,0x009e542,0x068b692,0x066e5ad,0x11a378d, - 0x0ae35c3,0x0646c64,0x0cab896,0x148ba27,0x15267a3,0x042bce0, - 0x1155301,0x16e6aed,0x00d9773 }, - { 0x018c299,0x0523981,0x08ce588,0x0733ef1,0x09be29b,0x07a0a7b, - 0x0802521,0x1a88d09,0x19a2ca4,0x163a49b,0x0deacec,0x0e7cd1b, - 0x1f09c07,0x09ae1ab,0x007c166,0x1c7e4c3,0x03d8b7d,0x0049898, - 0x03edb82,0x1ff9a1c,0x0060f3e } }, - /* 90 */ - { { 0x05d6530,0x00a5f59,0x103dc8f,0x13352fa,0x1e015b3,0x1bfb112, - 0x0f12fef,0x1e24138,0x014b4f0,0x1ec62ce,0x1a3b3e0,0x1fbc7ef, - 0x0fcf002,0x0f58f78,0x14d4f24,0x018c06b,0x0a5201f,0x01ca621, - 0x0fa3b8d,0x025156f,0x01b5787 }, - { 0x10110cd,0x1be9d5b,0x06d6824,0x188ef22,0x00fa4ef,0x1d260cf, - 0x0bd6f14,0x1e58d59,0x138d509,0x0980879,0x0b071af,0x1057ca9, - 0x1f3ee2a,0x127951d,0x1a99f0f,0x18f7263,0x06ef089,0x1bd2653, - 0x1288d8b,0x14589e6,0x00b05bd } }, - /* 91 */ - { { 0x1f575cd,0x05038e8,0x060ad09,0x034a46e,0x15693b0,0x164ea00, - 0x0d80a68,0x0c02826,0x19c914a,0x0621a45,0x0cc7054,0x0e7a12b, - 0x0290245,0x117ea4b,0x05d7f48,0x164eedf,0x086e210,0x1d0b824, - 0x16ea4de,0x137026d,0x01f6ac2 }, - { 0x15da491,0x0f7aabb,0x160827b,0x1c56d55,0x05953f9,0x1a06ad9, - 0x084186e,0x1b0cd2d,0x14d5127,0x1e22988,0x0b418b3,0x195303d, - 0x032f21d,0x179db89,0x0f93c1e,0x1e41a7e,0x0b89646,0x1896683, - 0x0443d6e,0x06c6d2d,0x015e241 } }, - /* 92 */ - { { 0x0cfc44e,0x027e81f,0x0f54321,0x10a0876,0x0095f2c,0x1e82cd2, - 0x19f6f26,0x1bf34bf,0x0f65bec,0x1c9947d,0x0587348,0x08e34cf, - 0x1de3102,0x1ddaefe,0x078e6fe,0x18b75d5,0x0d0133d,0x0c0115b, - 0x1c4b0de,0x0f5536b,0x0141bed }, - { 0x194d941,0x1802cfe,0x006025b,0x00fa9fe,0x1c6e9f0,0x0f82f1f, - 0x1d661de,0x133cc75,0x100483c,0x0207859,0x0661c13,0x1ddee54, - 0x1104d2f,0x0325253,0x1dced6d,0x0fe3db6,0x10f4936,0x1005b3b, - 0x0a7ef4a,0x1c06025,0x01694f7 } }, - /* 93 */ - { { 0x09095fd,0x0eeb9c5,0x15e837d,0x03a79d0,0x04b7a02,0x16e3b3e, - 0x1e5af97,0x0112154,0x1180a08,0x124bf7f,0x042aad5,0x1c3ecde, - 0x06b9856,0x1cc3cbb,0x0a62090,0x00c0262,0x0f73ba8,0x0b0ba46, - 0x1576a4a,0x120ed8a,0x001207d }, - { 0x044394d,0x04d008e,0x19142c1,0x0e19c93,0x15f25ef,0x14a132f, - 0x027c2c5,0x1f03c74,0x0109b33,0x02decff,0x04cb90b,0x087f461, - 0x1207f2a,0x0367c57,0x1aaff2b,0x0ce44e6,0x004f336,0x056fbfd, - 0x0a749ac,0x1d25f7f,0x00e02f1 } }, - /* 94 */ - { { 0x1be4d4a,0x0725331,0x1246549,0x1acde79,0x1fa57be,0x1d3e668, - 0x04fe9f9,0x1a7baf9,0x088c5d1,0x07467b5,0x147c79c,0x12f47e4, - 0x15b2579,0x11aaa67,0x17b163b,0x0e21214,0x0d7065a,0x1346934, - 0x014227a,0x07a9a41,0x004c7c2 }, - { 0x152d132,0x12badde,0x13158eb,0x0e71903,0x0fb8daa,0x131dcc8, - 0x1b94793,0x10e12d4,0x0b239d3,0x0eb59b3,0x127fb54,0x10e94ba, - 0x1aed5f8,0x01d4603,0x1424765,0x0d5c404,0x05ae468,0x10807c2, - 0x1ad3bd6,0x0b3ae8f,0x01c21af } }, - /* 95 */ - { { 0x1441308,0x1e00f6e,0x02417de,0x090c611,0x0dc3494,0x0b08e68, - 0x029d1d6,0x0cc55e7,0x14c23ce,0x0d38930,0x0bfb484,0x0f6bf17, - 0x1937f31,0x0649f03,0x1eee7fd,0x0a59e9d,0x0dd8ecc,0x1440787, - 0x172760a,0x19ba59b,0x0028480 }, - { 0x1f807ac,0x0e506e1,0x1527a3c,0x057a0e0,0x0a3e4fc,0x1c5db63, - 0x0285247,0x19b5a7a,0x13d6dfa,0x1f70e7e,0x11bfef8,0x0372bf6, - 0x1cee46b,0x1eeae7d,0x01eceb1,0x1d16ea4,0x0d9b1b8,0x16ac060, - 0x1ef7446,0x0cd3e98,0x008452c } }, - /* 96 */ - { { 0x0ace6d5,0x1a3a3e0,0x1eb690a,0x177ce50,0x15acb64,0x1e130a6, - 0x1226626,0x03de660,0x0ff05c7,0x0bff41b,0x0b11420,0x048da6b, - 0x1c772eb,0x1bad4e1,0x17f0858,0x1adfafe,0x01acbc0,0x1fdb7cf, - 0x083a5cc,0x07862ae,0x009a764 }, - { 0x1845ccf,0x10b5a79,0x16f52c8,0x0121780,0x1c174e8,0x02481bc, - 0x031d358,0x00cf4aa,0x16358c8,0x0b91050,0x1dedb6f,0x188354c, - 0x0e838f9,0x1371704,0x0ccb065,0x0db4a6e,0x15e496f,0x0d81943, - 0x10c18c3,0x04e99f3,0x000c52b } }, - /* 97 */ - { { 0x0a58beb,0x173c147,0x0921bb0,0x1a6ccbf,0x0b404c1,0x1a07f81, - 0x17eb482,0x14aa8da,0x029d3e6,0x1aefbdb,0x006647e,0x08dacd9, - 0x1ef1868,0x17167f1,0x1a42f79,0x1a2d77c,0x1a01410,0x14bd75c, - 0x0b323a4,0x102a917,0x00cb59d }, - { 0x0f66a23,0x0e9d6dd,0x0207641,0x0e81bf6,0x0333738,0x007a196, - 0x0d7792c,0x07cdaaa,0x007d3a0,0x0bff474,0x0f2a038,0x1fee0cd, - 0x1529544,0x1d6ffd2,0x10ae5b2,0x0dd48c1,0x19445a2,0x04f80c6, - 0x128d3ff,0x0702ce4,0x011ed54 } }, - /* 98 */ - { { 0x17f8a61,0x039fdde,0x02ed8aa,0x0377cb0,0x1e18cd7,0x1fb4c02, - 0x07acd99,0x181fab9,0x1571d3d,0x1c6a7b0,0x1e6f22a,0x042af07, - 0x14e2e45,0x121cc58,0x10ddd2c,0x0236a6d,0x16374d8,0x196da51, - 0x17af8f0,0x1e252e5,0x01389f7 }, - { 0x18fefb2,0x1f90e3c,0x09caee5,0x0a20f75,0x1c76fcb,0x0ddab44, - 0x1dd83eb,0x18a25f7,0x1d33ea6,0x13245f3,0x04d2946,0x132646c, - 0x1b412a2,0x04c2c49,0x0f605a6,0x15b4894,0x18f3e66,0x1b0a24a, - 0x1a1ed15,0x1f8f36e,0x0140b4d } }, - /* 99 */ - { { 0x0be5bb9,0x0a2b83d,0x06fa0ec,0x11ca3b0,0x0e0cbfd,0x013d7fd, - 0x17d2726,0x0a841b5,0x0a687b5,0x1d392a4,0x105ccf0,0x07f7dd6, - 0x0308026,0x09c13e3,0x053f70f,0x16e1ce0,0x184b5e3,0x03e80c7, - 0x0f3dc5a,0x107c01f,0x00151d4 }, - { 0x1578aa3,0x11e3e35,0x16b8553,0x0ba6087,0x111ce9b,0x004080a, - 0x07a6ed8,0x0deabf1,0x0f405ac,0x1618889,0x02b1ed3,0x09b0401, - 0x067e66a,0x12e297d,0x10034e4,0x185d6e7,0x1988aca,0x1f70dcc, - 0x02d5d14,0x063b2ac,0x008fdfa } }, - /* 100 */ - { { 0x11cf8d8,0x0507012,0x0f4b31d,0x1a083e5,0x14d8949,0x15e7296, - 0x12924cf,0x15c16e6,0x15c5bcd,0x0d62fa8,0x002e4f8,0x1f982c4, - 0x0ed3ecd,0x13c9b9b,0x01a899a,0x0d2804a,0x08bea6e,0x0ac2d0e, - 0x0643e4d,0x19baa72,0x000e081 }, - { 0x1e28412,0x1ccab29,0x192c157,0x05b64e2,0x0d1526f,0x19d6e38, - 0x097ac77,0x1bb9aac,0x0dd35de,0x16229e5,0x03ff8b4,0x1093507, - 0x09ed442,0x0e0672c,0x08304dd,0x16c135a,0x081bd99,0x196afdd, - 0x08bbec1,0x083b98c,0x01ad5be } }, - /* 101 */ - { { 0x1850756,0x17b33c7,0x165d58e,0x1ca5e76,0x06d37aa,0x14217ac, - 0x0294de5,0x12e21a7,0x1f743f9,0x0d57ccf,0x06a2eb3,0x0bcb27e, - 0x192fa75,0x004fbe6,0x1c13855,0x0ca1635,0x00ad6d0,0x131dfcd, - 0x16aff66,0x039d5aa,0x000e67b }, - { 0x1f43178,0x054705a,0x0cccd98,0x1b3986b,0x16bd412,0x07b4042, - 0x1e98e20,0x0e27af7,0x02e622c,0x19b96b3,0x009115f,0x17cedff, - 0x11ad7b7,0x06d8272,0x0af7a02,0x0b91a1e,0x1fe4bd1,0x170f3c0, - 0x03940bc,0x0eb7f77,0x01941f4 } }, - /* 102 */ - { { 0x03543ec,0x015fceb,0x1cf9e52,0x19422fd,0x185cb67,0x066631c, - 0x018e058,0x03d158a,0x1729bdc,0x0b65f6a,0x1a1b7d5,0x12fb444, - 0x1cd62ed,0x040f5bb,0x0932d7f,0x05db362,0x16672fa,0x126bda7, - 0x00cd6e5,0x05354ef,0x017260b }, - { 0x03df7c6,0x1e3db52,0x01b086f,0x077840e,0x05acac2,0x0ecac04, - 0x0def0d1,0x179d6de,0x0a32a08,0x0c79069,0x14f17a7,0x09eda32, - 0x10f0892,0x027b406,0x0975f1b,0x12258fa,0x0372de9,0x0327351, - 0x0b39913,0x180d88a,0x00ebda1 } }, - /* 103 */ - { { 0x11dd110,0x1be2e20,0x1128999,0x1459323,0x0d6787a,0x0b336b0, - 0x1a90691,0x02aa77c,0x0c15f9f,0x1f38b55,0x131ec9c,0x0c7e1c1, - 0x10a93b8,0x1531255,0x015c45c,0x184c148,0x16e1a39,0x072f3b2, - 0x1bdbc4c,0x1af16a5,0x0046af8 }, - { 0x0f38dff,0x10a58b8,0x0415e58,0x1024742,0x1e35d82,0x1f6c091, - 0x1135255,0x0c208d4,0x00da601,0x0c7d4dd,0x01104d8,0x054aa9f, - 0x0be7cdd,0x0cf54ad,0x10958f8,0x06169e3,0x014cb2a,0x0e222cf, - 0x07fe6aa,0x115bacc,0x0183c74 } }, - /* 104 */ - { { 0x1e58caf,0x00f9cce,0x0990ca6,0x1b0ea7d,0x05bb80f,0x08ca430, - 0x07c90b4,0x015907f,0x003eeb0,0x0486783,0x0f5e73d,0x04a2f8e, - 0x1b4037f,0x1926a30,0x10827f5,0x0419f08,0x0d22724,0x13581fb, - 0x0d0e3e8,0x17a53d6,0x01526f4 }, - { 0x189e51c,0x081a561,0x063a593,0x12db6fb,0x0cda55e,0x09e2c1d, - 0x05f7ba4,0x081655d,0x1feb034,0x1c983bd,0x1878a41,0x06f13a8, - 0x1eaa16e,0x021dfc5,0x099d4cc,0x1187f61,0x042ba7d,0x04eba4d, - 0x0ee4977,0x03cdacd,0x00ec7c4 } }, - /* 105 */ - { { 0x1da8398,0x19a2ee2,0x10c0ba6,0x1f76718,0x1c66841,0x1dda3d5, - 0x11589f0,0x1bb9c75,0x1738d2c,0x1df5895,0x0c46163,0x15aed0e, - 0x14d4bc2,0x1dea7a7,0x0876c72,0x0361d2a,0x0aefe4e,0x1153486, - 0x0ffaf8f,0x042bd6f,0x0194375 }, - { 0x0dfd661,0x11a7897,0x07d132c,0x1ddaa58,0x0149984,0x1c7cc60, - 0x1c98363,0x12065a4,0x07be385,0x13b7272,0x02d9cbf,0x0e7b2bd, - 0x0254358,0x1958074,0x1b0e5ff,0x03d7122,0x105bad6,0x11dcdfb, - 0x184c6ef,0x1203055,0x00007ee } }, - /* 106 */ - { { 0x1fbcb5c,0x1f54f49,0x0a6f4db,0x073f50a,0x182be58,0x108dd01, - 0x0c497f5,0x06e1648,0x1cd8a26,0x0cd71bf,0x151c129,0x0c1c7b1, - 0x19ab78c,0x02620db,0x0b090f5,0x1398a37,0x1eaeda4,0x1e2000f, - 0x0f71fa7,0x1d48950,0x00f6988 }, - { 0x077f79e,0x0655278,0x0435364,0x03b3c4b,0x14d1760,0x0da5bbf, - 0x0eecf48,0x16c23bd,0x09037e1,0x18d9fb0,0x0fb3c00,0x1b0426b, - 0x1af113e,0x19481ee,0x1004de7,0x1252ded,0x1caa6f1,0x09b5ef3, - 0x16eeb61,0x076d093,0x006c57d } }, - /* 107 */ - { { 0x0bfccb0,0x1f71c4d,0x198e58f,0x0972ced,0x0c6e2a2,0x1d3693b, - 0x03c0a12,0x1a3f0ed,0x0465853,0x1c5d1dd,0x0ae6db0,0x06da371, - 0x116e3ab,0x03d0399,0x1f25d09,0x07e6403,0x1182523,0x17eea0b, - 0x118779e,0x19f5035,0x00214da }, - { 0x0a3198c,0x14f9bf5,0x0754d96,0x0bf9173,0x0be8a34,0x1af65e6, - 0x1c4ab53,0x029484f,0x00c2375,0x020ffb0,0x09ec17a,0x18b4514, - 0x135d9e8,0x1142cff,0x0ddd111,0x1bc6e5a,0x0ffea8b,0x00e0230, - 0x073d6fe,0x1c93425,0x01810a0 } }, - /* 108 */ - { { 0x1843c3e,0x101d7a2,0x0b9da20,0x07557d7,0x0601e30,0x06fb15a, - 0x023cd89,0x15072f6,0x0d21e5a,0x1439a45,0x10ac395,0x18e7344, - 0x0d2cf12,0x1953b63,0x123b404,0x0a34590,0x1c2f527,0x0db9550, - 0x0b00b41,0x052d872,0x00f3b63 }, - { 0x0f3d1f0,0x1a156e3,0x0e53392,0x065ea65,0x0f0dcc5,0x021ece1, - 0x0ccd60d,0x196af02,0x0dc8dd9,0x0808c77,0x1c64bed,0x034bdd0, - 0x023039e,0x0aba0ce,0x1dc99f5,0x0d61932,0x04c30f9,0x123177d, - 0x134f0d6,0x1f6f2c7,0x01f7454 } }, - /* 109 */ - { { 0x1153926,0x140ca4e,0x152043c,0x03056ae,0x02e28c9,0x0f4a64a, - 0x0ecc142,0x0ae9684,0x0de9d6b,0x0d66295,0x128c531,0x1873167, - 0x05aa746,0x031eade,0x13a8c1f,0x193121e,0x1a2e1cc,0x0212aa9, - 0x1db6465,0x03317fe,0x008e271 }, - { 0x08e672b,0x007231e,0x109f1e4,0x1a7e5bf,0x103675c,0x10b1e4b, - 0x147debc,0x160e092,0x07aceaa,0x06b4c84,0x148da5d,0x0352fd1, - 0x15482f2,0x009ee08,0x1ef0772,0x19a27b9,0x08004f6,0x106715e, - 0x0afebfc,0x08cc590,0x003f2a5 } }, - /* 110 */ - { { 0x188a8bc,0x1a0f30a,0x0b2c373,0x1c4218a,0x0f48cd0,0x073d22b, - 0x18af5d6,0x0ae670a,0x148b9b9,0x1006aa5,0x026e785,0x10174d7, - 0x0f461df,0x04c6641,0x1f53c5c,0x0e28fef,0x1cd1497,0x08b3f80, - 0x045b17e,0x070a22c,0x0048b13 }, - { 0x12617f0,0x1b199ae,0x181b7ad,0x04dd970,0x1f9a577,0x08fe749, - 0x00cb46e,0x12f5278,0x16c84b9,0x1d21c45,0x1296fbd,0x044b047, - 0x0bbfe80,0x1ad197b,0x06700a0,0x0b8b0de,0x1ade3cb,0x0f9366a, - 0x1430776,0x1bb8eed,0x01e77f5 } }, - /* 111 */ - { { 0x0e764c9,0x1f76437,0x0b30f27,0x0d60f90,0x11bec83,0x02d8a16, - 0x0cb9a80,0x1d4d7e3,0x129e8a5,0x077a8d1,0x189071c,0x131c7ff, - 0x08517d2,0x194b361,0x0e278a1,0x198ed76,0x0a92c7a,0x09d16d4, - 0x0ca886d,0x19224ce,0x004a902 }, - { 0x17ce110,0x08dce47,0x1bc65b1,0x0f5d606,0x1cc33a8,0x152cf16, - 0x1426029,0x00104d2,0x1e78db5,0x1579353,0x0ec0c33,0x070992b, - 0x0282f3c,0x126217a,0x15ba7dc,0x09414db,0x02970ac,0x03b46ef, - 0x0f48bbf,0x1b9c960,0x016f4ae } }, - /* 112 */ - { { 0x1ed03c0,0x1819576,0x15341df,0x04b11bb,0x0684a05,0x02df079, - 0x0f13e6a,0x176da13,0x1e0b9b6,0x0ed063f,0x0d621ef,0x18fde5f, - 0x1e19689,0x161e673,0x0a5a583,0x055cbf1,0x1d5768d,0x15821ec, - 0x0c84866,0x101037b,0x006829c }, - { 0x059f006,0x0397d6f,0x1d69afe,0x0d972fd,0x02b9ffc,0x173f7c6, - 0x0576d62,0x03e6e32,0x1f4ccaa,0x1711e50,0x09f3130,0x0c1d138, - 0x061af8c,0x0435ee6,0x1975f9f,0x1bc87dd,0x07f9bd8,0x1c912da, - 0x0c93c22,0x0fe8c69,0x00b453e } }, - /* 113 */ - { { 0x1048bda,0x04b6871,0x1939531,0x128787b,0x02b6749,0x16a84f7, - 0x127dd30,0x1135840,0x0543c50,0x00fb48f,0x08d96ec,0x014620b, - 0x09cd996,0x1c58b82,0x164fff9,0x128ce69,0x1b3f82c,0x0814fcc, - 0x05869d5,0x18bd440,0x0091785 }, - { 0x13dbdb6,0x0fcbc4a,0x067ed15,0x132fd94,0x0a9e84d,0x0a6bad7, - 0x140a4db,0x1f48e77,0x0c15276,0x0e0be54,0x1d8d5aa,0x02668f8, - 0x129cf66,0x01cb9c6,0x1a0d82c,0x06c1294,0x0a86973,0x0e9f218, - 0x0ac9fc8,0x0a65bdc,0x01b40ae } }, - /* 114 */ - { { 0x164cb8b,0x0874128,0x19f5a04,0x1e4aa54,0x0979af4,0x0c2a93b, - 0x1b43a34,0x189c21a,0x1fb64ea,0x1b62bc3,0x09164b3,0x0c77588, - 0x1084081,0x1e706c0,0x03ffcdf,0x182b8bb,0x049da84,0x0c59427, - 0x0998fb2,0x00aace6,0x0010ed8 }, - { 0x1f3ee9e,0x1a01828,0x1c7841b,0x136715b,0x0e8e3ee,0x1eb2249, - 0x1e9ba84,0x163a790,0x180e1ab,0x1da4fa2,0x15ca609,0x02f217f, - 0x1fc283d,0x17e3d1a,0x1943e96,0x15a9f1f,0x145ade3,0x13b9ed2, - 0x068877c,0x1f55c9b,0x01f878b } }, - /* 115 */ - { { 0x1ad5678,0x06c7455,0x096eb98,0x1dcc018,0x0afa72c,0x1447108, - 0x182d130,0x13f73a9,0x0d254cf,0x0223fbb,0x18ae959,0x17892b3, - 0x0c1fb36,0x14b0899,0x0f1135c,0x01e3272,0x01ffc14,0x06bd444, - 0x1425992,0x10c2511,0x009127a }, - { 0x09e690c,0x16010c5,0x0856d4d,0x03d569f,0x05dcc52,0x0772a64, - 0x1108ec0,0x090135e,0x1af3a8e,0x1bc9a92,0x0c7616c,0x06116ee, - 0x15e1f36,0x0a0e7da,0x0d875e0,0x08a536a,0x09eeffc,0x07520f9, - 0x1df498d,0x0eab633,0x00e8cf5 } }, - /* 116 */ - { { 0x012b398,0x0dc06e9,0x0dcc07b,0x03aa7ba,0x1039618,0x097d4ae, - 0x1811e29,0x0da1c10,0x0a7825e,0x08f3219,0x1b393eb,0x178a661, - 0x0fe0185,0x183c49b,0x03dcc4e,0x0dd46a1,0x0fd9e7f,0x00ee4c1, - 0x1555ad8,0x074c05a,0x00e8dbf }, - { 0x19e05bc,0x1191a13,0x0f4f0dd,0x19e888a,0x1f5f40e,0x1183c9b, - 0x17d35fe,0x0446218,0x0108d7e,0x07fd69b,0x062ef17,0x1de7855, - 0x00f2f01,0x0bea3fc,0x0ac5c67,0x05c3861,0x118a9b2,0x03de4fc, - 0x00d37e5,0x1b8a55d,0x01f9f53 } }, - /* 117 */ - { { 0x183f89b,0x15a4f60,0x1b53c99,0x04beb00,0x13fb5f0,0x1618406, - 0x10ad653,0x02fa614,0x0371cd9,0x1b58ca0,0x1f89b52,0x15576fe, - 0x04f7541,0x16adbdb,0x149a7ac,0x06d8bca,0x1c17f80,0x0870d42, - 0x097c99d,0x1e1e45b,0x01cea0f }, - { 0x08e11f8,0x1eab51d,0x0d5180a,0x03ebf35,0x0986402,0x06496b9, - 0x0b16833,0x0178ce8,0x0523f65,0x122b4f3,0x0afed35,0x1037eff, - 0x0bc8e46,0x01e4f36,0x09d651f,0x1fe4168,0x0d538f5,0x1159ca9, - 0x1c12ba8,0x1f1c703,0x01b0818 } }, - /* 118 */ - { { 0x10d90f0,0x0dffd72,0x1370ef9,0x17ea023,0x0cb3b11,0x08efd62, - 0x09c469a,0x0e7c219,0x14ea1a7,0x176108e,0x1bbad98,0x1d77cb0, - 0x1d5a979,0x106178f,0x1c5aac6,0x17fd49b,0x17ec57b,0x17f4f1f, - 0x0b949bd,0x0b2c1cb,0x015e1b0 }, - { 0x030e62e,0x10252c3,0x06dc723,0x1cc88fc,0x1d00310,0x1a223d1, - 0x1ad850e,0x1479e3c,0x17462e7,0x155dc28,0x09c9364,0x1410000, - 0x1f8309e,0x12294b6,0x00175c3,0x1b0243b,0x1b33d4e,0x1079c24, - 0x00d3513,0x17ff78d,0x00962d6 } }, - /* 119 */ - { { 0x0e07711,0x1f2c6a4,0x0ecb44f,0x11a4e14,0x10f8364,0x0ff8263, - 0x024b633,0x0282a2f,0x051411f,0x0ddb2bc,0x1e29545,0x1b207c9, - 0x0f6c31c,0x02099b1,0x1e1c548,0x0da9ae7,0x1eeeca0,0x197f012, - 0x1538c5f,0x0dc82f2,0x00ad32a }, - { 0x1d147df,0x0631fb4,0x0dedf8e,0x1ce217e,0x169bb06,0x0a8a6f5, - 0x1afbca3,0x1b3729b,0x18d11c3,0x19183fd,0x1718112,0x1bf2070, - 0x033b369,0x13c0074,0x1a8bd27,0x03838d1,0x0587d50,0x0781459, - 0x13bde06,0x0f0442b,0x0055970 } }, - /* 120 */ - { { 0x0c1d751,0x1a8edaa,0x1448430,0x03741f2,0x0144530,0x0e45f6c, - 0x0cd3eff,0x0154efd,0x0cf2368,0x0c6c09c,0x1ca1812,0x0949c09, - 0x1a928c1,0x0b52db6,0x064b6e8,0x122072c,0x15b5f9a,0x124ef54, - 0x05c9040,0x1a8af00,0x008580d }, - { 0x009221c,0x1928007,0x015ba41,0x03e43bc,0x02e05b2,0x1304a83, - 0x0be8783,0x0528919,0x16f7751,0x0bfdcbd,0x0d2b299,0x037be3e, - 0x165d299,0x04ff8ae,0x1b356b1,0x1d8f34c,0x097d049,0x06e0eb4, - 0x1caebaa,0x1f9509c,0x0067388 } }, - /* 121 */ - { { 0x0ef1dd3,0x05a4ed3,0x15d9948,0x1c774d9,0x191a045,0x1eafa41, - 0x0602bcc,0x0953909,0x0ef0747,0x09e7ad9,0x1ec7ab9,0x1d34f17, - 0x1aa35b2,0x16d4837,0x0a5ff5b,0x059e9d9,0x1891b9f,0x0f8d49b, - 0x0aca162,0x0a66d27,0x010d667 }, - { 0x1691faf,0x0824b39,0x18616d4,0x13aafd8,0x1c73d3a,0x054292e, - 0x086ee4c,0x0d2fc52,0x040b05b,0x0a7ab8f,0x0fb7282,0x002e827, - 0x185e96a,0x068d35c,0x1f53dca,0x1d16f3c,0x1da3ead,0x0aa8a1f, - 0x05b9153,0x170889a,0x00fb859 } }, - /* 122 */ - { { 0x0667aaf,0x1041f3e,0x12e9f08,0x1295239,0x13545cb,0x1074a51, - 0x064c632,0x18f943d,0x1e4eaa0,0x1d7ff91,0x15a1130,0x086c85e, - 0x0ba21ac,0x106a968,0x11a2a2d,0x003a9f9,0x05b6a93,0x0a00d2c, - 0x01eaf38,0x1eec592,0x00a3547 }, - { 0x1e260ce,0x09f69fd,0x07e98f7,0x1b01b80,0x0717752,0x0ed1f21, - 0x0dd75bc,0x01dabf5,0x05261f1,0x18b4325,0x135aed7,0x1ec7a41, - 0x16be7b1,0x110d632,0x18e3040,0x1231d3a,0x0f6673b,0x0189bdc, - 0x0b68bee,0x1688709,0x017423e } }, - /* 123 */ - { { 0x01fbcf4,0x113e215,0x17b8653,0x16bf59a,0x0c0d285,0x0f3303a, - 0x1af7645,0x134eb85,0x0ef0a6a,0x134b288,0x13d1607,0x1f420cf, - 0x1a13c5a,0x1df70fd,0x1804f05,0x0f3ce57,0x0d6dad2,0x0c2d203, - 0x050b3d6,0x052a3aa,0x0031004 }, - { 0x02bbc45,0x1af60d1,0x1361a9c,0x14feade,0x0ee5391,0x1000ef2, - 0x1e7408d,0x04a60b5,0x1aa2f8d,0x0590c28,0x16de2aa,0x0db030f, - 0x030e2c3,0x10d4446,0x13020fe,0x0fab79f,0x17fbd3e,0x1dc8ed5, - 0x13f7408,0x10a8c1e,0x00f462d } }, - /* 124 */ - { { 0x172d703,0x05d0124,0x080fd5a,0x1a72131,0x1c44ca1,0x14642af, - 0x1950ab8,0x06dd371,0x05b1b45,0x1ea79b0,0x1df9213,0x00f698f, - 0x1d2e08b,0x1118411,0x0bcee60,0x1fa2608,0x1131889,0x0e4ffe9, - 0x1b1a0d6,0x1e0ca58,0x01bb56a }, - { 0x0e0f16a,0x182f103,0x1297b6f,0x15ae8c8,0x1c1ac2f,0x09638d7, - 0x02a603e,0x143cb34,0x136c800,0x1d71beb,0x05e3704,0x1f8c46c, - 0x105f20e,0x15a3778,0x0e962e0,0x013c888,0x1cf4425,0x064a8be, - 0x103b66c,0x17682ac,0x01667d0 } }, - /* 125 */ - { { 0x122842d,0x185309e,0x1380ea8,0x0b6789d,0x0c6e00f,0x1c15bcc, - 0x13e1db7,0x18b0ec9,0x178d208,0x1496c36,0x02152b6,0x0723cf1, - 0x140a52d,0x12cd84c,0x06c9bee,0x1f93493,0x1ad04c5,0x02ee099, - 0x138fc4d,0x0124d26,0x01dda5c }, - { 0x0d6d673,0x0e5617d,0x0ff9bc3,0x0a01e76,0x0d8fdf0,0x0bab74b, - 0x065058c,0x1c7d9ce,0x10a4d80,0x0c87a49,0x04c004e,0x126c63a, - 0x18f2aca,0x1aac0b1,0x04659b1,0x0acf3dd,0x174e6dd,0x136f87a, - 0x135c736,0x0490d19,0x0111be1 } }, - /* 126 */ - { { 0x15cc1b4,0x0639323,0x1e33d91,0x1256e72,0x115fc2f,0x1ebf5bc, - 0x19b4438,0x1c0cb4f,0x0f40c38,0x1a2710d,0x1493f2e,0x0573c35, - 0x0598866,0x01ab037,0x02e9377,0x127ee4e,0x02c1a4f,0x1e1c1a5, - 0x0d8a935,0x0193446,0x002193d }, - { 0x169fd7f,0x1bdc67b,0x0ee78b2,0x0f13442,0x1815da9,0x0887f78, - 0x03159ae,0x070f69f,0x1269314,0x0445984,0x0cdf008,0x037b24b, - 0x05477b7,0x1353207,0x126a484,0x18ddf40,0x1bdfd21,0x169eef8, - 0x0ca95ac,0x1f3afa4,0x00649b5 } }, - /* 127 */ - { { 0x19a9c35,0x056fc33,0x1e5b590,0x0796e9a,0x0dad98e,0x074ed7e, - 0x03aed7e,0x0788c97,0x0ad4a07,0x19c30a7,0x17955d1,0x01dc5db, - 0x19bd86c,0x0bb6705,0x0cc5ce1,0x1f72cee,0x1274095,0x0cdae99, - 0x1826bab,0x015d67d,0x013672f }, - { 0x0e54ba5,0x063b6b2,0x14868e2,0x03b88e9,0x03fe7af,0x13b840b, - 0x1a746ca,0x15aff47,0x0de1240,0x023da4f,0x00c0e81,0x16cd8e4, - 0x13d9f64,0x135e810,0x11e00a7,0x07d4b63,0x0700aa0,0x18e578e, - 0x0ee174a,0x0301d67,0x0103179 } }, - /* 128 */ - { { 0x12ed12f,0x1a7cfd7,0x162ab6f,0x09e701f,0x0e1d19e,0x0f40d76, - 0x0f6d68e,0x17812af,0x1626ef6,0x0c19990,0x16ca37e,0x0bd419e, - 0x14110ae,0x101c966,0x0565140,0x0f0ab56,0x0876bc6,0x133e24c, - 0x0ff5871,0x1cb2714,0x004ace7 }, - { 0x0c7dea9,0x0dcf794,0x0611671,0x1414d4e,0x102f95b,0x013b4e6, - 0x1095e08,0x12c069b,0x094dd68,0x09d8584,0x1aa5688,0x16ff6bb, - 0x0903730,0x10be544,0x090fb41,0x140a5fc,0x117fb1b,0x10b67a6, - 0x09be5b6,0x123ad64,0x01c0d86 } }, - /* 129 */ - { { 0x18015c2,0x16f9fdf,0x0b62a8b,0x1b892a0,0x07f8236,0x1218abf, - 0x1db829a,0x019d121,0x1a2d04b,0x0c77992,0x076eacc,0x0d1b501, - 0x019cc06,0x0d33e51,0x09a4deb,0x17893ba,0x12c83fe,0x04793e0, - 0x126e611,0x07b65e7,0x002987b }, - { 0x12e3dc7,0x1d7687e,0x1554df9,0x16e82bf,0x098e8bd,0x122f92a, - 0x1b26962,0x1a1f81a,0x0209c85,0x1eadd5d,0x0787ba0,0x1b8daaf, - 0x0d31ec8,0x12815ff,0x132b42e,0x17de23e,0x0ce1f41,0x0e21973, - 0x0fff299,0x015f557,0x01913b1 } }, - /* 130 */ - { { 0x1053af7,0x1bef829,0x13d2f67,0x0b65143,0x0030476,0x14821c3, - 0x1e3f1f3,0x1ba882e,0x0ac8c5d,0x1df69b7,0x07b1863,0x0277f6b, - 0x0f27b13,0x10d8df6,0x0995bfe,0x0e7533a,0x1459459,0x099a709, - 0x0d8ad65,0x0311198,0x018c326 }, - { 0x07f6ff8,0x1d20a55,0x11ebd04,0x107f56f,0x092aeb8,0x0183dd0, - 0x021adf3,0x01df43b,0x1234610,0x040e092,0x10324f7,0x04e6042, - 0x1593d4d,0x1308241,0x1b5f8f3,0x12be743,0x0cfdf17,0x1715c8f, - 0x1a7b505,0x1b82346,0x0191160 } }, - /* 131 */ - { { 0x157d7cc,0x17a3745,0x0e1a69c,0x0a97e04,0x1140b0e,0x19d48e9, - 0x0e5b816,0x1c110d8,0x1a4ec26,0x1cd59d4,0x1d63a46,0x15d78a1, - 0x10742fe,0x0af1357,0x04b1821,0x1b3ee2b,0x076bb1c,0x0ca1e6a, - 0x1fc0b22,0x12ffa98,0x017c3ed }, - { 0x0d54964,0x01281f3,0x03014ec,0x058d463,0x19bd116,0x0146116, - 0x1b3d273,0x08031fe,0x0035346,0x02e3c20,0x1019a29,0x06bd699, - 0x038ea33,0x1a16df0,0x15c9fe3,0x1879af5,0x111fdf6,0x158abf4, - 0x1264b5d,0x112993d,0x01b3a7f } }, - /* 132 */ - { { 0x109ea77,0x171cbd7,0x1716479,0x12ebb84,0x06a760b,0x050cbd9, - 0x03022e5,0x0331808,0x0b68ce6,0x00dd654,0x08d5901,0x1a2ab7a, - 0x1fa19a0,0x0cbbd99,0x1296e53,0x1a0530d,0x1f8e5fb,0x0f98fc3, - 0x06407e6,0x18ab4d6,0x00b8f76 }, - { 0x046ec9f,0x1fc619c,0x09185d6,0x193bd59,0x1462205,0x0846f87, - 0x17b028c,0x0512596,0x1cfaed9,0x1ced941,0x127eca1,0x0008ca0, - 0x11477dc,0x0b77281,0x1492eb2,0x19c8a91,0x11656ad,0x1d3edb5, - 0x0c71a13,0x019b575,0x00fc011 } }, - /* 133 */ - { { 0x1308bf2,0x1b36c26,0x0010546,0x1facc70,0x19013c9,0x1c1dfcc, - 0x17e4bf4,0x1f8d125,0x03ffc8e,0x0877ec2,0x1a8a1e8,0x02d8627, - 0x00527e3,0x1d06fba,0x1db8f34,0x1a5431d,0x030f6eb,0x165cb72, - 0x1c3b933,0x17d9e54,0x018cc1e }, - { 0x070404c,0x0a56b8d,0x08c2034,0x01f39c5,0x0ad21dd,0x11f0393, - 0x0f378ea,0x1217299,0x16363a6,0x15acb08,0x078ad02,0x1e8b8d6, - 0x1be70bf,0x1367762,0x05b742d,0x0af8025,0x0747477,0x06a6595, - 0x15f647a,0x11194c7,0x00aa089 } }, - /* 134 */ - { { 0x0db0396,0x0e7e57c,0x09daa8b,0x0f6845b,0x08ae8f3,0x042b927, - 0x00d2659,0x07eca5f,0x07bf149,0x123e1e2,0x11e93bd,0x168d604, - 0x0e8b600,0x1d75ed4,0x1cf90e5,0x11be157,0x11fa795,0x1170e91, - 0x0206eac,0x0d2563f,0x00ef38e }, - { 0x0cf3047,0x00b4493,0x01607cf,0x08b2a73,0x1ad14f9,0x1f905b6, - 0x17470a4,0x02ffbd0,0x0f57abb,0x152a1b7,0x1378e0b,0x1ff82f2, - 0x0f0d1a8,0x15ff669,0x0942388,0x0c08537,0x07fdb78,0x0088785, - 0x1378c7e,0x1cdec8f,0x01962ad } }, - /* 135 */ - { { 0x0c78898,0x1529bff,0x1dff265,0x05bc1f4,0x0b39de7,0x0658478, - 0x1dab34d,0x0a7eda0,0x0da78d3,0x06c5dc1,0x04b306b,0x09a7407, - 0x1d5fe80,0x12c0aa4,0x1eb7b7b,0x18db356,0x1a0c067,0x1c41c80, - 0x1b64fcd,0x0bff449,0x0191585 }, - { 0x19ebef3,0x1871b5f,0x05dca55,0x0bbe966,0x021046a,0x00b5ae7, - 0x06a569a,0x023f371,0x1288d0e,0x0f9c940,0x04566ab,0x17ca72f, - 0x12d6baa,0x0e47d5d,0x06bfb81,0x15e2082,0x1afe5c7,0x1f8c961, - 0x1f738de,0x05d039a,0x00f7aa7 } }, - /* 136 */ - { { 0x0c386ee,0x11e078b,0x00e483e,0x13a9813,0x133b046,0x15189b5, - 0x15c8a1d,0x00cf3c1,0x03c406c,0x01e0549,0x0f89f4d,0x1c7c9bd, - 0x0aef220,0x0cb7807,0x15ec784,0x1b9fe13,0x1d824a9,0x0a507ae, - 0x0707421,0x105d8b3,0x01e2535 }, - { 0x138c7ed,0x1793128,0x0237323,0x08ca8ff,0x1ec4319,0x054a446, - 0x14eb774,0x1b856dc,0x08257eb,0x1cf8f7d,0x032627a,0x0dd63e1, - 0x08c583c,0x000b1bb,0x1cda445,0x01c7be2,0x18bdbc2,0x131417f, - 0x12f5453,0x10200b3,0x00d526b } }, - /* 137 */ - { { 0x0025949,0x0a917d0,0x0514912,0x1e177b1,0x126d888,0x1b90b7d, - 0x0bd7f98,0x1ec6688,0x0472827,0x0761db2,0x109a076,0x034733f, - 0x0d91d8a,0x1463b88,0x08cbab5,0x04ec4da,0x02fe51b,0x1c72dff, - 0x14427e9,0x1e9fdbf,0x00040f9 }, - { 0x14a05e0,0x17528b5,0x03ac654,0x1de438f,0x0b0d48e,0x0befede, - 0x1986466,0x1fac9a6,0x08b4c21,0x088d902,0x08c0e83,0x136d7d2, - 0x09a6f56,0x1c62f40,0x03d8259,0x0bb1c57,0x1ab3680,0x139135a, - 0x0cd2728,0x1fe301b,0x01bdd6c } }, - /* 138 */ - { { 0x03cc612,0x1c2bb4a,0x071e927,0x1d06566,0x0914319,0x056f5ee, - 0x18a5f33,0x043244b,0x0b06198,0x08c7da1,0x0731f12,0x01084b6, - 0x10accb3,0x132372f,0x074cd1e,0x07c44ea,0x0ae590e,0x0757da5, - 0x1128002,0x08c0705,0x0151821 }, - { 0x196a461,0x040eddf,0x0e90f09,0x136a547,0x11c122e,0x06d845a, - 0x0163919,0x03a4385,0x06d6a08,0x080a5bc,0x0f3bdec,0x1da9ea6, - 0x1c167d3,0x00aa2fb,0x1ecca52,0x0f73ed9,0x11c449b,0x0f52369, - 0x18870a6,0x1aec272,0x0081cfa } }, - /* 139 */ - { { 0x18a7f0e,0x0b193a3,0x0177bde,0x05bc2ee,0x114183e,0x108bf44, - 0x09b7d5c,0x19fa494,0x1b7cd52,0x06d8d84,0x0f0580f,0x13f75b0, - 0x099e42b,0x184f7c6,0x1c74ba9,0x0999ad2,0x05b8ee5,0x00c4a7e, - 0x129483f,0x0f69ca6,0x00fcf75 }, - { 0x0b62347,0x08c6643,0x04a1695,0x04f7855,0x0c51c9d,0x13393ff, - 0x0ac14a5,0x0de5dd4,0x00ae43e,0x045471d,0x0819aef,0x16bc0b9, - 0x0d80535,0x0419cc3,0x1ff36c6,0x099bb23,0x1ba3237,0x197a52d, - 0x1480890,0x0c74921,0x0124087 } }, - /* 140 */ - { { 0x0fac14d,0x05cb927,0x14f3926,0x1b4f353,0x16f4bf8,0x103e14d, - 0x036f75b,0x0701e3d,0x1717715,0x161867e,0x00c98fe,0x1a44e36, - 0x154c91e,0x0cda2af,0x04e0cd4,0x1257f7f,0x1891270,0x0bb52f3, - 0x1204ef6,0x0ce9c36,0x0128a97 }, - { 0x03e5924,0x11e20ac,0x1418a6d,0x031e2e3,0x01f9aff,0x113d143, - 0x0cf36ac,0x0e0568b,0x08a11ab,0x1ceaeed,0x0da5c64,0x0f61d1b, - 0x052bfb4,0x0760840,0x08de77c,0x03002ac,0x08124ce,0x157ad32, - 0x13e52ae,0x1188686,0x01508d9 } }, - /* 141 */ - { { 0x1ffc80f,0x0ff39e7,0x0fdb7aa,0x17a868e,0x023e2e9,0x09bdd3f, - 0x0fb4f27,0x0ae4ff6,0x07a3fc3,0x19bb369,0x1280f5c,0x19e71c0, - 0x03d0db4,0x15df07a,0x1805d48,0x0de9f19,0x119da98,0x1ec3f5b, - 0x1f9ac0d,0x16a15c5,0x01536d1 }, - { 0x040bab1,0x1aef7ed,0x098cdc7,0x1f3657b,0x07d6a8a,0x0565438, - 0x1722435,0x156bd14,0x1643ff8,0x0b9787f,0x03b0bd3,0x01b297f, - 0x029c4c1,0x075c9f1,0x0c3aae8,0x1fa026d,0x08f1d2d,0x15e2587, - 0x14d2820,0x0a5cb53,0x01429f2 } }, - /* 142 */ - { { 0x10e7020,0x1ea60be,0x05a12bf,0x156a904,0x1b169aa,0x079a47c, - 0x05c2162,0x177b7c0,0x1885986,0x175fb7f,0x070e076,0x0fea2bf, - 0x1bb3398,0x0254a53,0x1157cb0,0x0d092fc,0x042a0ed,0x01cd20a, - 0x1bdde63,0x15a94c3,0x01541c1 }, - { 0x12709c4,0x1db1403,0x17f9d91,0x171021c,0x1330d68,0x1707b1d, - 0x021d3a4,0x175a37b,0x1f8bea9,0x02727dc,0x0260685,0x1831063, - 0x07c15af,0x1b46350,0x071720a,0x016cdc3,0x1a236e0,0x042c62b, - 0x1f2debb,0x0aa2200,0x00119b2 } }, - /* 143 */ - { { 0x087027d,0x07693e4,0x0a18487,0x0a57f56,0x0050f33,0x0a88f13, - 0x0f07067,0x1eadc6e,0x17f4c69,0x16a61d4,0x09aed00,0x0d5e4a4, - 0x10e6f35,0x01f3d61,0x040470e,0x1fbf677,0x03d33d8,0x1a1d861, - 0x1cba8d8,0x0721ef5,0x000ba8c }, - { 0x0851bac,0x061eb3f,0x13f310c,0x134bea8,0x0991c38,0x1dd030c, - 0x0f1919f,0x1e800d7,0x097cbdb,0x04e8127,0x12b6b75,0x0fbaee6, - 0x0a4539b,0x1465b69,0x0ea3e7c,0x1675b21,0x0304de4,0x03d490c, - 0x1ee5a4a,0x0e65df4,0x006ab28 } }, - /* 144 */ - { { 0x0ed5986,0x15a9691,0x1819c76,0x14b0a67,0x1eee627,0x0aaff1e, - 0x18deb3c,0x065d1fd,0x17ae8b1,0x0b0a486,0x022e533,0x030a694, - 0x102706e,0x1ce0ae1,0x17ff54b,0x15a8d50,0x0f351a5,0x1ead112, - 0x135c02e,0x036daaa,0x01e644d }, - { 0x02e4e9c,0x1834343,0x1f925a0,0x1890ec7,0x1e5cd76,0x01ce557, - 0x059e702,0x05ac061,0x18d83d6,0x07265f5,0x112b8b0,0x0a9c237, - 0x02911e2,0x127e503,0x0835f21,0x0e08b2d,0x1d5e9a2,0x07abc2e, - 0x0f8104b,0x0cefa1e,0x01be2f4 } }, - /* 145 */ - { { 0x101a6dc,0x0096ed5,0x0da5300,0x035c35b,0x191bd6c,0x18283c9, - 0x16bb2e6,0x03e75cf,0x062a106,0x138a7cf,0x14dadf0,0x1dcf52c, - 0x0b71978,0x0f0bb2a,0x1046f41,0x07ba9dd,0x0e0efab,0x0e388b3, - 0x1fb6fd8,0x154ae50,0x01d70f7 }, - { 0x1eb5932,0x137bea8,0x12909ba,0x14bf105,0x154ea0a,0x1cfbee1, - 0x1825ddc,0x0682eb6,0x09be579,0x19a8c95,0x117b334,0x0846f0a, - 0x1d9801f,0x1db21e4,0x0e38959,0x157d865,0x1d723e3,0x0dca08e, - 0x1c71942,0x1bd4d19,0x00ee656 } }, - /* 146 */ - { { 0x0890deb,0x070a050,0x12f534e,0x1b79d70,0x1f7bd87,0x020ef65, - 0x1fdcae8,0x1d2a3e1,0x0a6820b,0x1f76385,0x018a62b,0x0147189, - 0x0475519,0x1380876,0x16e9563,0x0f363d9,0x1b88c78,0x0676c8e, - 0x1d78857,0x1c7c99d,0x014c08d }, - { 0x0266da2,0x09a768b,0x0026705,0x16f6992,0x1ce322e,0x093b444, - 0x12bbda6,0x09a6fbd,0x105c284,0x09284bf,0x1466ad9,0x1c26358, - 0x06d23b7,0x12d1e64,0x0baedc9,0x08aead0,0x1b9628c,0x186298e, - 0x0e014dc,0x01d170e,0x00be2e0 } }, - /* 147 */ - { { 0x1ed32e9,0x1e4002b,0x065ce01,0x1ef8049,0x027e40c,0x1aa4182, - 0x1aaeeae,0x1e8b0a0,0x1ce820b,0x124bbb7,0x10fa055,0x0527658, - 0x08b5353,0x07f7b32,0x07a0d4f,0x1b94ace,0x13f903b,0x09390be, - 0x004ff5e,0x1382135,0x01dc40a }, - { 0x1b21a38,0x153619e,0x1f91afa,0x03ae7de,0x0ae222e,0x0ea83fe, - 0x0139ef4,0x1563fed,0x0587a77,0x0dd6332,0x12935bd,0x1ec418c, - 0x0a58c74,0x153e1bc,0x0a0df65,0x1c81299,0x1313e42,0x1fa1efa, - 0x0d27853,0x14868ff,0x013f8a9 } }, - /* 148 */ - { { 0x12f8923,0x1a76fcc,0x07ce16a,0x00dfa41,0x024aa5e,0x09a0777, - 0x06e1c6c,0x0804f7d,0x191e0bb,0x0abe88f,0x1318b0a,0x15a5e7a, - 0x0f425af,0x03ffbd5,0x08c4a1b,0x197d25a,0x12b0114,0x0cb2095, - 0x0f88d4a,0x0d44638,0x019f670 }, - { 0x05c02af,0x1dde911,0x06341ac,0x0c7f47d,0x13ebc16,0x07a4172, - 0x0add6e1,0x1bf4dbe,0x12bfc55,0x095a290,0x09cf6a4,0x1a80a25, - 0x0430bdb,0x1ea9f55,0x03d0f64,0x1faa758,0x1e40c27,0x07e1ac7, - 0x065092d,0x03077d2,0x00a32cb } }, - /* 149 */ - { { 0x1a6a746,0x186169f,0x12a38e6,0x043ab44,0x084a792,0x06f95af, - 0x02451e3,0x166e14b,0x130666c,0x144033e,0x1c741a2,0x013deda, - 0x04b09a7,0x0032e8c,0x001e8f8,0x12890a0,0x14bb8dc,0x0382357, - 0x19524eb,0x1462538,0x01fd2b6 }, - { 0x05f2771,0x0eadef2,0x16574f5,0x15e865d,0x0542b08,0x19535dc, - 0x103efc8,0x1645d9a,0x1e8becc,0x1e5b0a1,0x1891fc3,0x02757f1, - 0x1bcecc5,0x06d181c,0x1755bde,0x141bf2a,0x01956c2,0x148abe3, - 0x00c7f8a,0x06b97e6,0x018ca6d } }, - /* 150 */ - { { 0x00c4923,0x0058ddf,0x01ef760,0x00d2052,0x046ae74,0x1de8638, - 0x0cdfe55,0x1704731,0x19655f8,0x1470d4e,0x1d0542a,0x0ff4a01, - 0x0ecd292,0x10173d7,0x1aa71b4,0x0d25d04,0x0b39f29,0x05a67ac, - 0x1d055df,0x070d197,0x011f309 }, - { 0x13ed442,0x1af3d19,0x1deeb72,0x1f20dfd,0x0e5c8e2,0x0c79145, - 0x0048cf6,0x0b85b36,0x07ffe12,0x119796d,0x0c60d51,0x0e63744, - 0x1259487,0x0969628,0x12ab96c,0x1b38941,0x0589857,0x15f8073, - 0x13c803d,0x02010ca,0x0172c5d } }, - /* 151 */ - { { 0x1c283e0,0x0a02317,0x0039625,0x08fdc11,0x1763398,0x1e8b117, - 0x0d03adf,0x1dbf5e3,0x0f598c5,0x07a8a8f,0x0366efb,0x05eefc0, - 0x146b4d9,0x14621fe,0x10f8ece,0x1a3a4ea,0x12c6511,0x19cca70, - 0x1c16db4,0x08343b5,0x00c6dd8 }, - { 0x1b991ad,0x10bf011,0x14508f6,0x06e3f74,0x0ab2b21,0x0e0c3cd, - 0x1b16837,0x1b9682f,0x15f63ac,0x19de456,0x09f5405,0x04203c5, - 0x082fcf5,0x1083680,0x0dcff41,0x0259ec6,0x1de7db0,0x18f4108, - 0x1d9517b,0x0ecdb2a,0x018ca07 } }, - /* 152 */ - { { 0x180dfaf,0x1a3dcd7,0x1fce390,0x1f388cc,0x080b631,0x0de11c5, - 0x16c99b7,0x140dfe3,0x1aa8718,0x0b0f1b2,0x070d7d8,0x19215e6, - 0x08e7f7a,0x1e34237,0x0e0c747,0x0eb6980,0x1106841,0x10f334e, - 0x0d2dcc6,0x13ac412,0x00c76da }, - { 0x1e4e78b,0x1acbdd1,0x1e6a607,0x18aa133,0x0c14ded,0x0446309, - 0x0e6564c,0x0b17e6e,0x19b2074,0x02b4183,0x1da401f,0x188f444, - 0x13c4440,0x1bf36d7,0x17c8f23,0x122076d,0x0254292,0x1a7b316, - 0x0cede58,0x14db631,0x00f9f4e } }, - /* 153 */ - { { 0x0d36049,0x0f5c467,0x07e319a,0x03e8373,0x07a4ffe,0x1970844, - 0x1d58da9,0x114d216,0x065a0bb,0x1eeb546,0x10a5559,0x18b12dc, - 0x0d42cf8,0x0d55ffd,0x01ad7cc,0x04d48a5,0x0f28f6f,0x18fbefd, - 0x186b940,0x13c1581,0x0120c5d }, - { 0x0c10da7,0x171ffd6,0x1b96bef,0x1328928,0x07e2d5f,0x01107fb, - 0x1fa18f1,0x05d1d82,0x0bd6f63,0x137ba0a,0x127bd3f,0x181f87f, - 0x104a9e3,0x01dfdc3,0x1fcf2e8,0x0685a4b,0x000bb03,0x10c7e9b, - 0x014334b,0x07cea60,0x01ac1e6 } }, - /* 154 */ - { { 0x13d6a02,0x1e83e47,0x0347760,0x18fde9a,0x11fc143,0x03d7b0b, - 0x12fc353,0x1e19532,0x0827c5c,0x0549f4c,0x05e20b2,0x18f656d, - 0x1a4a102,0x052af45,0x0f21f56,0x0c9e0c6,0x02fcc2d,0x00d7441, - 0x01b407f,0x136a7f3,0x01c12ce }, - { 0x1dc1b79,0x11cfeca,0x05aa165,0x087e9cc,0x0728f75,0x117dcf9, - 0x0f133b7,0x13cdce0,0x0d50fae,0x017bb40,0x14c3b41,0x187785a, - 0x0c0546b,0x06eacc5,0x09001af,0x0922001,0x0c9e129,0x09f9943, - 0x1afe58a,0x1044ab6,0x0146777 } }, - /* 155 */ - { { 0x10c98fe,0x0a10f71,0x1c16be0,0x01f859a,0x1eb0feb,0x0fb5696, - 0x1329853,0x1d13658,0x09ba314,0x1c09a6f,0x12c5b74,0x1d709e0, - 0x08a443d,0x183fc65,0x155bb83,0x0722ff8,0x1bb3a4f,0x09e0e41, - 0x06b7350,0x0fba496,0x0199839 }, - { 0x14781e6,0x0f0bf6f,0x0407280,0x128de3f,0x12d7c31,0x18486d1, - 0x0984ed4,0x00f444f,0x0a7c8c6,0x04ad8ee,0x1a5c249,0x17ddbb8, - 0x181cf2f,0x02b0404,0x0f60aed,0x069ae3a,0x1a30851,0x0e7e6ee, - 0x19e6310,0x02e36b2,0x00d23dd } }, - /* 156 */ - { { 0x0dd7e96,0x007c26a,0x10325e9,0x150813f,0x1114c8e,0x0889c9b, - 0x0a79aa7,0x1ad8ade,0x18fd8c6,0x1b03310,0x1a79f0e,0x150c004, - 0x1fad3ba,0x02c94ea,0x04f1ac0,0x06cb628,0x040222e,0x060d6bf, - 0x1e62abb,0x04c4348,0x01d36a8 }, - { 0x1003c81,0x022e260,0x180abab,0x15e87b0,0x1ef9ef5,0x1bba34c, - 0x17d7983,0x0b06d4c,0x1bf5d28,0x18973d5,0x0b3bc7c,0x1903909, - 0x122f53e,0x0e9245a,0x18cb28a,0x0b8c0c7,0x1c581e6,0x1ff4d53, - 0x0a1065c,0x10d934a,0x0017e36 } }, - /* 157 */ - { { 0x090de99,0x17f32cf,0x0d8c2cb,0x195a0b5,0x1e4485b,0x0724495, - 0x1a94b85,0x10f8914,0x0226286,0x16c2a18,0x0f6d50a,0x1d2abd6, - 0x01261f0,0x0a2f2c2,0x1a0618f,0x0ae7291,0x00f8ed7,0x067f0e7, - 0x1612b79,0x1e3feaf,0x003fbd6 }, - { 0x1bf968c,0x188eee8,0x11cb50d,0x1a91bf4,0x1558d7c,0x12d2b36, - 0x0488f90,0x08293e1,0x05c26d0,0x07c199c,0x105d0c3,0x03e2f85, - 0x19be7b8,0x08a1ece,0x0f70cf9,0x07f5dc7,0x03594fd,0x179c2d6, - 0x1f46046,0x039e853,0x0113755 } }, - /* 158 */ - { { 0x0193bb2,0x07aad90,0x01c924a,0x00e6217,0x16e579d,0x02e93b4, - 0x18c274d,0x114bdc0,0x0a87186,0x121f219,0x0e1a0e6,0x07c2220, - 0x0828c11,0x1199788,0x01bb3ce,0x1976905,0x0370385,0x199a455, - 0x1c5636b,0x1ff955d,0x00c6698 }, - { 0x0908745,0x062a57b,0x0fee811,0x08d466a,0x06b336e,0x10f410d, - 0x0a14b55,0x0fed298,0x0363491,0x194bcb8,0x184c546,0x077303e, - 0x0f6e102,0x17a352f,0x05f70af,0x09efed0,0x0af8e11,0x1c9ef50, - 0x15cb16f,0x1e79abd,0x0136c3c } }, - /* 159 */ - { { 0x1080de4,0x1ccd5bd,0x0e5aee1,0x1bad3b0,0x1b8f781,0x17c7b19, - 0x0aaaa61,0x194ed68,0x0a54bc5,0x0ba601c,0x0beee57,0x0c0b538, - 0x1076fcb,0x000bc49,0x146d102,0x0de1b08,0x0389d28,0x1a07806, - 0x1150c98,0x11d2a41,0x014c303 }, - { 0x177aad9,0x1e1c0b4,0x0f8f252,0x05ae10f,0x0dbfd08,0x0ff6845, - 0x008321d,0x1f80da1,0x0345656,0x0e7426a,0x1b753b8,0x11c01fa, - 0x0071c4d,0x152fd5a,0x0ce2c89,0x1d6de46,0x0c10bae,0x06a3bf5, - 0x1e0309b,0x161176b,0x0078e4d } }, - /* 160 */ - { { 0x078342a,0x0e89508,0x0190044,0x1cab342,0x0534725,0x09ffee8, - 0x075643f,0x03fd48b,0x106f0ac,0x1b4a54f,0x06f1a73,0x15b67c3, - 0x00f6d24,0x1ceee68,0x18e3d7a,0x1ba9c79,0x166b632,0x09c2007, - 0x0578715,0x11fbf7c,0x0085cab }, - { 0x109422f,0x01fb5c6,0x10ec2a5,0x0c1f311,0x17d2975,0x19726c8, - 0x107e8bb,0x07eab48,0x135f7c1,0x1a1a91d,0x0b4ffd9,0x080fdb5, - 0x0d274d3,0x09a3921,0x10450d6,0x0c2bab2,0x1013bb8,0x08e5939, - 0x15de533,0x06e0097,0x007da04 } }, - /* 161 */ - { { 0x1712c44,0x1ccd316,0x15de092,0x114d2c4,0x148368f,0x0f11438, - 0x010cb59,0x1f11dad,0x06f5bc5,0x0014183,0x0d1e745,0x02429d8, - 0x10e6cf3,0x09936db,0x16dbd12,0x126d72d,0x098ca32,0x1e52d60, - 0x1fa886b,0x04918e5,0x004d69e }, - { 0x11269fb,0x0484953,0x0d802aa,0x1030ca1,0x0f6bdba,0x1aaed91, - 0x10a8e7e,0x1a03b39,0x16311e9,0x1e7586f,0x10b0743,0x0f39215, - 0x0a6faeb,0x058f9b9,0x04ec88b,0x0832647,0x1dfbc8c,0x0315379, - 0x1fa399d,0x1461645,0x00019de } }, - /* 162 */ - { { 0x0b3118b,0x144d609,0x0959f7d,0x1ad96dd,0x106ee39,0x1e6cbc6, - 0x08b0861,0x10f9f98,0x18d537d,0x0c2db40,0x15b6cae,0x02a5d3e, - 0x1575845,0x0f04c60,0x00e61c5,0x059a41f,0x1c83b21,0x1df4b52, - 0x06b0711,0x140671b,0x01fb3dd }, - { 0x1a0a9b8,0x1bff067,0x1dd7c1a,0x0fc45b9,0x1478bac,0x1443e44, - 0x178104d,0x179e702,0x0914c54,0x0c08eef,0x07a993b,0x02c01ea, - 0x17c8c24,0x064382b,0x045360d,0x17968c7,0x152a8ab,0x1769272, - 0x1913d4b,0x1d73d04,0x00019e5 } }, - /* 163 */ - { { 0x0d52313,0x0d02733,0x0af47d9,0x0a9a7ee,0x1d69454,0x1bd708f, - 0x176be9a,0x08e5781,0x0571ab2,0x10fbcec,0x0a35a24,0x12cd5cb, - 0x13d4c5f,0x1762e70,0x185dc5a,0x17a73fb,0x1a4b764,0x1b87376, - 0x04359e0,0x12810b3,0x01efffe }, - { 0x08f92e8,0x10713ec,0x08f3cfe,0x1b38ee2,0x021ef0f,0x13a6dd5, - 0x05d3224,0x0c4c4b3,0x1b9ba27,0x067d252,0x0f2bdb5,0x13a48dd, - 0x1010c90,0x07c7143,0x05e8436,0x1dd4406,0x1e1453a,0x1d83b8e, - 0x031ac28,0x188f22d,0x00eadf0 } }, - /* 164 */ - { { 0x0854477,0x00f2426,0x11f046f,0x090c71c,0x0bec25b,0x0e2a6c9, - 0x180ae1a,0x1a487a9,0x0be1e7e,0x18c6f19,0x18312b8,0x1d60d68, - 0x1ef5471,0x1521357,0x0b9efce,0x05b8271,0x0ddd845,0x091d713, - 0x1e0b7a7,0x1f83aaa,0x01649d3 }, - { 0x0de1979,0x0571885,0x1ca361f,0x1a76978,0x0847041,0x01e4df5, - 0x0f1015b,0x0ce7124,0x0d74ae4,0x17f0c15,0x1926b8d,0x0de9d97, - 0x1592bff,0x0e20fcf,0x0036e03,0x00e2acd,0x06fe463,0x19add60, - 0x1b41cc1,0x11698fa,0x00c06d6 } }, - /* 165 */ - { { 0x14dfcf2,0x115f3c2,0x0f436f8,0x1f4d5c7,0x0e21a7d,0x10f6237, - 0x0eb4694,0x099e8c6,0x041a948,0x14a293d,0x048fcfb,0x1736554, - 0x121145e,0x0571e54,0x0d2a0ab,0x1b24aac,0x0a0fc85,0x070bb56, - 0x0420b63,0x19eff83,0x0078504 }, - { 0x199793c,0x073e21b,0x1ed75d3,0x116aa33,0x14ddd61,0x1fcc043, - 0x17e4e57,0x1cc59ed,0x1b8bf61,0x07522e8,0x13d53c0,0x0c27b9f, - 0x1026863,0x01801ad,0x108edd8,0x15396ce,0x1344028,0x14fde3a, - 0x14681df,0x059c6e0,0x00f47b5 } }, - /* 166 */ - { { 0x0bec962,0x1ec56cb,0x01ebafd,0x0c2fc02,0x11cc81f,0x07082c6, - 0x1142485,0x13ec988,0x142394c,0x014c621,0x18144db,0x0a5a34c, - 0x03d9100,0x086fc12,0x190dd52,0x1bd4986,0x01efe5c,0x09189df, - 0x09fedec,0x14c1efa,0x0076249 }, - { 0x0f593a0,0x1ac1c0e,0x1679d25,0x1706c98,0x0c9ceef,0x0e4cc88, - 0x04ccf81,0x1c65eb4,0x1421808,0x0752f0f,0x1a3d3cc,0x149e9eb, - 0x0756fb3,0x1b6065a,0x0b9b8ba,0x198d459,0x1fd08bd,0x1b05983, - 0x1fe3045,0x0f20381,0x001aee1 } }, - /* 167 */ - { { 0x1aa9e14,0x019b5c4,0x003f012,0x03ecece,0x0663427,0x15b4c03, - 0x010ce41,0x0469b54,0x1ebb7ab,0x0123f70,0x06814cc,0x154fd6b, - 0x15969b4,0x00007a6,0x03be096,0x0d6b7af,0x0eb4602,0x072ed9c, - 0x15a15b1,0x087cbaf,0x003b06a }, - { 0x12a0ee7,0x1741c76,0x004ea82,0x11e2dd1,0x04bbe52,0x13209b8, - 0x17d713a,0x0cf156d,0x006e298,0x1f4065b,0x07b4ad6,0x16e5e8b, - 0x1af19b1,0x0bb0a90,0x0733934,0x0de76f5,0x194aa51,0x09cd7fc, - 0x0d05a49,0x125d0d6,0x000797d } }, - /* 168 */ - { { 0x0f3a8ca,0x176f0ad,0x07b096b,0x054b86a,0x1392478,0x1f60401, - 0x08fefe4,0x16883cf,0x0e6f425,0x027c9e2,0x1d8026c,0x05d903c, - 0x06e4ec1,0x08c07fe,0x1cd9b51,0x1de74f2,0x1b50e0a,0x0e949e5, - 0x035c764,0x12d288d,0x0061a14 }, - { 0x15a67a1,0x02a0e33,0x041bd4b,0x011ebfd,0x07d38d3,0x1f4c473, - 0x0f333da,0x10c54e1,0x0185898,0x101f65f,0x1c116eb,0x0c2ce0c, - 0x16ecd02,0x086546c,0x0b37664,0x0e6ba3f,0x08230c0,0x03d5085, - 0x0ca3c87,0x0fcaa86,0x00152a2 } }, - /* 169 */ - { { 0x0057e27,0x104f073,0x1368f75,0x0f8f48a,0x07e8b6a,0x196eadc, - 0x045147c,0x1c5feb3,0x0d0ef51,0x11cbd44,0x19d51ba,0x0d424aa, - 0x00c4986,0x19145a4,0x11722c4,0x132f5d4,0x077dd01,0x11edf07, - 0x14619f4,0x1d451f8,0x01f80e2 }, - { 0x1d0820b,0x0a096b4,0x08618a5,0x0e3d4cb,0x0317312,0x031c068, - 0x00887ac,0x00d84f9,0x075fe97,0x1fea77e,0x074941f,0x14aeb4e, - 0x037b396,0x03e5baa,0x1200147,0x17dc6c3,0x0d7ad4d,0x0f03eda, - 0x0c64b51,0x0903e93,0x01431c7 } }, - /* 170 */ - { { 0x0e1cc4d,0x1968204,0x07b97aa,0x075a5b8,0x093758d,0x0e39c9f, - 0x1f7f972,0x10619d6,0x1d33796,0x186c354,0x1e1b5d4,0x0795c49, - 0x0bef528,0x1858dd8,0x1746993,0x09c7956,0x01f54db,0x0cb555e, - 0x0f00316,0x1b0f987,0x01443e3 }, - { 0x160e7b0,0x141098e,0x0063942,0x16ba67a,0x1c9b629,0x0299c6f, - 0x1b90bf4,0x1d58a95,0x0e821c6,0x13c7960,0x10272c1,0x0ebe0d5, - 0x16e5c9d,0x0980c6f,0x0d5d44d,0x18ccf06,0x1ac0bf8,0x0c0e537, - 0x142b8b7,0x10041d3,0x00e17fc } }, - /* 171 */ - { { 0x1aaa5eb,0x0a3a08d,0x00da2b7,0x12f37b0,0x02cbb75,0x1ff6910, - 0x0310337,0x083b0d0,0x04e0911,0x011d478,0x122e1c7,0x03da40e, - 0x0965d14,0x12cf494,0x1a855d5,0x1b7fcb0,0x1cd5006,0x03e346b, - 0x095a69d,0x15a1be4,0x0148da0 }, - { 0x19069d7,0x062edbf,0x069323f,0x0ab80a6,0x0487d24,0x116d9d1, - 0x12267a6,0x0418b56,0x0b4fe97,0x15fea9c,0x1cd7914,0x1949a4f, - 0x1373a04,0x1716d64,0x0ef1527,0x1cfc4f9,0x09dff3e,0x0014391, - 0x036a4d8,0x130f1a5,0x00d0317 } }, - /* 172 */ - { { 0x166c047,0x1f4dd9d,0x187626d,0x12c0547,0x02e6586,0x0dce001, - 0x08a5f23,0x14689f0,0x1d08a74,0x13b5651,0x0e63783,0x0e3bf9a, - 0x0afbf1a,0x0190733,0x0edbaaa,0x13f8a5f,0x0bc179c,0x0541687, - 0x19eacad,0x019ede9,0x000f4e0 }, - { 0x090c439,0x0074d24,0x1ac9093,0x17786b4,0x17564a2,0x1ba4be9, - 0x11e7766,0x0852b48,0x1612de9,0x0ff9f86,0x1400ce8,0x0ff9cc1, - 0x1a35862,0x09120be,0x176a301,0x1070b02,0x0d4ef6b,0x1283082, - 0x05ba5aa,0x0e51a5e,0x0120800 } }, - /* 173 */ - { { 0x1039042,0x191b955,0x13b65db,0x193f410,0x10e6978,0x1f60a18, - 0x174bd62,0x187a07f,0x1fe2045,0x1006080,0x16a4a0c,0x1ef5614, - 0x18e6868,0x130fd7f,0x1257477,0x044ca4d,0x127b7b1,0x1d0f100, - 0x0a97b45,0x07baf18,0x00898e6 }, - { 0x0bba4ee,0x099ed11,0x15d2ed9,0x0fe92d4,0x1eff639,0x19535c9, - 0x0a7dc53,0x07e8126,0x11dfdd7,0x041245e,0x1286c68,0x1e5cd37, - 0x0762f33,0x1d17019,0x05df992,0x1ee8334,0x19375dd,0x05e2874, - 0x095af47,0x152f3e9,0x0095b87 } }, - /* 174 */ - { { 0x1c1f177,0x19b54b3,0x0f27a0d,0x10c0026,0x1b6d350,0x164d2d8, - 0x0ee49ba,0x0392849,0x0c27ef3,0x14e00d3,0x0d21c1e,0x174a245, - 0x05ad93b,0x0e8d64c,0x0e538aa,0x02eb73d,0x006d53f,0x0288e01, - 0x040b645,0x1d64a4a,0x00b1d13 }, - { 0x15a1171,0x1edf5b3,0x0ac73f9,0x182d81a,0x1228295,0x1e44655, - 0x16d6815,0x19f1b64,0x0d300e9,0x1f54f4b,0x154badc,0x06fe4d2, - 0x1fb0e00,0x0f07cc6,0x0740d72,0x0901fd5,0x1b8d290,0x0c30724, - 0x00dacc6,0x1d2a258,0x0037a35 } }, - /* 175 */ - { { 0x100df48,0x194f747,0x0c13159,0x0c23590,0x189ca7b,0x1d4091d, - 0x15fe62c,0x1d492f4,0x1c21ca3,0x0218d8c,0x0cf39f8,0x1bd7c57, - 0x1945a73,0x16e3bc0,0x01b30ae,0x07be25f,0x1e4e5eb,0x02ff802, - 0x149f73c,0x0bbaf5b,0x005ef95 }, - { 0x0ee402f,0x117fd00,0x0d33830,0x1476617,0x1b335e2,0x1e5880a, - 0x1474190,0x110a84a,0x13cd196,0x10c1fa2,0x1952d31,0x1e45e17, - 0x04c6664,0x061066f,0x1d33fb9,0x188eb4b,0x12f80a4,0x0ee554b, - 0x04447b6,0x15e400b,0x019cde4 } }, - /* 176 */ - { { 0x171f428,0x085e46b,0x0e0a7a7,0x13c8794,0x1ac1ecd,0x09d6781, - 0x19203ae,0x07f1abd,0x1065a2a,0x11197c0,0x0e29cc5,0x1f545e1, - 0x021fc04,0x012a3a5,0x037df9c,0x0bede95,0x1f23bb1,0x128d627, - 0x0254394,0x0436e7c,0x006b66e }, - { 0x1a41dee,0x0c24033,0x0cfd672,0x1cf67c5,0x0cfa95a,0x0a2a709, - 0x00e1a24,0x148a9b3,0x1eefca6,0x06eedef,0x072dd7c,0x164823d, - 0x035f691,0x1f79046,0x0e79d9b,0x079ed53,0x00018b3,0x0f46f88, - 0x0705d2a,0x0ab593a,0x01c4b8a } }, - /* 177 */ - { { 0x04cccb8,0x1ac312e,0x0fbea67,0x125de9a,0x10bf520,0x17e43c3, - 0x195da27,0x0dc51e9,0x0da1420,0x11b37cb,0x0841f68,0x1400f8a, - 0x1090331,0x0a50787,0x03533ab,0x08f608f,0x0e2472a,0x0d944cf, - 0x1081d52,0x0ca69cc,0x0110ae9 }, - { 0x0ed05b0,0x0eb2ae6,0x150cb30,0x1202eb2,0x0bac3f0,0x0bbe6bd, - 0x1c29239,0x0db75d6,0x140e98d,0x0580449,0x1493c61,0x0ca6c07, - 0x1d26983,0x12b90b9,0x051620c,0x083bcdc,0x1266111,0x00e9a45, - 0x1e89fcd,0x04afb9d,0x006be52 } }, - /* 178 */ - { { 0x147e655,0x1c799e4,0x1e56499,0x1411246,0x1f0fb76,0x011ce8f, - 0x19d15e4,0x19d65bf,0x03cdbb7,0x1043a49,0x1b5073a,0x1b720be, - 0x0821326,0x1cee2ac,0x06ba6b9,0x02e04b6,0x00ce9c3,0x070a29a, - 0x0b0e2a7,0x0058534,0x00c3075 }, - { 0x156ace2,0x12788e0,0x14a4304,0x0ef3fe4,0x0c170fe,0x08b8d91, - 0x06a05b8,0x12ec1bf,0x155de27,0x0cde541,0x131e768,0x0fd4f8d, - 0x101ad92,0x0eb0fbb,0x1640448,0x00d7650,0x026261c,0x1ff4064, - 0x08990ae,0x01a6715,0x015e405 } }, - /* 179 */ - { { 0x0ad87bc,0x0bc14f5,0x12f724e,0x0f03d09,0x00ac936,0x0f27ef7, - 0x10935ab,0x0ad6af3,0x1690d7f,0x05cd5d2,0x1ec2e54,0x13a7a29, - 0x16f09b2,0x12d073d,0x1a13c8c,0x09fe7a0,0x1d3606f,0x1828a74, - 0x02b5cce,0x17ba4dd,0x0077e63 }, - { 0x0d25c6d,0x0837670,0x173c2bf,0x1401745,0x1d90021,0x0dd9cc6, - 0x15dc231,0x1f83604,0x0198ff8,0x1bf836c,0x0b35a01,0x1fe36fc, - 0x1287d50,0x131d1ab,0x1d7815c,0x0b535de,0x092fa92,0x0df92bc, - 0x0e743a5,0x1a7be0e,0x0111847 } }, - /* 180 */ - { { 0x0c82924,0x1ce63ff,0x15a54aa,0x134e441,0x1c76dd6,0x1778710, - 0x09f7a81,0x0094c6a,0x0271839,0x19f28e1,0x001f22a,0x0bd4e2d, - 0x06f4db3,0x1a47892,0x0fb7829,0x0c12b1e,0x0444115,0x178a49b, - 0x1d2ce37,0x0b07a30,0x00f75f6 }, - { 0x1927eb7,0x0c4f085,0x049e8e4,0x1385c5e,0x087c635,0x14b37a5, - 0x108cdff,0x10a16e5,0x0105e55,0x015c1c1,0x10e7e44,0x000dcb1, - 0x0963fee,0x0c8da99,0x014bb8e,0x1f2f67e,0x14ccbaf,0x03fadc2, - 0x1e01418,0x1cbed8b,0x016a935 } }, - /* 181 */ - { { 0x1d88d38,0x101aaef,0x1d03c66,0x078a93b,0x155cd8e,0x080370a, - 0x0a78c13,0x1cc644e,0x0fd0b0c,0x0b5b836,0x0ab4c7c,0x18126be, - 0x1ff156d,0x1bd1efc,0x031484f,0x0bf6b66,0x092a55e,0x14f94e6, - 0x0e16368,0x19fba85,0x0144a0e }, - { 0x0658a92,0x08aefa9,0x185ad70,0x0f88502,0x1ce3ed1,0x0c9548d, - 0x17dc1ff,0x12d4ab2,0x19cd5d8,0x11e45fe,0x11cac59,0x087eb52, - 0x1d07763,0x1819f0d,0x19132a2,0x005f629,0x1861e5c,0x113d0e4, - 0x113fecc,0x01e5899,0x01b5ece } }, - /* 182 */ - { { 0x1211943,0x13dd598,0x09705c4,0x0cad086,0x04a8cac,0x0afe1f2, - 0x02e2361,0x14ba5fc,0x0ce91ee,0x1d5d586,0x11f4491,0x1b88f1d, - 0x1a5d23d,0x066cff7,0x061b79c,0x0aecd47,0x0678265,0x11963dc, - 0x1abb1fe,0x080317d,0x00873e5 }, - { 0x18d17c1,0x1437959,0x103725b,0x18e3f40,0x1cbfbd0,0x024ce5c, - 0x0ade7e2,0x017c223,0x0f71ec8,0x0a3e2e7,0x025a487,0x17828d9, - 0x11acaa3,0x1e98b19,0x0487038,0x0ecb6bf,0x01ee768,0x018fd04, - 0x07bfc9c,0x15fabe8,0x00fed5d } }, - /* 183 */ - { { 0x0da1348,0x085cea6,0x04ea2bc,0x044b860,0x10769fd,0x0be115d, - 0x096c625,0x1888a15,0x1f5acf1,0x057eb63,0x1e00a57,0x02813fd, - 0x1dcf71a,0x17044fa,0x080a7d7,0x05751c2,0x0fb0fbd,0x04ba954, - 0x1dc32d6,0x044ebed,0x009061e }, - { 0x1bda16a,0x125628f,0x0a8adc2,0x13e3bf4,0x19910e7,0x0a2fb7b, - 0x184cb66,0x1df7459,0x0eb4ba4,0x086acd7,0x0b54f51,0x136697e, - 0x086a8e0,0x131063d,0x0040813,0x18de8ec,0x03d0a53,0x131fc4a, - 0x1fabd5a,0x123a330,0x013214c } }, - /* 184 */ - { { 0x10d66c3,0x1d89024,0x0813953,0x1141b90,0x0aed732,0x1a14a6f, - 0x130e012,0x0cf7402,0x131ddc4,0x197d155,0x0bb444f,0x0bd5068, - 0x0e70ff5,0x1181a70,0x0369cbc,0x1c78363,0x1bebd8a,0x156e186, - 0x1a51680,0x17bede7,0x009c179 }, - { 0x084c26f,0x09477ba,0x0ec51b2,0x03de55b,0x006b7db,0x0c6ed39, - 0x1d520fd,0x16c110f,0x04bc7ed,0x0f27106,0x12bf73f,0x043b2eb, - 0x00484d1,0x035f761,0x0d659c2,0x1b6cf8b,0x088a6d6,0x05abcd5, - 0x0461d22,0x0db0fc8,0x001522c } }, - /* 185 */ - { { 0x071d4ae,0x083abe2,0x09d82a2,0x0a8743b,0x1ef4b1a,0x1380d0f, - 0x0c609aa,0x1277125,0x059c65f,0x1a6a729,0x077cd6f,0x1253af1, - 0x12923af,0x05bce1f,0x12d1b18,0x1e26079,0x0e7cf4c,0x04aac16, - 0x15fc3b1,0x0103684,0x011c7da }, - { 0x0eef274,0x03572cd,0x020fe4b,0x1e286f8,0x06c5bf4,0x1e4357f, - 0x0c08f84,0x0c154e9,0x02a2253,0x10ed673,0x027e974,0x057044b, - 0x0fb3d57,0x0fd3a58,0x128e45b,0x123527a,0x0dcb128,0x0f3b66c, - 0x07d33ef,0x12347eb,0x019aa03 } }, - /* 186 */ - { { 0x03fc3f1,0x1d34f10,0x08a4152,0x16c420d,0x09168cc,0x0afd4f8, - 0x01502ab,0x0df6103,0x0bff7ed,0x05c7907,0x052bf7b,0x0c317df, - 0x1b2c80a,0x1855e8e,0x1763282,0x014f9c4,0x041028e,0x13af33d, - 0x1ba56e6,0x0cc5bba,0x01b2dd7 }, - { 0x089d7ee,0x1f93cf9,0x01721f7,0x13dd444,0x0d755d5,0x056d632, - 0x1f55306,0x0335d61,0x17ec010,0x1462367,0x15c290e,0x1cfd691, - 0x186fc90,0x0859cf7,0x1714f04,0x0b4412c,0x1cc3854,0x122abbb, - 0x1f7408f,0x0861eea,0x016ea33 } }, - /* 187 */ - { { 0x1f53d2c,0x19ca487,0x06e7ea7,0x0d60069,0x0dc9159,0x0cbcb3c, - 0x1405356,0x115e214,0x1a8a6b7,0x0eb96d5,0x05ec413,0x0a8116a, - 0x00ef5de,0x1369cdf,0x0ae42f2,0x0fee028,0x1e9eda1,0x0657551, - 0x1acc446,0x0d13ac0,0x016da01 }, - { 0x06afff7,0x052b1fa,0x17cfa9b,0x14694bc,0x1945c7b,0x0cc7ec1, - 0x19322aa,0x0bd83ff,0x0b63f53,0x15300a3,0x1427950,0x1111a3e, - 0x1b50816,0x0fc6686,0x04636aa,0x0cee5a3,0x0bb78a3,0x13282f3, - 0x131b719,0x0075033,0x01ef4ab } }, - /* 188 */ - { { 0x176d986,0x04e8a69,0x16c0182,0x0f45b86,0x10f4e07,0x1f96436, - 0x1c2694f,0x1903822,0x1123c3f,0x17a5d22,0x15bf0bf,0x0b4e36c, - 0x1b852cd,0x0ff7d45,0x1f1d224,0x016ef6a,0x03e4811,0x0c7829c, - 0x0b1684a,0x0ba75aa,0x004c4b5 }, - { 0x1827633,0x067f9f9,0x1a59444,0x0bc015f,0x086784d,0x16997d0, - 0x1e208fa,0x10d9670,0x02b91cd,0x0e7a68b,0x0d8e28f,0x14b1cde, - 0x02078b6,0x145bfea,0x1e4844b,0x107ce66,0x04dee56,0x1b4b202, - 0x038a10c,0x08421e5,0x01223b8 } }, - /* 189 */ - { { 0x1ebeb27,0x054d4e1,0x03e1b0a,0x0a7deb2,0x17bcdcb,0x173f9be, - 0x0b84536,0x193d114,0x0726ea7,0x19a9172,0x104e200,0x070d182, - 0x1599d50,0x10b10ab,0x0c6bb29,0x0c9b0b3,0x1ebfcc5,0x138cfe7, - 0x0bae38d,0x0ef5e23,0x00433a5 }, - { 0x1eba922,0x1367037,0x1a4f0fc,0x1c8eb4a,0x1f6c83e,0x1f9bc72, - 0x19d00a2,0x1e2fef2,0x0bdc3f6,0x152f1b4,0x1642bb4,0x14154dd, - 0x153d034,0x0523e5e,0x070e931,0x0579076,0x06e4dce,0x1d27855, - 0x132803a,0x0f5e86e,0x01c097c } }, - /* 190 */ - { { 0x1c28de7,0x1b8bc3c,0x0c3000d,0x1557386,0x017aa2a,0x1e30f5b, - 0x060999a,0x0088610,0x14d78b5,0x05adae7,0x03f1cb8,0x0a5b30e, - 0x05d76a7,0x0a05bde,0x11a27d7,0x1a07476,0x06787f2,0x0d4bfec, - 0x158182a,0x0f6bddf,0x01c06ab }, - { 0x1b71704,0x156d8ff,0x0ec7a67,0x16721fc,0x036e58b,0x078cd52, - 0x0e0b2ad,0x1b9dd95,0x0e0f3d9,0x12496fd,0x02b44b6,0x097adc4, - 0x022a0f5,0x1edde93,0x027e83d,0x1d6a95f,0x01ae8d2,0x06e6285, - 0x1df41d6,0x13f02dd,0x00b7979 } }, - /* 191 */ - { { 0x04f98cc,0x0323108,0x1aba7b1,0x04e55db,0x0511592,0x110c37a, - 0x0f741f9,0x16cf5d2,0x08d6d69,0x0be7013,0x0ea3cf4,0x0c11fa8, - 0x17b5347,0x1e055bc,0x1fc704d,0x1323bd0,0x1a8139f,0x11dfacb, - 0x151f835,0x0750b7c,0x008de29 }, - { 0x0f668b1,0x156e9c7,0x1d90260,0x1ac2392,0x054e6b2,0x0ea131e, - 0x1ac4870,0x0e679ce,0x0eff64e,0x09a5947,0x0584a8c,0x135850e, - 0x14af71a,0x1d049ac,0x1222bca,0x011d063,0x112ba91,0x105b248, - 0x13d0df6,0x178b8ab,0x01138fe } }, - /* 192 */ - { { 0x0a2daa2,0x052c4e2,0x0231fa7,0x18801ec,0x18ea703,0x0ba8818, - 0x1416354,0x052df19,0x04abb6f,0x1249a39,0x05aad09,0x07c3285, - 0x1d0be55,0x1628b2b,0x1e4e63e,0x01d5135,0x0ec4f88,0x0f1196f, - 0x1ec786c,0x02ec3cc,0x01372f8 }, - { 0x020f662,0x0a5e39d,0x1409440,0x1893db2,0x1fb7e77,0x15cb290, - 0x025bed8,0x0fd13ea,0x1a2e8d3,0x132ce33,0x105c38e,0x144cb00, - 0x140f2b2,0x0f6a851,0x1d3f39a,0x1801e2c,0x17efdc3,0x1d55229, - 0x13a6764,0x077fb49,0x0198f3c } }, - /* 193 */ - { { 0x1614189,0x0fae6c0,0x07deeac,0x0a4964b,0x07d56c4,0x1da0af6, - 0x092c917,0x1f38f75,0x07af6be,0x015e46e,0x123a08c,0x01c0e96, - 0x1f91b77,0x0db68d8,0x04cdb82,0x0192e94,0x157e668,0x0942e09, - 0x1f32d89,0x1970278,0x012d59b }, - { 0x0019927,0x0c1da3e,0x156f76b,0x0ec61bf,0x010f266,0x102e91f, - 0x1b168c7,0x0c02bb7,0x0456ac4,0x15372fd,0x12b208a,0x0a52487, - 0x0946956,0x06e464f,0x07271fd,0x080cb8d,0x009e24a,0x1d6d93f, - 0x1904c06,0x0f469d5,0x01ccdfa } }, - /* 194 */ - { { 0x1cb1a7d,0x14326ac,0x03b85da,0x06d5df7,0x0d864ca,0x11586c2, - 0x0eb2c70,0x03a1dd0,0x1d980df,0x1405375,0x133b65f,0x1988ff2, - 0x15f582a,0x1d39608,0x073448c,0x0f76f45,0x0a8c710,0x0670951, - 0x1b6028c,0x1394ac9,0x0150022 }, - { 0x11c180b,0x05d6a97,0x08425dd,0x11ae935,0x108be99,0x0de8dd6, - 0x122ad5b,0x1352f18,0x00afbea,0x169f1f2,0x1717f1b,0x12f62a7, - 0x108a8be,0x0df49f6,0x11fc256,0x0477b5b,0x1082cee,0x1469214, - 0x109ca77,0x0a478db,0x0016417 } }, - /* 195 */ - { { 0x014a31e,0x16678b6,0x10b5d3b,0x0965bc7,0x088e253,0x1621e1a, - 0x0d665f3,0x06df376,0x1916ac9,0x10822ce,0x1910010,0x18053ef, - 0x0371d15,0x022a9ac,0x071f049,0x148cf19,0x08dec94,0x0e64baa, - 0x059eeb6,0x0cf0306,0x014e4ca }, - { 0x10312bf,0x1782ac6,0x19980ce,0x0aa82c3,0x1d1bf4f,0x00bc0ed, - 0x1169fe9,0x1aa4b32,0x000eef1,0x1a4a6d4,0x0ee340c,0x1d80f38, - 0x096c505,0x0e4fb73,0x0b86b78,0x01554e1,0x0c17683,0x0014478, - 0x18a8183,0x19fc774,0x000c7f4 } }, - /* 196 */ - { { 0x17d6006,0x1a23e82,0x02c0362,0x0dfae39,0x18b976e,0x07a07a9, - 0x180a6af,0x106bcef,0x0f103a7,0x1df71c3,0x1cb12c4,0x1840bc8, - 0x1420a6a,0x18fe58c,0x0c117d8,0x17e9287,0x19fc00a,0x0f2ee0e, - 0x1555ade,0x0178e14,0x01b528c }, - { 0x08640b8,0x083f745,0x004aea7,0x07a1c68,0x0561102,0x1257449, - 0x1956ef8,0x19b8f9c,0x0fa579d,0x1ac7292,0x0eff978,0x0e2a6ef, - 0x0457ce2,0x1e04a3f,0x19471b0,0x0f04cc8,0x150f4a9,0x12fdec6, - 0x0b87056,0x1ba51fc,0x008d6fc } }, - /* 197 */ - { { 0x07202c8,0x0517b2e,0x0362d59,0x04b4a96,0x1d63405,0x1a7dfab, - 0x159c850,0x1470829,0x01d9830,0x08a10af,0x03ef860,0x11aabde, - 0x1fc7a75,0x137abfc,0x01773e3,0x0d3a6ae,0x056d922,0x1aeea4d, - 0x16d27e5,0x02baf57,0x00f18f0 }, - { 0x0799ce6,0x188885a,0x1f6c1c4,0x1259796,0x15bbfb9,0x1d10f11, - 0x0327fde,0x1fd83e0,0x1b18f49,0x04eb489,0x1e566c0,0x12a3579, - 0x0e8da61,0x06a10a3,0x1a1c84c,0x047e21c,0x017ae5f,0x1aac194, - 0x0b9ce1a,0x0b76d13,0x0143c9b } }, - /* 198 */ - { { 0x0c74424,0x1946da4,0x0bad08c,0x03a3396,0x12616e1,0x0b710b9, - 0x064a903,0x0a5ca68,0x00cbdc7,0x0c1d4a6,0x0eec077,0x00a1ae6, - 0x005c623,0x0dbd229,0x0358c69,0x023919a,0x0259a40,0x0e66e05, - 0x11b9f35,0x022598c,0x01e622f }, - { 0x01e4c4b,0x1714d1f,0x12291f5,0x113f62a,0x15f8253,0x09f18ce, - 0x016d53f,0x0ccfc6e,0x00a08b9,0x02672cd,0x0fa36e3,0x13cfb19, - 0x15bca74,0x17761eb,0x1125baa,0x0627b98,0x03a8a1a,0x00bee39, - 0x13ae4d8,0x1feef51,0x01a5250 } }, - /* 199 */ - { { 0x029bd79,0x103937f,0x0cd2956,0x009f321,0x0574a81,0x0ab4c1b, - 0x051b6ab,0x1ded20d,0x150d41f,0x12c055c,0x1dfd143,0x0a28dcd, - 0x0abc75b,0x1879b8c,0x03325ef,0x0810ea1,0x0a4a563,0x028dd16, - 0x1936244,0x0720efc,0x017275c }, - { 0x17ca6bd,0x06657fb,0x17d7cdf,0x037b631,0x00a0df4,0x0f00fbf, - 0x13fe006,0x0573e8d,0x0aa65d7,0x1279ea2,0x198fa6f,0x1158dc6, - 0x0d7822d,0x1f7cedb,0x0dfe488,0x15354be,0x19dabe4,0x13f8569, - 0x1a7322e,0x0af8e1e,0x0098a0a } }, - /* 200 */ - { { 0x0fd5286,0x0867a00,0x00f3671,0x0ae5496,0x1ea5b9d,0x0d739f0, - 0x03e7814,0x049ebcc,0x0951b38,0x14da8a1,0x13599ff,0x05a13f6, - 0x16b034b,0x16e2842,0x14dea03,0x0045c96,0x0128cb0,0x134f708, - 0x09522bb,0x173cb8d,0x00ed7c8 }, - { 0x133619b,0x003de6c,0x1865d18,0x1c573bf,0x0ce7668,0x1715170, - 0x1574f31,0x05f53dd,0x17eebf3,0x0d0a7af,0x113d90d,0x131acf9, - 0x0c75cb8,0x1c2860b,0x08617f1,0x1392d96,0x07645f7,0x004c3a5, - 0x1f6d1d1,0x11f15c4,0x0139746 } }, - /* 201 */ - { { 0x08684f6,0x13456e4,0x16ff177,0x16c334f,0x1c1edaa,0x1d0c7ab, - 0x05cd6c9,0x1d64b1a,0x18ecd89,0x13f3db2,0x07dfaac,0x138db0f, - 0x1b3d888,0x13eadf7,0x1f725b5,0x1ae7951,0x0ae37ba,0x1e426c3, - 0x1a395b5,0x1232ed9,0x01a4c7e }, - { 0x119ffa6,0x0d2a031,0x0131400,0x18269d8,0x0cae64e,0x0092160, - 0x0a5b355,0x1dc3ed3,0x0bf2cae,0x0d12cf7,0x1ba0167,0x0f18517, - 0x0488e79,0x1c74487,0x1212fae,0x0ffb3d2,0x0d0fb22,0x0072923, - 0x09758c6,0x054a94c,0x01b78be } }, - /* 202 */ - { { 0x072f13a,0x1aaa57a,0x0472888,0x0eae67d,0x1ac993b,0x00b4517, - 0x1a7c25b,0x06a4d5f,0x14b1275,0x07f3b0e,0x01c329f,0x10e7cee, - 0x1684301,0x03f3e6f,0x0daaab7,0x05da8cd,0x1eaa156,0x06d16ea, - 0x07ebe36,0x145c007,0x0016a81 }, - { 0x03de3bf,0x03ace27,0x022aa20,0x02a5e61,0x0c1e2e1,0x1f5d2d8, - 0x1b66aa9,0x195965b,0x19f9c11,0x032eaa9,0x1170653,0x1b0f61b, - 0x010ab9b,0x051fa5b,0x0be325b,0x0bf3fa6,0x1cc28cb,0x1a4c217, - 0x0438877,0x1c4f997,0x00f431a } }, - /* 203 */ - { { 0x00ccd0a,0x10506b5,0x1554eca,0x04b3276,0x03eeec8,0x1339535, - 0x01bf677,0x19f6269,0x00da05d,0x0ce28a4,0x061d363,0x089ace7, - 0x09c4aa4,0x114d1ae,0x13cd6cb,0x0fd5bb3,0x15f8917,0x0eb5ecd, - 0x0811c28,0x01eb3a5,0x01d69af }, - { 0x07535fd,0x02263dd,0x1ce6cbe,0x1b5085f,0x05bd4c3,0x08cba5a, - 0x127b7a5,0x1d8bfc2,0x1fd4453,0x0c174cb,0x0df039a,0x00bbcd8, - 0x0aa63f7,0x0961f7b,0x0c3daa7,0x151ac13,0x1861776,0x05f6e9a, - 0x17846de,0x1148d5d,0x0176404 } }, - /* 204 */ - { { 0x1a251d1,0x03772a8,0x17f691f,0x041a4f3,0x1ef4bf1,0x08c5145, - 0x14e33b1,0x0dc985a,0x13880be,0x195bc43,0x06c82c6,0x1f1c37d, - 0x1ec69cc,0x1bcb50c,0x077fab8,0x17bd5c8,0x1c9fb50,0x012b3b7, - 0x0f86030,0x02b40a0,0x016a8b8 }, - { 0x1f5ef65,0x042fb29,0x0414b28,0x12ef64a,0x01dfbbf,0x1a37f33, - 0x01f8e8c,0x1df11d5,0x01b95f7,0x0eefef7,0x17abb09,0x1cd2b6c, - 0x1b22074,0x0617011,0x01a6855,0x0776a23,0x17742e8,0x0c300da, - 0x0a1df9f,0x08ca59f,0x0015146 } }, - /* 205 */ - { { 0x1fa58f1,0x029e42b,0x19c0942,0x1099498,0x158a4e6,0x00fa06d, - 0x1b4286e,0x17a0f72,0x0558e8c,0x0328f08,0x0e233e9,0x08dc85c, - 0x081a640,0x0221b04,0x0c354e5,0x11fa0a3,0x1b3e26b,0x1615f9a, - 0x1c0b3f3,0x0f0e12a,0x00fd4ae }, - { 0x153d498,0x0de14ef,0x1890f1e,0x1c226fe,0x0cf31c4,0x11e76fa, - 0x015b05e,0x0bb276d,0x06cd911,0x030898e,0x03376c9,0x08a7245, - 0x11ab30a,0x069015f,0x1dd5eda,0x10c25d2,0x07ce610,0x053336f, - 0x1d809ad,0x01fcca9,0x0051c20 } }, - /* 206 */ - { { 0x1a2b4b5,0x1081e58,0x05a3aa5,0x1d08781,0x18dccbf,0x17fdadc, - 0x01cb661,0x184d46e,0x0169d3a,0x1d03d79,0x0dc7c4b,0x1734ee2, - 0x0f8bb85,0x13e14cf,0x18434d3,0x05df9d5,0x069e237,0x09ea5ee, - 0x17615bc,0x1beebb1,0x0039378 }, - { 0x07ff5d9,0x0817fef,0x0728c7a,0x0464b41,0x0e9a85d,0x0c97e68, - 0x04e9bd0,0x167ae37,0x115b076,0x0952b9b,0x047473d,0x150cdce, - 0x19d726a,0x1614940,0x186c77c,0x0bbcc16,0x15cc801,0x191272b, - 0x02de791,0x1127c23,0x01dc68e } }, - /* 207 */ - { { 0x1feda73,0x127fcb7,0x0062de4,0x0d41b44,0x0709f40,0x0ac26ff, - 0x083abe2,0x0806d1c,0x08355a0,0x04a8897,0x1df5f00,0x0a51fae, - 0x08259d4,0x15fc796,0x1125594,0x0623761,0x12844c5,0x0bfb18c, - 0x119b675,0x1a1c9f0,0x00d5698 }, - { 0x15d204d,0x0b27d00,0x114f843,0x14dba21,0x1b626bf,0x14c64a3, - 0x0398e9d,0x0ac10ff,0x105337a,0x12d32a3,0x11e0bd4,0x0489beb, - 0x1f558e2,0x02afdd7,0x0a87906,0x0706091,0x18e47ee,0x1a47910, - 0x0e118f4,0x0472b22,0x004df25 } }, - /* 208 */ - { { 0x0695310,0x07eb4ec,0x03a9dbd,0x1efd0ed,0x028eb09,0x0a99547, - 0x0604b83,0x0f20738,0x0c572ac,0x0d33ba2,0x158a4f7,0x01c0f0b, - 0x121f980,0x1ed3b5d,0x1f8a968,0x0e42e57,0x190a2bc,0x13768ad, - 0x05e22a3,0x1cc37fa,0x004cd80 }, - { 0x0730056,0x001b80b,0x150ee7d,0x1fb9da7,0x06f45fe,0x1283a12, - 0x1d8f06a,0x0e615fa,0x0ff92ae,0x0f2e329,0x0818fc8,0x061a376, - 0x006ef08,0x096912a,0x0c1bb30,0x0003830,0x13a1f15,0x0276ecd, - 0x0331509,0x164b718,0x01f4e4e } }, - /* 209 */ - { { 0x1db5c18,0x0d38a50,0x1d33b58,0x1cecee0,0x1454e61,0x1b42ef4, - 0x1ef95ef,0x1cbd2e1,0x1d2145b,0x10d8629,0x0697c88,0x1037dc9, - 0x03b9318,0x0a588e8,0x0e46be8,0x0426e01,0x0493ec2,0x1e3577f, - 0x098802b,0x0a9d28a,0x013c505 }, - { 0x164c92e,0x022f3b9,0x03a350b,0x0ae6a43,0x0050026,0x09f9e2f, - 0x1680a13,0x0d7a503,0x0dbf764,0x097c212,0x1cc13cc,0x1e5490b, - 0x13e1a88,0x0893d28,0x0fd58c4,0x1c178b0,0x0c71a60,0x076bca8, - 0x0dedc29,0x0abc209,0x00c6928 } }, - /* 210 */ - { { 0x04614e7,0x10c2e32,0x1092341,0x1c8e934,0x0e906ca,0x03f2941, - 0x04ba896,0x19ab0a8,0x0d12857,0x1b1cc85,0x164ed4d,0x1ee174a, - 0x06770c7,0x0eae952,0x13db713,0x1437585,0x0563b69,0x12b26d2, - 0x01e2576,0x1efc283,0x01c8639 }, - { 0x0589620,0x0b5817c,0x0150172,0x0683c88,0x0fe468a,0x15684e1, - 0x1684425,0x1dd7e45,0x09c652a,0x039e14c,0x186e3ef,0x1f16a8f, - 0x13cdef9,0x0bbedfb,0x1cde16a,0x0aa5ae0,0x1aa7e13,0x1854950, - 0x08e4f4f,0x0c22807,0x015b227 } }, - /* 211 */ - { { 0x1bfaf32,0x0d3d80f,0x1486269,0x017ccc3,0x1c5a62d,0x11da26a, - 0x03d7bd7,0x0c48f2e,0x1f43bbf,0x15000f6,0x0b9680f,0x050a4c1, - 0x0ca8e74,0x134be31,0x0267af4,0x0ec87d7,0x1e6751a,0x11b5001, - 0x081c969,0x0f18a37,0x00eaef1 }, - { 0x1d51f28,0x1c74fcd,0x0112ab3,0x1750e24,0x19febbd,0x1e41b29, - 0x0b4e96f,0x11f0f01,0x110e6f0,0x0451a66,0x06ac390,0x1421048, - 0x018104c,0x0c53315,0x0f9c73a,0x091ad08,0x1142320,0x1cee742, - 0x13cf461,0x14477c3,0x01fa5cb } }, - /* 212 */ - { { 0x173a15c,0x064e914,0x07ccbfa,0x1ba852f,0x06fec8d,0x157d9f3, - 0x128e42d,0x044735e,0x0ab65ef,0x1d8f21b,0x17f36c2,0x003ccd8, - 0x0b8f262,0x0d7a438,0x1ffa28d,0x09c4879,0x06f2bb4,0x132d714, - 0x07745c8,0x1c5074a,0x0114da2 }, - { 0x1e3d708,0x04d2b60,0x1e992a7,0x1e3961d,0x0fe62d3,0x143aa02, - 0x0a6125f,0x1f5e0e0,0x13cea46,0x1c5beb5,0x01898c4,0x069d071, - 0x0907806,0x18e1848,0x1a10a01,0x10c8e4f,0x1d7e583,0x1f857bc, - 0x08da899,0x10cb056,0x0104c1b } }, - /* 213 */ - { { 0x126c894,0x184f6d2,0x148ccbf,0x002958f,0x15abf12,0x0c949a4, - 0x13734f3,0x0ad6df2,0x092e6b5,0x1d57589,0x1b0c6ff,0x0dd4206, - 0x0e19379,0x183ff99,0x148df9d,0x0cf7153,0x10d829d,0x1eb2d2d, - 0x0ca4922,0x1b6aadb,0x01b348e }, - { 0x0d46575,0x0fcd96f,0x0b3dbba,0x15ff4d3,0x096ca08,0x169be8a, - 0x0ce87c5,0x003ab5d,0x1789e5d,0x1283ed8,0x1f31152,0x1c53904, - 0x1705e2c,0x14b2733,0x0db9294,0x08de453,0x0ba4c0e,0x082b1d8, - 0x0f11921,0x1848909,0x00a3e75 } }, - /* 214 */ - { { 0x0f6615d,0x1a3b7e9,0x06a43f2,0x11b31b5,0x0b7f9b7,0x1ef883a, - 0x17c734a,0x063c5fb,0x09b956f,0x1ed1843,0x1bab7ca,0x05ef6b2, - 0x18f3cca,0x1aad929,0x1027e2c,0x08db723,0x0f3c6c8,0x12379fb, - 0x085190b,0x12731c5,0x01ff9bb }, - { 0x17bd645,0x06a7ad0,0x1549446,0x17b7ada,0x17033ea,0x0684aba, - 0x01bf1cd,0x06a00fd,0x15f53c4,0x065032f,0x1f74666,0x137ffa4, - 0x0a9949d,0x14a968e,0x1138c11,0x02039bb,0x0fb81ac,0x1c2655a, - 0x095ac01,0x00f3f29,0x000346d } }, - /* 215 */ - { { 0x0bfdedd,0x1c727d3,0x1be657a,0x1cf4e98,0x193a285,0x04d1294, - 0x15344f4,0x0cf17ab,0x019a5f7,0x15085f3,0x0ecd03a,0x107c19d, - 0x03d3db0,0x0edfbd4,0x0ce9e2c,0x047c38c,0x03ec30f,0x093325e, - 0x1e820de,0x01f1e20,0x01c9663 }, - { 0x0f86a80,0x065a5ef,0x06aeefd,0x107f04b,0x1fa4ec7,0x0a99640, - 0x1d81182,0x125497e,0x08b909e,0x0ddbd66,0x010581c,0x062e2f1, - 0x08ca1d7,0x050d5c9,0x1fc52fb,0x0ab4afe,0x16e5f84,0x0dff500, - 0x1c87a26,0x18ed737,0x002d7b8 } }, - /* 216 */ - { { 0x19f8e7d,0x102b1a5,0x02a11a1,0x0ec7f8b,0x001176b,0x176b451, - 0x169f8bf,0x121cf4b,0x0651831,0x033bb1f,0x1deb5b3,0x0205d26, - 0x017d7d0,0x1b81919,0x1f11c81,0x16a0b99,0x031534b,0x0ab9f70, - 0x1c689da,0x03df181,0x00f31bf }, - { 0x0935667,0x1ae2586,0x0e2d8d7,0x120c1a5,0x14152c3,0x01d2ba3, - 0x0b0b8df,0x19bdff5,0x00b72e0,0x0afe626,0x18091ff,0x1373e9e, - 0x13b743f,0x1cf0b79,0x10b8d51,0x1df380b,0x0473074,0x1d111a6, - 0x056ab38,0x05e4f29,0x0124409 } }, - /* 217 */ - { { 0x10f9170,0x0bc28d9,0x16c56ff,0x126ff9c,0x115aa1e,0x021bdcb, - 0x157824a,0x0e79ffa,0x1c32f12,0x056692c,0x1878d22,0x19e4917, - 0x0b5a145,0x1d2de31,0x0d02181,0x0de8c74,0x1151815,0x1b14b75, - 0x1dd3870,0x1f5a324,0x01e7397 }, - { 0x08225b5,0x1ccfa4e,0x1134d8b,0x128d6ef,0x13efce4,0x00f48d9, - 0x1d4c215,0x1268a3b,0x038f3d6,0x1e96c9a,0x1ed5382,0x05adce4, - 0x000b5de,0x1b116ca,0x164a709,0x1529685,0x12356f6,0x09b5673, - 0x132bc81,0x0319abf,0x004464a } }, - /* 218 */ - { { 0x1a95d63,0x10555d5,0x11b636f,0x02f6966,0x12780c6,0x06c0a14, - 0x1e18c38,0x098c861,0x0b56ef0,0x1adf015,0x18d8ce1,0x172af0b, - 0x04c28fe,0x009649f,0x1005e57,0x10547aa,0x1c1e36f,0x144ffa8, - 0x03babf5,0x11912a2,0x016b3c4 }, - { 0x0f064be,0x03f5d6a,0x0a65e4a,0x0aa9d7b,0x1a77d55,0x1b93f50, - 0x17bc988,0x18c8ce8,0x189f366,0x088fac8,0x15baf6a,0x0b9b8b3, - 0x137e543,0x1a92690,0x0136ba9,0x1671a75,0x11c4395,0x0e3d8ee, - 0x0a08f12,0x07ce083,0x001cca1 } }, - /* 219 */ - { { 0x14d64b0,0x0c30643,0x18318e6,0x042ca79,0x1375b09,0x108cc31, - 0x00003aa,0x0ba2ce0,0x1621cd1,0x1633c84,0x1c37358,0x1bacefa, - 0x0dbe1d7,0x182dea6,0x1c3c9c0,0x11e61df,0x021362f,0x003b763, - 0x19116de,0x00902cf,0x01d8812 }, - { 0x01f9758,0x04d070b,0x138a05d,0x1d4789f,0x060915f,0x0eec57f, - 0x1390644,0x013ea6f,0x079a51a,0x11b5456,0x173e3bf,0x0968594, - 0x1567fb5,0x12482bf,0x172b81f,0x096c837,0x0c5a424,0x1db8ff8, - 0x0d81960,0x0b4a6c9,0x0106481 } }, - /* 220 */ - { { 0x139cc39,0x14e1f77,0x1b45e31,0x09f4c6a,0x1830456,0x17dcc84, - 0x0d50904,0x14b7a78,0x179dbb2,0x0ea98e9,0x1d78f68,0x0311cfc, - 0x114865f,0x0580a3d,0x0b13888,0x135605b,0x1ca33d2,0x1facf28, - 0x1ec1d3b,0x09effc6,0x00f1c96 }, - { 0x0301262,0x0605307,0x08b5c20,0x00a7214,0x1a45806,0x054814c, - 0x1fe6b32,0x185b4ce,0x114c0f1,0x1d7482b,0x1b67df7,0x1e2cdcc, - 0x043665f,0x03c2349,0x19b7631,0x060f990,0x18fc4cc,0x062d7f4, - 0x02fd439,0x0774c7c,0x003960e } }, - /* 221 */ - { { 0x19ecdb3,0x0289b4a,0x06f869e,0x0ff3d2b,0x089af61,0x106e441, - 0x0cae337,0x02aa28b,0x07c079e,0x1483858,0x089057f,0x09a6a1c, - 0x02f77f0,0x1ac6b6a,0x0adcdc8,0x0c53567,0x1b9ba7b,0x08a7ea0, - 0x1003f49,0x05b01ce,0x01937b3 }, - { 0x147886f,0x006a6b8,0x072b976,0x02aed90,0x008ced6,0x138bddf, - 0x01a4990,0x043c29d,0x0abb4bd,0x0e6f8cc,0x00c22e7,0x0c8cca6, - 0x07658be,0x0cce8ce,0x1c64b6b,0x1624df7,0x1b3304a,0x0aad1e8, - 0x089378c,0x1e97cbf,0x000e943 } }, - /* 222 */ - { { 0x1e9ea48,0x1202c3f,0x121b150,0x0ac36ae,0x0f24f82,0x18cba05, - 0x104f1e1,0x09b3a58,0x170eb87,0x1d4df3c,0x0e8ea89,0x11c16c5, - 0x0c43fef,0x160df85,0x08fca18,0x061c214,0x0f34af1,0x1a8e13b, - 0x19573af,0x1a3d355,0x0185f6c }, - { 0x0369093,0x17d3fa0,0x1828937,0x0cb0b03,0x11f1d9d,0x0976cf0, - 0x0fccf94,0x12d3201,0x1ed1208,0x1c5422c,0x0f0e66f,0x0abd16e, - 0x1e83245,0x07b7aa7,0x08c15a6,0x046aaa9,0x1a53c25,0x0954eb6, - 0x0824ecc,0x0df2085,0x016ae6a } }, - /* 223 */ - { { 0x12cdd35,0x091e48a,0x1bc6cb8,0x110c805,0x0e6e43a,0x072dead, - 0x1c37ee7,0x0291257,0x0758049,0x0565c25,0x0bbb0ad,0x0bffea0, - 0x0e8c7f5,0x1519f7a,0x029ee4e,0x0400339,0x157fd9d,0x1835881, - 0x0e8ef3a,0x033fe01,0x00273e3 }, - { 0x1e360a3,0x017bbd5,0x129860b,0x095bfdf,0x17ef5c8,0x05b7e62, - 0x0329994,0x005349e,0x0aaf0b2,0x1a7c72b,0x1bc558f,0x1141449, - 0x135c850,0x0f522f8,0x1d8bf64,0x0db7db1,0x1a02803,0x1f96491, - 0x093440e,0x1949803,0x018a4a9 } }, - /* 224 */ - { { 0x048e339,0x1dbcc2a,0x05d8a8f,0x1e31473,0x1e8770c,0x148b866, - 0x15d35e9,0x15822c0,0x12b6067,0x1d82e2c,0x04e2ad2,0x1b61090, - 0x14de0d2,0x0484f3c,0x076ae49,0x02bee29,0x0b67903,0x041d19b, - 0x0cd6896,0x00e9b34,0x013ccd9 }, - { 0x01b784d,0x0e2f056,0x0b87a0e,0x0ddca4f,0x0b65c8c,0x0447605, - 0x1851a87,0x0b1a790,0x046c1bf,0x100fbc8,0x0940a88,0x0c4e7fb, - 0x0571cec,0x112dc83,0x0fe23ac,0x1bf9bfe,0x098c556,0x0360f86, - 0x013e973,0x0445549,0x00acaa3 } }, - /* 225 */ - { { 0x1b4dfd6,0x1a5e1e4,0x0a4c5f9,0x07f1cec,0x05ba805,0x061a901, - 0x1701676,0x168060f,0x0b85a20,0x0481b66,0x1c4d647,0x1e14470, - 0x0ef2c63,0x054afda,0x0676763,0x18d8c35,0x1399850,0x01ebe27, - 0x00a659a,0x12d392d,0x0169162 }, - { 0x163ee53,0x1e133e5,0x0d4df44,0x02ebd58,0x07b12e6,0x0d5fe53, - 0x0684464,0x13f666d,0x1ee1af6,0x168324e,0x10479d6,0x1e0023b, - 0x054d7a6,0x0dcfcbb,0x1c0c2e3,0x0266501,0x1a3f0ab,0x1510000, - 0x0763318,0x1931a47,0x0194e17 } }, - /* 226 */ - { { 0x18fe898,0x0c05a0e,0x14d1c83,0x0e64308,0x0d7a28b,0x190ba04, - 0x10e1413,0x15fe3e7,0x1166aa6,0x09c0e6a,0x1838d57,0x010998a, - 0x0d9cde6,0x0f30f16,0x0107c29,0x12a3596,0x0f5d9b4,0x031088b, - 0x1b8ab0b,0x1c2da6f,0x00c4509 }, - { 0x06fd79e,0x1106216,0x0c3ae0a,0x1c75ef1,0x15b7ee4,0x0c0ce54, - 0x18f06eb,0x0d27b36,0x0985525,0x06b3a6f,0x06743c4,0x0965f38, - 0x0917de6,0x03e2f35,0x0feaebd,0x1b6df40,0x0ad2ce2,0x142c5e2, - 0x1f27463,0x0470143,0x00c976c } }, - /* 227 */ - { { 0x064f114,0x18f7c58,0x1d32445,0x0a9e5e1,0x03cb156,0x19315bc, - 0x161515e,0x0d860a4,0x10f3493,0x1463380,0x107fb51,0x05fd334, - 0x09ef26d,0x13fbfb5,0x168899e,0x1f837ed,0x0dba01b,0x012b1dc, - 0x0d03b50,0x06d90b8,0x000e14b }, - { 0x1db67e6,0x1f13212,0x017d795,0x12fe5d2,0x05df4e8,0x1621344, - 0x1945009,0x126f065,0x03e8750,0x095f131,0x0e1a44c,0x17b078a, - 0x1d856b5,0x0ab9a7c,0x072b956,0x090c2b6,0x1e2d5aa,0x02d03df, - 0x1a2aed6,0x192de19,0x01d07a4 } }, - /* 228 */ - { { 0x03aa2e9,0x0a682a9,0x0181efd,0x19da7a1,0x08841e0,0x0dfdb4e, - 0x1db89fe,0x10aad07,0x0162bdf,0x0583fa2,0x0373277,0x10720f6, - 0x0e62d17,0x12bd29b,0x12ee2ad,0x0fa7945,0x0d27cf4,0x04c5cd0, - 0x1ba98dc,0x0a9ad0b,0x01f2ff1 }, - { 0x0b232ac,0x1bb452b,0x0aad5a2,0x0c7e54a,0x0e8d6e3,0x1bfe302, - 0x1e85a20,0x12375d0,0x1d10a76,0x1e2c541,0x157efba,0x15e1f28, - 0x0ead5e4,0x1eb2a71,0x0835b0d,0x104aa34,0x0b9da7c,0x0c6207e, - 0x0366e4c,0x1679aec,0x00b26d7 } }, - /* 229 */ - { { 0x12eaf45,0x0861f5d,0x04bdec2,0x18c5ff7,0x0d24d91,0x1b791ef, - 0x0fa929c,0x1c77e54,0x16ff0fd,0x0dccf5e,0x040bd6d,0x0abb942, - 0x08bca2b,0x03f0195,0x080f360,0x02f51ec,0x048a8bf,0x0aa085a, - 0x077156c,0x0cc14fc,0x0109b86 }, - { 0x0a2fbd8,0x058ed01,0x0296c52,0x167645d,0x1ed85e8,0x095a84f, - 0x083921c,0x02c26f1,0x0c6a3e5,0x02b00a4,0x0ed40da,0x04382c6, - 0x1171009,0x12a8938,0x049450c,0x0208f27,0x1d207d3,0x1bda498, - 0x150b82e,0x1ce4570,0x00ea623 } }, - /* 230 */ - { { 0x0972688,0x011e992,0x1d88212,0x04007ea,0x18b83c1,0x06a2942, - 0x19a41b4,0x0fc329a,0x02c6f74,0x010cac2,0x1b626a1,0x05d2028, - 0x02c8f8a,0x1a28dde,0x1b0779d,0x109f453,0x0b8f7f2,0x1fb115b, - 0x0dc7913,0x03b7d2f,0x006083f }, - { 0x19dd56b,0x04999cc,0x17a6659,0x152f48f,0x0cfac0b,0x147d901, - 0x162baef,0x194ccc1,0x0f61d7b,0x1e14eec,0x1705351,0x0a3b0b5, - 0x1c6f5fb,0x07cfea0,0x16b1e21,0x07cd9cc,0x1d4ff51,0x10e734e, - 0x1f9674f,0x1cb23df,0x00231ac } }, - /* 231 */ - { { 0x1fda771,0x1d21c54,0x0038b99,0x190cc62,0x026f652,0x19f91db, - 0x0792384,0x03fbf63,0x0035d2d,0x0cfc479,0x0fa1e16,0x02251a2, - 0x071723a,0x1da8e70,0x02a8a4b,0x1750512,0x10ebbd9,0x072f9d3, - 0x1d1452d,0x104ce66,0x0155dde }, - { 0x0f59a95,0x15bbf6b,0x108022c,0x0604040,0x13f853e,0x163bcbc, - 0x0ab07ae,0x0eca44a,0x1b56b66,0x166e5cc,0x0a9401b,0x13f32e4, - 0x104abdb,0x02715d6,0x0843cfc,0x1ba9a4c,0x0ff3034,0x08652d0, - 0x0b02e03,0x1b0101b,0x0041333 } }, - /* 232 */ - { { 0x1a85a06,0x083849a,0x0d13a14,0x0c85de3,0x0e166e7,0x1d9d36a, - 0x02dc681,0x0d50952,0x030329e,0x16eb600,0x1549675,0x14ca7aa, - 0x1e20c4b,0x17c5682,0x0ec9abd,0x1999bdc,0x1412ab4,0x01071ea, - 0x0501909,0x1312695,0x01bd797 }, - { 0x00c7ff0,0x0e8c247,0x0d03ca8,0x192a876,0x1ae85ef,0x0e98c5d, - 0x0c6bbd4,0x14dd2c8,0x075878f,0x0e9f6a7,0x057d4b9,0x13b7851, - 0x1c4d2a2,0x0f88833,0x1c9e1dc,0x09dca75,0x1649e7f,0x13666f4, - 0x15b5d36,0x111b434,0x0192351 } }, - /* 233 */ - { { 0x1d310ed,0x1909001,0x0c46c20,0x1930f60,0x120ee8c,0x02ac546, - 0x0749a13,0x1913ca9,0x0b7167e,0x112f9e7,0x156ed57,0x09e897e, - 0x17acf11,0x030e480,0x07b71dc,0x0878103,0x0e6deb3,0x0bacd22, - 0x1326d7b,0x1f3efc0,0x007858d }, - { 0x1f13222,0x03f5d9d,0x08453e9,0x1bd40fb,0x1e451dc,0x0c12178, - 0x1eb0f03,0x03c37d3,0x136eb87,0x192bea6,0x0c64364,0x0eb57d4, - 0x13f49e7,0x075f159,0x1b4647d,0x0012c80,0x13c0c11,0x033d562, - 0x0e06b1e,0x0b9f17a,0x01f4521 } }, - /* 234 */ - { { 0x0493b79,0x145477d,0x0ab0e1f,0x169d638,0x120e270,0x1911905, - 0x0fe827f,0x07b3e72,0x0a91c39,0x170dd57,0x0a36597,0x0c34271, - 0x04deda9,0x0bdea87,0x0ac8e32,0x191c0d3,0x08a2363,0x17fb46a, - 0x1931305,0x1c01cb9,0x0158af8 }, - { 0x1c509a1,0x0e78367,0x01d5b33,0x1f84d98,0x00f411e,0x0e2bf83, - 0x17f5936,0x158da19,0x132e99c,0x0a8a429,0x1a5442a,0x167b171, - 0x1d58f9a,0x1886e1f,0x1a61c26,0x06a134f,0x03d75ef,0x1c1c842, - 0x0a4c4b1,0x1993a0b,0x01b628c } }, - /* 235 */ - { { 0x141463f,0x1a78071,0x1e80764,0x1c2a1b4,0x14c8a6c,0x04aa9f8, - 0x183f104,0x123b690,0x0a93f4a,0x11def2d,0x16019f0,0x0f0e59a, - 0x009f47c,0x0219ee4,0x0cc0152,0x054fa3a,0x1f975a3,0x08605f3, - 0x031d76a,0x0eefab1,0x012e08b }, - { 0x1a10d37,0x0940bb0,0x16977f0,0x02b8a1e,0x0d7b618,0x03be307, - 0x0576de5,0x016515f,0x133c531,0x05515bb,0x06099e8,0x1570a62, - 0x1f905fa,0x15a0cac,0x03a6059,0x0ef09e8,0x05216b3,0x04e65a1, - 0x0619ab3,0x0baef8d,0x00c5683 } }, - /* 236 */ - { { 0x1450a66,0x18a6595,0x1053a75,0x18fb7fb,0x1318885,0x1350600, - 0x03616d1,0x14ccab5,0x15bdfc1,0x1510f4c,0x1e4b440,0x1931cce, - 0x177a0d7,0x1aa853c,0x006ed5e,0x1a66e54,0x0335d74,0x0a16231, - 0x036b525,0x09c3811,0x008b7be }, - { 0x1812273,0x1d81fca,0x15fc61c,0x05dc7ee,0x0e26ed3,0x1310bd1, - 0x03ab9b6,0x09e58e2,0x0261d9f,0x1a85aba,0x0768b66,0x1f536f8, - 0x0743971,0x02542ef,0x113ee1f,0x026f645,0x051ec22,0x17b961a, - 0x1ee8649,0x0acd18e,0x0173134 } }, - /* 237 */ - { { 0x03ba183,0x1463d45,0x1e9cf8f,0x17fc713,0x0e8cebb,0x0dd307a, - 0x11a1c3e,0x1071d48,0x1cb601a,0x08bb71a,0x14b6d15,0x184c25c, - 0x11f90bd,0x07b895f,0x1e79166,0x0a99b2b,0x00fbea0,0x1cde990, - 0x157f502,0x0337edb,0x017a2cf }, - { 0x0736feb,0x1b65133,0x18bdc73,0x13bcf9f,0x1de86f4,0x1482b1d, - 0x0f3a3f0,0x09f8c15,0x0726b6e,0x17451e7,0x048d6ea,0x088a7e5, - 0x1ed2382,0x1287fd2,0x0d55fd5,0x1ee8949,0x054113e,0x150a29f, - 0x1909b74,0x0ed4a67,0x01b07c6 } }, - /* 238 */ - { { 0x1d96872,0x101f91a,0x032bd79,0x187f4b7,0x0b1a23c,0x046e2fd, - 0x01c6fa6,0x17aa8b3,0x1d430c0,0x1974244,0x16730f8,0x13c0ec9, - 0x0d7ec26,0x1960620,0x08e084b,0x10769ee,0x183887b,0x096ca30, - 0x1c62904,0x1f4ce25,0x0010281 }, - { 0x0858b37,0x00247b2,0x176600a,0x1e6afbc,0x00e149a,0x0f5d8c7, - 0x01e4586,0x1416443,0x19f2b0b,0x0810059,0x072eb88,0x15cc207, - 0x1d5a87e,0x1cabce8,0x1f7376c,0x0a2bc9d,0x0aa2788,0x10d9c47, - 0x0061e2a,0x0a58799,0x002c1a5 } }, - /* 239 */ - { { 0x0a723dc,0x1fa8007,0x08c5eb1,0x088562a,0x0a5f04f,0x042e430, - 0x05116fa,0x004c7a9,0x1ff1197,0x0fccc9f,0x1633a98,0x08b9898, - 0x16c3fba,0x1ce6b01,0x145479a,0x04777cd,0x11557b9,0x13ad1d5, - 0x1acbf51,0x00f8a59,0x01474ec }, - { 0x188239d,0x11e9976,0x1a5311a,0x0d06b5c,0x0d1b8ae,0x1759738, - 0x18c967f,0x16be9fb,0x043bc0b,0x11dfb8e,0x0a9c148,0x016f1ec, - 0x053cd22,0x0ff3ccd,0x092183a,0x0ff2644,0x10324ab,0x1ec2ac3, - 0x1652562,0x1ee6616,0x010f8e0 } }, - /* 240 */ - { { 0x067d520,0x0e3dd9e,0x07b2bcd,0x1647f95,0x18f4958,0x1d54046, - 0x1c6522e,0x15c0ef1,0x02135e8,0x0c61867,0x03bfdd0,0x1353911, - 0x0bcdd8d,0x1b98a25,0x01d77c3,0x14a68e4,0x0954506,0x0daa4e4, - 0x1eedff1,0x0712f2b,0x011c4ef }, - { 0x1f5e698,0x164d621,0x18e8ff8,0x19c714b,0x0e77fcb,0x04e170e, - 0x12438c2,0x002da0b,0x1ac1d58,0x13a79ff,0x0e74a96,0x0440703, - 0x0baeeda,0x1af9cb0,0x162c50f,0x1577db2,0x0510db7,0x032ffe8, - 0x0816dc6,0x0fcd00f,0x00ce8e9 } }, - /* 241 */ - { { 0x0e86a83,0x0f30dc6,0x0580894,0x1f7efce,0x0604159,0x1819bbc, - 0x1f75d23,0x085f824,0x1450522,0x1e5961b,0x1a826e1,0x01e9269, - 0x01bd495,0x0233ca2,0x11b100f,0x082d4a2,0x11023ba,0x0f456a3, - 0x1d8e3ac,0x1034c15,0x01b389b }, - { 0x0150c69,0x0c9a774,0x12f39a6,0x11c4f82,0x14f7590,0x00ca7fb, - 0x0a245a8,0x0ecbb81,0x01bd51b,0x07a4e99,0x1e58c0e,0x00bc30e, - 0x086bc33,0x1e9da53,0x0bcfeff,0x1e313fc,0x177d7ca,0x18a04d9, - 0x0e3c426,0x1d42773,0x01b3029 } }, - /* 242 */ - { { 0x1a2fd88,0x09c6912,0x180fbde,0x199d740,0x090f2f7,0x136ffa4, - 0x072035e,0x10c987c,0x02883f9,0x063c79b,0x194c140,0x0b25331, - 0x13ed92b,0x192eee3,0x02a3c6c,0x0e11403,0x187d5d3,0x1b6ffec, - 0x147ca2e,0x06aa9e1,0x0059dcd }, - { 0x1a74e7d,0x1720e91,0x17d85f1,0x1cbb665,0x14b61eb,0x1ffd05c, - 0x1fe9e79,0x01a785f,0x12ebb7a,0x19b315b,0x17e70d1,0x0bdc035, - 0x04a8641,0x0a33c93,0x00b0c99,0x138ae2a,0x1492fa0,0x10b4889, - 0x11d2421,0x1e69544,0x0195897 } }, - /* 243 */ - { { 0x1adc253,0x0e9acd5,0x0579211,0x198f2f9,0x0054b92,0x10c1097, - 0x0d6f668,0x04e4553,0x0a52b88,0x1dc052f,0x0719da6,0x0f1c5cc, - 0x13ea38e,0x04587c5,0x09d2c68,0x10a99f6,0x0e3db9d,0x1db5521, - 0x1804b5c,0x044a46a,0x01638ba }, - { 0x1c8c576,0x00737ba,0x1749f3b,0x19c978f,0x0bb20e7,0x0c03935, - 0x08321a7,0x16e12b1,0x08a023e,0x0846335,0x042c56a,0x01d4ec2, - 0x06ca9f5,0x0c37b0d,0x0326650,0x0d3b0cd,0x0ed2a0a,0x1ceef91, - 0x0fe2843,0x1c312f7,0x01e0bfe } }, - /* 244 */ - { { 0x0319e4f,0x0340c24,0x1e809b6,0x0ab4b0d,0x0be6f6b,0x189932b, - 0x1621899,0x1f57deb,0x198529c,0x0129562,0x0a73eeb,0x0be2c56, - 0x0de7cc4,0x11531ac,0x0141826,0x158e1dc,0x0a42940,0x07be5ce, - 0x0216c7c,0x0955d95,0x01adfb4 }, - { 0x198678e,0x1d49b73,0x10e19ad,0x0732a80,0x0a01e10,0x14305be, - 0x078de05,0x0afe492,0x1b745d8,0x17fea41,0x017b5bb,0x0c5148e, - 0x175dbb3,0x1952e87,0x15a3526,0x1fdc6af,0x09a2389,0x168d429, - 0x09ff5a1,0x184a923,0x01addbb } }, - /* 245 */ - { { 0x09686a3,0x05d104b,0x0fd7843,0x0bc780a,0x108b1c5,0x1a38811, - 0x0c4d09b,0x0702e25,0x1490330,0x1c8b2d8,0x0549ec7,0x002e5a0, - 0x0245b72,0x154d1a7,0x13d991e,0x06b90df,0x194b0be,0x128faa5, - 0x08578e0,0x16454ab,0x00e3fcc }, - { 0x14dc0be,0x0f2762d,0x1712a9c,0x11b639a,0x1b13624,0x170803d, - 0x1fd0c11,0x147e6d7,0x1da9c99,0x134036b,0x06f1416,0x0ddd069, - 0x109cbfc,0x109f042,0x01c79cf,0x091824d,0x02767f4,0x0af3551, - 0x169eebe,0x0ef0f85,0x01b9ba7 } }, - /* 246 */ - { { 0x1a73375,0x12c7762,0x10e06af,0x1af5158,0x175df69,0x0541ad0, - 0x0542b3b,0x01e59e6,0x1f507d3,0x03d8304,0x0c1092e,0x14578c1, - 0x0c9ae53,0x0087c87,0x0c78609,0x1137692,0x10fadd6,0x122963e, - 0x1d8c6a3,0x0a69228,0x0013ab4 }, - { 0x084f3af,0x0ec2b46,0x0cfabcb,0x043755c,0x029dc09,0x0b58384, - 0x0aa162e,0x02c8ca8,0x0e8a825,0x11306a0,0x14c8ad0,0x1b58b86, - 0x12b9e5e,0x1cf6d06,0x09e5580,0x1721579,0x1c6b962,0x1435e83, - 0x07b14c0,0x05b58f6,0x010a2e2 } }, - /* 247 */ - { { 0x19d8f0a,0x1e04e91,0x0085997,0x1957142,0x12b2e03,0x19a3bdc, - 0x05da005,0x009c86d,0x18e3616,0x19c76cf,0x0186faa,0x123b3d6, - 0x1079b00,0x1f422b3,0x1089950,0x145c19a,0x0c72fe1,0x1d07bbf, - 0x18280c3,0x0842c4e,0x00931d2 }, - { 0x0646bc3,0x1c1a67c,0x1be7ea7,0x04815d2,0x1df94a5,0x08bbe8b, - 0x0e240de,0x19b2038,0x0ffeb66,0x0fe8322,0x0491967,0x05d8ef7, - 0x0f81aec,0x06cc0ea,0x1cedfcb,0x161265b,0x169f377,0x1e4de1f, - 0x1616762,0x1e69e7b,0x0125dae } }, - /* 248 */ - { { 0x0c123bc,0x0228dd1,0x0952b02,0x101031f,0x11e83a6,0x0abdc56, - 0x15c0a62,0x02cadba,0x0f0f12f,0x03f971a,0x1e85373,0x1866153, - 0x0c1f6a9,0x197f3c1,0x1268aee,0x0a9bbdf,0x097709f,0x1e98ce3, - 0x1918294,0x047197a,0x01dc0b8 }, - { 0x0dfb6f6,0x09480a2,0x149bd92,0x08dc803,0x070d7cb,0x09bd6c1, - 0x0903921,0x1b234e1,0x170d8db,0x06b30da,0x03562e1,0x0475e2e, - 0x12ca272,0x11a270e,0x0d33c51,0x1c3f5dd,0x095ab9d,0x1912afe, - 0x0f717a9,0x1c2215b,0x01f8cd6 } }, - /* 249 */ - { { 0x0b8a0a7,0x1e35cbc,0x17a8a95,0x0dd067d,0x04b4aeb,0x089ff39, - 0x05f052f,0x1c93c8c,0x0fc2e8e,0x00c3444,0x11fbbf1,0x1493f62, - 0x1b8d398,0x1733167,0x1c647c4,0x145d9d3,0x089958b,0x0b0c391, - 0x02e3543,0x1a1e360,0x002dbd6 }, - { 0x0c93cc9,0x07eff12,0x039e257,0x0173ce3,0x09ed778,0x1d7bf59, - 0x0e960e2,0x0d20391,0x04ddcbf,0x1129c3f,0x035aec0,0x017f430, - 0x0264b25,0x04a3e3e,0x1a39523,0x1e79ada,0x0329923,0x14153db, - 0x1440f34,0x006c265,0x000fb8f } }, - /* 250 */ - { { 0x0d9d494,0x059f846,0x07ce066,0x1329e9f,0x1b2065b,0x19c7d4c, - 0x08880f1,0x196ecc9,0x0d8d229,0x0cfa60a,0x1152cc6,0x0b898a3, - 0x12ddad7,0x0909d19,0x0cb382f,0x0f65f34,0x085888c,0x179d108, - 0x0c7fc82,0x1f46c4b,0x00d16de }, - { 0x1a296eb,0x002a40c,0x0c4d138,0x0ba3522,0x1d94ff1,0x1522a78, - 0x0b4affa,0x0ffafbd,0x14d40bd,0x132d401,0x0692beb,0x08fc300, - 0x17604f1,0x12f06f3,0x0c123e6,0x0594130,0x0a5ff57,0x1d1d8ce, - 0x0087445,0x0fb74e3,0x00e0a23 } }, - /* 251 */ - { { 0x1630ee8,0x15fc248,0x0c07b6e,0x040bd6a,0x1e6589c,0x08fa3de, - 0x0acb681,0x1033efa,0x0212bbe,0x1554fcb,0x048492b,0x1abd285, - 0x1bdced3,0x1a21af2,0x07d6e27,0x1ecded2,0x0339411,0x10cb026, - 0x0d5bc36,0x1813948,0x00e6b7f }, - { 0x14f811c,0x07209fb,0x176c4a5,0x03bf1b1,0x1a42d83,0x1a0c648, - 0x1c85e58,0x1d84fea,0x088ebcd,0x1ef290c,0x016f257,0x00ddd46, - 0x01fdd5e,0x163345b,0x0798222,0x030c3da,0x016eb81,0x0199d78, - 0x17773af,0x16325a2,0x01c95ec } }, - /* 252 */ - { { 0x0bde442,0x19bd1f0,0x1cfa49e,0x10cdef4,0x00543fe,0x0886177, - 0x074823b,0x065a61b,0x1a6617a,0x1bce1a0,0x173e2eb,0x10e1a3a, - 0x0be7367,0x11d5e7c,0x14373a7,0x0bcf605,0x0dd772b,0x0ff11e9, - 0x1ff1c31,0x19dd403,0x010b29f }, - { 0x0d803ff,0x05726b1,0x1aa4c6f,0x1fb7860,0x13ee913,0x0083314, - 0x19eaf63,0x0b15e3b,0x0e7a6d6,0x042bc15,0x1d381b5,0x125c205, - 0x0691265,0x09b7d7f,0x08c49fc,0x0242723,0x0408837,0x0235c9a, - 0x0c7858d,0x1687014,0x00ba53b } }, - /* 253 */ - { { 0x05636b0,0x08bfe65,0x171d8b9,0x02d5742,0x0296e02,0x173d96a, - 0x1f5f084,0x108b551,0x15717ad,0x08be736,0x0bcd5e5,0x10b7316, - 0x1ce762b,0x0facd83,0x1e65ad7,0x1ede085,0x0bbf37e,0x0f9b995, - 0x150ad22,0x028bd48,0x015da5d }, - { 0x07f6e3f,0x1e2af55,0x16f079d,0x0f54940,0x1f4d99a,0x0141139, - 0x1f5dd16,0x1f74ada,0x177b748,0x1844afd,0x07d7476,0x199c0c5, - 0x1b1c484,0x1acc01f,0x0c72428,0x171a1eb,0x1291720,0x121d627, - 0x0ab04fc,0x017fd0e,0x00e98c1 } }, - /* 254 */ - { { 0x06c4fd6,0x023c2e0,0x0e76747,0x0ba4b85,0x1f4b902,0x0c17925, - 0x17ac752,0x0560826,0x0ba4fef,0x159f6e1,0x181eace,0x073f31b, - 0x1d55a52,0x04b7a5b,0x1f126ac,0x1902bab,0x1603844,0x1e28514, - 0x159daca,0x0291a02,0x0047db1 }, - { 0x0f3bad9,0x1ce6288,0x0753127,0x1804520,0x090888f,0x1da26fa, - 0x157af11,0x0d122f4,0x0f39f2b,0x05975e3,0x0658a88,0x075e09d, - 0x170c58e,0x0b9eead,0x0adf06d,0x1eed8a5,0x1d6a329,0x195aa56, - 0x0bd328e,0x15a3d70,0x010859d } }, - /* 255 */ - { { 0x182d1ad,0x0209450,0x111598b,0x1c4122d,0x1751796,0x140b23b, - 0x109cae9,0x1834ee0,0x0b92c85,0x164587d,0x0cb81fe,0x05bf5df, - 0x0d207ab,0x1c30d99,0x0d4c281,0x1a28b8e,0x16588ae,0x0b1edf6, - 0x094e927,0x179b941,0x00bd547 }, - { 0x1056b51,0x09c17c3,0x044a9f0,0x16261f3,0x03d91ed,0x002da16, - 0x1791b4e,0x12bef8f,0x1fd31a9,0x0b080f5,0x1ee2a91,0x05699a7, - 0x0e1efd2,0x0f58bde,0x0e477de,0x01865fc,0x0c6616c,0x05a6a60, - 0x046fbbd,0x00477ce,0x011219f } }, -}; - -/* Multiply the base point of P521 by the scalar and return the result. - * If map is true then convert result to affine coordinates. - * - * Stripe implementation. - * Pre-generated: 2^0, 2^65, ... - * 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_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k, - int map, int ct, void* heap) -{ - return sp_521_ecc_mulmod_stripe_21(r, &p521_base, p521_table, - k, map, ct, heap); -} - -#endif - -/* Multiply the base point of P521 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_521(const mp_int* km, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 1); - SP_DECL_VAR(sp_digit, k, 21); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 21, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(k, 21, km); - - err = sp_521_ecc_mulmod_base_21(point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_21(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Multiply the base point of P521 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 multiply result. - * inMont Point to add is in montgomery 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_521(const mp_int* km, const ecc_point* am, - int inMont, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 2); - SP_DECL_VAR(sp_digit, k, 21 + 21 * 2 * 6); - sp_point_521* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 21 + 21 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - addP = point + 1; - tmp = k + 21; - - sp_521_from_mp(k, 21, km); - sp_521_point_from_ecc_point_21(addP, am); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_21(addP->x, addP->x, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_21(addP->y, addP->y, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_21(addP->z, addP->z, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_21(point, k, 0, 0, heap); - } - if (err == MP_OKAY) { - sp_521_proj_point_add_21(point, point, addP, tmp); - - if (map) { - sp_521_map_21(point, point, tmp); - } - - err = sp_521_point_to_ecc_point_21(point, r); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ -#ifndef WC_NO_RNG -/* Add 1 to a. (a = a + 1) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_521_add_one_21(sp_digit* a) -{ - a[0]++; - sp_521_norm_21(a); -} - -#endif -/* 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_521_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; - } -} - -/* Generates a scalar that is in the range 1..order-1. - * - * rng Random number generator. - * k Scalar value. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. - */ -static int sp_521_ecc_gen_k_21(WC_RNG* rng, sp_digit* k) -{ -#ifndef WC_NO_RNG - int err; - byte buf[66]; - - do { - err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); - if (err == 0) { - buf[0] &= 0x1; - sp_521_from_bin(k, 21, buf, (int)sizeof(buf)); - if (sp_521_cmp_21(k, p521_order2) <= 0) { - sp_521_add_one_21(k); - break; - } - } - } - while (err == 0); - - return err; -#else - (void)rng; - (void)k; - return NOT_COMPILED_IN; -#endif -} - -/* Makes a random EC key pair. - * - * rng Random number generator. - * priv Generated private value. - * pub Generated public point. - * heap Heap to use for allocation. - * returns ECC_INF_E when the point does not have the correct order, RNG - * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) -{ -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_DECL_VAR(sp_point_521, point, 2); -#else - SP_DECL_VAR(sp_point_521, point, 1); -#endif - SP_DECL_VAR(sp_digit, k, 21); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_521* infinity = NULL; -#endif - int err = MP_OKAY; - - - (void)heap; - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_ALLOC_VAR(sp_point_521, point, 2, heap, DYNAMIC_TYPE_ECC); -#else - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); -#endif - SP_ALLOC_VAR(sp_digit, k, 21, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - infinity = point + 1; - #endif - - err = sp_521_ecc_gen_k_21(rng, k); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, NULL); - } - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_21(infinity, point, p521_order, 1, 1, NULL); - } - if (err == MP_OKAY) { - if (sp_521_iszero_21(point->x) || sp_521_iszero_21(point->y)) { - err = ECC_INF_E; - } - } -#endif - - if (err == MP_OKAY) { - err = sp_521_to_mp(k, priv); - } - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_21(point, pub); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - /* point is not sensitive, so no need to zeroize */ - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_key_gen_521_ctx { - int state; - sp_521_ecc_mulmod_21_ctx mulmod_ctx; - sp_digit k[21]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_521 point[2]; -#else - sp_point_521 point[1]; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ -} sp_ecc_key_gen_521_ctx; - -int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, - ecc_point* pub, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_521* infinity = ctx->point + 1; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - - typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) - >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - err = sp_521_ecc_gen_k_21(rng, ctx->k); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - ctx->state = 1; - } - break; - case 1: - err = sp_521_ecc_mulmod_base_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - #else - ctx->state = 3; - #endif - } - break; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - case 2: - err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p521_order, 1, 1); - if (err == MP_OKAY) { - if (sp_521_iszero_21(ctx->point->x) || - sp_521_iszero_21(ctx->point->y)) { - err = ECC_INF_E; - } - else { - err = FP_WOULDBLOCK; - ctx->state = 3; - } - } - break; - #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - case 3: - err = sp_521_to_mp(ctx->k, priv); - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_21(ctx->point, pub); - } - break; - } - - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#ifdef HAVE_ECC_DHE -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 66 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_521_to_bin_21(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<20; i++) { - r[i+1] += r[i] >> 25; - r[i] &= 0x1ffffff; - } - j = 528 / 8 - 1; - a[j] = 0; - for (i=0; i<21 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 25) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 25); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Multiply the point by the scalar and serialize the X ordinate. - * The number is 0 padded to maximum size on output. - * - * priv Scalar to multiply the point by. - * pub Point to multiply. - * out Buffer to hold X ordinate. - * outLen On entry, size of the buffer in bytes. - * On exit, length of data in buffer in bytes. - * heap Heap to use for allocation. - * 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_521(const mp_int* priv, const ecc_point* pub, byte* out, - word32* outLen, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 1); - SP_DECL_VAR(sp_digit, k, 21); - int err = MP_OKAY; - - if (*outLen < 65U) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 21, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(k, 21, priv); - sp_521_point_from_ecc_point_21(point, pub); - err = sp_521_ecc_mulmod_21(point, point, k, 1, 1, heap); - } - if (err == MP_OKAY) { - sp_521_to_bin_21(point->x, out); - *outLen = 66; - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sec_gen_521_ctx { - int state; - union { - sp_521_ecc_mulmod_21_ctx mulmod_ctx; - }; - sp_digit k[21]; - sp_point_521 point; -} sp_ecc_sec_gen_521_ctx; - -int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, - const ecc_point* pub, byte* out, word32* outLen, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - if (*outLen < 32U) { - err = BUFFER_E; - } - - switch (ctx->state) { - case 0: - sp_521_from_mp(ctx->k, 21, priv); - sp_521_point_from_ecc_point_21(&ctx->point, pub); - ctx->state = 1; - break; - case 1: - err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - sp_521_to_bin_21(ctx->point.x, out); - *outLen = 66; - } - break; - } - - if (err == MP_OKAY && ctx->state != 1) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_DHE */ - -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -SP_NOINLINE static void sp_521_rshift_21(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<20; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (25 - n))) & 0x1ffffff); - } -#else - for (i=0; i<16; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (25 - n)) & 0x1ffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (25 - n)) & 0x1ffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (25 - n)) & 0x1ffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (25 - n)) & 0x1ffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (25 - n)) & 0x1ffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (25 - n)) & 0x1ffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (25 - n)) & 0x1ffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (25 - n)) & 0x1ffffff); - } - r[16] = (a[16] >> n) | (sp_digit)((a[17] << (25 - n)) & 0x1ffffff); - r[17] = (a[17] >> n) | (sp_digit)((a[18] << (25 - n)) & 0x1ffffff); - r[18] = (a[18] >> n) | (sp_digit)((a[19] << (25 - n)) & 0x1ffffff); - r[19] = (a[19] >> n) | (sp_digit)((a[20] << (25 - n)) & 0x1ffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[20] = a[20] >> n; -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* 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_521_mul_d_21(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 21; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1ffffff); - t >>= 25; - } - r[21] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 20; 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[20]; - r[20] = (sp_digit)(t & 0x1ffffff); - t >>= 25; - r[21] = (sp_digit)(t & 0x1ffffff); -#endif /* WOLFSSL_SP_SMALL */ -} - -SP_NOINLINE static void sp_521_lshift_42(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[42] = a[41] >> (25 - n); - for (i=41; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (25 - n))) & 0x1ffffff); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[41]; - r[42] = s >> (25U - n); - s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); - r[41] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); - r[40] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); - r[39] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); - r[38] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); - r[37] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); - r[36] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (25U - n))) & 0x1ffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0x1ffffff); -} - -/* 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. - * - * Simplified based on top word of divisor being (1 << 25) - 1 - * - * 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_521_div_21(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 21 + 3); - int i; - sp_digit r1; - sp_digit mask; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 21 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 42 + 1; - sd = t2 + 21 + 1; - - sp_521_mul_d_21(sd, d, (sp_digit)1 << 4); - sp_521_lshift_42(t1, a, 4); - t1[21 + 21] += t1[21 + 21 - 1] >> 25; - t1[21 + 21 - 1] &= 0x1ffffff; - for (i=20; i>=0; i--) { - r1 = t1[21 + i]; - sp_521_mul_d_21(t2, sd, r1); - (void)sp_521_sub_21(&t1[i], &t1[i], t2); - t1[21 + i] -= t2[21]; - sp_521_norm_21(&t1[i + 1]); - - mask = ~((t1[21 + i] - 1) >> 31); - sp_521_cond_sub_21(t1 + i, t1 + i, sd, mask); - sp_521_norm_21(&t1[i + 1]); - } - sp_521_norm_21(t1); - /* Correction: at loop i=0, sp_521_norm_21(&t1[1]) skips t1[0], so a - * borrow there is invisible to the correction mask that checks t1[21]. - * After the outer sp_521_norm_21(t1) the borrow lands in t1[20]. - * Add sd back when t1[20] is negative. */ - mask = (sp_digit)(t1[20] >> 31); - for (i = 0; i < 21; i++) - t1[i] += sd[i] & mask; - sp_521_norm_21(t1); - sp_521_rshift_21(r, t1, 4); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_521_mod_21(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_521_div_21(a, m, NULL, r); -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply two number mod the order of P521 curve. (r = a * b mod order) - * - * r Result of the multiplication. - * a First operand of the multiplication. - * b Second operand of the multiplication. - */ -static void sp_521_mont_mul_order_21(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_521_mul_21(r, a, b); - sp_521_mont_reduce_order_21(r, p521_order, p521_mp_order); -} - -#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL)) -#ifdef WOLFSSL_SP_SMALL -/* Order-2 for the P521 curve. */ -static const word32 p521_order_minus_2[17] = { - 0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U, - 0xbf2f966bU,0x51868783U,0xfffffffaU,0xffffffffU,0xffffffffU,0xffffffffU, - 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU -}; -#else -/* The low half of the order-2 of the P521 curve. */ -static const word32 p521_order_low[9] = { - 0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U, - 0xbf2f966bU,0x51868783U,0xfffffffaU -}; -#endif /* WOLFSSL_SP_SMALL */ - -/* Square number mod the order of P521 curve. (r = a * a mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_521_mont_sqr_order_21(sp_digit* r, const sp_digit* a) -{ - sp_521_sqr_21(r, a); - sp_521_mont_reduce_order_21(r, p521_order, p521_mp_order); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square number mod the order of P521 curve a number of times. - * (r = a ^ n mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_521_mont_sqr_n_order_21(sp_digit* r, const sp_digit* a, int n) -{ - int i; - - sp_521_mont_sqr_order_21(r, a); - for (i=1; i= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - XMEMCPY(t, a, sizeof(sp_digit) * 21); - ctx->i = 519; - ctx->state = 1; - break; - case 1: - sp_521_mont_sqr_order_21(t, t); - ctx->state = 2; - break; - case 2: - if ((p521_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { - sp_521_mont_mul_order_21(t, t, a); - } - ctx->i--; - ctx->state = (ctx->i >= 0) ? 1 : 3; - break; - case 3: - XMEMCPY(r, t, sizeof(sp_digit) * 21U); - err = MP_OKAY; - break; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -static void sp_521_mont_inv_order_21(sp_digit* r, const sp_digit* a, - sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 21); - for (i=519; i>=0; i--) { - sp_521_mont_sqr_order_21(t, t); - if ((p521_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_521_mont_mul_order_21(t, t, a); - } - } - XMEMCPY(r, t, sizeof(sp_digit) * 21U); -#else - sp_digit* t = td; - sp_digit* t2 = td + 2 * 21; - sp_digit* t3 = td + 4 * 21; - int i; - - /* t = a^2 */ - sp_521_mont_sqr_order_21(t, a); - /* t = a^3 = t * a */ - sp_521_mont_mul_order_21(t, t, a); - /* t= a^c = t ^ 2 ^ 2 */ - sp_521_mont_sqr_n_order_21(t2, t, 2); - /* t = a^f = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - - /* t3 = a^1e */ - sp_521_mont_sqr_order_21(t3, t); - /* t3 = a^1f = t3 * a */ - sp_521_mont_mul_order_21(t3, t3, a); - - /* t2= a^f0 = t ^ 2 ^ 4 */ - sp_521_mont_sqr_n_order_21(t2, t, 4); - /* t = a^ff = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - /* t2= a^ff00 = t ^ 2 ^ 8 */ - sp_521_mont_sqr_n_order_21(t2, t, 8); - /* t3= a^ffff = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - /* t2= a^ffff0000 = t ^ 2 ^ 16 */ - sp_521_mont_sqr_n_order_21(t2, t, 16); - /* t = a^ffffffff = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - - /* t2= a^ffffffff00000000 = t ^ 2 ^ 32 */ - sp_521_mont_sqr_n_order_21(t2, t, 32); - /* t = a^ffffffffffffffff = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - /* t2= a^ffffffffffffffff0000000000000000 = t ^ 2 ^ 64 */ - sp_521_mont_sqr_n_order_21(t2, t, 64); - /* t = a^ffffffffffffffffffffffffffffffff = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - /* t2= a^ffffffffffffffffffffffffffffffff00000000000000000000000000000000 = t ^ 2 ^ 128 */ - sp_521_mont_sqr_n_order_21(t2, t, 128); - /* t = a^ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ - sp_521_mont_mul_order_21(t, t2, t); - - /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 */ - sp_521_mont_sqr_n_order_21(t2, t, 5); - /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t * t3 */ - sp_521_mont_mul_order_21(t2, t2, t3); - - for (i=259; i>=1; i--) { - sp_521_mont_sqr_order_21(t2, t2); - if ((p521_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { - sp_521_mont_mul_order_21(t2, t2, a); - } - } - sp_521_mont_sqr_order_21(t2, t2); - sp_521_mont_mul_order_21(r, t2, a); -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */ -#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_521_calc_s_21(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; - sp_int32 c; - sp_digit* kInv = k; - - /* Conv k to Montgomery form (mod order) */ - sp_521_mul_21(k, k, p521_norm_order); - err = sp_521_mod_21(k, k, p521_order); - if (err == MP_OKAY) { - sp_521_norm_21(k); - - /* kInv = 1/k mod order */ - sp_521_mont_inv_order_21(kInv, k, tmp); - sp_521_norm_21(kInv); - - /* s = r * x + e */ - sp_521_mul_21(x, x, r); - err = sp_521_mod_21(x, x, p521_order); - } - if (err == MP_OKAY) { - sp_521_norm_21(x); - carry = sp_521_add_21(s, e, x); - sp_521_cond_sub_21(s, s, p521_order, 0 - carry); - sp_521_norm_21(s); - c = sp_521_cmp_21(s, p521_order); - sp_521_cond_sub_21(s, s, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_21(s); - - /* s = s * k^-1 mod order */ - sp_521_mont_mul_order_21(s, s, kInv); - sp_521_norm_21(s); - } - - return err; -} - -/* Sign the hash using the private key. - * e = [hash, 521 bits] from binary - * r = (k.G)->x mod order - * s = (r * x + e) / k mod order - * The hash is truncated to the first 521 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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. - */ -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ - SP_DECL_VAR(sp_digit, e, 7 * 2 * 21); - SP_DECL_VAR(sp_point_521, point, 1); - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, e, 7 * 2 * 21, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - x = e + 2 * 21; - k = e + 4 * 21; - r = e + 6 * 21; - tmp = e + 8 * 21; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_21(rng, k); - } - else { - sp_521_from_mp(k, 21, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 21U); - sp_521_norm_21(r); - c = sp_521_cmp_21(r, p521_order); - sp_521_cond_sub_21(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_21(r); - - if (!sp_521_iszero_21(r)) { - /* x is modified in calculation of s. */ - sp_521_from_mp(x, 21, priv); - /* s ptr == e ptr, e is modified in calculation of s. */ - sp_521_from_bin(e, 21, hash, (int)hashLen); - - /* Take 521 leftmost bits of hash. */ - if (hashLen == 66U) { - sp_521_rshift_21(e, e, 7); - e[20] |= ((sp_digit)hash[0]) << 13; - } - - err = sp_521_calc_s_21(s, r, k, x, e, tmp); - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (!sp_521_iszero_21(s))) { - break; - } - } - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - - SP_ZEROFREE_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_digit, e, 7 * 2 * 21, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sign_521_ctx { - int state; - union { - sp_521_ecc_mulmod_21_ctx mulmod_ctx; - sp_521_mont_inv_order_21_ctx mont_inv_order_ctx; - }; - sp_digit e[2*21]; - sp_digit x[2*21]; - sp_digit k[2*21]; - sp_digit r[2*21]; - sp_digit tmp[3 * 2*21]; - sp_point_521 point; - sp_digit* s; - sp_digit* kInv; - int i; -} sp_ecc_sign_521_ctx; - -int sp_ecc_sign_521_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_521_ctx* ctx = (sp_ecc_sign_521_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - ctx->s = ctx->e; - ctx->kInv = ctx->k; - - ctx->i = SP_ECC_MAX_SIG_GEN; - ctx->state = 1; - break; - case 1: /* GEN */ - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_21(rng, ctx->k); - } - else { - sp_521_from_mp(ctx->k, 21, km); - mp_zero(km); - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - break; - case 2: /* MULMOD */ - err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &p521_base, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - ctx->state = 3; - } - break; - case 3: /* MODORDER */ - { - sp_int32 c; - /* r = point->x mod order */ - XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 21U); - sp_521_norm_21(ctx->r); - c = sp_521_cmp_21(ctx->r, p521_order); - sp_521_cond_sub_21(ctx->r, ctx->r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_21(ctx->r); - - if (hashLen > 66U) { - hashLen = 66U; - } - sp_521_from_mp(ctx->x, 21, priv); - sp_521_from_bin(ctx->e, 21, hash, (int)hashLen); - if (hashLen == 66U) { - sp_521_rshift_21(ctx->e, ctx->e, 7); - ctx->e[20] |= ((sp_digit)hash[0]) << 13; - } - ctx->state = 4; - break; - } - case 4: /* KMODORDER */ - /* Conv k to Montgomery form (mod order) */ - sp_521_mul_21(ctx->k, ctx->k, p521_norm_order); - err = sp_521_mod_21(ctx->k, ctx->k, p521_order); - if (err == MP_OKAY) { - sp_521_norm_21(ctx->k); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 5; - } - break; - case 5: /* KINV */ - /* kInv = 1/k mod order */ - err = sp_521_mont_inv_order_21_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); - if (err == MP_OKAY) { - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 6; - } - break; - case 6: /* KINVNORM */ - sp_521_norm_21(ctx->kInv); - ctx->state = 7; - break; - case 7: /* R */ - /* s = r * x + e */ - sp_521_mul_21(ctx->x, ctx->x, ctx->r); - ctx->state = 8; - break; - case 8: /* S1 */ - err = sp_521_mod_21(ctx->x, ctx->x, p521_order); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* S2 */ - { - sp_digit carry; - sp_int32 c; - sp_521_norm_21(ctx->x); - carry = sp_521_add_21(ctx->s, ctx->e, ctx->x); - sp_521_cond_sub_21(ctx->s, ctx->s, - p521_order, 0 - carry); - sp_521_norm_21(ctx->s); - c = sp_521_cmp_21(ctx->s, p521_order); - sp_521_cond_sub_21(ctx->s, ctx->s, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_21(ctx->s); - - /* s = s * k^-1 mod order */ - sp_521_mont_mul_order_21(ctx->s, ctx->s, ctx->kInv); - sp_521_norm_21(ctx->s); - - /* Check that signature is usable. */ - if (sp_521_iszero_21(ctx->s) == 0) { - ctx->state = 10; - break; - } - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - ctx->i = 1; - #endif - - /* not usable gen, try again */ - ctx->i--; - if (ctx->i == 0) { - err = RNG_FAILURE_E; - } - ctx->state = 1; - break; - } - case 10: /* RES */ - err = sp_521_to_mp(ctx->r, rm); - if (err == MP_OKAY) { - err = sp_521_to_mp(ctx->s, sm); - } - break; - } - - if (err == MP_OKAY && ctx->state != 10) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 21U); - XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 21U); - XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 21U); - XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 21U); - XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 21U); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_SIGN */ - -#ifndef WOLFSSL_SP_SMALL -static const char sp_521_tab32_21[32] = { - 1, 10, 2, 11, 14, 22, 3, 30, - 12, 15, 17, 19, 23, 26, 4, 31, - 9, 13, 21, 29, 16, 18, 25, 8, - 20, 28, 24, 7, 27, 6, 5, 32}; - -static int sp_521_num_bits_25_21(sp_digit v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return sp_521_tab32_21[(word32)(v*0x07C4ACDD) >> 27]; -} - -static int sp_521_num_bits_21(const sp_digit* a) -{ - int i; - int r = 0; - - for (i = 20; i >= 0; i--) { - if (a[i] != 0) { - r = sp_521_num_bits_25_21(a[i]); - r += i * 25; - break; - } - } - - return r; -} - -/* 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. - * @return MEMEORY_E when dynamic memory allocation fails. - */ -static int sp_521_mod_inv_21(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int err = MP_OKAY; - SP_DECL_VAR(sp_digit, u, 21 * 4); - sp_digit* v = NULL; - sp_digit* b = NULL; - sp_digit* d = NULL; - int ut; - int vt; - - SP_ALLOC_VAR(sp_digit, u, 21 * 4, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - v = u + 21; - b = u + 2 * 21; - d = u + 3 * 21; - - XMEMCPY(u, m, sizeof(sp_digit) * 21); - XMEMCPY(v, a, sizeof(sp_digit) * 21); - - ut = sp_521_num_bits_21(u); - vt = sp_521_num_bits_21(v); - - XMEMSET(b, 0, sizeof(sp_digit) * 21); - if ((v[0] & 1) == 0) { - sp_521_rshift1_21(v, v); - XMEMCPY(d, m, sizeof(sp_digit) * 21); - d[0]++; - sp_521_rshift1_21(d, d); - vt--; - - while ((v[0] & 1) == 0) { - sp_521_rshift1_21(v, v); - if (d[0] & 1) - sp_521_add_21(d, d, m); - sp_521_rshift1_21(d, d); - vt--; - } - } - else { - XMEMSET(d+1, 0, sizeof(sp_digit) * (21 - 1)); - d[0] = 1; - } - - while (ut > 1 && vt > 1) { - if ((ut > vt) || ((ut == vt) && - (sp_521_cmp_21(u, v) >= 0))) { - sp_521_sub_21(u, u, v); - sp_521_norm_21(u); - - sp_521_sub_21(b, b, d); - sp_521_norm_21(b); - if (b[20] < 0) - sp_521_add_21(b, b, m); - sp_521_norm_21(b); - ut = sp_521_num_bits_21(u); - - do { - sp_521_rshift1_21(u, u); - if (b[0] & 1) - sp_521_add_21(b, b, m); - sp_521_rshift1_21(b, b); - ut--; - } - while (ut > 0 && (u[0] & 1) == 0); - } - else { - sp_521_sub_21(v, v, u); - sp_521_norm_21(v); - - sp_521_sub_21(d, d, b); - sp_521_norm_21(d); - if (d[20] < 0) - sp_521_add_21(d, d, m); - sp_521_norm_21(d); - vt = sp_521_num_bits_21(v); - - do { - sp_521_rshift1_21(v, v); - if (d[0] & 1) - sp_521_add_21(d, d, m); - sp_521_rshift1_21(d, d); - vt--; - } - while (vt > 0 && (v[0] & 1) == 0); - } - } - - if (ut == 1) - XMEMCPY(r, b, sizeof(sp_digit) * 21); - else - XMEMCPY(r, d, sizeof(sp_digit) * 21); - } - SP_FREE_VAR(u, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#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_521_add_points_21(sp_point_521* p1, const sp_point_521* p2, - sp_digit* tmp) -{ - - sp_521_proj_point_add_21(p1, p1, p2, tmp); - if (sp_521_iszero_21(p1->z)) { - if (sp_521_iszero_21(p1->x) && sp_521_iszero_21(p1->y)) { - sp_521_proj_point_dbl_21(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; - p1->x[15] = 0; - p1->x[16] = 0; - p1->x[17] = 0; - p1->x[18] = 0; - p1->x[19] = 0; - p1->x[20] = 0; - XMEMCPY(p1->z, p521_norm_mod, sizeof(p521_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 Temporary number. - * heap Heap to use for allocation. - * returns MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -static int sp_521_calc_vfy_point_21(sp_point_521* p1, sp_point_521* p2, - sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) -{ - int err; - -#ifndef WOLFSSL_SP_SMALL - err = sp_521_mod_inv_21(s, s, p521_order); - if (err == MP_OKAY) -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_521_mul_21(s, s, p521_norm_order); - err = sp_521_mod_21(s, s, p521_order); - } - if (err == MP_OKAY) { - sp_521_norm_21(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_521_mont_inv_order_21(s, s, tmp); - sp_521_mont_mul_order_21(u1, u1, s); - sp_521_mont_mul_order_21(u2, u2, s); - } -#else - { - sp_521_mont_mul_order_21(u1, u1, s); - sp_521_mont_mul_order_21(u2, u2, s); - } -#endif /* WOLFSSL_SP_SMALL */ - { - err = sp_521_ecc_mulmod_base_21(p1, u1, 0, 0, heap); - } - } - if ((err == MP_OKAY) && sp_521_iszero_21(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_21(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_521_iszero_21(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - sp_521_add_points_21(p1, p2, tmp); - } - - return err; -} - -#ifdef HAVE_ECC_VERIFY -/* Verify the signature values with the hash and public key. - * e = Truncate(hash, 521) - * u1 = e/s mod order - * u2 = r/s mod order - * r == (u1.G + u2.Q)->x mod order - * Optimization: Leave point in projective form. - * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') - * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' - * The hash is truncated to the first 521 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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 MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_verify_521(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) -{ - SP_DECL_VAR(sp_digit, u1, 18 * 21); - SP_DECL_VAR(sp_point_521, p1, 2); - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, u1, 18 * 21, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p1, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - u2 = u1 + 2 * 21; - s = u1 + 4 * 21; - tmp = u1 + 6 * 21; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 21, hash, (int)hashLen); - sp_521_from_mp(u2, 21, rm); - sp_521_from_mp(s, 21, sm); - sp_521_from_mp(p2->x, 21, pX); - sp_521_from_mp(p2->y, 21, pY); - sp_521_from_mp(p2->z, 21, pZ); - - if (hashLen == 66U) { - sp_521_rshift_21(u1, u1, 7); - u1[20] |= ((sp_digit)hash[0]) << 13; - } - - err = sp_521_calc_vfy_point_21(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 21, rm); - err = sp_521_mod_mul_norm_21(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_21(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_21(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 21, rm); - carry = sp_521_add_21(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_21(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_21(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_21(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_21(p1->x, u1) == 0); - } - } - } - - SP_FREE_VAR(p1, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(u1, heap, DYNAMIC_TYPE_ECC); - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_verify_521_ctx { - int state; - union { - sp_521_ecc_mulmod_21_ctx mulmod_ctx; - sp_521_mont_inv_order_21_ctx mont_inv_order_ctx; - sp_521_proj_point_dbl_21_ctx dbl_ctx; - sp_521_proj_point_add_21_ctx add_ctx; - }; - sp_digit u1[2*21]; - sp_digit u2[2*21]; - sp_digit s[2*21]; - sp_digit tmp[2*21 * 6]; - sp_point_521 p1; - sp_point_521 p2; -} sp_ecc_verify_521_ctx; - -int sp_ecc_verify_521_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_521_ctx* ctx = (sp_ecc_verify_521_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_verify_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(ctx->u1, 21, hash, (int)hashLen); - sp_521_from_mp(ctx->u2, 21, rm); - sp_521_from_mp(ctx->s, 21, sm); - sp_521_from_mp(ctx->p2.x, 21, pX); - sp_521_from_mp(ctx->p2.y, 21, pY); - sp_521_from_mp(ctx->p2.z, 21, pZ); - if (hashLen == 66U) { - sp_521_rshift_21(ctx->u1, ctx->u1, 7); - ctx->u1[20] |= ((sp_digit)hash[0]) << 13; - } - ctx->state = 1; - break; - case 1: /* NORMS0 */ - sp_521_mul_21(ctx->s, ctx->s, p521_norm_order); - err = sp_521_mod_21(ctx->s, ctx->s, p521_order); - if (err == MP_OKAY) - ctx->state = 2; - break; - case 2: /* NORMS1 */ - sp_521_norm_21(ctx->s); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 3; - break; - case 3: /* NORMS2 */ - err = sp_521_mont_inv_order_21_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 4; - } - break; - case 4: /* NORMS3 */ - sp_521_mont_mul_order_21(ctx->u1, ctx->u1, ctx->s); - ctx->state = 5; - break; - case 5: /* NORMS4 */ - sp_521_mont_mul_order_21(ctx->u2, ctx->u2, ctx->s); - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 6; - break; - case 6: /* MULBASE */ - err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p521_base, ctx->u1, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_521_iszero_21(ctx->p1.z)) { - ctx->p1.infinity = 1; - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 7; - } - break; - case 7: /* MULMOD */ - err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_521_iszero_21(ctx->p2.z)) { - ctx->p2.infinity = 1; - } - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 8; - } - break; - case 8: /* ADD */ - err = sp_521_proj_point_add_21_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* MONT */ - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(ctx->u2, 21, rm); - err = sp_521_mod_mul_norm_21(ctx->u2, ctx->u2, p521_mod); - if (err == MP_OKAY) - ctx->state = 10; - break; - case 10: /* SQR */ - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_21(ctx->p1.z, ctx->p1.z, p521_mod, p521_mp_mod); - ctx->state = 11; - break; - case 11: /* MUL */ - sp_521_mont_mul_21(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, p521_mp_mod); - ctx->state = 12; - break; - case 12: /* RES */ - { - sp_int32 c = 0; - err = MP_OKAY; /* math okay, now check result */ - *res = (int)(sp_521_cmp_21(ctx->p1.x, ctx->u1) == 0); - if (*res == 0) { - sp_digit carry; - - /* Reload r and add order. */ - sp_521_from_mp(ctx->u2, 21, rm); - carry = sp_521_add_21(ctx->u2, ctx->u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_21(ctx->u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_21(ctx->u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_21(ctx->u2, ctx->u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_521_mont_mul_21(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, - p521_mp_mod); - *res = (int)(sp_521_cmp_21(ctx->p1.x, ctx->u1) == 0); - } - } - break; - } - } /* switch */ - - if (err == MP_OKAY && ctx->state != 12) { - err = FP_WOULDBLOCK; - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_VERIFY */ - -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* Check that the x and y ordinates 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_521_ecc_is_point_21(const sp_point_521* point, - void* heap) -{ - SP_DECL_VAR(sp_digit, t1, 21 * 4); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 21 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 21; - - /* y^2 - x^3 - a.x = b */ - sp_521_sqr_21(t1, point->y); - (void)sp_521_mod_21(t1, t1, p521_mod); - sp_521_sqr_21(t2, point->x); - (void)sp_521_mod_21(t2, t2, p521_mod); - sp_521_mul_21(t2, t2, point->x); - (void)sp_521_mod_21(t2, t2, p521_mod); - sp_521_mont_sub_21(t1, t1, t2, p521_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - sp_521_mont_add_21(t1, t1, point->x, p521_mod); - sp_521_mont_add_21(t1, t1, point->x, p521_mod); - sp_521_mont_add_21(t1, t1, point->x, p521_mod); - - - if (sp_521_cmp_21(t1, p521_b) != 0) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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_521(const mp_int* pX, const mp_int* pY) -{ - SP_DECL_VAR(sp_point_521, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, pub, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(pub->x, 21, pX); - sp_521_from_mp(pub->y, 21, pY); - sp_521_from_bin(pub->z, 21, one, (int)sizeof(one)); - - err = sp_521_ecc_is_point_21(pub, NULL); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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_521(const mp_int* pX, const mp_int* pY, - const mp_int* privm, void* heap) -{ - SP_DECL_VAR(sp_digit, priv, 21); - SP_DECL_VAR(sp_point_521, pub, 2); - sp_point_521* 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) > 521) || - (mp_count_bits(pY) > 521) || - ((privm != NULL) && (mp_count_bits(privm) > 521)))) { - err = ECC_OUT_OF_RANGE_E; - } - - SP_ALLOC_VAR(sp_digit, priv, 21, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, pub, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - p = pub + 1; - - sp_521_from_mp(pub->x, 21, pX); - sp_521_from_mp(pub->y, 21, pY); - sp_521_from_bin(pub->z, 21, one, (int)sizeof(one)); - if (privm) - sp_521_from_mp(priv, 21, privm); - - /* Check point at infinitiy. */ - if ((sp_521_iszero_21(pub->x) != 0) && - (sp_521_iszero_21(pub->y) != 0)) { - err = ECC_INF_E; - } - } - - /* Check range of X and Y */ - if ((err == MP_OKAY) && - ((sp_521_cmp_21(pub->x, p521_mod) >= 0) || - (sp_521_cmp_21(pub->y, p521_mod) >= 0))) { - err = ECC_OUT_OF_RANGE_E; - } - - if (err == MP_OKAY) { - /* Check point is on curve */ - err = sp_521_ecc_is_point_21(pub, heap); - } - - if (err == MP_OKAY) { - /* Point * order = infinity */ - err = sp_521_ecc_mulmod_21(p, pub, p521_order, 1, 1, heap); - } - /* Check result is infinity */ - if ((err == MP_OKAY) && ((sp_521_iszero_21(p->x) == 0) || - (sp_521_iszero_21(p->y) == 0))) { - err = ECC_INF_E; - } - - if (privm) { - if (err == MP_OKAY) { - /* Base * private = point */ - err = sp_521_ecc_mulmod_base_21(p, priv, 1, 1, heap); - } - /* Check result is public key */ - if ((err == MP_OKAY) && - ((sp_521_cmp_21(p->x, pub->x) != 0) || - (sp_521_cmp_21(p->y, pub->y) != 0))) { - err = ECC_PRIV_KEY_E; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL -/* Add two projective EC points together. - * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) - * - * pX First EC point's X ordinate. - * pY First EC point's Y ordinate. - * pZ First EC point's Z ordinate. - * qX Second EC point's X ordinate. - * qY Second EC point's Y ordinate. - * qZ Second EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_proj_add_point_521(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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 21 * 6); - SP_DECL_VAR(sp_point_521, p, 2); - sp_point_521* q = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 21 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p, 2, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - q = p + 1; - - sp_521_from_mp(p->x, 21, pX); - sp_521_from_mp(p->y, 21, pY); - sp_521_from_mp(p->z, 21, pZ); - sp_521_from_mp(q->x, 21, qX); - sp_521_from_mp(q->y, 21, qY); - sp_521_from_mp(q->z, 21, qZ); - p->infinity = sp_521_iszero_21(p->x) & - sp_521_iszero_21(p->y); - q->infinity = sp_521_iszero_21(q->x) & - sp_521_iszero_21(q->y); - - sp_521_proj_point_add_21(p, p, q, tmp); - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Double a projective EC point. - * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_proj_dbl_point_521(mp_int* pX, mp_int* pY, mp_int* pZ, - mp_int* rX, mp_int* rY, mp_int* rZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 21 * 2); - SP_DECL_VAR(sp_point_521, p, 1); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 21 * 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(p->x, 21, pX); - sp_521_from_mp(p->y, 21, pY); - sp_521_from_mp(p->z, 21, pZ); - p->infinity = sp_521_iszero_21(p->x) & - sp_521_iszero_21(p->y); - - sp_521_proj_point_dbl_21(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Map a projective EC point to affine in place. - * pZ will be one. - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_map_521(mp_int* pX, mp_int* pY, mp_int* pZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 21 * 5); - SP_DECL_VAR(sp_point_521, p, 1); - int err = MP_OKAY; - - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 21 * 5, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(p->x, 21, pX); - sp_521_from_mp(p->y, 21, pY); - sp_521_from_mp(p->z, 21, pZ); - p->infinity = sp_521_iszero_21(p->x) & - sp_521_iszero_21(p->y); - - sp_521_map_21(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(p->x, pX); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, pY); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, pZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifdef HAVE_COMP_KEY -/* Square root power for the P521 curve. */ -static const word32 p521_sqrt_power[17] = { - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000080 -}; - -/* Find the square root of a number mod the prime of the curve. - * - * y The number to operate on and the result. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -static int sp_521_mont_sqrt_21(sp_digit* y) -{ - SP_DECL_VAR(sp_digit, t, 2 * 21); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, t, 2 * 21, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - - { - int i; - - XMEMCPY(t, y, sizeof(sp_digit) * 21); - for (i=518; i>=0; i--) { - sp_521_mont_sqr_21(t, t, p521_mod, p521_mp_mod); - if (p521_sqrt_power[i / 32] & ((sp_digit)1 << (i % 32))) - sp_521_mont_mul_21(t, t, y, p521_mod, p521_mp_mod); - } - XMEMCPY(y, t, sizeof(sp_digit) * 21); - } - } - - SP_FREE_VAR(t, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - - -/* Uncompress the point given the X ordinate. - * - * xm X ordinate. - * odd Whether the Y ordinate is odd. - * ym Calculated Y ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_uncompress_521(mp_int* xm, int odd, mp_int* ym) -{ - SP_DECL_VAR(sp_digit, x, 4 * 21); - sp_digit* y = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, x, 4 * 21, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - y = x + 2 * 21; - - sp_521_from_mp(x, 21, xm); - err = sp_521_mod_mul_norm_21(x, x, p521_mod); - } - if (err == MP_OKAY) { - /* y = x^3 */ - { - sp_521_mont_sqr_21(y, x, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(y, y, x, p521_mod, p521_mp_mod); - } - /* y = x^3 - 3x */ - sp_521_mont_sub_21(y, y, x, p521_mod); - sp_521_mont_sub_21(y, y, x, p521_mod); - sp_521_mont_sub_21(y, y, x, p521_mod); - /* y = x^3 - 3x + b */ - err = sp_521_mod_mul_norm_21(x, p521_b, p521_mod); - } - if (err == MP_OKAY) { - sp_521_mont_add_21(y, y, x, p521_mod); - /* y = sqrt(x^3 - 3x + b) */ - err = sp_521_mont_sqrt_21(y); - } - if (err == MP_OKAY) { - XMEMSET(y + 21, 0, 21U * sizeof(sp_digit)); - sp_521_mont_reduce_21(y, p521_mod, p521_mp_mod); - if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { - sp_521_mont_sub_21(y, p521_mod, y, p521_mod); - } - - err = sp_521_to_mp(y, ym); - } - - SP_FREE_VAR(x, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* WOLFSSL_SP_521 */ -#ifdef WOLFCRYPT_HAVE_SAKKE -#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) -{ - sp_int64 t0 = ((sp_int64)a[ 0]) * b[ 0]; - sp_int64 t1 = ((sp_int64)a[ 0]) * b[ 1] - + ((sp_int64)a[ 1]) * b[ 0]; - sp_int64 t2 = ((sp_int64)a[ 0]) * b[ 2] - + ((sp_int64)a[ 1]) * b[ 1] - + ((sp_int64)a[ 2]) * b[ 0]; - sp_int64 t3 = ((sp_int64)a[ 0]) * b[ 3] - + ((sp_int64)a[ 1]) * b[ 2] - + ((sp_int64)a[ 2]) * b[ 1] - + ((sp_int64)a[ 3]) * b[ 0]; - sp_int64 t4 = ((sp_int64)a[ 0]) * b[ 4] - + ((sp_int64)a[ 1]) * b[ 3] - + ((sp_int64)a[ 2]) * b[ 2] - + ((sp_int64)a[ 3]) * b[ 1] - + ((sp_int64)a[ 4]) * b[ 0]; - sp_int64 t5 = ((sp_int64)a[ 0]) * b[ 5] - + ((sp_int64)a[ 1]) * b[ 4] - + ((sp_int64)a[ 2]) * b[ 3] - + ((sp_int64)a[ 3]) * b[ 2] - + ((sp_int64)a[ 4]) * b[ 1] - + ((sp_int64)a[ 5]) * b[ 0]; - sp_int64 t6 = ((sp_int64)a[ 0]) * b[ 6] - + ((sp_int64)a[ 1]) * b[ 5] - + ((sp_int64)a[ 2]) * b[ 4] - + ((sp_int64)a[ 3]) * b[ 3] - + ((sp_int64)a[ 4]) * b[ 2] - + ((sp_int64)a[ 5]) * b[ 1] - + ((sp_int64)a[ 6]) * b[ 0]; - sp_int64 t7 = ((sp_int64)a[ 1]) * b[ 6] - + ((sp_int64)a[ 2]) * b[ 5] - + ((sp_int64)a[ 3]) * b[ 4] - + ((sp_int64)a[ 4]) * b[ 3] - + ((sp_int64)a[ 5]) * b[ 2] - + ((sp_int64)a[ 6]) * b[ 1]; - sp_int64 t8 = ((sp_int64)a[ 2]) * b[ 6] - + ((sp_int64)a[ 3]) * b[ 5] - + ((sp_int64)a[ 4]) * b[ 4] - + ((sp_int64)a[ 5]) * b[ 3] - + ((sp_int64)a[ 6]) * b[ 2]; - sp_int64 t9 = ((sp_int64)a[ 3]) * b[ 6] - + ((sp_int64)a[ 4]) * b[ 5] - + ((sp_int64)a[ 5]) * b[ 4] - + ((sp_int64)a[ 6]) * b[ 3]; - sp_int64 t10 = ((sp_int64)a[ 4]) * b[ 6] - + ((sp_int64)a[ 5]) * b[ 5] - + ((sp_int64)a[ 6]) * b[ 4]; - sp_int64 t11 = ((sp_int64)a[ 5]) * b[ 6] - + ((sp_int64)a[ 6]) * b[ 5]; - sp_int64 t12 = ((sp_int64)a[ 6]) * b[ 6]; - - t1 += t0 >> 25; r[ 0] = (sp_digit)(t0 & 0x1ffffff); - t2 += t1 >> 25; r[ 1] = (sp_digit)(t1 & 0x1ffffff); - t3 += t2 >> 25; r[ 2] = (sp_digit)(t2 & 0x1ffffff); - t4 += t3 >> 25; r[ 3] = (sp_digit)(t3 & 0x1ffffff); - t5 += t4 >> 25; r[ 4] = (sp_digit)(t4 & 0x1ffffff); - t6 += t5 >> 25; r[ 5] = (sp_digit)(t5 & 0x1ffffff); - t7 += t6 >> 25; r[ 6] = (sp_digit)(t6 & 0x1ffffff); - t8 += t7 >> 25; r[ 7] = (sp_digit)(t7 & 0x1ffffff); - t9 += t8 >> 25; r[ 8] = (sp_digit)(t8 & 0x1ffffff); - t10 += t9 >> 25; r[ 9] = (sp_digit)(t9 & 0x1ffffff); - t11 += t10 >> 25; r[10] = (sp_digit)(t10 & 0x1ffffff); - t12 += t11 >> 25; r[11] = (sp_digit)(t11 & 0x1ffffff); - r[13] = (sp_digit)(t12 >> 25); - r[12] = (sp_digit)(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) -{ - sp_int64 t0 = ((sp_int64)a[ 0]) * a[ 0]; - sp_int64 t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2; - sp_int64 t2 = (((sp_int64)a[ 0]) * a[ 2]) * 2 - + ((sp_int64)a[ 1]) * a[ 1]; - sp_int64 t3 = (((sp_int64)a[ 0]) * a[ 3] - + ((sp_int64)a[ 1]) * a[ 2]) * 2; - sp_int64 t4 = (((sp_int64)a[ 0]) * a[ 4] - + ((sp_int64)a[ 1]) * a[ 3]) * 2 - + ((sp_int64)a[ 2]) * a[ 2]; - sp_int64 t5 = (((sp_int64)a[ 0]) * a[ 5] - + ((sp_int64)a[ 1]) * a[ 4] - + ((sp_int64)a[ 2]) * a[ 3]) * 2; - sp_int64 t6 = (((sp_int64)a[ 0]) * a[ 6] - + ((sp_int64)a[ 1]) * a[ 5] - + ((sp_int64)a[ 2]) * a[ 4]) * 2 - + ((sp_int64)a[ 3]) * a[ 3]; - sp_int64 t7 = (((sp_int64)a[ 1]) * a[ 6] - + ((sp_int64)a[ 2]) * a[ 5] - + ((sp_int64)a[ 3]) * a[ 4]) * 2; - sp_int64 t8 = (((sp_int64)a[ 2]) * a[ 6] - + ((sp_int64)a[ 3]) * a[ 5]) * 2 - + ((sp_int64)a[ 4]) * a[ 4]; - sp_int64 t9 = (((sp_int64)a[ 3]) * a[ 6] - + ((sp_int64)a[ 4]) * a[ 5]) * 2; - sp_int64 t10 = (((sp_int64)a[ 4]) * a[ 6]) * 2 - + ((sp_int64)a[ 5]) * a[ 5]; - sp_int64 t11 = (((sp_int64)a[ 5]) * a[ 6]) * 2; - sp_int64 t12 = ((sp_int64)a[ 6]) * a[ 6]; - - t1 += t0 >> 25; r[ 0] = (sp_digit)(t0 & 0x1ffffff); - t2 += t1 >> 25; r[ 1] = (sp_digit)(t1 & 0x1ffffff); - t3 += t2 >> 25; r[ 2] = (sp_digit)(t2 & 0x1ffffff); - t4 += t3 >> 25; r[ 3] = (sp_digit)(t3 & 0x1ffffff); - t5 += t4 >> 25; r[ 4] = (sp_digit)(t4 & 0x1ffffff); - t6 += t5 >> 25; r[ 5] = (sp_digit)(t5 & 0x1ffffff); - t7 += t6 >> 25; r[ 6] = (sp_digit)(t6 & 0x1ffffff); - t8 += t7 >> 25; r[ 7] = (sp_digit)(t7 & 0x1ffffff); - t9 += t8 >> 25; r[ 8] = (sp_digit)(t8 & 0x1ffffff); - t10 += t9 >> 25; r[ 9] = (sp_digit)(t9 & 0x1ffffff); - t11 += t10 >> 25; r[10] = (sp_digit)(t10 & 0x1ffffff); - t12 += t11 >> 25; r[11] = (sp_digit)(t11 & 0x1ffffff); - r[13] = (sp_digit)(t12 >> 25); - r[12] = (sp_digit)(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 imax; - int k; - sp_uint64 c; - sp_uint64 lo; - - c = ((sp_uint64)a[41]) * b[41]; - r[83] = (sp_digit)(c >> 25); - c &= 0x1ffffff; - for (k = 81; k >= 0; k--) { - if (k >= 42) { - i = k - 41; - imax = 41; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint64)a[i]) * b[k - i]; - } - c += lo >> 25; - r[k + 2] += (sp_digit)(c >> 25); - r[k + 1] = (sp_digit)(c & 0x1ffffff); - c = lo & 0x1ffffff; - } - r[0] = (sp_digit)c; -} - -/* 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 imax; - int k; - sp_uint64 c; - sp_uint64 t; - - c = ((sp_uint64)a[41]) * a[41]; - r[83] = (sp_digit)(c >> 25); - c = (c & 0x1ffffff) << 25; - for (k = 81; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint64)a[i]) * a[i]; - i++; - } - if (k < 41) { - imax = k; - } - else { - imax = 41; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint64)a[i]) * a[k - i]; - } - c += t * 2; - - 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 Montgomery 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 Montgomery 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, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0 - }, - /* 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, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0 - }, - /* 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, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; - -/* Normalize the values in each word to 25 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_1024_norm_41(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 40; 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; - } -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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 - sp_int64 tb = b; - sp_int64 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 - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 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 */ -} - -/* 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_84(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int64 tb = b; - sp_int64 t = 0; - int i; - - for (i = 0; i < 84; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1ffffff); - t >>= 25; - } - r[84] = (sp_digit)t; -#else - sp_int64 tb = b; - sp_int64 t = 0; - sp_digit t2; - sp_int64 p[4]; - int i; - - for (i = 0; i < 84; 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; - } - r[84] = (sp_digit)(t & 0x1ffffff); -#endif /* WOLFSSL_SP_SMALL */ -} - -#ifdef 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) -{ - int i; - - for (i = 0; i < 42; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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) -{ - 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 /* WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_1024_rshift_42(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<41; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (25 - n))) & 0x1ffffff); - } -#else - for (i=0; i<40; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (25 - n)) & 0x1ffffff); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (25 - n)) & 0x1ffffff); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (25 - n)) & 0x1ffffff); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (25 - n)) & 0x1ffffff); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (25 - n)) & 0x1ffffff); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (25 - n)) & 0x1ffffff); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (25 - n)) & 0x1ffffff); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (25 - n)) & 0x1ffffff); - } - r[40] = (a[40] >> n) | (sp_digit)((a[41] << (25 - n)) & 0x1ffffff); -#endif /* WOLFSSL_SP_SMALL */ - r[41] = a[41] >> n; -} - -static WC_INLINE sp_digit sp_1024_div_word_42(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int64 d = ((sp_int64)d1 << 25) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int64 d = ((sp_int64)d1 << 25) + d0; - sp_uint32 lo = (sp_uint32)d; - sp_digit hi = (sp_digit)(d >> 32); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int64 d = ((sp_int64)d1 << 25) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 25); - sp_digit t0 = (sp_digit)(d & 0x1ffffff); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int64 m; - - r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - t1 -= dv & (0 - r); - for (i = 23; i >= 1; i--) { - t1 += t1 + (((sp_uint32)t0 >> 24) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 25); - m = d - ((sp_int64)r * div); - r += (sp_digit)(m >> 50) - (sp_digit)(d >> 50); - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - - m = d - ((sp_int64)r * div); - sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31); - r += sign * t2; - return r; -#else - sp_int64 d = ((sp_int64)d1 << 25) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 10) + 1; - - t = (sp_digit)(d >> 20); - t = (t / dv) << 10; - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)(d >> 5); - t = t / (dv << 5); - r += t; - d -= (sp_int64)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int64)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_1024_word_div_word_42(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint32)(div - d) >> 31); -#endif -} -/* 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_1024_div_42(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 42 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 42 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 84 + 1; - sd = t2 + 42 + 1; - - sp_1024_mul_d_42(sd, d, (sp_digit)1 << 1); - sp_1024_mul_d_84(t1, a, (sp_digit)1 << 1); - dv = sd[40]; - t1[41 + 41] += t1[41 + 41 - 1] >> 25; - t1[41 + 41 - 1] &= 0x1ffffff; - for (i=41; i>=0; i--) { - r1 = sp_1024_div_word_42(t1[41 + i], t1[41 + i - 1], dv); - - sp_1024_mul_d_42(t2, sd, r1); - (void)sp_1024_sub_42(&t1[i], &t1[i], t2); - sp_1024_norm_41(&t1[i]); - t1[41 + i] += t1[41 + i - 1] >> 25; - t1[41 + i - 1] &= 0x1ffffff; - r1 = sp_1024_div_word_42(-t1[41 + i], -t1[41 + i - 1], dv); - r1 -= t1[41 + i]; - sp_1024_mul_d_42(t2, sd, 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 = sp_1024_word_div_word_42(t1[41 - 1], dv); - - sp_1024_mul_d_42(t2, sd, r1); - 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, sd, r[40] >> 31); - - sp_1024_norm_41(r); - sp_1024_rshift_42(r, r, 1); - r[41] = 0; - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 Montgomery 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - (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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) -/* 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - /* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else - /* Clear point data if requested. */ - if ((p != NULL) && clear) { - 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 i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 24); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 24); - } -#elif DIGIT_BIT > 25 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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) * 41); - r->used = 41; - mp_clamp(r); -#elif DIGIT_BIT < 25 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 41; 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 < 41; 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]) & ~(((sp_digit)0 - r) >> 24); - } -#else - int i; - - r |= (a[41] - b[41]) & (0 - (sp_digit)1); - r |= (a[40] - b[40]) & ~(((sp_digit)0 - r) >> 24); - for (i = 32; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 24); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 24); - } -#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 - sp_int64 tb = b; - sp_int64 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 40; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1ffffff); - t[1] += t[0] >> 25; - r[i+1] = (sp_digit)(t[1] & 0x1ffffff); - t[2] += t[1] >> 25; - r[i+2] = (sp_digit)(t[2] & 0x1ffffff); - t[3] += t[2] >> 25; - r[i+3] = (sp_digit)(t[3] & 0x1ffffff); - t[0] = t[3] >> 25; - } - t[0] += (tb * a[40]) + r[40]; - t[1] = (tb * a[41]) + r[41]; - r[40] = (sp_digit)(t[0] & 0x1ffffff); - t[1] += t[0] >> 25; - r[41] = (sp_digit)(t[1] & 0x1ffffff); - r[42] += (sp_digit)(t[1] >> 25); -#else - sp_int64 tb = b; - sp_int64 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 bits. - * - * 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[41] += a[40] >> 25; a[40] &= 0x1ffffff; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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; - sp_uint32 n; - - n = a[40] >> 24; - for (i = 0; i < 40; i++) { - n += (sp_uint32)a[41 + i] << 1; - r[i] = (sp_digit)(n & 0x1ffffff); - n >>= 25; - } - n += (sp_uint32)a[81] << 1; - r[40] = n; -#else - sp_uint32 n; - int i; - - n = (sp_uint32)a[40]; - n = n >> 24U; - for (i = 0; i < 40; i += 8) { - n += (sp_uint32)a[i+41] << 1U; r[i+0] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+42] << 1U; r[i+1] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+43] << 1U; r[i+2] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+44] << 1U; r[i+3] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+45] << 1U; r[i+4] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+46] << 1U; r[i+5] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+47] << 1U; r[i+6] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - n += (sp_uint32)a[i+48] << 1U; r[i+7] = (sp_digit)(n & 0x1ffffff); n >>= 25U; - } - n += (sp_uint32)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_digit over; - - sp_1024_norm_42(a + 41); - - if (mp != 1) { - for (i=0; i<40; i++) { - mu = (sp_digit)((a[i] * mp) & 0x1ffffff); - sp_1024_mul_add_42(a+i, m, mu); - a[i+1] += a[i] >> 25; - } - mu = (sp_digit)((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 = (sp_digit)(a[i] & 0x1ffffff); - sp_1024_mul_add_42(a+i, m, mu); - a[i+1] += a[i] >> 25; - } - mu = (sp_digit)(a[i] & 0xffffffL); - sp_1024_mul_add_42(a+i, m, mu); - a[i+1] += a[i] >> 25; - a[i] &= 0x1ffffff; - } - sp_1024_norm_42(a + 41); - sp_1024_mont_shift_42(a, a); - over = a[40] - m[40]; - sp_1024_cond_sub_42(a, a, m, ~((over - 1) >> 31)); - sp_1024_norm_42(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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 Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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 word8 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[32 * 2 * 42]; - int i; - int j; - sp_digit* table[32]; - - for (i = 0; i < 32; i++) { - table[i] = &td[2 * 42 * i]; - } - 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; - sp_int32 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(sp_digit) * 42U); - 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, (sp_digit)~(n >> 24)); - 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(sp_digit) * 42U); - 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, (sp_digit)~(n >> 24)); - sp_1024_norm_42(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery 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) -{ - sp_digit over; - (void)sp_1024_add_42(r, a, b); - sp_1024_norm_42(r); - over = r[40] - m[40]; - sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31)); - sp_1024_norm_42(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_1024_mont_dbl_42(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_1024_add_42(r, a, a); - sp_1024_norm_42(r); - over = r[40] - m[40]; - sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31)); - sp_1024_norm_42(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_1024_mont_tpl_42(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_1024_add_42(r, a, a); - sp_1024_norm_42(r); - over = r[40] - m[40]; - sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31)); - sp_1024_norm_42(r); - (void)sp_1024_add_42(r, r, a); - sp_1024_norm_42(r); - over = r[40] - m[40]; - sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31)); - sp_1024_norm_42(r); -} - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery 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) + (sp_digit)((a[i + 1] << 24) & 0x1ffffff); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 24) & 0x1ffffff); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 24) & 0x1ffffff); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 24) & 0x1ffffff); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 24) & 0x1ffffff); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 24) & 0x1ffffff); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 24) & 0x1ffffff); - r[6] = (a[6] >> 1) + (sp_digit)((a[7] << 24) & 0x1ffffff); - r[7] = (a[7] >> 1) + (sp_digit)((a[8] << 24) & 0x1ffffff); - r[8] = (a[8] >> 1) + (sp_digit)((a[9] << 24) & 0x1ffffff); - r[9] = (a[9] >> 1) + (sp_digit)((a[10] << 24) & 0x1ffffff); - r[10] = (a[10] >> 1) + (sp_digit)((a[11] << 24) & 0x1ffffff); - r[11] = (a[11] >> 1) + (sp_digit)((a[12] << 24) & 0x1ffffff); - r[12] = (a[12] >> 1) + (sp_digit)((a[13] << 24) & 0x1ffffff); - r[13] = (a[13] >> 1) + (sp_digit)((a[14] << 24) & 0x1ffffff); - r[14] = (a[14] >> 1) + (sp_digit)((a[15] << 24) & 0x1ffffff); - r[15] = (a[15] >> 1) + (sp_digit)((a[16] << 24) & 0x1ffffff); - r[16] = (a[16] >> 1) + (sp_digit)((a[17] << 24) & 0x1ffffff); - r[17] = (a[17] >> 1) + (sp_digit)((a[18] << 24) & 0x1ffffff); - r[18] = (a[18] >> 1) + (sp_digit)((a[19] << 24) & 0x1ffffff); - r[19] = (a[19] >> 1) + (sp_digit)((a[20] << 24) & 0x1ffffff); - r[20] = (a[20] >> 1) + (sp_digit)((a[21] << 24) & 0x1ffffff); - r[21] = (a[21] >> 1) + (sp_digit)((a[22] << 24) & 0x1ffffff); - r[22] = (a[22] >> 1) + (sp_digit)((a[23] << 24) & 0x1ffffff); - r[23] = (a[23] >> 1) + (sp_digit)((a[24] << 24) & 0x1ffffff); - r[24] = (a[24] >> 1) + (sp_digit)((a[25] << 24) & 0x1ffffff); - r[25] = (a[25] >> 1) + (sp_digit)((a[26] << 24) & 0x1ffffff); - r[26] = (a[26] >> 1) + (sp_digit)((a[27] << 24) & 0x1ffffff); - r[27] = (a[27] >> 1) + (sp_digit)((a[28] << 24) & 0x1ffffff); - r[28] = (a[28] >> 1) + (sp_digit)((a[29] << 24) & 0x1ffffff); - r[29] = (a[29] >> 1) + (sp_digit)((a[30] << 24) & 0x1ffffff); - r[30] = (a[30] >> 1) + (sp_digit)((a[31] << 24) & 0x1ffffff); - r[31] = (a[31] >> 1) + (sp_digit)((a[32] << 24) & 0x1ffffff); - r[32] = (a[32] >> 1) + (sp_digit)((a[33] << 24) & 0x1ffffff); - r[33] = (a[33] >> 1) + (sp_digit)((a[34] << 24) & 0x1ffffff); - r[34] = (a[34] >> 1) + (sp_digit)((a[35] << 24) & 0x1ffffff); - r[35] = (a[35] >> 1) + (sp_digit)((a[36] << 24) & 0x1ffffff); - r[36] = (a[36] >> 1) + (sp_digit)((a[37] << 24) & 0x1ffffff); - r[37] = (a[37] >> 1) + (sp_digit)((a[38] << 24) & 0x1ffffff); - r[38] = (a[38] >> 1) + (sp_digit)((a[39] << 24) & 0x1ffffff); - r[39] = (a[39] >> 1) + (sp_digit)((a[40] << 24) & 0x1ffffff); - r[40] = (a[40] >> 1) + (sp_digit)((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_mont_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. - */ -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_mont_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); -} - -#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; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -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_mont_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 */ -/* 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; -} - -/* 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; -} - - -/* Add two Montgomery form projective points. - * - * 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_42(sp_point_1024* r, - const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*42; - sp_digit* t2 = t + 4*42; - sp_digit* t3 = t + 6*42; - sp_digit* t4 = t + 8*42; - sp_digit* t5 = t + 10*42; - - /* 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, p->x, p1024_mod, p1024_mp_mod); - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_42(t2, p->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(t4, t2, p->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, p->y, p1024_mod, p1024_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_1024_cmp_equal_42(t2, t1) & - sp_1024_cmp_equal_42(t4, t3)) { - sp_1024_proj_point_dbl_42(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* 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); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - 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); - /* Z3 = H*Z1*Z2 */ - sp_1024_mont_mul_42(z, p->z, t2, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(z, z, q->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_sqr_42(x, t4, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_42(x, x, t5, p1024_mod); - sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod); - sp_1024_mont_dbl_42(t3, y, p1024_mod); - sp_1024_mont_sub_42(x, x, t3, 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_sub_42(y, y, t5, p1024_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 42; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 42; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 42; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_1024_proj_point_add_42_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -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; - - typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_1024* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*42; - ctx->t2 = t + 4*42; - ctx->t3 = t + 6*42; - ctx->t4 = t + 8*42; - ctx->t5 = t + 10*42; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_1024_mont_sqr_42(ctx->t1, q->z, p1024_mod, p1024_mp_mod); - ctx->state = 2; - break; - case 2: - sp_1024_mont_mul_42(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); - ctx->state = 3; - break; - case 3: - sp_1024_mont_mul_42(ctx->t1, ctx->t1, p->x, p1024_mod, p1024_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_42(ctx->t2, p->z, p1024_mod, p1024_mp_mod); - ctx->state = 5; - break; - case 5: - sp_1024_mont_mul_42(ctx->t4, ctx->t2, p->z, p1024_mod, p1024_mp_mod); - ctx->state = 6; - break; - case 6: - sp_1024_mont_mul_42(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_1024_mont_mul_42(ctx->t3, ctx->t3, p->y, p1024_mod, p1024_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_1024_mont_mul_42(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_1024_cmp_equal_42(ctx->t2, ctx->t1) & - sp_1024_cmp_equal_42(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_1024_proj_point_dbl_42(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_1024_mont_sub_42(ctx->t2, ctx->t2, ctx->t1, p1024_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_1024_mont_sub_42(ctx->t4, ctx->t4, ctx->t3, p1024_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_1024_mont_sqr_42(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); - ctx->state = 13; - break; - case 13: - sp_1024_mont_mul_42(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); - ctx->state = 14; - break; - case 14: - sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_1024_mont_mul_42(ctx->z, p->z, ctx->t2, p1024_mod, p1024_mp_mod); - ctx->state = 16; - break; - case 16: - sp_1024_mont_mul_42(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); - ctx->state = 17; - break; - case 17: - sp_1024_mont_sqr_42(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); - ctx->state = 18; - break; - case 18: - sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t5, p1024_mod); - ctx->state = 19; - break; - case 19: - sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); - ctx->state = 20; - break; - case 20: - sp_1024_mont_dbl_42(ctx->t3, ctx->y, p1024_mod); - sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t3, p1024_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->x, p1024_mod); - ctx->state = 22; - break; - case 22: - sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); - ctx->state = 23; - break; - case 23: - sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t5, p1024_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 42; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 42; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 42; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#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. - */ -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) -{ - SP_DECL_VAR(sp_point_1024, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 42 * 37); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_1024, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 42 * 37, heap, DYNAMIC_TYPE_ECC); - - 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)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 42 * 37, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_1024, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#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 * 37]; - 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 */ - -#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 i, - 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; - volatile int n = i - 1; - - 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); - /* B = 2.(B - X) */ - sp_1024_mont_sub_42(t2, b, x, p1024_mod); - sp_1024_mont_dbl_42(b, t2, p1024_mod); - /* Z = Z*Y */ - sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod); - /* t1 = 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_mul_42(y, b, a, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_42(y, y, t1, p1024_mod); - n = n - 1; - } -#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); - /* B = 2.(B - X) */ - sp_1024_mont_sub_42(t2, b, x, p1024_mod); - sp_1024_mont_dbl_42(b, t2, p1024_mod); - /* Z = Z*Y */ - sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod); - /* t1 = Y^4 */ - sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_42(y, y, t1, p1024_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_1024_mont_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(t1, y, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(b, t1, 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(t2, b, p1024_mod); - sp_1024_mont_sub_42(x, x, t2, p1024_mod); - /* B = 2.(B - X) */ - sp_1024_mont_sub_42(t2, b, x, p1024_mod); - sp_1024_mont_dbl_42(b, t2, p1024_mod); - /* Z = Z*Y */ - sp_1024_mont_mul_42(r[j].z, z, y, p1024_mod, p1024_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod); - if (i != n) { - /* 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_mul_42(y, b, a, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_42(y, y, t1, p1024_mod); - /* Y = Y/2 */ - sp_1024_mont_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* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, 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, xa, p1024_mod, p1024_mp_mod); - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_42(t2, za, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(t4, t2, za, 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, ya, 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(za, za, q->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(za, za, t2, p1024_mod, p1024_mp_mod); - XMEMCPY(zs, za, 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(xa, 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(ya, 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(xa, xa, t5, p1024_mod); - sp_1024_mont_sub_42(xs, xs, t5, p1024_mod); - sp_1024_mont_dbl_42(t1, ya, p1024_mod); - sp_1024_mont_sub_42(xa, xa, 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, ya, xs, p1024_mod); - sp_1024_mont_sub_42(ya, ya, xa, p1024_mod); - sp_1024_mont_mul_42(ya, ya, 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(ya, ya, 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. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_1024; - -/* The index into pre-computation table to use. */ -static const word8 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 word8 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; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<147; i++) { - y = (word8)(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 |= (word8)((n << (25 - o)) & 0x7f); - o -= 18; - n >>= o; - } - - y = (word8)(y + 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) -{ - SP_DECL_VAR(sp_point_1024, t, 65+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 42 * 37); - 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; - - SP_ALLOC_VAR(sp_point_1024, t, 65+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 42 * 37, heap, DYNAMIC_TYPE_ECC); - 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)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*42; - sp_digit* t6 = t + 4*42; - sp_digit* t1 = t + 6*42; - sp_digit* t4 = t + 8*42; - sp_digit* t5 = t + 10*42; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_42(t2, p->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(t4, t2, p->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); - - if ((~p->infinity) & (~q->infinity) & - sp_1024_cmp_equal_42(p->x, t2) & - sp_1024_cmp_equal_42(p->y, t4)) { - sp_1024_proj_point_dbl_42(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_1024_mont_sub_42(t2, t2, p->x, p1024_mod); - /* R = S2 - Y1 */ - sp_1024_mont_sub_42(t4, t4, p->y, p1024_mod); - /* Z3 = H*Z1 */ - sp_1024_mont_mul_42(z, p->z, t2, p1024_mod, p1024_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_1024_mont_sqr_42(t1, t2, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(t3, p->x, t1, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_42(t1, t1, t2, p1024_mod, p1024_mp_mod); - sp_1024_mont_sqr_42(t2, t4, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_42(t2, t2, t1, p1024_mod); - sp_1024_mont_dbl_42(t5, t3, p1024_mod); - sp_1024_mont_sub_42(x, t2, t5, 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(t1, t1, p->y, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_42(y, t3, t1, p1024_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 42; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 42; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 42; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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) -{ - SP_DECL_VAR(sp_point_1024, t, 3); - sp_point_1024* s1 = NULL; - sp_point_1024* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_1024, t, 3, heap, DYNAMIC_TYPE_ECC); - 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)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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) -{ - SP_DECL_VAR(sp_point_1024, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 42 * 37); - 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; - - - SP_ALLOC_VAR(sp_point_1024, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 42 * 37, heap, DYNAMIC_TYPE_ECC); - 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)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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. */ - word32 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 - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_1024 = 0; - #endif - static wolfSSL_Mutex sp_cache_1024_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_1024_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * 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; - word32 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_DECL_VAR(sp_digit, tmp, 2 * 42 * 38); - sp_cache_1024_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 42 * 38, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_1024 == 0) { - wc_InitMutex(&sp_cache_1024_lock); - initCacheMutex_1024 = 1; - } - #endif - 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); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, k, 42); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 42, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_1024_ecc_mulmod_base_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_1024_ecc_mulmod_42_nb(sp_ctx, r, &p1024_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, k, 42); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 42, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_1024, point, 2); - SP_DECL_VAR(sp_digit, k, 42 + 42 * 2 * 37); - sp_point_1024* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 42 + 42 * 2 * 37, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - 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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, t, 38 * 2 * 42); - 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 = WC_NO_ERR_TRACE(LENGTH_ONLY_E); - } - if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 38 * 2 * 42, heap, DYNAMIC_TYPE_ECC); - 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; - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 = WC_NO_ERR_TRACE(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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, k, 42); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 42, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Multiply p* in projective coordinates 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 coordinates. - * - * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td; - sp_digit* t; - sp_digit* tx; - sp_digit* ty; - sp_digit* b; - sp_digit* e; -#else - sp_digit t[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 40 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - tx = td + 36 * 42 * 2; - ty = td + 37 * 42 * 2; - b = td + 38 * 42 * 2; - e = td + 39 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td; - sp_digit* t; - sp_digit* tx; - sp_digit* ty; -#else - sp_digit t[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 38 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - tx = td + 36 * 42 * 2; - ty = td + 37 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return err; -} - -#endif /* WOLFSSL_SP_SMALL */ -/* Multiply p* by q* in projective coordinates. - * - * 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_mont_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_mont_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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td = NULL; - sp_digit* t; - sp_digit* vx; - sp_digit* vy; - sp_digit* qx_px; -#else - sp_digit t[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - vx = td + 36 * 42 * 2; - vy = td + 37 * 42 * 2; - qx_px = td + 38 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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_mont_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_mont_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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - vx = td + 36 * 42 * 2; - vy = td + 37 * 42 * 2; - pre_vx = (sp_digit(*)[84])(td + 38 * 42 * 2); - pre_vy = (sp_digit(*)[84])(td + 54 * 42 * 2); - pre_nvy = (sp_digit(*)[84])(td + 70 * 42 * 2); - pre_p = (sp_point_1024*)(td + 86 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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 = WC_NO_ERR_TRACE(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 + 33 * 2 * 42; - sp_digit* t2 = t + 34 * 2 * 42; - sp_digit* l = t + 35 * 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 + 33 * 2 * 42; - sp_digit* c = t + 34 * 2 * 42; - sp_digit* l = t + 35 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td = NULL; - sp_digit* t; - sp_point_1024* pre_p; -#else - sp_digit t[36 * 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 = WC_NO_ERR_TRACE(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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - pre_p = (sp_point_1024*)(td + 36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - vx = td + 36 * 42 * 2; - vy = td + 37 * 42 * 2; - pre_vx = (sp_digit(*)[84])(td + 38 * 42 * 2); - pre_vy = (sp_digit(*)[84])(td + 54 * 42 * 2); - pre_nvy = (sp_digit(*)[84])(td + 70 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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 */ -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* 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 ordinates 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) -{ - SP_DECL_VAR(sp_digit, t1, 42 * 4); - sp_digit* t2 = NULL; - sp_int32 n; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 42 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 42; - - /* y^2 - x^3 - a.x = b */ - 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); - sp_1024_mont_sub_42(t1, t1, t2, p1024_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - 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, (sp_digit)~(n >> 24)); - sp_1024_norm_42(t1); - if (!sp_1024_iszero_42(t1)) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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) -{ - SP_DECL_VAR(sp_point_1024, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, pub, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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) -{ - SP_DECL_VAR(sp_digit, priv, 42); - SP_DECL_VAR(sp_point_1024, pub, 2); - 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; - } - - SP_ALLOC_VAR(sp_digit, priv, 42, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_1024, pub, 2, heap, DYNAMIC_TYPE_ECC); - 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; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* WOLFSSL_SP_1024 */ -#endif /* WOLFCRYPT_HAVE_SAKKE */ -#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 */ diff --git a/wolfssl-src/patches/sp_c64.c b/wolfssl-src/patches/sp_c64.c deleted file mode 100644 index a9c02fe..0000000 --- a/wolfssl-src/patches/sp_c64.c +++ /dev/null @@ -1,49957 +0,0 @@ -/* sp.c - * - * Copyright (C) 2006-2026 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 3 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 - */ - -/* Implementation by Sean Parkinson. */ - -#include - -#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ - defined(WOLFSSL_HAVE_SP_ECC) - -#include -#ifdef NO_INLINE - #include -#else - #define WOLFSSL_MISC_INCLUDED - #include -#endif - -#ifdef RSA_LOW_MEM -#ifndef SP_RSA_PRIVATE_EXP_D -#define SP_RSA_PRIVATE_EXP_D -#endif - -#ifndef WOLFSSL_SP_SMALL -#define WOLFSSL_SP_SMALL -#endif -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) -#undef WOLFSSL_SP_SMALL_STACK -#define WOLFSSL_SP_SMALL_STACK -#endif - -#include - -#ifdef __IAR_SYSTEMS_ICC__ -#define __asm__ asm -#define __volatile__ volatile -#define WOLFSSL_NO_VAR_ASSIGN_REG -#endif /* __IAR_SYSTEMS_ICC__ */ -#ifdef __KEIL__ -#define __asm__ __asm -#define __volatile__ volatile -#endif - -#ifdef WOLFSSL_SP_SMALL_STACK - #define SP_DECL_VAR(TYPE, NAME, CNT) \ - TYPE* NAME = NULL - #define SP_ALLOC_VAR(TYPE, NAME, CNT, HEAP, DT) \ - if (err == MP_OKAY) { \ - (NAME) = (TYPE*)XMALLOC(sizeof(TYPE) * (CNT), (HEAP), DT); \ - if ((NAME) == NULL) { \ - err = MEMORY_E; \ - } \ - } - - #define SP_VAR_OK(NAME) ((NAME) != NULL) - - #define SP_FREE_VAR(NAME, HEAP, DT) \ - XFREE(NAME, (HEAP), DT) - #define SP_ZEROFREE_VAR(TYPE, NAME, CNT, HEAP, DT) \ - do { \ - if ((NAME) != NULL) { \ - ForceZero(NAME, sizeof(TYPE) * (CNT)); \ - } \ - SP_FREE_VAR(NAME, HEAP, DT); \ - } while (0) - #define SP_ZEROFREE_VAR_ALT(TYPE, NAME, FZ_NAME, CNT, HEAP, DT) \ - do { \ - if ((FZ_NAME) != NULL) { \ - ForceZero(FZ_NAME, sizeof(TYPE) * (CNT)); \ - } \ - SP_FREE_VAR(NAME, HEAP, DT); \ - } while (0) -#else - #define SP_DECL_VAR(TYPE, NAME, CNT) \ - TYPE NAME[CNT] - #define SP_ALLOC_VAR(TYPE, NAME, CNT, HEAP, DT) \ - WC_DO_NOTHING - #define SP_VAR_OK(NAME) (1) - #define SP_FREE_VAR(NAME, HEAP, DT) \ - WC_DO_NOTHING - #define SP_ZEROFREE_VAR(TYPE, NAME, CNT, HEAP, DT) \ - do { \ - if ((NAME) != NULL) { \ - ForceZero(NAME, sizeof(TYPE) * (CNT)); \ - } \ - } while (0) - #define SP_ZEROFREE_VAR_ALT(TYPE, NAME, FZ_NAME, CNT, HEAP, DT) \ - do { \ - if ((FZ_NAME) != NULL) { \ - ForceZero(FZ_NAME, sizeof(TYPE) * (CNT)); \ - } \ - } while (0) -#endif - -#ifndef WOLFSSL_SP_ASM -#if SP_WORD_SIZE == 64 -#define SP_PRINT_NUM(var, name, total, words, bits) \ - do { \ - int ii; \ - byte nb[((bits) + 7) / 8]; \ - sp_digit _s[words]; \ - XMEMCPY(_s, var, sizeof(_s)); \ - sp_##total##_norm_##words(_s); \ - sp_##total##_to_bin_##words(_s, nb); \ - fprintf(stderr, name "=0x"); \ - for (ii=0; ii<((bits) + 7) / 8; ii++) \ - fprintf(stderr, "%02x", nb[ii]); \ - fprintf(stderr, "\n"); \ - } while (0) - -#define SP_PRINT_VAL(var, name) \ - fprintf(stderr, name "=0x" SP_PRINT_FMT "\n", var) - -#define SP_PRINT_INT(var, name) \ - fprintf(stderr, name "=%d\n", var) - -#if defined(WOLFSSL_SP_SMALL) && \ - defined(WOLFSSL_HAVE_SP_ECC) && (!defined(WOLFSSL_SP_NO_256) || \ - defined(WOLFSSL_SP_384) || defined(WOLFSSL_SP_521) || \ - defined(WOLFSSL_SP_1024)) - #define NEED_ADDR_MASK -#endif -#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) - #if !defined(WC_NO_CACHE_RESISTANT) && \ - (defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) - #define NEED_ADDR_MASK - #endif -#endif - -#ifdef NEED_ADDR_MASK -/* Mask for address to obfuscate which of the two address will be used. */ -static const size_t addr_mask[2] = { 0, (size_t)-1 }; -#endif - -#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || \ - !defined(WOLFSSL_SP_SMALL)) - #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC) -#endif - -#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) -#ifndef WOLFSSL_SP_NO_2048 -#ifdef WOLFSSL_SP_SMALL -/* 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_2048_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 >= 53U) { - r[j] &= 0x1fffffffffffffffL; - s = 61U - 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; - } -} - -/* 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_2048_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 61 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 60); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 60); - } -#elif DIGIT_BIT > 61 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x1fffffffffffffffL; - s = 61U - 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 + 61U) <= (word32)DIGIT_BIT) { - s += 61U; - r[j] &= 0x1fffffffffffffffL; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 61) { - r[j] &= 0x1fffffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 61 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 256 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_2048_to_bin_34(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<33; i++) { - r[i+1] += r[i] >> 61; - r[i] &= 0x1fffffffffffffffL; - } - j = 2055 / 8 - 1; - a[j] = 0; - for (i=0; i<34 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 61) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 61); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 61 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_17(sp_digit* a) -{ - int i; - for (i = 0; i < 16; i++) { - a[i+1] += a[i] >> 61; - a[i] &= 0x1fffffffffffffffL; - } -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 61 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_34(sp_digit* a) -{ - int i; - for (i = 0; i < 33; i++) { - a[i+1] += a[i] >> 61; - a[i] &= 0x1fffffffffffffffL; - } -} - -/* 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_2048_mul_34(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[33]) * b[33]; - r[67] = (sp_digit)(c >> 61); - c &= 0x1fffffffffffffffL; - for (k = 65; k >= 0; k--) { - if (k >= 34) { - i = k - 33; - imax = 33; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 61; - lo &= 0x1fffffffffffffffL; - } - r[k + 2] += (sp_digit)(c >> 61); - r[k + 1] = (sp_digit)(c & 0x1fffffffffffffffL); - c = lo & 0x1fffffffffffffffL; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 61; - r[k + 2] += (sp_digit)(c >> 61); - r[k + 1] = (sp_digit)(c & 0x1fffffffffffffffL); - c = lo & 0x1fffffffffffffffL; - } - } - r[0] = (sp_digit)c; -} - -/* 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_2048_sqr_34(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[33]) * a[33]; - r[67] = (sp_digit)(c >> 61); - c = (c & 0x1fffffffffffffffL) << 61; - for (k = 65; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 33) { - imax = k; - } - else { - imax = 33; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint128 hi; - - hi = c >> 61; - c &= 0x1fffffffffffffffL; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 61; - c &= 0x1fffffffffffffffL; - } - r[k + 2] += (sp_digit)(hi >> 61); - r[k + 1] = (sp_digit)(hi & 0x1fffffffffffffffL); - c <<= 61; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 122); - r[k + 1] = (sp_digit)((c >> 61) & 0x1fffffffffffffffL); - c = (c & 0x1fffffffffffffffL) << 61; - } - } - r[0] = (sp_digit)(c >> 61); -} - -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ - x &= 0x1fffffffffffffffL; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 61) - x; -} - -/* 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_2048_mul_d_34(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 34; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffffffffffffL); - t >>= 61; - } - r[34] = (sp_digit)t; -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* 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_17(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 17; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_2048_mont_norm_17(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<16; i++) { - r[i] = 0x1fffffffffffffffL; - } - r[16] = 0xffffffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_2048_sub_17(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_2048_cmp_17(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=16; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 60); - } - - 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_2048_cond_sub_17(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 17; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_2048_mul_add_17(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 16; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffffffffffffL); - t[1] += t[0] >> 61; - r[i+1] = (sp_digit)(t[1] & 0x1fffffffffffffffL); - t[2] += t[1] >> 61; - r[i+2] = (sp_digit)(t[2] & 0x1fffffffffffffffL); - t[3] += t[2] >> 61; - r[i+3] = (sp_digit)(t[3] & 0x1fffffffffffffffL); - t[0] = t[3] >> 61; - } - t[0] += (tb * a[16]) + r[16]; - r[16] = (sp_digit)(t[0] & 0x1fffffffffffffffL); - r[17] += (sp_digit)(t[0] >> 61); -} - -/* 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_2048_mont_shift_17(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[16] >> 48; - n += ((sp_int128)a[17]) << 13; - - for (i = 0; i < 16; i++) { - r[i] = (sp_digit)(n & 0x1fffffffffffffffL); - n >>= 61; - n += ((sp_int128)a[18 + i]) << 13; - } - r[16] = (sp_digit)n; - XMEMSET(&r[17], 0, sizeof(*r) * 17U); -} - -/* 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. - */ -static void sp_2048_mont_reduce_17(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_2048_norm_17(a + 17); - - for (i=0; i<16; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffffL); - sp_2048_mul_add_17(a+i, m, mu); - a[i+1] += a[i] >> 61; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xffffffffffffL); - sp_2048_mul_add_17(a+i, m, mu); - a[i+1] += a[i] >> 61; - a[i] &= 0x1fffffffffffffffL; - sp_2048_mont_shift_17(a, a); - over = a[16] - m[16]; - sp_2048_cond_sub_17(a, a, m, ~((over - 1) >> 63)); - sp_2048_norm_17(a); -} - -/* 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_2048_mul_17(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[16]) * b[16]; - r[33] = (sp_digit)(c >> 61); - c &= 0x1fffffffffffffffL; - for (k = 31; k >= 0; k--) { - if (k >= 17) { - i = k - 16; - imax = 16; - } - else { - i = 0; - imax = k; - } - if (imax - i > 15) { - int imaxlo; - lo = 0; - for (imaxlo = i; imaxlo <= imax; imaxlo += 15) { - for (; i <= imax && i < imaxlo + 15; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 61; - lo &= 0x1fffffffffffffffL; - } - r[k + 2] += (sp_digit)(c >> 61); - r[k + 1] = (sp_digit)(c & 0x1fffffffffffffffL); - c = lo & 0x1fffffffffffffffL; - } - else { - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 61; - r[k + 2] += (sp_digit)(c >> 61); - r[k + 1] = (sp_digit)(c & 0x1fffffffffffffffL); - c = lo & 0x1fffffffffffffffL; - } - } - r[0] = (sp_digit)c; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_2048_mont_mul_17(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_2048_mul_17(r, a, b); - sp_2048_mont_reduce_17(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_2048_sqr_17(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[16]) * a[16]; - r[33] = (sp_digit)(c >> 61); - c = (c & 0x1fffffffffffffffL) << 61; - for (k = 31; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 16) { - imax = k; - } - else { - imax = 16; - } - if (imax - i >= 14) { - int imaxlo; - sp_uint128 hi; - - hi = c >> 61; - c &= 0x1fffffffffffffffL; - for (imaxlo = i; imaxlo <= imax; imaxlo += 14) { - t = 0; - for (; i <= imax && i < imaxlo + 14; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - hi += c >> 61; - c &= 0x1fffffffffffffffL; - } - r[k + 2] += (sp_digit)(hi >> 61); - r[k + 1] = (sp_digit)(hi & 0x1fffffffffffffffL); - c <<= 61; - } - else - { - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 122); - r[k + 1] = (sp_digit)((c >> 61) & 0x1fffffffffffffffL); - c = (c & 0x1fffffffffffffffL) << 61; - } - } - r[0] = (sp_digit)(c >> 61); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_2048_mont_sqr_17(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_2048_sqr_17(r, a); - sp_2048_mont_reduce_17(r, m, mp); -} - -/* 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_2048_mul_d_17(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 17; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffffffffffffL); - t >>= 61; - } - r[17] = (sp_digit)t; -} - -#ifdef 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_2048_cond_add_17(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 17; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_2048_add_17(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 17; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_2048_rshift_17(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<16; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (61 - n))) & 0x1fffffffffffffffL); - } - r[16] = a[16] >> n; -} - -static WC_INLINE sp_digit sp_2048_div_word_17(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 61) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 61) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 61) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 61); - sp_digit t0 = (sp_digit)(d & 0x1fffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 59; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 60) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 61); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 122) - (sp_digit)(d >> 122); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 61) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 30) + 1; - - t = (sp_digit)(d >> 60); - t = (t / dv) << 30; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 29); - t = t / (dv << 1); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_2048_word_div_word_17(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_17(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 17 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 17 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 34 + 1; - sd = t2 + 17 + 1; - - sp_2048_mul_d_17(sd, d, (sp_digit)1 << 13); - sp_2048_mul_d_34(t1, a, (sp_digit)1 << 13); - dv = sd[16]; - t1[17 + 17] += t1[17 + 17 - 1] >> 61; - t1[17 + 17 - 1] &= 0x1fffffffffffffffL; - for (i=17; i>=0; i--) { - r1 = sp_2048_div_word_17(t1[17 + i], t1[17 + i - 1], dv); - - sp_2048_mul_d_17(t2, sd, r1); - (void)sp_2048_sub_17(&t1[i], &t1[i], t2); - sp_2048_norm_17(&t1[i]); - t1[17 + i] -= t2[17]; - t1[17 + i] += t1[17 + i - 1] >> 61; - t1[17 + i - 1] &= 0x1fffffffffffffffL; - r1 = sp_2048_div_word_17(-t1[17 + i], -t1[17 + i - 1], dv); - r1 -= t1[17 + i]; - sp_2048_mul_d_17(t2, sd, r1); - (void)sp_2048_add_17(&t1[i], &t1[i], t2); - t1[17 + i] += t1[17 + i - 1] >> 61; - t1[17 + i - 1] &= 0x1fffffffffffffffL; - } - t1[17 - 1] += t1[17 - 2] >> 61; - t1[17 - 2] &= 0x1fffffffffffffffL; - r1 = sp_2048_word_div_word_17(t1[17 - 1], dv); - - sp_2048_mul_d_17(t2, sd, r1); - sp_2048_sub_17(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 34U); - for (i=0; i<16; i++) { - r[i+1] += r[i] >> 61; - r[i] &= 0x1fffffffffffffffL; - } - sp_2048_cond_add_17(r, r, sd, r[16] >> 63); - - sp_2048_norm_17(r); - sp_2048_rshift_17(r, r, 13); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_2048_mod_17(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_2048_div_17(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_2048_mod_exp_17(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 34); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 17 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 17U * 2U); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_17(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_17(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 17U); - } - } - if (err == MP_OKAY) { - sp_2048_mul_17(t[1], t[1], norm); - err = sp_2048_mod_17(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 61; - c = bits % 61; - n = e[i--] << (61 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 61; - } - - y = (int)((n >> 60) & 1); - n <<= 1; - - sp_2048_mont_mul_17(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 17 * 2); - sp_2048_mont_sqr_17(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 17 * 2); - } - - sp_2048_mont_reduce_17(t[0], m, mp); - n = sp_2048_cmp_17(t[0], m); - sp_2048_cond_sub_17(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 17 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 34); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 17 * 2); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_17(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_17(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_17(t[1], t[1], norm); - err = sp_2048_mod_17(t[1], t[1], m); - } - } - else { - sp_2048_mul_17(t[1], a, norm); - err = sp_2048_mod_17(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 61; - c = bits % 61; - n = e[i--] << (61 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 61; - } - - y = (int)((n >> 60) & 1); - n <<= 1; - - sp_2048_mont_mul_17(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 17 * 2); - sp_2048_mont_sqr_17(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 17 * 2); - } - - sp_2048_mont_reduce_17(t[0], m, mp); - n = sp_2048_cmp_17(t[0], m); - sp_2048_cond_sub_17(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 17 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 34) + 34); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 34) + 34, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 34; - rt = td + 1088; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_17(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_17(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_17(t[1], t[1], norm); - err = sp_2048_mod_17(t[1], t[1], m); - } - } - else { - sp_2048_mul_17(t[1], a, norm); - err = sp_2048_mod_17(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_2048_mont_sqr_17(t[ 2], t[ 1], m, mp); - sp_2048_mont_mul_17(t[ 3], t[ 2], t[ 1], m, mp); - sp_2048_mont_sqr_17(t[ 4], t[ 2], m, mp); - sp_2048_mont_mul_17(t[ 5], t[ 3], t[ 2], m, mp); - sp_2048_mont_sqr_17(t[ 6], t[ 3], m, mp); - sp_2048_mont_mul_17(t[ 7], t[ 4], t[ 3], m, mp); - sp_2048_mont_sqr_17(t[ 8], t[ 4], m, mp); - sp_2048_mont_mul_17(t[ 9], t[ 5], t[ 4], m, mp); - sp_2048_mont_sqr_17(t[10], t[ 5], m, mp); - sp_2048_mont_mul_17(t[11], t[ 6], t[ 5], m, mp); - sp_2048_mont_sqr_17(t[12], t[ 6], m, mp); - sp_2048_mont_mul_17(t[13], t[ 7], t[ 6], m, mp); - sp_2048_mont_sqr_17(t[14], t[ 7], m, mp); - sp_2048_mont_mul_17(t[15], t[ 8], t[ 7], m, mp); - sp_2048_mont_sqr_17(t[16], t[ 8], m, mp); - sp_2048_mont_mul_17(t[17], t[ 9], t[ 8], m, mp); - sp_2048_mont_sqr_17(t[18], t[ 9], m, mp); - sp_2048_mont_mul_17(t[19], t[10], t[ 9], m, mp); - sp_2048_mont_sqr_17(t[20], t[10], m, mp); - sp_2048_mont_mul_17(t[21], t[11], t[10], m, mp); - sp_2048_mont_sqr_17(t[22], t[11], m, mp); - sp_2048_mont_mul_17(t[23], t[12], t[11], m, mp); - sp_2048_mont_sqr_17(t[24], t[12], m, mp); - sp_2048_mont_mul_17(t[25], t[13], t[12], m, mp); - sp_2048_mont_sqr_17(t[26], t[13], m, mp); - sp_2048_mont_mul_17(t[27], t[14], t[13], m, mp); - sp_2048_mont_sqr_17(t[28], t[14], m, mp); - sp_2048_mont_mul_17(t[29], t[15], t[14], m, mp); - sp_2048_mont_sqr_17(t[30], t[15], m, mp); - sp_2048_mont_mul_17(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 60) / 61) - 1; - c = bits % 61; - if (c == 0) { - c = 61; - } - if (i < 17) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (3 - c); - c += 61; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 34); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 56; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 3; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 61 - c; - } - - sp_2048_mont_sqr_17(rt, rt, m, mp); - sp_2048_mont_sqr_17(rt, rt, m, mp); - sp_2048_mont_sqr_17(rt, rt, m, mp); - sp_2048_mont_sqr_17(rt, rt, m, mp); - sp_2048_mont_sqr_17(rt, rt, m, mp); - - sp_2048_mont_mul_17(rt, rt, t[y], m, mp); - } - - sp_2048_mont_reduce_17(rt, m, mp); - n = sp_2048_cmp_17(rt, m); - sp_2048_cond_sub_17(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 34); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ - -/* 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_34(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 34; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_2048_mont_norm_34(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<33; i++) { - r[i] = 0x1fffffffffffffffL; - } - r[33] = 0x7ffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_2048_sub_34(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_2048_cmp_34(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=33; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 60); - } - - 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_2048_cond_sub_34(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 34; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_2048_mul_add_34(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 32; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1fffffffffffffffL); - t[1] += t[0] >> 61; - r[i+1] = (sp_digit)(t[1] & 0x1fffffffffffffffL); - t[2] += t[1] >> 61; - r[i+2] = (sp_digit)(t[2] & 0x1fffffffffffffffL); - t[3] += t[2] >> 61; - r[i+3] = (sp_digit)(t[3] & 0x1fffffffffffffffL); - t[0] = t[3] >> 61; - } - t[0] += (tb * a[32]) + r[32]; - t[1] = (tb * a[33]) + r[33]; - r[32] = (sp_digit)(t[0] & 0x1fffffffffffffffL); - t[1] += t[0] >> 61; - r[33] = (sp_digit)(t[1] & 0x1fffffffffffffffL); - r[34] += (sp_digit)(t[1] >> 61); -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_2048_mont_shift_34(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[33] >> 35; - n += ((sp_int128)a[34]) << 26; - - for (i = 0; i < 33; i++) { - r[i] = (sp_digit)(n & 0x1fffffffffffffffL); - n >>= 61; - n += ((sp_int128)a[35 + i]) << 26; - } - r[33] = (sp_digit)n; - XMEMSET(&r[34], 0, sizeof(*r) * 34U); -} - -/* 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. - */ -static void sp_2048_mont_reduce_34(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_2048_norm_34(a + 34); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<33; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffffL); - sp_2048_mul_add_34(a+i, m, mu); - a[i+1] += a[i] >> 61; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffL); - sp_2048_mul_add_34(a+i, m, mu); - a[i+1] += a[i] >> 61; - a[i] &= 0x1fffffffffffffffL; - } - else { - for (i=0; i<33; i++) { - mu = (sp_digit)(a[i] & 0x1fffffffffffffffL); - sp_2048_mul_add_34(a+i, m, mu); - a[i+1] += a[i] >> 61; - } - mu = (sp_digit)(a[i] & 0x7ffffffffL); - sp_2048_mul_add_34(a+i, m, mu); - a[i+1] += a[i] >> 61; - a[i] &= 0x1fffffffffffffffL; - } -#else - for (i=0; i<33; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffffL); - sp_2048_mul_add_34(a+i, m, mu); - a[i+1] += a[i] >> 61; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffL); - sp_2048_mul_add_34(a+i, m, mu); - a[i+1] += a[i] >> 61; - a[i] &= 0x1fffffffffffffffL; -#endif - sp_2048_mont_shift_34(a, a); - over = a[33] - m[33]; - sp_2048_cond_sub_34(a, a, m, ~((over - 1) >> 63)); - sp_2048_norm_34(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_2048_mont_mul_34(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_2048_mul_34(r, a, b); - sp_2048_mont_reduce_34(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_2048_mont_sqr_34(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_2048_sqr_34(r, a); - sp_2048_mont_reduce_34(r, m, mp); -} - -/* 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_2048_mul_d_68(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 68; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1fffffffffffffffL); - t >>= 61; - } - r[68] = (sp_digit)t; -} - -#ifdef 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_2048_cond_add_34(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 34; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_2048_add_34(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 34; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_2048_rshift_34(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<33; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (61 - n))) & 0x1fffffffffffffffL); - } - r[33] = a[33] >> n; -} - -static WC_INLINE sp_digit sp_2048_div_word_34(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 61) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 61) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 61) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 61); - sp_digit t0 = (sp_digit)(d & 0x1fffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 59; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 60) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 61); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 122) - (sp_digit)(d >> 122); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 61) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 30) + 1; - - t = (sp_digit)(d >> 60); - t = (t / dv) << 30; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 29); - t = t / (dv << 1); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_2048_word_div_word_34(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_34(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 34 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 34 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 68 + 1; - sd = t2 + 34 + 1; - - sp_2048_mul_d_34(sd, d, (sp_digit)1 << 26); - sp_2048_mul_d_68(t1, a, (sp_digit)1 << 26); - dv = sd[33]; - t1[34 + 34] += t1[34 + 34 - 1] >> 61; - t1[34 + 34 - 1] &= 0x1fffffffffffffffL; - for (i=34; i>=0; i--) { - r1 = sp_2048_div_word_34(t1[34 + i], t1[34 + i - 1], dv); - - sp_2048_mul_d_34(t2, sd, r1); - (void)sp_2048_sub_34(&t1[i], &t1[i], t2); - sp_2048_norm_34(&t1[i]); - t1[34 + i] -= t2[34]; - t1[34 + i] += t1[34 + i - 1] >> 61; - t1[34 + i - 1] &= 0x1fffffffffffffffL; - r1 = sp_2048_div_word_34(-t1[34 + i], -t1[34 + i - 1], dv); - r1 -= t1[34 + i]; - sp_2048_mul_d_34(t2, sd, r1); - (void)sp_2048_add_34(&t1[i], &t1[i], t2); - t1[34 + i] += t1[34 + i - 1] >> 61; - t1[34 + i - 1] &= 0x1fffffffffffffffL; - } - t1[34 - 1] += t1[34 - 2] >> 61; - t1[34 - 2] &= 0x1fffffffffffffffL; - r1 = sp_2048_word_div_word_34(t1[34 - 1], dv); - - sp_2048_mul_d_34(t2, sd, r1); - sp_2048_sub_34(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 68U); - for (i=0; i<33; i++) { - r[i+1] += r[i] >> 61; - r[i] &= 0x1fffffffffffffffL; - } - sp_2048_cond_add_34(r, r, sd, r[33] >> 63); - - sp_2048_norm_34(r); - sp_2048_rshift_34(r, r, 26); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_2048_mod_34(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_2048_div_34(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_2048_mod_exp_34(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 68); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 68, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 34 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 34U * 2U); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_34(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_34(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 34U); - } - } - if (err == MP_OKAY) { - sp_2048_mul_34(t[1], t[1], norm); - err = sp_2048_mod_34(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 61; - c = bits % 61; - n = e[i--] << (61 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 61; - } - - y = (int)((n >> 60) & 1); - n <<= 1; - - sp_2048_mont_mul_34(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 34 * 2); - sp_2048_mont_sqr_34(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 34 * 2); - } - - sp_2048_mont_reduce_34(t[0], m, mp); - n = sp_2048_cmp_34(t[0], m); - sp_2048_cond_sub_34(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 34 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 68); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 68, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 34 * 2); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_34(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_34(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_34(t[1], t[1], norm); - err = sp_2048_mod_34(t[1], t[1], m); - } - } - else { - sp_2048_mul_34(t[1], a, norm); - err = sp_2048_mod_34(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 61; - c = bits % 61; - n = e[i--] << (61 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 61; - } - - y = (int)((n >> 60) & 1); - n <<= 1; - - sp_2048_mont_mul_34(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 34 * 2); - sp_2048_mont_sqr_34(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 34 * 2); - } - - sp_2048_mont_reduce_34(t[0], m, mp); - n = sp_2048_cmp_34(t[0], m); - sp_2048_cond_sub_34(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 34 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 68) + 68); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 68) + 68, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 68; - rt = td + 1088; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_34(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_34(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_34(t[1], t[1], norm); - err = sp_2048_mod_34(t[1], t[1], m); - } - } - else { - sp_2048_mul_34(t[1], a, norm); - err = sp_2048_mod_34(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_2048_mont_sqr_34(t[ 2], t[ 1], m, mp); - sp_2048_mont_mul_34(t[ 3], t[ 2], t[ 1], m, mp); - sp_2048_mont_sqr_34(t[ 4], t[ 2], m, mp); - sp_2048_mont_mul_34(t[ 5], t[ 3], t[ 2], m, mp); - sp_2048_mont_sqr_34(t[ 6], t[ 3], m, mp); - sp_2048_mont_mul_34(t[ 7], t[ 4], t[ 3], m, mp); - sp_2048_mont_sqr_34(t[ 8], t[ 4], m, mp); - sp_2048_mont_mul_34(t[ 9], t[ 5], t[ 4], m, mp); - sp_2048_mont_sqr_34(t[10], t[ 5], m, mp); - sp_2048_mont_mul_34(t[11], t[ 6], t[ 5], m, mp); - sp_2048_mont_sqr_34(t[12], t[ 6], m, mp); - sp_2048_mont_mul_34(t[13], t[ 7], t[ 6], m, mp); - sp_2048_mont_sqr_34(t[14], t[ 7], m, mp); - sp_2048_mont_mul_34(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 60) / 61) - 1; - c = bits % 61; - if (c == 0) { - c = 61; - } - if (i < 34) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (3 - c); - c += 61; - } - y = (int)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 68); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c = 57; - } - else { - y = (byte)((n >> 60) & 0xf); - n = e[i--] << 3; - c = 4 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 61 - c; - } - - sp_2048_mont_sqr_34(rt, rt, m, mp); - sp_2048_mont_sqr_34(rt, rt, m, mp); - sp_2048_mont_sqr_34(rt, rt, m, mp); - sp_2048_mont_sqr_34(rt, rt, m, mp); - - sp_2048_mont_mul_34(rt, rt, t[y], m, mp); - } - - sp_2048_mont_reduce_34(rt, m, mp); - n = sp_2048_cmp_34(rt, m); - sp_2048_cond_sub_34(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 68); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 34 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 256U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 34 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 34 * 2; - m = r + 34 * 2; - norm = r; - - sp_2048_from_bin(a, 34, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_2048_from_mp(m, 34, mm); - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_34(norm, m); - } - if (err == MP_OKAY) { - sp_2048_mul_34(a, a, norm); - err = sp_2048_mod_34(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 34 * 2); - for (i--; i>=0; i--) { - sp_2048_mont_sqr_34(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_2048_mont_mul_34(r, r, a, m, mp); - } - } - sp_2048_mont_reduce_34(r, m, mp); - mp = sp_2048_cmp_34(r, m); - sp_2048_cond_sub_34(r, r, m, ~(mp >> 63)); - - sp_2048_to_bin_34(r, out); - *outLen = 256; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 34 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 34 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 34 * 2; - m = r + 34 * 2; - - sp_2048_from_bin(a, 34, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_2048_from_mp(m, 34, mm); - - if (e[0] == 0x3) { - sp_2048_sqr_34(r, a); - err = sp_2048_mod_34(r, r, m); - if (err == MP_OKAY) { - sp_2048_mul_34(r, a, r); - err = sp_2048_mod_34(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_34(norm, m); - - sp_2048_mul_34(a, a, norm); - err = sp_2048_mod_34(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 68U); - for (i--; i>=0; i--) { - sp_2048_mont_sqr_34(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_2048_mont_mul_34(r, r, a, m, mp); - } - } - sp_2048_mont_reduce_34(r, m, mp); - mp = sp_2048_cmp_34(r, m); - sp_2048_cond_sub_34(r, r, m, ~(mp >> 63)); - } - } - } - - if (err == MP_OKAY) { - sp_2048_to_bin_34(r, out); - *outLen = 256; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 34 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 2048) { - err = MP_READ_E; - } - else if (inLen > 256) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 34 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 34; - m = a + 68; - r = a; - - sp_2048_from_bin(a, 34, in, inLen); - sp_2048_from_mp(d, 34, dm); - sp_2048_from_mp(m, 34, mm); - err = sp_2048_mod_exp_34(r, a, d, 2048, m, 0); - } - - if (err == MP_OKAY) { - sp_2048_to_bin_34(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 34, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 34 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 2048) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 34 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 34; - m = a + 68; - r = a; - - sp_2048_from_bin(a, 34, in, inLen); - sp_2048_from_mp(d, 34, dm); - sp_2048_from_mp(m, 34, mm); - err = sp_2048_mod_exp_34(r, a, d, 2048, m, 0); - } - - if (err == MP_OKAY) { - sp_2048_to_bin_34(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 34, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 17 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 256) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 17 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 34; - qi = dq = dp = p + 17; - tmpa = qi + 17; - tmpb = tmpa + 34; - r = a; - - sp_2048_from_bin(a, 34, in, inLen); - sp_2048_from_mp(p, 17, pm); - sp_2048_from_mp(dp, 17, dpm); - err = sp_2048_mod_exp_17(tmpa, a, dp, 1024, p, 1); - } - if (err == MP_OKAY) { - sp_2048_from_mp(p, 17, qm); - sp_2048_from_mp(dq, 17, dqm); - err = sp_2048_mod_exp_17(tmpb, a, dq, 1024, p, 1); - } - if (err == MP_OKAY) { - sp_2048_from_mp(p, 17, pm); - (void)sp_2048_sub_17(tmpa, tmpa, tmpb); - sp_2048_norm_17(tmpa); - sp_2048_cond_add_17(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[16] >> 63)); - sp_2048_cond_add_17(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[16] >> 63)); - sp_2048_norm_17(tmpa); - - sp_2048_from_mp(qi, 17, qim); - sp_2048_mul_17(tmpa, tmpa, qi); - err = sp_2048_mod_17(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_2048_from_mp(p, 17, qm); - sp_2048_mul_17(tmpa, p, tmpa); - (void)sp_2048_add_34(r, tmpb, tmpa); - sp_2048_norm_34(r); - - sp_2048_to_bin_34(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR(sp_digit, a, 17 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 17 * 13); - 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; - (void)mm; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 17 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 34 * 2; - q = p + 17; - dp = q + 17; - dq = dp + 17; - qi = dq + 17; - tmpa = qi + 17; - tmpb = tmpa + 34; - r = a; - - sp_2048_from_bin(a, 34, in, inLen); - sp_2048_from_mp(p, 17, pm); - sp_2048_from_mp(q, 17, qm); - sp_2048_from_mp(dp, 17, dpm); - sp_2048_from_mp(dq, 17, dqm); - sp_2048_from_mp(qi, 17, qim); - - err = sp_2048_mod_exp_17(tmpa, a, dp, 1024, p, 1); - } - if (err == MP_OKAY) { - err = sp_2048_mod_exp_17(tmpb, a, dq, 1024, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_2048_sub_17(tmpa, tmpa, tmpb); - sp_2048_norm_17(tmpa); - sp_2048_cond_add_17(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[16] >> 63)); - sp_2048_cond_add_17(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[16] >> 63)); - sp_2048_norm_17(tmpa); - sp_2048_mul_17(tmpa, tmpa, qi); - err = sp_2048_mod_17(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_2048_mul_17(tmpa, tmpa, q); - (void)sp_2048_add_34(r, tmpb, tmpa); - sp_2048_norm_34(r); - - sp_2048_to_bin_34(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR(sp_digit, a, 17 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_2048_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 61 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 34); - r->used = 34; - mp_clamp(r); -#elif DIGIT_BIT < 61 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 34; 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 <= 61) { - 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 = 61 - s; - } - r->used = (2048 + 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 < 34; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 61 >= 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 = 61 - s; - } - else { - s += 61; - } - } - r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 34 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expBits > 2048) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 34 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 34 * 2; - m = e + 34; - r = b; - - sp_2048_from_mp(b, 34, base); - sp_2048_from_mp(e, 34, exp); - sp_2048_from_mp(m, 34, mod); - - err = sp_2048_mod_exp_34(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 34U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 34 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expBits > 2048) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 34 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 34 * 2; - m = e + 34; - r = b; - - sp_2048_from_mp(b, 34, base); - sp_2048_from_mp(e, 34, exp); - sp_2048_from_mp(m, 34, mod); - - err = sp_2048_mod_exp_34(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 34U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_2048 -SP_NOINLINE static void sp_2048_lshift_34(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - r[34] = a[33] >> (61 - n); - for (i=33; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (61 - n))) & 0x1fffffffffffffffL); - } - r[0] = (sp_digit)((a[0] << n) & 0x1fffffffffffffffL); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_2048_mod_exp_2_34(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 103); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 103, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 68; - XMEMSET(td, 0, sizeof(sp_digit) * 103); - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_34(norm, m); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 60) / 61) - 1; - c = bits % 61; - if (c == 0) { - c = 61; - } - if (i < 34) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (3 - c); - c += 61; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - sp_2048_lshift_34(r, norm, (byte)y); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 3; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 56; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 3; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 61 - c; - } - - sp_2048_mont_sqr_34(r, r, m, mp); - sp_2048_mont_sqr_34(r, r, m, mp); - sp_2048_mont_sqr_34(r, r, m, mp); - sp_2048_mont_sqr_34(r, r, m, mp); - sp_2048_mont_sqr_34(r, r, m, mp); - - sp_2048_lshift_34(r, r, (byte)y); - sp_2048_mul_d_34(tmp, norm, (r[34] << 26) + (r[33] >> 35)); - r[34] = 0; - r[33] &= 0x7ffffffffL; - (void)sp_2048_add_34(r, r, tmp); - sp_2048_norm_34(r); - o = sp_2048_cmp_34(r, m); - sp_2048_cond_sub_34(r, r, m, ~(o >> 63)); - } - - sp_2048_mont_reduce_34(r, m, mp); - n = sp_2048_cmp_34(r, m); - sp_2048_cond_sub_34(r, r, m, (sp_digit)~(n >> 63)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_2048 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 34 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 34 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 34 * 2; - m = e + 34; - r = b; - - sp_2048_from_mp(b, 34, base); - sp_2048_from_bin(e, 34, exp, expLen); - sp_2048_from_mp(m, 34, mod); - - #ifdef HAVE_FFDHE_2048 - if (base->used == 1 && base->dp[0] == 2U && - (m[33] >> 3) == 0xffffffffL) { - err = sp_2048_mod_exp_2_34(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_2048_mod_exp_34(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_2048 - } - #endif - } - - if (err == MP_OKAY) { - sp_2048_to_bin_34(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 34U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 17 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1024) { - err = MP_READ_E; - } - else if (expBits > 1024) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1024) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 17 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 17 * 2; - m = e + 17; - r = b; - - sp_2048_from_mp(b, 17, base); - sp_2048_from_mp(e, 17, exp); - sp_2048_from_mp(m, 17, mod); - - err = sp_2048_mod_exp_17(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 17, 0, sizeof(*r) * 17U); - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 34U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 17 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1024) { - err = MP_READ_E; - } - else if (expBits > 1024) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1024) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 17 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 17 * 2; - m = e + 17; - r = b; - - sp_2048_from_mp(b, 17, base); - sp_2048_from_mp(e, 17, exp); - sp_2048_from_mp(m, 17, mod); - - err = sp_2048_mod_exp_17(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 17, 0, sizeof(*r) * 17U); - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 34U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#else -/* 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_2048_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; - } -} - -/* 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_2048_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 57 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 56); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 56); - } -#elif DIGIT_BIT > 57 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 256 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_2048_to_bin_36(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<35; i++) { - r[i+1] += r[i] >> 57; - r[i] &= 0x1ffffffffffffffL; - } - j = 2055 / 8 - 1; - a[j] = 0; - for (i=0; i<36 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 57) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 57); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 57 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_18(sp_digit* a) -{ - 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[17] += a[16] >> 57; a[16] &= 0x1ffffffffffffffL; -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 57 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_2048_norm_36(sp_digit* a) -{ - int i; - for (i = 0; i < 32; 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[33] += a[32] >> 57; a[32] &= 0x1ffffffffffffffL; - a[34] += a[33] >> 57; a[33] &= 0x1ffffffffffffffL; - a[35] += a[34] >> 57; a[34] &= 0x1ffffffffffffffL; -} - -#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_2048_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_uint128 t0; - sp_uint128 t1; - sp_digit t[9]; - - t0 = ((sp_uint128)a[ 0]) * b[ 0]; - t1 = ((sp_uint128)a[ 0]) * b[ 1] - + ((sp_uint128)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 2] - + ((sp_uint128)a[ 1]) * b[ 1] - + ((sp_uint128)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 0]) * b[ 3] - + ((sp_uint128)a[ 1]) * b[ 2] - + ((sp_uint128)a[ 2]) * b[ 1] - + ((sp_uint128)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 4] - + ((sp_uint128)a[ 1]) * b[ 3] - + ((sp_uint128)a[ 2]) * b[ 2] - + ((sp_uint128)a[ 3]) * b[ 1] - + ((sp_uint128)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 0]) * b[ 5] - + ((sp_uint128)a[ 1]) * b[ 4] - + ((sp_uint128)a[ 2]) * b[ 3] - + ((sp_uint128)a[ 3]) * b[ 2] - + ((sp_uint128)a[ 4]) * b[ 1] - + ((sp_uint128)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 6] - + ((sp_uint128)a[ 1]) * b[ 5] - + ((sp_uint128)a[ 2]) * b[ 4] - + ((sp_uint128)a[ 3]) * b[ 3] - + ((sp_uint128)a[ 4]) * b[ 2] - + ((sp_uint128)a[ 5]) * b[ 1] - + ((sp_uint128)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 0]) * b[ 7] - + ((sp_uint128)a[ 1]) * b[ 6] - + ((sp_uint128)a[ 2]) * b[ 5] - + ((sp_uint128)a[ 3]) * b[ 4] - + ((sp_uint128)a[ 4]) * b[ 3] - + ((sp_uint128)a[ 5]) * b[ 2] - + ((sp_uint128)a[ 6]) * b[ 1] - + ((sp_uint128)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 8] - + ((sp_uint128)a[ 1]) * b[ 7] - + ((sp_uint128)a[ 2]) * b[ 6] - + ((sp_uint128)a[ 3]) * b[ 5] - + ((sp_uint128)a[ 4]) * b[ 4] - + ((sp_uint128)a[ 5]) * b[ 3] - + ((sp_uint128)a[ 6]) * b[ 2] - + ((sp_uint128)a[ 7]) * b[ 1] - + ((sp_uint128)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 1]) * b[ 8] - + ((sp_uint128)a[ 2]) * b[ 7] - + ((sp_uint128)a[ 3]) * b[ 6] - + ((sp_uint128)a[ 4]) * b[ 5] - + ((sp_uint128)a[ 5]) * b[ 4] - + ((sp_uint128)a[ 6]) * b[ 3] - + ((sp_uint128)a[ 7]) * b[ 2] - + ((sp_uint128)a[ 8]) * b[ 1]; - t[ 8] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 2]) * b[ 8] - + ((sp_uint128)a[ 3]) * b[ 7] - + ((sp_uint128)a[ 4]) * b[ 6] - + ((sp_uint128)a[ 5]) * b[ 5] - + ((sp_uint128)a[ 6]) * b[ 4] - + ((sp_uint128)a[ 7]) * b[ 3] - + ((sp_uint128)a[ 8]) * b[ 2]; - r[ 9] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 3]) * b[ 8] - + ((sp_uint128)a[ 4]) * b[ 7] - + ((sp_uint128)a[ 5]) * b[ 6] - + ((sp_uint128)a[ 6]) * b[ 5] - + ((sp_uint128)a[ 7]) * b[ 4] - + ((sp_uint128)a[ 8]) * b[ 3]; - r[10] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 4]) * b[ 8] - + ((sp_uint128)a[ 5]) * b[ 7] - + ((sp_uint128)a[ 6]) * b[ 6] - + ((sp_uint128)a[ 7]) * b[ 5] - + ((sp_uint128)a[ 8]) * b[ 4]; - r[11] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 5]) * b[ 8] - + ((sp_uint128)a[ 6]) * b[ 7] - + ((sp_uint128)a[ 7]) * b[ 6] - + ((sp_uint128)a[ 8]) * b[ 5]; - r[12] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 6]) * b[ 8] - + ((sp_uint128)a[ 7]) * b[ 7] - + ((sp_uint128)a[ 8]) * b[ 6]; - r[13] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 7]) * b[ 8] - + ((sp_uint128)a[ 8]) * b[ 7]; - r[14] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 8]) * b[ 8]; - r[15] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - r[16] = (sp_digit)(t0 & 0x1ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 57); - XMEMCPY(r, t, sizeof(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. - */ -SP_NOINLINE static int sp_2048_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_2048_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_2048_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_2048_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_2048_add_9(a1, a, &a[9]); - (void)sp_2048_add_9(b1, b, &b[9]); - sp_2048_mul_9(z2, &a[9], &b[9]); - sp_2048_mul_9(z0, a, b); - sp_2048_mul_9(z1, a1, b1); - (void)sp_2048_sub_18(z1, z1, z2); - (void)sp_2048_sub_18(z1, z1, z0); - (void)sp_2048_add_18(r + 9, r + 9, z1); -} - -/* 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 < 32; 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[32] = a[32] + b[32]; - r[33] = a[33] + b[33]; - r[34] = a[34] + b[34]; - r[35] = a[35] + b[35]; - - 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_2048_sub_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] - b[32]; - r[33] = a[33] - b[33]; - r[34] = a[34] - b[34]; - r[35] = a[35] - b[35]; - - 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_2048_mul_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[36]; - sp_digit* a1 = z1; - sp_digit b1[18]; - sp_digit* z2 = r + 36; - (void)sp_2048_add_18(a1, a, &a[18]); - (void)sp_2048_add_18(b1, b, &b[18]); - sp_2048_mul_18(z2, &a[18], &b[18]); - sp_2048_mul_18(z0, a, b); - sp_2048_mul_18(z1, a1, b1); - (void)sp_2048_sub_36(z1, z1, z2); - (void)sp_2048_sub_36(z1, z1, z0); - (void)sp_2048_add_36(r + 18, r + 18, 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_2048_sqr_9(sp_digit* r, const sp_digit* a) -{ - sp_uint128 t0; - sp_uint128 t1; - sp_digit t[9]; - - t0 = ((sp_uint128)a[ 0]) * a[ 0]; - t1 = (((sp_uint128)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 2]) * 2 - + ((sp_uint128)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 0]) * a[ 3] - + ((sp_uint128)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 4] - + ((sp_uint128)a[ 1]) * a[ 3]) * 2 - + ((sp_uint128)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 0]) * a[ 5] - + ((sp_uint128)a[ 1]) * a[ 4] - + ((sp_uint128)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 6] - + ((sp_uint128)a[ 1]) * a[ 5] - + ((sp_uint128)a[ 2]) * a[ 4]) * 2 - + ((sp_uint128)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 0]) * a[ 7] - + ((sp_uint128)a[ 1]) * a[ 6] - + ((sp_uint128)a[ 2]) * a[ 5] - + ((sp_uint128)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 8] - + ((sp_uint128)a[ 1]) * a[ 7] - + ((sp_uint128)a[ 2]) * a[ 6] - + ((sp_uint128)a[ 3]) * a[ 5]) * 2 - + ((sp_uint128)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 1]) * a[ 8] - + ((sp_uint128)a[ 2]) * a[ 7] - + ((sp_uint128)a[ 3]) * a[ 6] - + ((sp_uint128)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 2]) * a[ 8] - + ((sp_uint128)a[ 3]) * a[ 7] - + ((sp_uint128)a[ 4]) * a[ 6]) * 2 - + ((sp_uint128)a[ 5]) * a[ 5]; - r[ 9] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 3]) * a[ 8] - + ((sp_uint128)a[ 4]) * a[ 7] - + ((sp_uint128)a[ 5]) * a[ 6]) * 2; - r[10] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 4]) * a[ 8] - + ((sp_uint128)a[ 5]) * a[ 7]) * 2 - + ((sp_uint128)a[ 6]) * a[ 6]; - r[11] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 5]) * a[ 8] - + ((sp_uint128)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 6]) * a[ 8]) * 2 - + ((sp_uint128)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - r[16] = (sp_digit)(t0 & 0x1ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 57); - XMEMCPY(r, t, sizeof(t)); -} - -/* 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_2048_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_2048_add_9(a1, a, &a[9]); - sp_2048_sqr_9(z2, &a[9]); - sp_2048_sqr_9(z0, a); - sp_2048_sqr_9(z1, a1); - (void)sp_2048_sub_18(z1, z1, z2); - (void)sp_2048_sub_18(z1, z1, z0); - (void)sp_2048_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_2048_sqr_36(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[36]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 36; - (void)sp_2048_add_18(a1, a, &a[18]); - sp_2048_sqr_18(z2, &a[18]); - sp_2048_sqr_18(z0, a); - sp_2048_sqr_18(z1, a1); - (void)sp_2048_sub_36(z1, z1, z2); - (void)sp_2048_sub_36(z1, z1, z0); - (void)sp_2048_add_36(r + 18, r + 18, z1); -} - -#endif /* !WOLFSSL_SP_SMALL */ -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ - x &= 0x1ffffffffffffffL; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 57) - x; -} - -/* 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_2048_mul_d_36(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 36; 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; - } - r[36] = (sp_digit)(t & 0x1ffffffffffffffL); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_2048_mont_norm_18(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 16; i += 8) { - r[i + 0] = 0x1ffffffffffffffL; - r[i + 1] = 0x1ffffffffffffffL; - r[i + 2] = 0x1ffffffffffffffL; - r[i + 3] = 0x1ffffffffffffffL; - r[i + 4] = 0x1ffffffffffffffL; - r[i + 5] = 0x1ffffffffffffffL; - r[i + 6] = 0x1ffffffffffffffL; - r[i + 7] = 0x1ffffffffffffffL; - } - r[16] = 0x1ffffffffffffffL; - r[17] = 0x7fffffffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_2048_sub_18(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_2048_cmp_18(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[17] - b[17]) & (0 - (sp_digit)1); - r |= (a[16] - b[16]) & ~(((sp_digit)0 - r) >> 56); - for (i = 8; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 56); - } - - 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_2048_cond_sub_18(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - 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); -} - -/* 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_2048_mul_add_18(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 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); -} - -/* 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_2048_mont_shift_18(sp_digit* r, const sp_digit* a) -{ - sp_uint64 n; - int i; - - n = (sp_uint64)a[17]; - n = n >> 55U; - for (i = 0; i < 16; i += 8) { - n += (sp_uint64)a[i+18] << 2U; r[i+0] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+19] << 2U; r[i+1] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+20] << 2U; r[i+2] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+21] << 2U; r[i+3] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+22] << 2U; r[i+4] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+23] << 2U; r[i+5] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+24] << 2U; r[i+6] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+25] << 2U; r[i+7] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - } - n += (sp_uint64)a[34] << 2U; r[16] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[35] << 2U; r[17] = n; - XMEMSET(&r[18], 0, sizeof(*r) * 18U); -} - -/* 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. - */ -static void sp_2048_mont_reduce_18(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_2048_norm_18(a + 18); - - for (i=0; i<17; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_2048_mul_add_18(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7fffffffffffffL); - 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); - over = a[17] - m[17]; - sp_2048_cond_sub_18(a, a, m, ~((over - 1) >> 63)); - sp_2048_norm_18(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_2048_mul_d_18(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 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); -} - -#ifndef 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_2048_cond_add_18(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - 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 */ - -SP_NOINLINE static void sp_2048_rshift_18(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<16; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (57 - n)) & 0x1ffffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (57 - n)) & 0x1ffffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (57 - n)) & 0x1ffffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (57 - n)) & 0x1ffffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (57 - n)) & 0x1ffffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (57 - n)) & 0x1ffffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (57 - n)) & 0x1ffffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (57 - n)) & 0x1ffffffffffffffL); - } - r[16] = (a[16] >> n) | (sp_digit)((a[17] << (57 - n)) & 0x1ffffffffffffffL); - r[17] = a[17] >> n; -} - -static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 57) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 57); - sp_digit t0 = (sp_digit)(d & 0x1ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 55; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 56) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 57); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 114) - (sp_digit)(d >> 114); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 26) + 1; - - t = (sp_digit)(d >> 52); - t = (t / dv) << 26; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 21); - t = t / (dv << 5); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_2048_word_div_word_18(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_18(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 18 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 18 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 36 + 1; - sd = t2 + 18 + 1; - - sp_2048_mul_d_18(sd, d, (sp_digit)1 << 2); - sp_2048_mul_d_36(t1, a, (sp_digit)1 << 2); - dv = sd[17]; - t1[18 + 18] += t1[18 + 18 - 1] >> 57; - t1[18 + 18 - 1] &= 0x1ffffffffffffffL; - for (i=18; i>=0; i--) { - r1 = sp_2048_div_word_18(t1[18 + i], t1[18 + i - 1], dv); - - sp_2048_mul_d_18(t2, sd, r1); - (void)sp_2048_sub_18(&t1[i], &t1[i], t2); - sp_2048_norm_18(&t1[i]); - t1[18 + i] -= t2[18]; - t1[18 + i] += t1[18 + i - 1] >> 57; - t1[18 + i - 1] &= 0x1ffffffffffffffL; - r1 = sp_2048_div_word_18(-t1[18 + i], -t1[18 + i - 1], dv); - r1 -= t1[18 + i]; - sp_2048_mul_d_18(t2, sd, r1); - (void)sp_2048_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 = sp_2048_word_div_word_18(t1[18 - 1], dv); - - sp_2048_mul_d_18(t2, sd, r1); - sp_2048_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_2048_cond_add_18(r, r, sd, r[17] >> 63); - - sp_2048_norm_18(r); - sp_2048_rshift_18(r, r, 2); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_2048_mod_18(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_2048_div_18(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 36); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 36, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 18 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 18U * 2U); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_18(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_18(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 18U); - } - } - if (err == MP_OKAY) { - sp_2048_mul_18(t[1], t[1], norm); - err = sp_2048_mod_18(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 18 * 2); - sp_2048_mont_sqr_18(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 18 * 2); - } - - sp_2048_mont_reduce_18(t[0], m, mp); - n = sp_2048_cmp_18(t[0], m); - sp_2048_cond_sub_18(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 18 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 36); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 36, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 18 * 2); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_18(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_18(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_18(t[1], t[1], norm); - err = sp_2048_mod_18(t[1], t[1], m); - } - } - else { - sp_2048_mul_18(t[1], a, norm); - err = sp_2048_mod_18(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 18 * 2); - sp_2048_mont_sqr_18(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 18 * 2); - } - - sp_2048_mont_reduce_18(t[0], m, mp); - n = sp_2048_cmp_18(t[0], m); - sp_2048_cond_sub_18(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 18 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 36) + 36); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 36) + 36, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 36; - rt = td + 1152; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_18(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_18(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_18(t[1], t[1], norm); - err = sp_2048_mod_18(t[1], t[1], m); - } - } - else { - sp_2048_mul_18(t[1], a, norm); - err = sp_2048_mod_18(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_2048_mont_sqr_18(t[ 2], t[ 1], m, mp); - sp_2048_mont_mul_18(t[ 3], t[ 2], t[ 1], m, mp); - sp_2048_mont_sqr_18(t[ 4], t[ 2], m, mp); - sp_2048_mont_mul_18(t[ 5], t[ 3], t[ 2], m, mp); - sp_2048_mont_sqr_18(t[ 6], t[ 3], m, mp); - sp_2048_mont_mul_18(t[ 7], t[ 4], t[ 3], m, mp); - sp_2048_mont_sqr_18(t[ 8], t[ 4], m, mp); - sp_2048_mont_mul_18(t[ 9], t[ 5], t[ 4], m, mp); - sp_2048_mont_sqr_18(t[10], t[ 5], m, mp); - sp_2048_mont_mul_18(t[11], t[ 6], t[ 5], m, mp); - sp_2048_mont_sqr_18(t[12], t[ 6], m, mp); - sp_2048_mont_mul_18(t[13], t[ 7], t[ 6], m, mp); - sp_2048_mont_sqr_18(t[14], t[ 7], m, mp); - sp_2048_mont_mul_18(t[15], t[ 8], t[ 7], m, mp); - sp_2048_mont_sqr_18(t[16], t[ 8], m, mp); - sp_2048_mont_mul_18(t[17], t[ 9], t[ 8], m, mp); - sp_2048_mont_sqr_18(t[18], t[ 9], m, mp); - sp_2048_mont_mul_18(t[19], t[10], t[ 9], m, mp); - sp_2048_mont_sqr_18(t[20], t[10], m, mp); - sp_2048_mont_mul_18(t[21], t[11], t[10], m, mp); - sp_2048_mont_sqr_18(t[22], t[11], m, mp); - sp_2048_mont_mul_18(t[23], t[12], t[11], m, mp); - sp_2048_mont_sqr_18(t[24], t[12], m, mp); - sp_2048_mont_mul_18(t[25], t[13], t[12], m, mp); - sp_2048_mont_sqr_18(t[26], t[13], m, mp); - sp_2048_mont_mul_18(t[27], t[14], t[13], m, mp); - sp_2048_mont_sqr_18(t[28], t[14], m, mp); - sp_2048_mont_mul_18(t[29], t[15], t[14], m, mp); - sp_2048_mont_sqr_18(t[30], t[15], m, mp); - sp_2048_mont_mul_18(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 56) / 57) - 1; - c = bits % 57; - if (c == 0) { - c = 57; - } - if (i < 18) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (7 - c); - c += 57; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 36); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 7; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 52; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 7; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 57 - c; - } - - sp_2048_mont_sqr_18(rt, rt, m, mp); - sp_2048_mont_sqr_18(rt, rt, m, mp); - sp_2048_mont_sqr_18(rt, rt, m, mp); - sp_2048_mont_sqr_18(rt, rt, m, mp); - sp_2048_mont_sqr_18(rt, rt, m, mp); - - sp_2048_mont_mul_18(rt, rt, t[y], m, mp); - } - - sp_2048_mont_reduce_18(rt, m, mp); - n = sp_2048_cmp_18(rt, m); - sp_2048_cond_sub_18(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 36); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_2048_mont_norm_36(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 32; i += 8) { - r[i + 0] = 0x1ffffffffffffffL; - r[i + 1] = 0x1ffffffffffffffL; - r[i + 2] = 0x1ffffffffffffffL; - r[i + 3] = 0x1ffffffffffffffL; - r[i + 4] = 0x1ffffffffffffffL; - r[i + 5] = 0x1ffffffffffffffL; - r[i + 6] = 0x1ffffffffffffffL; - r[i + 7] = 0x1ffffffffffffffL; - } - r[32] = 0x1ffffffffffffffL; - r[33] = 0x1ffffffffffffffL; - r[34] = 0x1ffffffffffffffL; - r[35] = 0x1fffffffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_2048_sub_36(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_2048_cmp_36(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[35] - b[35]) & (0 - (sp_digit)1); - r |= (a[34] - b[34]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[33] - b[33]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[32] - b[32]) & ~(((sp_digit)0 - r) >> 56); - for (i = 24; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 56); - } - - 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_2048_cond_sub_36(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] - (b[32] & m); - r[33] = a[33] - (b[33] & m); - r[34] = a[34] - (b[34] & m); - r[35] = a[35] - (b[35] & m); -} - -/* 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_2048_mul_add_36(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[8]; - int i; - - t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffffffffffffL); - for (i = 0; i < 32; 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[33]; - r[33] += (sp_digit)((t[0] >> 57) + (t[1] & 0x1ffffffffffffffL)); - t[2] = tb * a[34]; - r[34] += (sp_digit)((t[1] >> 57) + (t[2] & 0x1ffffffffffffffL)); - t[3] = tb * a[35]; - r[35] += (sp_digit)((t[2] >> 57) + (t[3] & 0x1ffffffffffffffL)); - r[36] += (sp_digit)(t[3] >> 57); -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a) -{ - sp_digit n; - sp_digit s; - int i; - - s = a[36]; n = a[35] >> 53; - for (i = 0; i < 32; i += 8) { - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+0] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+37] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+1] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+38] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+2] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+39] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+3] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+40] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+4] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+41] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+5] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+42] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+6] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+43] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[i+7] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+44] + (s >> 57); - } - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[32] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[69] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[33] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[70] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 4); r[34] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[71] + (s >> 57); - n += s << 4; r[35] = n; - XMEMSET(&r[36], 0, sizeof(*r) * 36U); -} - -/* 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. - */ -static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_2048_norm_36(a + 36); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<35; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; - } - else { - for (i=0; i<35; i++) { - mu = (sp_digit)(a[i] & 0x1ffffffffffffffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(a[i] & 0x1fffffffffffffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; - } -#else - for (i=0; i<35; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffL); - sp_2048_mul_add_36(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; -#endif - sp_2048_mont_shift_36(a, a); - over = a[35] - m[35]; - sp_2048_cond_sub_36(a, a, m, ~((over - 1) >> 63)); - sp_2048_norm_36(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_2048_mul_d_72(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 72; 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; - } - r[72] = (sp_digit)(t & 0x1ffffffffffffffL); -} - -#ifndef 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_2048_cond_add_36(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] + (b[32] & m); - r[33] = a[33] + (b[33] & m); - r[34] = a[34] + (b[34] & m); - r[35] = a[35] + (b[35] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_2048_rshift_36(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<32; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (57 - n)) & 0x1ffffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (57 - n)) & 0x1ffffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (57 - n)) & 0x1ffffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (57 - n)) & 0x1ffffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (57 - n)) & 0x1ffffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (57 - n)) & 0x1ffffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (57 - n)) & 0x1ffffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (57 - n)) & 0x1ffffffffffffffL); - } - r[32] = (a[32] >> n) | (sp_digit)((a[33] << (57 - n)) & 0x1ffffffffffffffL); - r[33] = (a[33] >> n) | (sp_digit)((a[34] << (57 - n)) & 0x1ffffffffffffffL); - r[34] = (a[34] >> n) | (sp_digit)((a[35] << (57 - n)) & 0x1ffffffffffffffL); - r[35] = a[35] >> n; -} - -static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 57) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 57); - sp_digit t0 = (sp_digit)(d & 0x1ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 55; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 56) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 57); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 114) - (sp_digit)(d >> 114); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 26) + 1; - - t = (sp_digit)(d >> 52); - t = (t / dv) << 26; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 21); - t = t / (dv << 5); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_2048_word_div_word_36(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_36(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 36 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 36 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 72 + 1; - sd = t2 + 36 + 1; - - sp_2048_mul_d_36(sd, d, (sp_digit)1 << 4); - sp_2048_mul_d_72(t1, a, (sp_digit)1 << 4); - dv = sd[35]; - t1[36 + 36] += t1[36 + 36 - 1] >> 57; - t1[36 + 36 - 1] &= 0x1ffffffffffffffL; - for (i=36; i>=0; i--) { - r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv); - - sp_2048_mul_d_36(t2, sd, r1); - (void)sp_2048_sub_36(&t1[i], &t1[i], t2); - sp_2048_norm_36(&t1[i]); - t1[36 + i] -= t2[36]; - t1[36 + i] += t1[36 + i - 1] >> 57; - t1[36 + i - 1] &= 0x1ffffffffffffffL; - r1 = sp_2048_div_word_36(-t1[36 + i], -t1[36 + i - 1], dv); - r1 -= t1[36 + i]; - sp_2048_mul_d_36(t2, sd, r1); - (void)sp_2048_add_36(&t1[i], &t1[i], t2); - t1[36 + i] += t1[36 + i - 1] >> 57; - t1[36 + i - 1] &= 0x1ffffffffffffffL; - } - t1[36 - 1] += t1[36 - 2] >> 57; - t1[36 - 2] &= 0x1ffffffffffffffL; - r1 = sp_2048_word_div_word_36(t1[36 - 1], dv); - - sp_2048_mul_d_36(t2, sd, r1); - sp_2048_sub_36(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 72U); - for (i=0; i<35; i++) { - r[i+1] += r[i] >> 57; - r[i] &= 0x1ffffffffffffffL; - } - sp_2048_cond_add_36(r, r, sd, r[35] >> 63); - - sp_2048_norm_36(r); - sp_2048_rshift_36(r, r, 4); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_2048_mod_36(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_2048_div_36(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 72); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 72, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 36 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 36U * 2U); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_36(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 36U); - } - } - if (err == MP_OKAY) { - sp_2048_mul_36(t[1], t[1], norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 36 * 2); - sp_2048_mont_sqr_36(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 36 * 2); - } - - sp_2048_mont_reduce_36(t[0], m, mp); - n = sp_2048_cmp_36(t[0], m); - sp_2048_cond_sub_36(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 72); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 72, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 36 * 2); - } - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_36(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_36(t[1], t[1], norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - else { - sp_2048_mul_36(t[1], a, norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 36 * 2); - sp_2048_mont_sqr_36(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 36 * 2); - } - - sp_2048_mont_reduce_36(t[0], m, mp); - n = sp_2048_cmp_36(t[0], m); - sp_2048_cond_sub_36(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 72) + 72); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 72) + 72, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 72; - rt = td + 1152; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - if (reduceA != 0) { - err = sp_2048_mod_36(t[1], a, m); - if (err == MP_OKAY) { - sp_2048_mul_36(t[1], t[1], norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - else { - sp_2048_mul_36(t[1], a, norm); - err = sp_2048_mod_36(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp); - sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp); - sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp); - sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp); - sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp); - sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp); - sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp); - sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp); - sp_2048_mont_sqr_36(t[10], t[ 5], m, mp); - sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp); - sp_2048_mont_sqr_36(t[12], t[ 6], m, mp); - sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp); - sp_2048_mont_sqr_36(t[14], t[ 7], m, mp); - sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 56) / 57) - 1; - c = bits % 57; - if (c == 0) { - c = 57; - } - if (i < 36) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (7 - c); - c += 57; - } - y = (int)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 72); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 7; - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c = 53; - } - else { - y = (byte)((n >> 60) & 0xf); - n = e[i--] << 7; - c = 4 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 57 - c; - } - - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - sp_2048_mont_sqr_36(rt, rt, m, mp); - - sp_2048_mont_mul_36(rt, rt, t[y], m, mp); - } - - sp_2048_mont_reduce_36(rt, m, mp); - n = sp_2048_cmp_36(rt, m); - sp_2048_cond_sub_36(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 72); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 36 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 256U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 36 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 36 * 2; - m = r + 36 * 2; - norm = r; - - sp_2048_from_bin(a, 36, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_2048_from_mp(m, 36, mm); - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - } - if (err == MP_OKAY) { - sp_2048_mul_36(a, a, norm); - err = sp_2048_mod_36(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 36 * 2); - for (i--; i>=0; i--) { - sp_2048_mont_sqr_36(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_2048_mont_mul_36(r, r, a, m, mp); - } - } - sp_2048_mont_reduce_36(r, m, mp); - mp = sp_2048_cmp_36(r, m); - sp_2048_cond_sub_36(r, r, m, ~(mp >> 63)); - - sp_2048_to_bin_36(r, out); - *outLen = 256; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 36 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 36 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 36 * 2; - m = r + 36 * 2; - - sp_2048_from_bin(a, 36, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_2048_from_mp(m, 36, mm); - - if (e[0] == 0x3) { - sp_2048_sqr_36(r, a); - err = sp_2048_mod_36(r, r, m); - if (err == MP_OKAY) { - sp_2048_mul_36(r, a, r); - err = sp_2048_mod_36(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - sp_2048_mul_36(a, a, norm); - err = sp_2048_mod_36(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 72U); - for (i--; i>=0; i--) { - sp_2048_mont_sqr_36(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_2048_mont_mul_36(r, r, a, m, mp); - } - } - sp_2048_mont_reduce_36(r, m, mp); - mp = sp_2048_cmp_36(r, m); - sp_2048_cond_sub_36(r, r, m, ~(mp >> 63)); - } - } - } - - if (err == MP_OKAY) { - sp_2048_to_bin_36(r, out); - *outLen = 256; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 36 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 2048) { - err = MP_READ_E; - } - else if (inLen > 256) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 36 * 4, NULL, DYNAMIC_TYPE_RSA); - 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); - err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); - } - - if (err == MP_OKAY) { - sp_2048_to_bin_36(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 36, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 36 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 2048) { - err = MP_READ_E; - } - else if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 36 * 4, NULL, DYNAMIC_TYPE_RSA); - 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); - err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); - } - - if (err == MP_OKAY) { - sp_2048_to_bin_36(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 36, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 18 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 256) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 18 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 36; - qi = dq = dp = p + 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(dp, 18, dpm); - err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1); - } - if (err == MP_OKAY) { - sp_2048_from_mp(p, 18, qm); - sp_2048_from_mp(dq, 18, dqm); - err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, p, 1); - } - if (err == MP_OKAY) { - sp_2048_from_mp(p, 18, pm); - (void)sp_2048_sub_18(tmpa, tmpa, tmpb); - sp_2048_norm_18(tmpa); - sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); - sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); - sp_2048_norm_18(tmpa); - - sp_2048_from_mp(qi, 18, qim); - sp_2048_mul_18(tmpa, tmpa, qi); - err = sp_2048_mod_18(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_2048_from_mp(p, 18, qm); - sp_2048_mul_18(tmpa, p, tmpa); - (void)sp_2048_add_36(r, tmpb, tmpa); - sp_2048_norm_36(r); - - sp_2048_to_bin_36(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR(sp_digit, a, 18 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 18 * 13); - 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; - (void)mm; - - if (*outLen < 256U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 18 * 13, NULL, DYNAMIC_TYPE_RSA); - 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); - sp_2048_from_mp(dp, 18, dpm); - sp_2048_from_mp(dq, 18, dqm); - sp_2048_from_mp(qi, 18, qim); - - err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1); - } - if (err == MP_OKAY) { - err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_2048_sub_18(tmpa, tmpa, tmpb); - sp_2048_norm_18(tmpa); - sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); - sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); - sp_2048_norm_18(tmpa); - sp_2048_mul_18(tmpa, tmpa, qi); - err = sp_2048_mod_18(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_2048_mul_18(tmpa, tmpa, q); - (void)sp_2048_add_36(r, tmpb, tmpa); - sp_2048_norm_36(r); - - sp_2048_to_bin_36(r, out); - *outLen = 256; - } - - SP_ZEROFREE_VAR(sp_digit, a, 18 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_2048_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (2048 + 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) * 36); - r->used = 36; - mp_clamp(r); -#elif DIGIT_BIT < 57 - 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] &= ((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 = (2048 + 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 < 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] &= ((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 = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 36 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expBits > 2048) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 36 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 36U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 36 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expBits > 2048) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 36 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 36U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_2048 -SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, const sp_digit* a, - byte n) -{ - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[35]; - r[36] = s >> (57U - n); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - r[0] = (sp_digit)((a[0] << n) & 0x1ffffffffffffffL); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 109); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 109, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 72; - XMEMSET(td, 0, sizeof(sp_digit) * 109); - - sp_2048_mont_setup(m, &mp); - sp_2048_mont_norm_36(norm, m); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 56) / 57) - 1; - c = bits % 57; - if (c == 0) { - c = 57; - } - if (i < 36) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (7 - c); - c += 57; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - sp_2048_lshift_36(r, norm, (byte)y); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 7; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 52; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 7; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 57 - c; - } - - sp_2048_mont_sqr_36(r, r, m, mp); - sp_2048_mont_sqr_36(r, r, m, mp); - sp_2048_mont_sqr_36(r, r, m, mp); - sp_2048_mont_sqr_36(r, r, m, mp); - sp_2048_mont_sqr_36(r, r, m, mp); - - sp_2048_lshift_36(r, r, (byte)y); - sp_2048_mul_d_36(tmp, norm, (r[36] << 4) + (r[35] >> 53)); - r[36] = 0; - r[35] &= 0x1fffffffffffffL; - (void)sp_2048_add_36(r, r, tmp); - sp_2048_norm_36(r); - o = sp_2048_cmp_36(r, m); - sp_2048_cond_sub_36(r, r, m, ~(o >> 63)); - } - - sp_2048_mont_reduce_36(r, m, mp); - n = sp_2048_cmp_36(r, m); - sp_2048_cond_sub_36(r, r, m, (sp_digit)~(n >> 63)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_2048 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 256 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 36 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 2048) { - err = MP_READ_E; - } - else if (expLen > 256U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 2048) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 36 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - #ifdef HAVE_FFDHE_2048 - if (base->used == 1 && base->dp[0] == 2U && - (m[35] >> 21) == 0xffffffffL) { - err = sp_2048_mod_exp_2_36(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_2048_mod_exp_36(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_2048 - } - #endif - } - - if (err == MP_OKAY) { - sp_2048_to_bin_36(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 36U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 18 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1024) { - err = MP_READ_E; - } - else if (expBits > 1024) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1024) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 18 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_2048_mod_exp_18(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 18, 0, sizeof(*r) * 18U); - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 36U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 18 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1024) { - err = MP_READ_E; - } - else if (expBits > 1024) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1024) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 18 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_2048_mod_exp_18(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 18, 0, sizeof(*r) * 18U); - err = sp_2048_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 36U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#endif /* WOLFSSL_SP_SMALL */ -#endif /* !WOLFSSL_SP_NO_2048 */ - -#ifndef WOLFSSL_SP_NO_3072 -#ifdef WOLFSSL_SP_SMALL -/* 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_3072_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 >= 52U) { - r[j] &= 0xfffffffffffffffL; - s = 60U - 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; - } -} - -/* 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_3072_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 60 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 59); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 59); - } -#elif DIGIT_BIT > 60 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xfffffffffffffffL; - s = 60U - 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 + 60U) <= (word32)DIGIT_BIT) { - s += 60U; - r[j] &= 0xfffffffffffffffL; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 60) { - r[j] &= 0xfffffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 60 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 384 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_3072_to_bin_52(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<51; i++) { - r[i+1] += r[i] >> 60; - r[i] &= 0xfffffffffffffffL; - } - j = 3079 / 8 - 1; - a[j] = 0; - for (i=0; i<52 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 60) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 60); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 60 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_26(sp_digit* a) -{ - int i; - for (i = 0; i < 25; i++) { - a[i+1] += a[i] >> 60; - a[i] &= 0xfffffffffffffffL; - } -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 60 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_52(sp_digit* a) -{ - int i; - for (i = 0; i < 51; i++) { - a[i+1] += a[i] >> 60; - a[i] &= 0xfffffffffffffffL; - } -} - -/* 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_3072_mul_52(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[51]) * b[51]; - r[103] = (sp_digit)(c >> 60); - c &= 0xfffffffffffffffL; - for (k = 101; k >= 0; k--) { - if (k >= 52) { - i = k - 51; - imax = 51; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 60; - r[k + 2] += (sp_digit)(c >> 60); - r[k + 1] = (sp_digit)(c & 0xfffffffffffffffL); - c = lo & 0xfffffffffffffffL; - } - r[0] = (sp_digit)c; -} - -/* 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_3072_sqr_52(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[51]) * a[51]; - r[103] = (sp_digit)(c >> 60); - c = (c & 0xfffffffffffffffL) << 60; - for (k = 101; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 51) { - imax = k; - } - else { - imax = 51; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 120); - r[k + 1] = (sp_digit)((c >> 60) & 0xfffffffffffffffL); - c = (c & 0xfffffffffffffffL) << 60; - } - r[0] = (sp_digit)(c >> 60); -} - -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ - x &= 0xfffffffffffffffL; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 60) - x; -} - -/* 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_3072_mul_d_52(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 52; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0xfffffffffffffffL); - t >>= 60; - } - r[52] = (sp_digit)t; -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* 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_26(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 26; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_26(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<25; i++) { - r[i] = 0xfffffffffffffffL; - } - r[25] = 0xfffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_26(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_26(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=25; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 59); - } - - 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_3072_cond_sub_26(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 26; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_3072_mul_add_26(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 24; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0xfffffffffffffffL); - t[1] += t[0] >> 60; - r[i+1] = (sp_digit)(t[1] & 0xfffffffffffffffL); - t[2] += t[1] >> 60; - r[i+2] = (sp_digit)(t[2] & 0xfffffffffffffffL); - t[3] += t[2] >> 60; - r[i+3] = (sp_digit)(t[3] & 0xfffffffffffffffL); - t[0] = t[3] >> 60; - } - t[0] += (tb * a[24]) + r[24]; - t[1] = (tb * a[25]) + r[25]; - r[24] = (sp_digit)(t[0] & 0xfffffffffffffffL); - t[1] += t[0] >> 60; - r[25] = (sp_digit)(t[1] & 0xfffffffffffffffL); - r[26] += (sp_digit)(t[1] >> 60); -} - -/* Shift the result in the high 1536 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_26(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[25] >> 36; - n += ((sp_int128)a[26]) << 24; - - for (i = 0; i < 25; i++) { - r[i] = (sp_digit)(n & 0xfffffffffffffffL); - n >>= 60; - n += ((sp_int128)a[27 + i]) << 24; - } - r[25] = (sp_digit)n; - XMEMSET(&r[26], 0, sizeof(*r) * 26U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_26(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_26(a + 26); - - for (i=0; i<25; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffffffffffffffL); - sp_3072_mul_add_26(a+i, m, mu); - a[i+1] += a[i] >> 60; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffffffffL); - sp_3072_mul_add_26(a+i, m, mu); - a[i+1] += a[i] >> 60; - a[i] &= 0xfffffffffffffffL; - sp_3072_mont_shift_26(a, a); - over = a[25] - m[25]; - sp_3072_cond_sub_26(a, a, m, ~((over - 1) >> 63)); - sp_3072_norm_26(a); -} - -/* 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_3072_mul_26(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[25]) * b[25]; - r[51] = (sp_digit)(c >> 60); - c &= 0xfffffffffffffffL; - for (k = 49; k >= 0; k--) { - if (k >= 26) { - i = k - 25; - imax = 25; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 60; - r[k + 2] += (sp_digit)(c >> 60); - r[k + 1] = (sp_digit)(c & 0xfffffffffffffffL); - c = lo & 0xfffffffffffffffL; - } - r[0] = (sp_digit)c; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_mul_26(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_3072_mul_26(r, a, b); - sp_3072_mont_reduce_26(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_3072_sqr_26(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[25]) * a[25]; - r[51] = (sp_digit)(c >> 60); - c = (c & 0xfffffffffffffffL) << 60; - for (k = 49; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 25) { - imax = k; - } - else { - imax = 25; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 120); - r[k + 1] = (sp_digit)((c >> 60) & 0xfffffffffffffffL); - c = (c & 0xfffffffffffffffL) << 60; - } - r[0] = (sp_digit)(c >> 60); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_sqr_26(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_3072_sqr_26(r, a); - sp_3072_mont_reduce_26(r, m, mp); -} - -/* 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_3072_mul_d_26(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 26; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0xfffffffffffffffL); - t >>= 60; - } - r[26] = (sp_digit)t; -} - -#ifdef 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_3072_cond_add_26(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 26; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_3072_add_26(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 26; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_3072_rshift_26(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<25; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (60 - n))) & 0xfffffffffffffffL); - } - r[25] = a[25] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_26(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 60) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 60) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 60) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 60); - sp_digit t0 = (sp_digit)(d & 0xfffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 58; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 59) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 60); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 120) - (sp_digit)(d >> 120); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 60) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 29) + 1; - - t = (sp_digit)(d >> 58); - t = (t / dv) << 29; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 27); - t = t / (dv << 2); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_26(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_26(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 26 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 26 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 52 + 1; - sd = t2 + 26 + 1; - - sp_3072_mul_d_26(sd, d, (sp_digit)1 << 24); - sp_3072_mul_d_52(t1, a, (sp_digit)1 << 24); - dv = sd[25]; - t1[26 + 26] += t1[26 + 26 - 1] >> 60; - t1[26 + 26 - 1] &= 0xfffffffffffffffL; - for (i=26; i>=0; i--) { - r1 = sp_3072_div_word_26(t1[26 + i], t1[26 + i - 1], dv); - - sp_3072_mul_d_26(t2, sd, r1); - (void)sp_3072_sub_26(&t1[i], &t1[i], t2); - sp_3072_norm_26(&t1[i]); - t1[26 + i] -= t2[26]; - t1[26 + i] += t1[26 + i - 1] >> 60; - t1[26 + i - 1] &= 0xfffffffffffffffL; - r1 = sp_3072_div_word_26(-t1[26 + i], -t1[26 + i - 1], dv); - r1 -= t1[26 + i]; - sp_3072_mul_d_26(t2, sd, r1); - (void)sp_3072_add_26(&t1[i], &t1[i], t2); - t1[26 + i] += t1[26 + i - 1] >> 60; - t1[26 + i - 1] &= 0xfffffffffffffffL; - } - t1[26 - 1] += t1[26 - 2] >> 60; - t1[26 - 2] &= 0xfffffffffffffffL; - r1 = sp_3072_word_div_word_26(t1[26 - 1], dv); - - sp_3072_mul_d_26(t2, sd, r1); - sp_3072_sub_26(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 52U); - for (i=0; i<25; i++) { - r[i+1] += r[i] >> 60; - r[i] &= 0xfffffffffffffffL; - } - sp_3072_cond_add_26(r, r, sd, r[25] >> 63); - - sp_3072_norm_26(r); - sp_3072_rshift_26(r, r, 24); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_26(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_26(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_26(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 52); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 52, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 26 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 26U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_26(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_26(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 26U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_26(t[1], t[1], norm); - err = sp_3072_mod_26(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 60; - c = bits % 60; - n = e[i--] << (60 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 60; - } - - y = (int)((n >> 59) & 1); - n <<= 1; - - sp_3072_mont_mul_26(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 26 * 2); - sp_3072_mont_sqr_26(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 26 * 2); - } - - sp_3072_mont_reduce_26(t[0], m, mp); - n = sp_3072_cmp_26(t[0], m); - sp_3072_cond_sub_26(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 26 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 52); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 52, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 26 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_26(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_26(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_26(t[1], t[1], norm); - err = sp_3072_mod_26(t[1], t[1], m); - } - } - else { - sp_3072_mul_26(t[1], a, norm); - err = sp_3072_mod_26(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 60; - c = bits % 60; - n = e[i--] << (60 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 60; - } - - y = (int)((n >> 59) & 1); - n <<= 1; - - sp_3072_mont_mul_26(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 26 * 2); - sp_3072_mont_sqr_26(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 26 * 2); - } - - sp_3072_mont_reduce_26(t[0], m, mp); - n = sp_3072_cmp_26(t[0], m); - sp_3072_cond_sub_26(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 26 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 52) + 52); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 52) + 52, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 52; - rt = td + 1664; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_26(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_26(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_26(t[1], t[1], norm); - err = sp_3072_mod_26(t[1], t[1], m); - } - } - else { - sp_3072_mul_26(t[1], a, norm); - err = sp_3072_mod_26(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_26(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_26(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_26(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_26(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_26(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_26(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_26(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_26(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_26(t[10], t[ 5], m, mp); - sp_3072_mont_mul_26(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_26(t[12], t[ 6], m, mp); - sp_3072_mont_mul_26(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_26(t[14], t[ 7], m, mp); - sp_3072_mont_mul_26(t[15], t[ 8], t[ 7], m, mp); - sp_3072_mont_sqr_26(t[16], t[ 8], m, mp); - sp_3072_mont_mul_26(t[17], t[ 9], t[ 8], m, mp); - sp_3072_mont_sqr_26(t[18], t[ 9], m, mp); - sp_3072_mont_mul_26(t[19], t[10], t[ 9], m, mp); - sp_3072_mont_sqr_26(t[20], t[10], m, mp); - sp_3072_mont_mul_26(t[21], t[11], t[10], m, mp); - sp_3072_mont_sqr_26(t[22], t[11], m, mp); - sp_3072_mont_mul_26(t[23], t[12], t[11], m, mp); - sp_3072_mont_sqr_26(t[24], t[12], m, mp); - sp_3072_mont_mul_26(t[25], t[13], t[12], m, mp); - sp_3072_mont_sqr_26(t[26], t[13], m, mp); - sp_3072_mont_mul_26(t[27], t[14], t[13], m, mp); - sp_3072_mont_sqr_26(t[28], t[14], m, mp); - sp_3072_mont_mul_26(t[29], t[15], t[14], m, mp); - sp_3072_mont_sqr_26(t[30], t[15], m, mp); - sp_3072_mont_mul_26(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 59) / 60) - 1; - c = bits % 60; - if (c == 0) { - c = 60; - } - if (i < 26) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (4 - c); - c += 60; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 52); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 4; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 55; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 4; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 60 - c; - } - - sp_3072_mont_sqr_26(rt, rt, m, mp); - sp_3072_mont_sqr_26(rt, rt, m, mp); - sp_3072_mont_sqr_26(rt, rt, m, mp); - sp_3072_mont_sqr_26(rt, rt, m, mp); - sp_3072_mont_sqr_26(rt, rt, m, mp); - - sp_3072_mont_mul_26(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_26(rt, m, mp); - n = sp_3072_cmp_26(rt, m); - sp_3072_cond_sub_26(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 52); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ - -/* 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_52(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 52; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_52(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<51; i++) { - r[i] = 0xfffffffffffffffL; - } - r[51] = 0xfffL; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_52(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_52(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=51; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 59); - } - - 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_3072_cond_sub_52(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 52; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_3072_mul_add_52(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 48; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0xfffffffffffffffL); - t[1] += t[0] >> 60; - r[i+1] = (sp_digit)(t[1] & 0xfffffffffffffffL); - t[2] += t[1] >> 60; - r[i+2] = (sp_digit)(t[2] & 0xfffffffffffffffL); - t[3] += t[2] >> 60; - r[i+3] = (sp_digit)(t[3] & 0xfffffffffffffffL); - t[0] = t[3] >> 60; - } - t[0] += (tb * a[48]) + r[48]; - t[1] = (tb * a[49]) + r[49]; - t[2] = (tb * a[50]) + r[50]; - t[3] = (tb * a[51]) + r[51]; - r[48] = (sp_digit)(t[0] & 0xfffffffffffffffL); - t[1] += t[0] >> 60; - r[49] = (sp_digit)(t[1] & 0xfffffffffffffffL); - t[2] += t[1] >> 60; - r[50] = (sp_digit)(t[2] & 0xfffffffffffffffL); - t[3] += t[2] >> 60; - r[51] = (sp_digit)(t[3] & 0xfffffffffffffffL); - r[52] += (sp_digit)(t[3] >> 60); -} - -/* Shift the result in the high 3072 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_52(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[51] >> 12; - n += ((sp_int128)a[52]) << 48; - - for (i = 0; i < 51; i++) { - r[i] = (sp_digit)(n & 0xfffffffffffffffL); - n >>= 60; - n += ((sp_int128)a[53 + i]) << 48; - } - r[51] = (sp_digit)n; - XMEMSET(&r[52], 0, sizeof(*r) * 52U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_52(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_52(a + 52); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<51; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffffffffffffffL); - sp_3072_mul_add_52(a+i, m, mu); - a[i+1] += a[i] >> 60; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffL); - sp_3072_mul_add_52(a+i, m, mu); - a[i+1] += a[i] >> 60; - a[i] &= 0xfffffffffffffffL; - } - else { - for (i=0; i<51; i++) { - mu = (sp_digit)(a[i] & 0xfffffffffffffffL); - sp_3072_mul_add_52(a+i, m, mu); - a[i+1] += a[i] >> 60; - } - mu = (sp_digit)(a[i] & 0xfffL); - sp_3072_mul_add_52(a+i, m, mu); - a[i+1] += a[i] >> 60; - a[i] &= 0xfffffffffffffffL; - } -#else - for (i=0; i<51; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffffffffffffffL); - sp_3072_mul_add_52(a+i, m, mu); - a[i+1] += a[i] >> 60; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffL); - sp_3072_mul_add_52(a+i, m, mu); - a[i+1] += a[i] >> 60; - a[i] &= 0xfffffffffffffffL; -#endif - sp_3072_mont_shift_52(a, a); - over = a[51] - m[51]; - sp_3072_cond_sub_52(a, a, m, ~((over - 1) >> 63)); - sp_3072_norm_52(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_mul_52(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_3072_mul_52(r, a, b); - sp_3072_mont_reduce_52(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_3072_mont_sqr_52(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_3072_sqr_52(r, a); - sp_3072_mont_reduce_52(r, m, mp); -} - -/* 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_3072_mul_d_104(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 104; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0xfffffffffffffffL); - t >>= 60; - } - r[104] = (sp_digit)t; -} - -#ifdef 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_3072_cond_add_52(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 52; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_3072_add_52(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 52; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_3072_rshift_52(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<51; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (60 - n))) & 0xfffffffffffffffL); - } - r[51] = a[51] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_52(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 60) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 60) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 60) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 60); - sp_digit t0 = (sp_digit)(d & 0xfffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 58; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 59) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 60); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 120) - (sp_digit)(d >> 120); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 60) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 29) + 1; - - t = (sp_digit)(d >> 58); - t = (t / dv) << 29; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 27); - t = t / (dv << 2); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_52(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_52(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 52 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 52 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 104 + 1; - sd = t2 + 52 + 1; - - sp_3072_mul_d_52(sd, d, (sp_digit)1 << 48); - sp_3072_mul_d_104(t1, a, (sp_digit)1 << 48); - dv = sd[51]; - t1[52 + 52] += t1[52 + 52 - 1] >> 60; - t1[52 + 52 - 1] &= 0xfffffffffffffffL; - for (i=52; i>=0; i--) { - r1 = sp_3072_div_word_52(t1[52 + i], t1[52 + i - 1], dv); - - sp_3072_mul_d_52(t2, sd, r1); - (void)sp_3072_sub_52(&t1[i], &t1[i], t2); - sp_3072_norm_52(&t1[i]); - t1[52 + i] -= t2[52]; - t1[52 + i] += t1[52 + i - 1] >> 60; - t1[52 + i - 1] &= 0xfffffffffffffffL; - r1 = sp_3072_div_word_52(-t1[52 + i], -t1[52 + i - 1], dv); - r1 -= t1[52 + i]; - sp_3072_mul_d_52(t2, sd, r1); - (void)sp_3072_add_52(&t1[i], &t1[i], t2); - t1[52 + i] += t1[52 + i - 1] >> 60; - t1[52 + i - 1] &= 0xfffffffffffffffL; - } - t1[52 - 1] += t1[52 - 2] >> 60; - t1[52 - 2] &= 0xfffffffffffffffL; - r1 = sp_3072_word_div_word_52(t1[52 - 1], dv); - - sp_3072_mul_d_52(t2, sd, r1); - sp_3072_sub_52(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 104U); - for (i=0; i<51; i++) { - r[i+1] += r[i] >> 60; - r[i] &= 0xfffffffffffffffL; - } - sp_3072_cond_add_52(r, r, sd, r[51] >> 63); - - sp_3072_norm_52(r); - sp_3072_rshift_52(r, r, 48); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_52(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_52(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_52(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 104); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 104, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 52 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 52U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_52(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_52(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 52U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_52(t[1], t[1], norm); - err = sp_3072_mod_52(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 60; - c = bits % 60; - n = e[i--] << (60 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 60; - } - - y = (int)((n >> 59) & 1); - n <<= 1; - - sp_3072_mont_mul_52(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 52 * 2); - sp_3072_mont_sqr_52(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 52 * 2); - } - - sp_3072_mont_reduce_52(t[0], m, mp); - n = sp_3072_cmp_52(t[0], m); - sp_3072_cond_sub_52(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 52 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 104); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 104, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 52 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_52(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_52(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_52(t[1], t[1], norm); - err = sp_3072_mod_52(t[1], t[1], m); - } - } - else { - sp_3072_mul_52(t[1], a, norm); - err = sp_3072_mod_52(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 60; - c = bits % 60; - n = e[i--] << (60 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 60; - } - - y = (int)((n >> 59) & 1); - n <<= 1; - - sp_3072_mont_mul_52(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 52 * 2); - sp_3072_mont_sqr_52(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 52 * 2); - } - - sp_3072_mont_reduce_52(t[0], m, mp); - n = sp_3072_cmp_52(t[0], m); - sp_3072_cond_sub_52(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 52 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 104) + 104); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 104) + 104, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 104; - rt = td + 1664; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_52(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_52(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_52(t[1], t[1], norm); - err = sp_3072_mod_52(t[1], t[1], m); - } - } - else { - sp_3072_mul_52(t[1], a, norm); - err = sp_3072_mod_52(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_52(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_52(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_52(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_52(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_52(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_52(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_52(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_52(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_52(t[10], t[ 5], m, mp); - sp_3072_mont_mul_52(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_52(t[12], t[ 6], m, mp); - sp_3072_mont_mul_52(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_52(t[14], t[ 7], m, mp); - sp_3072_mont_mul_52(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 59) / 60) - 1; - c = bits % 60; - if (c == 0) { - c = 60; - } - if (i < 52) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (4 - c); - c += 60; - } - y = (int)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 104); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 4; - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c = 56; - } - else { - y = (byte)((n >> 60) & 0xf); - n = e[i--] << 4; - c = 4 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 60 - c; - } - - sp_3072_mont_sqr_52(rt, rt, m, mp); - sp_3072_mont_sqr_52(rt, rt, m, mp); - sp_3072_mont_sqr_52(rt, rt, m, mp); - sp_3072_mont_sqr_52(rt, rt, m, mp); - - sp_3072_mont_mul_52(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_52(rt, m, mp); - n = sp_3072_cmp_52(rt, m); - sp_3072_cond_sub_52(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 104); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 52 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 52 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 52 * 2; - m = r + 52 * 2; - norm = r; - - sp_3072_from_bin(a, 52, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_3072_from_mp(m, 52, mm); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_52(norm, m); - } - if (err == MP_OKAY) { - sp_3072_mul_52(a, a, norm); - err = sp_3072_mod_52(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 52 * 2); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_52(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_52(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_52(r, m, mp); - mp = sp_3072_cmp_52(r, m); - sp_3072_cond_sub_52(r, r, m, ~(mp >> 63)); - - sp_3072_to_bin_52(r, out); - *outLen = 384; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 52 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 52 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 52 * 2; - m = r + 52 * 2; - - sp_3072_from_bin(a, 52, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_3072_from_mp(m, 52, mm); - - if (e[0] == 0x3) { - sp_3072_sqr_52(r, a); - err = sp_3072_mod_52(r, r, m); - if (err == MP_OKAY) { - sp_3072_mul_52(r, a, r); - err = sp_3072_mod_52(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_52(norm, m); - - sp_3072_mul_52(a, a, norm); - err = sp_3072_mod_52(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 104U); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_52(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_52(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_52(r, m, mp); - mp = sp_3072_cmp_52(r, m); - sp_3072_cond_sub_52(r, r, m, ~(mp >> 63)); - } - } - } - - if (err == MP_OKAY) { - sp_3072_to_bin_52(r, out); - *outLen = 384; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 52 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 52 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 52; - m = a + 104; - r = a; - - sp_3072_from_bin(a, 52, in, inLen); - sp_3072_from_mp(d, 52, dm); - sp_3072_from_mp(m, 52, mm); - err = sp_3072_mod_exp_52(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_52(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 52, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 52 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 52 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 52; - m = a + 104; - r = a; - - sp_3072_from_bin(a, 52, in, inLen); - sp_3072_from_mp(d, 52, dm); - sp_3072_from_mp(m, 52, mm); - err = sp_3072_mod_exp_52(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_52(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 52, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 26 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 26 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 52; - qi = dq = dp = p + 26; - tmpa = qi + 26; - tmpb = tmpa + 52; - r = a; - - sp_3072_from_bin(a, 52, in, inLen); - sp_3072_from_mp(p, 26, pm); - sp_3072_from_mp(dp, 26, dpm); - err = sp_3072_mod_exp_26(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 26, qm); - sp_3072_from_mp(dq, 26, dqm); - err = sp_3072_mod_exp_26(tmpb, a, dq, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 26, pm); - (void)sp_3072_sub_26(tmpa, tmpa, tmpb); - sp_3072_norm_26(tmpa); - sp_3072_cond_add_26(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[25] >> 63)); - sp_3072_cond_add_26(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[25] >> 63)); - sp_3072_norm_26(tmpa); - - sp_3072_from_mp(qi, 26, qim); - sp_3072_mul_26(tmpa, tmpa, qi); - err = sp_3072_mod_26(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_from_mp(p, 26, qm); - sp_3072_mul_26(tmpa, p, tmpa); - (void)sp_3072_add_52(r, tmpb, tmpa); - sp_3072_norm_52(r); - - sp_3072_to_bin_52(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 26 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 26 * 13); - 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 26 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 52 * 2; - q = p + 26; - dp = q + 26; - dq = dp + 26; - qi = dq + 26; - tmpa = qi + 26; - tmpb = tmpa + 52; - r = a; - - sp_3072_from_bin(a, 52, in, inLen); - sp_3072_from_mp(p, 26, pm); - sp_3072_from_mp(q, 26, qm); - sp_3072_from_mp(dp, 26, dpm); - sp_3072_from_mp(dq, 26, dqm); - sp_3072_from_mp(qi, 26, qim); - - err = sp_3072_mod_exp_26(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - err = sp_3072_mod_exp_26(tmpb, a, dq, 1536, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_3072_sub_26(tmpa, tmpa, tmpb); - sp_3072_norm_26(tmpa); - sp_3072_cond_add_26(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[25] >> 63)); - sp_3072_cond_add_26(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[25] >> 63)); - sp_3072_norm_26(tmpa); - sp_3072_mul_26(tmpa, tmpa, qi); - err = sp_3072_mod_26(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_mul_26(tmpa, tmpa, q); - (void)sp_3072_add_52(r, tmpb, tmpa); - sp_3072_norm_52(r); - - sp_3072_to_bin_52(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 26 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_3072_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 60 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 52); - r->used = 52; - mp_clamp(r); -#elif DIGIT_BIT < 60 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 52; 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 <= 60) { - 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 = 60 - s; - } - r->used = (3072 + 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 < 52; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 60 >= 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 = 60 - s; - } - else { - s += 60; - } - } - r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 52 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 52 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 52 * 2; - m = e + 52; - r = b; - - sp_3072_from_mp(b, 52, base); - sp_3072_from_mp(e, 52, exp); - sp_3072_from_mp(m, 52, mod); - - err = sp_3072_mod_exp_52(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 52U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 52 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 52 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 52 * 2; - m = e + 52; - r = b; - - sp_3072_from_mp(b, 52, base); - sp_3072_from_mp(e, 52, exp); - sp_3072_from_mp(m, 52, mod); - - err = sp_3072_mod_exp_52(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 52U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_3072 -SP_NOINLINE static void sp_3072_lshift_52(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - r[52] = a[51] >> (60 - n); - for (i=51; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (60 - n))) & 0xfffffffffffffffL); - } - r[0] = (sp_digit)((a[0] << n) & 0xfffffffffffffffL); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_3072_mod_exp_2_52(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 157); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 157, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 104; - XMEMSET(td, 0, sizeof(sp_digit) * 157); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_52(norm, m); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 59) / 60) - 1; - c = bits % 60; - if (c == 0) { - c = 60; - } - if (i < 52) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (4 - c); - c += 60; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - sp_3072_lshift_52(r, norm, (byte)y); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 4; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 55; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 4; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 60 - c; - } - - sp_3072_mont_sqr_52(r, r, m, mp); - sp_3072_mont_sqr_52(r, r, m, mp); - sp_3072_mont_sqr_52(r, r, m, mp); - sp_3072_mont_sqr_52(r, r, m, mp); - sp_3072_mont_sqr_52(r, r, m, mp); - - sp_3072_lshift_52(r, r, (byte)y); - sp_3072_mul_d_52(tmp, norm, (r[52] << 48) + (r[51] >> 12)); - r[52] = 0; - r[51] &= 0xfffL; - (void)sp_3072_add_52(r, r, tmp); - sp_3072_norm_52(r); - o = sp_3072_cmp_52(r, m); - sp_3072_cond_sub_52(r, r, m, ~(o >> 63)); - } - - sp_3072_mont_reduce_52(r, m, mp); - n = sp_3072_cmp_52(r, m); - sp_3072_cond_sub_52(r, r, m, (sp_digit)~(n >> 63)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_3072 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 52 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 52 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 52 * 2; - m = e + 52; - r = b; - - sp_3072_from_mp(b, 52, base); - sp_3072_from_bin(e, 52, exp, expLen); - sp_3072_from_mp(m, 52, mod); - - #ifdef HAVE_FFDHE_3072 - if (base->used == 1 && base->dp[0] == 2U && - ((m[51] << 20) | (m[50] >> 40)) == 0xffffffffL) { - err = sp_3072_mod_exp_2_52(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_3072_mod_exp_52(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_3072 - } - #endif - } - - if (err == MP_OKAY) { - sp_3072_to_bin_52(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 52U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 26 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 26 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 26 * 2; - m = e + 26; - r = b; - - sp_3072_from_mp(b, 26, base); - sp_3072_from_mp(e, 26, exp); - sp_3072_from_mp(m, 26, mod); - - err = sp_3072_mod_exp_26(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 26, 0, sizeof(*r) * 26U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 52U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 26 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 26 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 26 * 2; - m = e + 26; - r = b; - - sp_3072_from_mp(b, 26, base); - sp_3072_from_mp(e, 26, exp); - sp_3072_from_mp(m, 26, mod); - - err = sp_3072_mod_exp_26(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 26, 0, sizeof(*r) * 26U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 52U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#else -/* 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_3072_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; - } -} - -/* 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_3072_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 57 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 56); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 56); - } -#elif DIGIT_BIT > 57 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 384 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_3072_to_bin_54(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<53; i++) { - r[i+1] += r[i] >> 57; - r[i] &= 0x1ffffffffffffffL; - } - j = 3079 / 8 - 1; - a[j] = 0; - for (i=0; i<54 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 57) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 57); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Normalize the values in each word to 57 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_27(sp_digit* a) -{ - int i; - for (i = 0; i < 24; 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[25] += a[24] >> 57; a[24] &= 0x1ffffffffffffffL; - a[26] += a[25] >> 57; a[25] &= 0x1ffffffffffffffL; -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 57 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_3072_norm_54(sp_digit* a) -{ - int i; - for (i = 0; i < 48; 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[49] += a[48] >> 57; a[48] &= 0x1ffffffffffffffL; - a[50] += a[49] >> 57; a[49] &= 0x1ffffffffffffffL; - a[51] += a[50] >> 57; a[50] &= 0x1ffffffffffffffL; - a[52] += a[51] >> 57; a[51] &= 0x1ffffffffffffffL; - a[53] += a[52] >> 57; a[52] &= 0x1ffffffffffffffL; -} - -#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_3072_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_uint128 t0; - sp_uint128 t1; - sp_digit t[9]; - - t0 = ((sp_uint128)a[ 0]) * b[ 0]; - t1 = ((sp_uint128)a[ 0]) * b[ 1] - + ((sp_uint128)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 2] - + ((sp_uint128)a[ 1]) * b[ 1] - + ((sp_uint128)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 0]) * b[ 3] - + ((sp_uint128)a[ 1]) * b[ 2] - + ((sp_uint128)a[ 2]) * b[ 1] - + ((sp_uint128)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 4] - + ((sp_uint128)a[ 1]) * b[ 3] - + ((sp_uint128)a[ 2]) * b[ 2] - + ((sp_uint128)a[ 3]) * b[ 1] - + ((sp_uint128)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 0]) * b[ 5] - + ((sp_uint128)a[ 1]) * b[ 4] - + ((sp_uint128)a[ 2]) * b[ 3] - + ((sp_uint128)a[ 3]) * b[ 2] - + ((sp_uint128)a[ 4]) * b[ 1] - + ((sp_uint128)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 6] - + ((sp_uint128)a[ 1]) * b[ 5] - + ((sp_uint128)a[ 2]) * b[ 4] - + ((sp_uint128)a[ 3]) * b[ 3] - + ((sp_uint128)a[ 4]) * b[ 2] - + ((sp_uint128)a[ 5]) * b[ 1] - + ((sp_uint128)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 0]) * b[ 7] - + ((sp_uint128)a[ 1]) * b[ 6] - + ((sp_uint128)a[ 2]) * b[ 5] - + ((sp_uint128)a[ 3]) * b[ 4] - + ((sp_uint128)a[ 4]) * b[ 3] - + ((sp_uint128)a[ 5]) * b[ 2] - + ((sp_uint128)a[ 6]) * b[ 1] - + ((sp_uint128)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 0]) * b[ 8] - + ((sp_uint128)a[ 1]) * b[ 7] - + ((sp_uint128)a[ 2]) * b[ 6] - + ((sp_uint128)a[ 3]) * b[ 5] - + ((sp_uint128)a[ 4]) * b[ 4] - + ((sp_uint128)a[ 5]) * b[ 3] - + ((sp_uint128)a[ 6]) * b[ 2] - + ((sp_uint128)a[ 7]) * b[ 1] - + ((sp_uint128)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 1]) * b[ 8] - + ((sp_uint128)a[ 2]) * b[ 7] - + ((sp_uint128)a[ 3]) * b[ 6] - + ((sp_uint128)a[ 4]) * b[ 5] - + ((sp_uint128)a[ 5]) * b[ 4] - + ((sp_uint128)a[ 6]) * b[ 3] - + ((sp_uint128)a[ 7]) * b[ 2] - + ((sp_uint128)a[ 8]) * b[ 1]; - t[ 8] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 2]) * b[ 8] - + ((sp_uint128)a[ 3]) * b[ 7] - + ((sp_uint128)a[ 4]) * b[ 6] - + ((sp_uint128)a[ 5]) * b[ 5] - + ((sp_uint128)a[ 6]) * b[ 4] - + ((sp_uint128)a[ 7]) * b[ 3] - + ((sp_uint128)a[ 8]) * b[ 2]; - r[ 9] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 3]) * b[ 8] - + ((sp_uint128)a[ 4]) * b[ 7] - + ((sp_uint128)a[ 5]) * b[ 6] - + ((sp_uint128)a[ 6]) * b[ 5] - + ((sp_uint128)a[ 7]) * b[ 4] - + ((sp_uint128)a[ 8]) * b[ 3]; - r[10] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 4]) * b[ 8] - + ((sp_uint128)a[ 5]) * b[ 7] - + ((sp_uint128)a[ 6]) * b[ 6] - + ((sp_uint128)a[ 7]) * b[ 5] - + ((sp_uint128)a[ 8]) * b[ 4]; - r[11] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 5]) * b[ 8] - + ((sp_uint128)a[ 6]) * b[ 7] - + ((sp_uint128)a[ 7]) * b[ 6] - + ((sp_uint128)a[ 8]) * b[ 5]; - r[12] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 6]) * b[ 8] - + ((sp_uint128)a[ 7]) * b[ 7] - + ((sp_uint128)a[ 8]) * b[ 6]; - r[13] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_uint128)a[ 7]) * b[ 8] - + ((sp_uint128)a[ 8]) * b[ 7]; - r[14] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 8]) * b[ 8]; - r[15] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - r[16] = (sp_digit)(t0 & 0x1ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 57); - XMEMCPY(r, t, sizeof(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. - */ -SP_NOINLINE static int sp_3072_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; -} - -/* 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_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; -} - -/* 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_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_3072_mul_27(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit p0[18]; - sp_digit p1[18]; - sp_digit p2[18]; - sp_digit p3[18]; - sp_digit p4[18]; - sp_digit p5[18]; - sp_digit t0[18]; - sp_digit t1[18]; - sp_digit t2[18]; - sp_digit a0[9]; - sp_digit a1[9]; - sp_digit a2[9]; - sp_digit b0[9]; - sp_digit b1[9]; - sp_digit b2[9]; - (void)sp_3072_add_9(a0, a, &a[9]); - (void)sp_3072_add_9(b0, b, &b[9]); - (void)sp_3072_add_9(a1, &a[9], &a[18]); - (void)sp_3072_add_9(b1, &b[9], &b[18]); - (void)sp_3072_add_9(a2, a0, &a[18]); - (void)sp_3072_add_9(b2, b0, &b[18]); - sp_3072_mul_9(p0, a, b); - sp_3072_mul_9(p2, &a[9], &b[9]); - sp_3072_mul_9(p4, &a[18], &b[18]); - sp_3072_mul_9(p1, a0, b0); - sp_3072_mul_9(p3, a1, b1); - sp_3072_mul_9(p5, a2, b2); - XMEMSET(r, 0, sizeof(*r)*2U*27U); - (void)sp_3072_sub_18(t0, p3, p2); - (void)sp_3072_sub_18(t1, p1, p2); - (void)sp_3072_sub_18(t2, p5, t0); - (void)sp_3072_sub_18(t2, t2, t1); - (void)sp_3072_sub_18(t0, t0, p4); - (void)sp_3072_sub_18(t1, t1, p0); - (void)sp_3072_add_18(r, r, p0); - (void)sp_3072_add_18(&r[9], &r[9], t1); - (void)sp_3072_add_18(&r[18], &r[18], t2); - (void)sp_3072_add_18(&r[27], &r[27], t0); - (void)sp_3072_add_18(&r[36], &r[36], 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_3072_add_27(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] + b[24]; - r[25] = a[25] + b[25]; - r[26] = a[26] + b[26]; - - 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_3072_add_54(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 48; 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[48] = a[48] + b[48]; - r[49] = a[49] + b[49]; - r[50] = a[50] + b[50]; - r[51] = a[51] + b[51]; - r[52] = a[52] + b[52]; - r[53] = a[53] + b[53]; - - 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_3072_sub_54(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 48; 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[48] = a[48] - b[48]; - r[49] = a[49] - b[49]; - r[50] = a[50] - b[50]; - r[51] = a[51] - b[51]; - r[52] = a[52] - b[52]; - r[53] = a[53] - b[53]; - - 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_3072_mul_54(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[54]; - sp_digit* a1 = z1; - sp_digit b1[27]; - sp_digit* z2 = r + 54; - (void)sp_3072_add_27(a1, a, &a[27]); - (void)sp_3072_add_27(b1, b, &b[27]); - sp_3072_mul_27(z2, &a[27], &b[27]); - sp_3072_mul_27(z0, a, b); - sp_3072_mul_27(z1, a1, b1); - (void)sp_3072_sub_54(z1, z1, z2); - (void)sp_3072_sub_54(z1, z1, z0); - (void)sp_3072_add_54(r + 27, r + 27, 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_3072_sqr_9(sp_digit* r, const sp_digit* a) -{ - sp_uint128 t0; - sp_uint128 t1; - sp_digit t[9]; - - t0 = ((sp_uint128)a[ 0]) * a[ 0]; - t1 = (((sp_uint128)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 2]) * 2 - + ((sp_uint128)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 0]) * a[ 3] - + ((sp_uint128)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 4] - + ((sp_uint128)a[ 1]) * a[ 3]) * 2 - + ((sp_uint128)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 0]) * a[ 5] - + ((sp_uint128)a[ 1]) * a[ 4] - + ((sp_uint128)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 6] - + ((sp_uint128)a[ 1]) * a[ 5] - + ((sp_uint128)a[ 2]) * a[ 4]) * 2 - + ((sp_uint128)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 0]) * a[ 7] - + ((sp_uint128)a[ 1]) * a[ 6] - + ((sp_uint128)a[ 2]) * a[ 5] - + ((sp_uint128)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 0]) * a[ 8] - + ((sp_uint128)a[ 1]) * a[ 7] - + ((sp_uint128)a[ 2]) * a[ 6] - + ((sp_uint128)a[ 3]) * a[ 5]) * 2 - + ((sp_uint128)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 1]) * a[ 8] - + ((sp_uint128)a[ 2]) * a[ 7] - + ((sp_uint128)a[ 3]) * a[ 6] - + ((sp_uint128)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 2]) * a[ 8] - + ((sp_uint128)a[ 3]) * a[ 7] - + ((sp_uint128)a[ 4]) * a[ 6]) * 2 - + ((sp_uint128)a[ 5]) * a[ 5]; - r[ 9] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 3]) * a[ 8] - + ((sp_uint128)a[ 4]) * a[ 7] - + ((sp_uint128)a[ 5]) * a[ 6]) * 2; - r[10] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 4]) * a[ 8] - + ((sp_uint128)a[ 5]) * a[ 7]) * 2 - + ((sp_uint128)a[ 6]) * a[ 6]; - r[11] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 5]) * a[ 8] - + ((sp_uint128)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_uint128)a[ 6]) * a[ 8]) * 2 - + ((sp_uint128)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_uint128)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_uint128)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - r[16] = (sp_digit)(t0 & 0x1ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 57); - XMEMCPY(r, t, sizeof(t)); -} - -/* Square a into r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) -{ - sp_digit p0[18]; - sp_digit p1[18]; - sp_digit p2[18]; - sp_digit p3[18]; - sp_digit p4[18]; - sp_digit p5[18]; - sp_digit t0[18]; - sp_digit t1[18]; - sp_digit t2[18]; - sp_digit a0[9]; - sp_digit a1[9]; - sp_digit a2[9]; - (void)sp_3072_add_9(a0, a, &a[9]); - (void)sp_3072_add_9(a1, &a[9], &a[18]); - (void)sp_3072_add_9(a2, a0, &a[18]); - sp_3072_sqr_9(p0, a); - sp_3072_sqr_9(p2, &a[9]); - sp_3072_sqr_9(p4, &a[18]); - sp_3072_sqr_9(p1, a0); - sp_3072_sqr_9(p3, a1); - sp_3072_sqr_9(p5, a2); - XMEMSET(r, 0, sizeof(*r)*2U*27U); - (void)sp_3072_sub_18(t0, p3, p2); - (void)sp_3072_sub_18(t1, p1, p2); - (void)sp_3072_sub_18(t2, p5, t0); - (void)sp_3072_sub_18(t2, t2, t1); - (void)sp_3072_sub_18(t0, t0, p4); - (void)sp_3072_sub_18(t1, t1, p0); - (void)sp_3072_add_18(r, r, p0); - (void)sp_3072_add_18(&r[9], &r[9], t1); - (void)sp_3072_add_18(&r[18], &r[18], t2); - (void)sp_3072_add_18(&r[27], &r[27], t0); - (void)sp_3072_add_18(&r[36], &r[36], p4); -} - -/* 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_3072_sqr_54(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[54]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 54; - (void)sp_3072_add_27(a1, a, &a[27]); - sp_3072_sqr_27(z2, &a[27]); - sp_3072_sqr_27(z0, a); - sp_3072_sqr_27(z1, a1); - (void)sp_3072_sub_54(z1, z1, z2); - (void)sp_3072_sub_54(z1, z1, z0); - (void)sp_3072_add_54(r + 27, r + 27, z1); -} - -#endif /* !WOLFSSL_SP_SMALL */ -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ - x &= 0x1ffffffffffffffL; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 57) - x; -} - -/* 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_3072_mul_d_54(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 52; 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[52]; - r[52] = (sp_digit)(t & 0x1ffffffffffffffL); - t >>= 57; - t += tb * a[53]; - r[53] = (sp_digit)(t & 0x1ffffffffffffffL); - t >>= 57; - r[54] = (sp_digit)(t & 0x1ffffffffffffffL); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* 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_27(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] - b[24]; - r[25] = a[25] - b[25]; - r[26] = a[26] - b[26]; - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_27(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 24; i += 8) { - r[i + 0] = 0x1ffffffffffffffL; - r[i + 1] = 0x1ffffffffffffffL; - r[i + 2] = 0x1ffffffffffffffL; - r[i + 3] = 0x1ffffffffffffffL; - r[i + 4] = 0x1ffffffffffffffL; - r[i + 5] = 0x1ffffffffffffffL; - r[i + 6] = 0x1ffffffffffffffL; - r[i + 7] = 0x1ffffffffffffffL; - } - r[24] = 0x1ffffffffffffffL; - r[25] = 0x1ffffffffffffffL; - r[26] = 0x3fffffffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_27(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_27(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[26] - b[26]) & (0 - (sp_digit)1); - r |= (a[25] - b[25]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[24] - b[24]) & ~(((sp_digit)0 - r) >> 56); - for (i = 16; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 56); - } - - 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_3072_cond_sub_27(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] - (b[24] & m); - r[25] = a[25] - (b[25] & m); - r[26] = a[26] - (b[26] & m); -} - -/* 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_3072_mul_add_27(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[8]; - int i; - - t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffffffffffffL); - for (i = 0; i < 24; 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[25]; - r[25] += (sp_digit)((t[0] >> 57) + (t[1] & 0x1ffffffffffffffL)); - t[2] = tb * a[26]; - r[26] += (sp_digit)((t[1] >> 57) + (t[2] & 0x1ffffffffffffffL)); - r[27] += (sp_digit)(t[2] >> 57); -} - -/* Shift the result in the high 1536 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a) -{ - sp_digit n; - sp_digit s; - int i; - - s = a[27]; n = a[26] >> 54; - for (i = 0; i < 24; i += 8) { - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+0] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+28] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+1] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+29] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+2] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+30] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+3] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+31] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+4] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+32] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+5] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+33] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+6] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+34] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[i+7] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[i+35] + (s >> 57); - } - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[24] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[52] + (s >> 57); - n += (sp_digit)((s & 0x1ffffffffffffffL) << 3); r[25] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; s = a[53] + (s >> 57); - n += s << 3; r[26] = n; - XMEMSET(&r[27], 0, sizeof(*r) * 27U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_27(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_27(a + 27); - - for (i=0; i<26; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_3072_mul_add_27(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x3fffffffffffffL); - 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); - over = a[26] - m[26]; - sp_3072_cond_sub_27(a, a, m, ~((over - 1) >> 63)); - sp_3072_norm_27(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_3072_mul_d_27(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 24; 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[24]; - r[24] = (sp_digit)(t & 0x1ffffffffffffffL); - t >>= 57; - t += tb * a[25]; - r[25] = (sp_digit)(t & 0x1ffffffffffffffL); - t >>= 57; - t += tb * a[26]; - r[26] = (sp_digit)(t & 0x1ffffffffffffffL); - t >>= 57; - r[27] = (sp_digit)(t & 0x1ffffffffffffffL); -} - -#ifndef 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_3072_cond_add_27(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] + (b[24] & m); - r[25] = a[25] + (b[25] & m); - r[26] = a[26] + (b[26] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_3072_rshift_27(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<24; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (57 - n)) & 0x1ffffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (57 - n)) & 0x1ffffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (57 - n)) & 0x1ffffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (57 - n)) & 0x1ffffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (57 - n)) & 0x1ffffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (57 - n)) & 0x1ffffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (57 - n)) & 0x1ffffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (57 - n)) & 0x1ffffffffffffffL); - } - r[24] = (a[24] >> n) | (sp_digit)((a[25] << (57 - n)) & 0x1ffffffffffffffL); - r[25] = (a[25] >> n) | (sp_digit)((a[26] << (57 - n)) & 0x1ffffffffffffffL); - r[26] = a[26] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 57) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 57); - sp_digit t0 = (sp_digit)(d & 0x1ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 55; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 56) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 57); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 114) - (sp_digit)(d >> 114); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 26) + 1; - - t = (sp_digit)(d >> 52); - t = (t / dv) << 26; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 21); - t = t / (dv << 5); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_27(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_27(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 27 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 27 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 54 + 1; - sd = t2 + 27 + 1; - - sp_3072_mul_d_27(sd, d, (sp_digit)1 << 3); - sp_3072_mul_d_54(t1, a, (sp_digit)1 << 3); - dv = sd[26]; - t1[27 + 27] += t1[27 + 27 - 1] >> 57; - t1[27 + 27 - 1] &= 0x1ffffffffffffffL; - for (i=27; i>=0; i--) { - r1 = sp_3072_div_word_27(t1[27 + i], t1[27 + i - 1], dv); - - sp_3072_mul_d_27(t2, sd, r1); - (void)sp_3072_sub_27(&t1[i], &t1[i], t2); - sp_3072_norm_27(&t1[i]); - t1[27 + i] -= t2[27]; - t1[27 + i] += t1[27 + i - 1] >> 57; - t1[27 + i - 1] &= 0x1ffffffffffffffL; - r1 = sp_3072_div_word_27(-t1[27 + i], -t1[27 + i - 1], dv); - r1 -= t1[27 + i]; - sp_3072_mul_d_27(t2, sd, r1); - (void)sp_3072_add_27(&t1[i], &t1[i], t2); - t1[27 + i] += t1[27 + i - 1] >> 57; - t1[27 + i - 1] &= 0x1ffffffffffffffL; - } - t1[27 - 1] += t1[27 - 2] >> 57; - t1[27 - 2] &= 0x1ffffffffffffffL; - r1 = sp_3072_word_div_word_27(t1[27 - 1], dv); - - sp_3072_mul_d_27(t2, sd, r1); - sp_3072_sub_27(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 54U); - for (i=0; i<26; i++) { - r[i+1] += r[i] >> 57; - r[i] &= 0x1ffffffffffffffL; - } - sp_3072_cond_add_27(r, r, sd, r[26] >> 63); - - sp_3072_norm_27(r); - sp_3072_rshift_27(r, r, 3); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_27(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_27(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 54); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 54, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 27 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 27U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_27(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_27(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 27U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_27(t[1], t[1], norm); - err = sp_3072_mod_27(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 27 * 2); - sp_3072_mont_sqr_27(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 27 * 2); - } - - sp_3072_mont_reduce_27(t[0], m, mp); - n = sp_3072_cmp_27(t[0], m); - sp_3072_cond_sub_27(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 27 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 54); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 54, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 27 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_27(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_27(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_27(t[1], t[1], norm); - err = sp_3072_mod_27(t[1], t[1], m); - } - } - else { - sp_3072_mul_27(t[1], a, norm); - err = sp_3072_mod_27(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 27 * 2); - sp_3072_mont_sqr_27(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 27 * 2); - } - - sp_3072_mont_reduce_27(t[0], m, mp); - n = sp_3072_cmp_27(t[0], m); - sp_3072_cond_sub_27(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 27 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 54) + 54); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 54) + 54, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 54; - rt = td + 1728; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_27(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_27(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_27(t[1], t[1], norm); - err = sp_3072_mod_27(t[1], t[1], m); - } - } - else { - sp_3072_mul_27(t[1], a, norm); - err = sp_3072_mod_27(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_27(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_27(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_27(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_27(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_27(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_27(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_27(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_27(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_27(t[10], t[ 5], m, mp); - sp_3072_mont_mul_27(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_27(t[12], t[ 6], m, mp); - sp_3072_mont_mul_27(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_27(t[14], t[ 7], m, mp); - sp_3072_mont_mul_27(t[15], t[ 8], t[ 7], m, mp); - sp_3072_mont_sqr_27(t[16], t[ 8], m, mp); - sp_3072_mont_mul_27(t[17], t[ 9], t[ 8], m, mp); - sp_3072_mont_sqr_27(t[18], t[ 9], m, mp); - sp_3072_mont_mul_27(t[19], t[10], t[ 9], m, mp); - sp_3072_mont_sqr_27(t[20], t[10], m, mp); - sp_3072_mont_mul_27(t[21], t[11], t[10], m, mp); - sp_3072_mont_sqr_27(t[22], t[11], m, mp); - sp_3072_mont_mul_27(t[23], t[12], t[11], m, mp); - sp_3072_mont_sqr_27(t[24], t[12], m, mp); - sp_3072_mont_mul_27(t[25], t[13], t[12], m, mp); - sp_3072_mont_sqr_27(t[26], t[13], m, mp); - sp_3072_mont_mul_27(t[27], t[14], t[13], m, mp); - sp_3072_mont_sqr_27(t[28], t[14], m, mp); - sp_3072_mont_mul_27(t[29], t[15], t[14], m, mp); - sp_3072_mont_sqr_27(t[30], t[15], m, mp); - sp_3072_mont_mul_27(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 56) / 57) - 1; - c = bits % 57; - if (c == 0) { - c = 57; - } - if (i < 27) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (7 - c); - c += 57; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 54); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 7; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 52; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 7; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 57 - c; - } - - sp_3072_mont_sqr_27(rt, rt, m, mp); - sp_3072_mont_sqr_27(rt, rt, m, mp); - sp_3072_mont_sqr_27(rt, rt, m, mp); - sp_3072_mont_sqr_27(rt, rt, m, mp); - sp_3072_mont_sqr_27(rt, rt, m, mp); - - sp_3072_mont_mul_27(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_27(rt, m, mp); - n = sp_3072_cmp_27(rt, m); - sp_3072_cond_sub_27(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 54); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_3072_mont_norm_54(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 48; i += 8) { - r[i + 0] = 0x1ffffffffffffffL; - r[i + 1] = 0x1ffffffffffffffL; - r[i + 2] = 0x1ffffffffffffffL; - r[i + 3] = 0x1ffffffffffffffL; - r[i + 4] = 0x1ffffffffffffffL; - r[i + 5] = 0x1ffffffffffffffL; - r[i + 6] = 0x1ffffffffffffffL; - r[i + 7] = 0x1ffffffffffffffL; - } - r[48] = 0x1ffffffffffffffL; - r[49] = 0x1ffffffffffffffL; - r[50] = 0x1ffffffffffffffL; - r[51] = 0x1ffffffffffffffL; - r[52] = 0x1ffffffffffffffL; - r[53] = 0x7ffffffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_3072_sub_54(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_3072_cmp_54(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[53] - b[53]) & (0 - (sp_digit)1); - r |= (a[52] - b[52]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[51] - b[51]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[50] - b[50]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[49] - b[49]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[48] - b[48]) & ~(((sp_digit)0 - r) >> 56); - for (i = 40; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 56); - } - - 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_3072_cond_sub_54(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 48; 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[48] = a[48] - (b[48] & m); - r[49] = a[49] - (b[49] & m); - r[50] = a[50] - (b[50] & m); - r[51] = a[51] - (b[51] & m); - r[52] = a[52] - (b[52] & m); - r[53] = a[53] - (b[53] & m); -} - -/* 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_3072_mul_add_54(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[8]; - int i; - - t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffffffffffffL); - for (i = 0; i < 48; 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[49]; - r[49] += (sp_digit)((t[0] >> 57) + (t[1] & 0x1ffffffffffffffL)); - t[2] = tb * a[50]; - r[50] += (sp_digit)((t[1] >> 57) + (t[2] & 0x1ffffffffffffffL)); - t[3] = tb * a[51]; - r[51] += (sp_digit)((t[2] >> 57) + (t[3] & 0x1ffffffffffffffL)); - t[4] = tb * a[52]; - r[52] += (sp_digit)((t[3] >> 57) + (t[4] & 0x1ffffffffffffffL)); - t[5] = tb * a[53]; - r[53] += (sp_digit)((t[4] >> 57) + (t[5] & 0x1ffffffffffffffL)); - r[54] += (sp_digit)(t[5] >> 57); -} - -/* Shift the result in the high 3072 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_3072_mont_shift_54(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[53] >> 51; - n += ((sp_int128)a[54]) << 6; - for (i = 0; i < 48; i += 8) { - r[i + 0] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 55]) << 6; - r[i + 1] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 56]) << 6; - r[i + 2] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 57]) << 6; - r[i + 3] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 58]) << 6; - r[i + 4] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 59]) << 6; - r[i + 5] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 60]) << 6; - r[i + 6] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 61]) << 6; - r[i + 7] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; n += ((sp_int128)a[i + 62]) << 6; - } - r[48] = (sp_digit)(n & 0x1ffffffffffffffL); n >>= 57; n += ((sp_int128)a[103]) << 6; - r[49] = (sp_digit)(n & 0x1ffffffffffffffL); n >>= 57; n += ((sp_int128)a[104]) << 6; - r[50] = (sp_digit)(n & 0x1ffffffffffffffL); n >>= 57; n += ((sp_int128)a[105]) << 6; - r[51] = (sp_digit)(n & 0x1ffffffffffffffL); n >>= 57; n += ((sp_int128)a[106]) << 6; - r[52] = (sp_digit)(n & 0x1ffffffffffffffL); n >>= 57; n += ((sp_int128)a[107]) << 6; - r[53] = (sp_digit)n; - XMEMSET(&r[54], 0, sizeof(*r) * 54U); -} - -/* 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. - */ -static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_3072_norm_54(a + 54); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<53; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_3072_mul_add_54(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffffffL); - sp_3072_mul_add_54(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; - } - else { - for (i=0; i<53; i++) { - mu = (sp_digit)(a[i] & 0x1ffffffffffffffL); - sp_3072_mul_add_54(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(a[i] & 0x7ffffffffffffL); - sp_3072_mul_add_54(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; - } -#else - for (i=0; i<53; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_3072_mul_add_54(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffffffL); - sp_3072_mul_add_54(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; -#endif - sp_3072_mont_shift_54(a, a); - over = a[53] - m[53]; - sp_3072_cond_sub_54(a, a, m, ~((over - 1) >> 63)); - sp_3072_norm_54(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_3072_mul_d_108(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 108; 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; - } - r[108] = (sp_digit)(t & 0x1ffffffffffffffL); -} - -#ifndef 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_3072_cond_add_54(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 48; 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[48] = a[48] + (b[48] & m); - r[49] = a[49] + (b[49] & m); - r[50] = a[50] + (b[50] & m); - r[51] = a[51] + (b[51] & m); - r[52] = a[52] + (b[52] & m); - r[53] = a[53] + (b[53] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_3072_rshift_54(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<48; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (57 - n)) & 0x1ffffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (57 - n)) & 0x1ffffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (57 - n)) & 0x1ffffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (57 - n)) & 0x1ffffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (57 - n)) & 0x1ffffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (57 - n)) & 0x1ffffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (57 - n)) & 0x1ffffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (57 - n)) & 0x1ffffffffffffffL); - } - r[48] = (a[48] >> n) | (sp_digit)((a[49] << (57 - n)) & 0x1ffffffffffffffL); - r[49] = (a[49] >> n) | (sp_digit)((a[50] << (57 - n)) & 0x1ffffffffffffffL); - r[50] = (a[50] >> n) | (sp_digit)((a[51] << (57 - n)) & 0x1ffffffffffffffL); - r[51] = (a[51] >> n) | (sp_digit)((a[52] << (57 - n)) & 0x1ffffffffffffffL); - r[52] = (a[52] >> n) | (sp_digit)((a[53] << (57 - n)) & 0x1ffffffffffffffL); - r[53] = a[53] >> n; -} - -static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 57) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 57); - sp_digit t0 = (sp_digit)(d & 0x1ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 55; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 56) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 57); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 114) - (sp_digit)(d >> 114); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 26) + 1; - - t = (sp_digit)(d >> 52); - t = (t / dv) << 26; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 21); - t = t / (dv << 5); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_3072_word_div_word_54(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_54(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 54 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 54 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 108 + 1; - sd = t2 + 54 + 1; - - sp_3072_mul_d_54(sd, d, (sp_digit)1 << 6); - sp_3072_mul_d_108(t1, a, (sp_digit)1 << 6); - dv = sd[53]; - t1[54 + 54] += t1[54 + 54 - 1] >> 57; - t1[54 + 54 - 1] &= 0x1ffffffffffffffL; - for (i=54; i>=0; i--) { - r1 = sp_3072_div_word_54(t1[54 + i], t1[54 + i - 1], dv); - - sp_3072_mul_d_54(t2, sd, r1); - (void)sp_3072_sub_54(&t1[i], &t1[i], t2); - sp_3072_norm_54(&t1[i]); - t1[54 + i] -= t2[54]; - t1[54 + i] += t1[54 + i - 1] >> 57; - t1[54 + i - 1] &= 0x1ffffffffffffffL; - r1 = sp_3072_div_word_54(-t1[54 + i], -t1[54 + i - 1], dv); - r1 -= t1[54 + i]; - sp_3072_mul_d_54(t2, sd, r1); - (void)sp_3072_add_54(&t1[i], &t1[i], t2); - t1[54 + i] += t1[54 + i - 1] >> 57; - t1[54 + i - 1] &= 0x1ffffffffffffffL; - } - t1[54 - 1] += t1[54 - 2] >> 57; - t1[54 - 2] &= 0x1ffffffffffffffL; - r1 = sp_3072_word_div_word_54(t1[54 - 1], dv); - - sp_3072_mul_d_54(t2, sd, r1); - sp_3072_sub_54(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 108U); - for (i=0; i<53; i++) { - r[i+1] += r[i] >> 57; - r[i] &= 0x1ffffffffffffffL; - } - sp_3072_cond_add_54(r, r, sd, r[53] >> 63); - - sp_3072_norm_54(r); - sp_3072_rshift_54(r, r, 6); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_3072_mod_54(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_3072_div_54(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 108); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 108, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 54 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 54U * 2U); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_54(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_54(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 54U); - } - } - if (err == MP_OKAY) { - sp_3072_mul_54(t[1], t[1], norm); - err = sp_3072_mod_54(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 54 * 2); - sp_3072_mont_sqr_54(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 54 * 2); - } - - sp_3072_mont_reduce_54(t[0], m, mp); - n = sp_3072_cmp_54(t[0], m); - sp_3072_cond_sub_54(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 54 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 108); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 108, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 54 * 2); - } - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_54(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_54(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_54(t[1], t[1], norm); - err = sp_3072_mod_54(t[1], t[1], m); - } - } - else { - sp_3072_mul_54(t[1], a, norm); - err = sp_3072_mod_54(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 57; - c = bits % 57; - n = e[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 57; - } - - y = (int)((n >> 56) & 1); - n <<= 1; - - sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 54 * 2); - sp_3072_mont_sqr_54(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 54 * 2); - } - - sp_3072_mont_reduce_54(t[0], m, mp); - n = sp_3072_cmp_54(t[0], m); - sp_3072_cond_sub_54(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 54 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 108) + 108); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 108) + 108, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 108; - rt = td + 1728; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_54(norm, m); - - if (reduceA != 0) { - err = sp_3072_mod_54(t[1], a, m); - if (err == MP_OKAY) { - sp_3072_mul_54(t[1], t[1], norm); - err = sp_3072_mod_54(t[1], t[1], m); - } - } - else { - sp_3072_mul_54(t[1], a, norm); - err = sp_3072_mod_54(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_3072_mont_sqr_54(t[ 2], t[ 1], m, mp); - sp_3072_mont_mul_54(t[ 3], t[ 2], t[ 1], m, mp); - sp_3072_mont_sqr_54(t[ 4], t[ 2], m, mp); - sp_3072_mont_mul_54(t[ 5], t[ 3], t[ 2], m, mp); - sp_3072_mont_sqr_54(t[ 6], t[ 3], m, mp); - sp_3072_mont_mul_54(t[ 7], t[ 4], t[ 3], m, mp); - sp_3072_mont_sqr_54(t[ 8], t[ 4], m, mp); - sp_3072_mont_mul_54(t[ 9], t[ 5], t[ 4], m, mp); - sp_3072_mont_sqr_54(t[10], t[ 5], m, mp); - sp_3072_mont_mul_54(t[11], t[ 6], t[ 5], m, mp); - sp_3072_mont_sqr_54(t[12], t[ 6], m, mp); - sp_3072_mont_mul_54(t[13], t[ 7], t[ 6], m, mp); - sp_3072_mont_sqr_54(t[14], t[ 7], m, mp); - sp_3072_mont_mul_54(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 56) / 57) - 1; - c = bits % 57; - if (c == 0) { - c = 57; - } - if (i < 54) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (7 - c); - c += 57; - } - y = (int)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 108); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 7; - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c = 53; - } - else { - y = (byte)((n >> 60) & 0xf); - n = e[i--] << 7; - c = 4 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 57 - c; - } - - sp_3072_mont_sqr_54(rt, rt, m, mp); - sp_3072_mont_sqr_54(rt, rt, m, mp); - sp_3072_mont_sqr_54(rt, rt, m, mp); - sp_3072_mont_sqr_54(rt, rt, m, mp); - - sp_3072_mont_mul_54(rt, rt, t[y], m, mp); - } - - sp_3072_mont_reduce_54(rt, m, mp); - n = sp_3072_cmp_54(rt, m); - sp_3072_cond_sub_54(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 108); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 54 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 54 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 54 * 2; - m = r + 54 * 2; - norm = r; - - sp_3072_from_bin(a, 54, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_3072_from_mp(m, 54, mm); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_54(norm, m); - } - if (err == MP_OKAY) { - sp_3072_mul_54(a, a, norm); - err = sp_3072_mod_54(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 54 * 2); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_54(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_54(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_54(r, m, mp); - mp = sp_3072_cmp_54(r, m); - sp_3072_cond_sub_54(r, r, m, ~(mp >> 63)); - - sp_3072_to_bin_54(r, out); - *outLen = 384; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 54 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 54 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 54 * 2; - m = r + 54 * 2; - - sp_3072_from_bin(a, 54, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_3072_from_mp(m, 54, mm); - - if (e[0] == 0x3) { - sp_3072_sqr_54(r, a); - err = sp_3072_mod_54(r, r, m); - if (err == MP_OKAY) { - sp_3072_mul_54(r, a, r); - err = sp_3072_mod_54(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_54(norm, m); - - sp_3072_mul_54(a, a, norm); - err = sp_3072_mod_54(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 108U); - for (i--; i>=0; i--) { - sp_3072_mont_sqr_54(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_3072_mont_mul_54(r, r, a, m, mp); - } - } - sp_3072_mont_reduce_54(r, m, mp); - mp = sp_3072_cmp_54(r, m); - sp_3072_cond_sub_54(r, r, m, ~(mp >> 63)); - } - } - } - - if (err == MP_OKAY) { - sp_3072_to_bin_54(r, out); - *outLen = 384; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 54 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 54 * 4, NULL, DYNAMIC_TYPE_RSA); - 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); - err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_54(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 54, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 54 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 3072) { - err = MP_READ_E; - } - else if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 54 * 4, NULL, DYNAMIC_TYPE_RSA); - 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); - err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); - } - - if (err == MP_OKAY) { - sp_3072_to_bin_54(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 54, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 27 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 27 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 54; - qi = dq = dp = p + 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(dp, 27, dpm); - err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 27, qm); - sp_3072_from_mp(dq, 27, dqm); - err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, p, 1); - } - if (err == MP_OKAY) { - sp_3072_from_mp(p, 27, pm); - (void)sp_3072_sub_27(tmpa, tmpa, tmpb); - sp_3072_norm_27(tmpa); - sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); - sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); - sp_3072_norm_27(tmpa); - - sp_3072_from_mp(qi, 27, qim); - sp_3072_mul_27(tmpa, tmpa, qi); - err = sp_3072_mod_27(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_from_mp(p, 27, qm); - sp_3072_mul_27(tmpa, p, tmpa); - (void)sp_3072_add_54(r, tmpb, tmpa); - sp_3072_norm_54(r); - - sp_3072_to_bin_54(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 27 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 27 * 13); - 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; - (void)mm; - - if (*outLen < 384U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 27 * 13, NULL, DYNAMIC_TYPE_RSA); - 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); - sp_3072_from_mp(dp, 27, dpm); - sp_3072_from_mp(dq, 27, dqm); - sp_3072_from_mp(qi, 27, qim); - - err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1); - } - if (err == MP_OKAY) { - err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_3072_sub_27(tmpa, tmpa, tmpb); - sp_3072_norm_27(tmpa); - sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); - sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); - sp_3072_norm_27(tmpa); - sp_3072_mul_27(tmpa, tmpa, qi); - err = sp_3072_mod_27(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_3072_mul_27(tmpa, tmpa, q); - (void)sp_3072_add_54(r, tmpb, tmpa); - sp_3072_norm_54(r); - - sp_3072_to_bin_54(r, out); - *outLen = 384; - } - - SP_ZEROFREE_VAR(sp_digit, a, 27 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_3072_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (3072 + 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) * 54); - r->used = 54; - mp_clamp(r); -#elif DIGIT_BIT < 57 - 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] &= ((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 = (3072 + 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 < 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] &= ((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 = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 54 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 54 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_3072_mod_exp_54(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 54U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 54 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expBits > 3072) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 54 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_3072_mod_exp_54(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 54U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_3072 -SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, const sp_digit* a, - byte n) -{ - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[53]; - r[54] = s >> (57U - n); - s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); - r[53] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); - r[52] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); - r[51] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); - r[50] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); - r[49] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); - r[48] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); - r[47] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); - r[46] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); - r[45] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); - r[44] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); - r[43] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); - r[42] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); - r[41] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); - r[40] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); - r[39] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); - r[38] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); - r[37] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); - r[36] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL); - r[0] = (sp_digit)((a[0] << n) & 0x1ffffffffffffffL); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 163); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 163, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 108; - XMEMSET(td, 0, sizeof(sp_digit) * 163); - - sp_3072_mont_setup(m, &mp); - sp_3072_mont_norm_54(norm, m); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 56) / 57) - 1; - c = bits % 57; - if (c == 0) { - c = 57; - } - if (i < 54) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (7 - c); - c += 57; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - sp_3072_lshift_54(r, norm, (byte)y); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 7; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 52; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 7; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 57 - c; - } - - sp_3072_mont_sqr_54(r, r, m, mp); - sp_3072_mont_sqr_54(r, r, m, mp); - sp_3072_mont_sqr_54(r, r, m, mp); - sp_3072_mont_sqr_54(r, r, m, mp); - sp_3072_mont_sqr_54(r, r, m, mp); - - sp_3072_lshift_54(r, r, (byte)y); - sp_3072_mul_d_54(tmp, norm, (r[54] << 6) + (r[53] >> 51)); - r[54] = 0; - r[53] &= 0x7ffffffffffffL; - (void)sp_3072_add_54(r, r, tmp); - sp_3072_norm_54(r); - o = sp_3072_cmp_54(r, m); - sp_3072_cond_sub_54(r, r, m, ~(o >> 63)); - } - - sp_3072_mont_reduce_54(r, m, mp); - n = sp_3072_cmp_54(r, m); - sp_3072_cond_sub_54(r, r, m, (sp_digit)~(n >> 63)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_3072 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 384 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 54 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 3072) { - err = MP_READ_E; - } - else if (expLen > 384U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 3072) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 54 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - #ifdef HAVE_FFDHE_3072 - if (base->used == 1 && base->dp[0] == 2U && - (m[53] >> 19) == 0xffffffffL) { - err = sp_3072_mod_exp_2_54(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_3072_mod_exp_54(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_3072 - } - #endif - } - - if (err == MP_OKAY) { - sp_3072_to_bin_54(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 54U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 27 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 27 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_3072_mod_exp_27(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 27, 0, sizeof(*r) * 27U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 54U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 27 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 1536) { - err = MP_READ_E; - } - else if (expBits > 1536) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 1536) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 27 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_3072_mod_exp_27(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - XMEMSET(r + 27, 0, sizeof(*r) * 27U); - err = sp_3072_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 54U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#endif /* WOLFSSL_SP_SMALL */ -#endif /* !WOLFSSL_SP_NO_3072 */ - -#ifdef WOLFSSL_SP_4096 -#ifdef WOLFSSL_SP_SMALL -/* 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_4096_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 >= 51U) { - r[j] &= 0x7ffffffffffffffL; - s = 59U - 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; - } -} - -/* 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_4096_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 59 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 58); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 58); - } -#elif DIGIT_BIT > 59 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x7ffffffffffffffL; - s = 59U - 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 + 59U) <= (word32)DIGIT_BIT) { - s += 59U; - r[j] &= 0x7ffffffffffffffL; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 59) { - r[j] &= 0x7ffffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 59 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 512 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_4096_to_bin_70(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<69; i++) { - r[i+1] += r[i] >> 59; - r[i] &= 0x7ffffffffffffffL; - } - j = 4103 / 8 - 1; - a[j] = 0; - for (i=0; i<70 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 59) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 59); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* Normalize the values in each word to 59 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_35(sp_digit* a) -{ - int i; - for (i = 0; i < 34; i++) { - a[i+1] += a[i] >> 59; - a[i] &= 0x7ffffffffffffffL; - } -} - -#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -/* Normalize the values in each word to 59 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_70(sp_digit* a) -{ - int i; - for (i = 0; i < 69; i++) { - a[i+1] += a[i] >> 59; - a[i] &= 0x7ffffffffffffffL; - } -} - -/* 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_4096_mul_70(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[69]) * b[69]; - r[139] = (sp_digit)(c >> 59); - c &= 0x7ffffffffffffffL; - for (k = 137; k >= 0; k--) { - if (k >= 70) { - i = k - 69; - imax = 69; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 59; - r[k + 2] += (sp_digit)(c >> 59); - r[k + 1] = (sp_digit)(c & 0x7ffffffffffffffL); - c = lo & 0x7ffffffffffffffL; - } - r[0] = (sp_digit)c; -} - -/* 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_4096_sqr_70(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[69]) * a[69]; - r[139] = (sp_digit)(c >> 59); - c = (c & 0x7ffffffffffffffL) << 59; - for (k = 137; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 69) { - imax = k; - } - else { - imax = 69; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 118); - r[k + 1] = (sp_digit)((c >> 59) & 0x7ffffffffffffffL); - c = (c & 0x7ffffffffffffffL) << 59; - } - r[0] = (sp_digit)(c >> 59); -} - -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ - x &= 0x7ffffffffffffffL; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 59) - x; -} - -/* 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_4096_mul_d_70(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 70; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x7ffffffffffffffL); - t >>= 59; - } - r[70] = (sp_digit)t; -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* 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_35(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 35; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_35(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<34; i++) { - r[i] = 0x7ffffffffffffffL; - } - r[34] = 0x3ffffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_35(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_35(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=34; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 58); - } - - 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_4096_cond_sub_35(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 35; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_4096_mul_add_35(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 32; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x7ffffffffffffffL); - t[1] += t[0] >> 59; - r[i+1] = (sp_digit)(t[1] & 0x7ffffffffffffffL); - t[2] += t[1] >> 59; - r[i+2] = (sp_digit)(t[2] & 0x7ffffffffffffffL); - t[3] += t[2] >> 59; - r[i+3] = (sp_digit)(t[3] & 0x7ffffffffffffffL); - t[0] = t[3] >> 59; - } - t[0] += (tb * a[32]) + r[32]; - t[1] = (tb * a[33]) + r[33]; - t[2] = (tb * a[34]) + r[34]; - r[32] = (sp_digit)(t[0] & 0x7ffffffffffffffL); - t[1] += t[0] >> 59; - r[33] = (sp_digit)(t[1] & 0x7ffffffffffffffL); - t[2] += t[1] >> 59; - r[34] = (sp_digit)(t[2] & 0x7ffffffffffffffL); - r[35] += (sp_digit)(t[2] >> 59); -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_35(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[34] >> 42; - n += ((sp_int128)a[35]) << 17; - - for (i = 0; i < 34; i++) { - r[i] = (sp_digit)(n & 0x7ffffffffffffffL); - n >>= 59; - n += ((sp_int128)a[36 + i]) << 17; - } - r[34] = (sp_digit)n; - XMEMSET(&r[35], 0, sizeof(*r) * 35U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_35(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_35(a + 35); - - for (i=0; i<34; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffffffffL); - sp_4096_mul_add_35(a+i, m, mu); - a[i+1] += a[i] >> 59; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x3ffffffffffL); - sp_4096_mul_add_35(a+i, m, mu); - a[i+1] += a[i] >> 59; - a[i] &= 0x7ffffffffffffffL; - sp_4096_mont_shift_35(a, a); - over = a[34] - m[34]; - sp_4096_cond_sub_35(a, a, m, ~((over - 1) >> 63)); - sp_4096_norm_35(a); -} - -/* 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_4096_mul_35(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[34]) * b[34]; - r[69] = (sp_digit)(c >> 59); - c &= 0x7ffffffffffffffL; - for (k = 67; k >= 0; k--) { - if (k >= 35) { - i = k - 34; - imax = 34; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 59; - r[k + 2] += (sp_digit)(c >> 59); - r[k + 1] = (sp_digit)(c & 0x7ffffffffffffffL); - c = lo & 0x7ffffffffffffffL; - } - r[0] = (sp_digit)c; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_mul_35(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_4096_mul_35(r, a, b); - sp_4096_mont_reduce_35(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_4096_sqr_35(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[34]) * a[34]; - r[69] = (sp_digit)(c >> 59); - c = (c & 0x7ffffffffffffffL) << 59; - for (k = 67; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 34) { - imax = k; - } - else { - imax = 34; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 118); - r[k + 1] = (sp_digit)((c >> 59) & 0x7ffffffffffffffL); - c = (c & 0x7ffffffffffffffL) << 59; - } - r[0] = (sp_digit)(c >> 59); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_sqr_35(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_4096_sqr_35(r, a); - sp_4096_mont_reduce_35(r, m, mp); -} - -/* 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_4096_mul_d_35(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 35; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x7ffffffffffffffL); - t >>= 59; - } - r[35] = (sp_digit)t; -} - -#ifdef 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_4096_cond_add_35(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 35; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_4096_add_35(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 35; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_4096_rshift_35(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<34; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (59 - n))) & 0x7ffffffffffffffL); - } - r[34] = a[34] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_35(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 59) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 59) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 59) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 59); - sp_digit t0 = (sp_digit)(d & 0x7ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 57; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 58) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 59); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 118) - (sp_digit)(d >> 118); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 59) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 28) + 1; - - t = (sp_digit)(d >> 56); - t = (t / dv) << 28; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 25); - t = t / (dv << 3); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_35(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_35(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 35 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 35 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 70 + 1; - sd = t2 + 35 + 1; - - sp_4096_mul_d_35(sd, d, (sp_digit)1 << 17); - sp_4096_mul_d_70(t1, a, (sp_digit)1 << 17); - dv = sd[34]; - t1[35 + 35] += t1[35 + 35 - 1] >> 59; - t1[35 + 35 - 1] &= 0x7ffffffffffffffL; - for (i=35; i>=0; i--) { - r1 = sp_4096_div_word_35(t1[35 + i], t1[35 + i - 1], dv); - - sp_4096_mul_d_35(t2, sd, r1); - (void)sp_4096_sub_35(&t1[i], &t1[i], t2); - sp_4096_norm_35(&t1[i]); - t1[35 + i] -= t2[35]; - t1[35 + i] += t1[35 + i - 1] >> 59; - t1[35 + i - 1] &= 0x7ffffffffffffffL; - r1 = sp_4096_div_word_35(-t1[35 + i], -t1[35 + i - 1], dv); - r1 -= t1[35 + i]; - sp_4096_mul_d_35(t2, sd, r1); - (void)sp_4096_add_35(&t1[i], &t1[i], t2); - t1[35 + i] += t1[35 + i - 1] >> 59; - t1[35 + i - 1] &= 0x7ffffffffffffffL; - } - t1[35 - 1] += t1[35 - 2] >> 59; - t1[35 - 2] &= 0x7ffffffffffffffL; - r1 = sp_4096_word_div_word_35(t1[35 - 1], dv); - - sp_4096_mul_d_35(t2, sd, r1); - sp_4096_sub_35(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 70U); - for (i=0; i<34; i++) { - r[i+1] += r[i] >> 59; - r[i] &= 0x7ffffffffffffffL; - } - sp_4096_cond_add_35(r, r, sd, r[34] >> 63); - - sp_4096_norm_35(r); - sp_4096_rshift_35(r, r, 17); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_35(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_35(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_35(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 70); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 70, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 35 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 35U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_35(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_35(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 35U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_35(t[1], t[1], norm); - err = sp_4096_mod_35(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 59; - c = bits % 59; - n = e[i--] << (59 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 59; - } - - y = (int)((n >> 58) & 1); - n <<= 1; - - sp_4096_mont_mul_35(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 35 * 2); - sp_4096_mont_sqr_35(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 35 * 2); - } - - sp_4096_mont_reduce_35(t[0], m, mp); - n = sp_4096_cmp_35(t[0], m); - sp_4096_cond_sub_35(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 35 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 70); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 70, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 35 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_35(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_35(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_35(t[1], t[1], norm); - err = sp_4096_mod_35(t[1], t[1], m); - } - } - else { - sp_4096_mul_35(t[1], a, norm); - err = sp_4096_mod_35(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 59; - c = bits % 59; - n = e[i--] << (59 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 59; - } - - y = (int)((n >> 58) & 1); - n <<= 1; - - sp_4096_mont_mul_35(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 35 * 2); - sp_4096_mont_sqr_35(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 35 * 2); - } - - sp_4096_mont_reduce_35(t[0], m, mp); - n = sp_4096_cmp_35(t[0], m); - sp_4096_cond_sub_35(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 35 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 70) + 70); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 70) + 70, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 70; - rt = td + 2240; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_35(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_35(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_35(t[1], t[1], norm); - err = sp_4096_mod_35(t[1], t[1], m); - } - } - else { - sp_4096_mul_35(t[1], a, norm); - err = sp_4096_mod_35(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_35(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_35(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_35(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_35(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_35(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_35(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_35(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_35(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_35(t[10], t[ 5], m, mp); - sp_4096_mont_mul_35(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_35(t[12], t[ 6], m, mp); - sp_4096_mont_mul_35(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_35(t[14], t[ 7], m, mp); - sp_4096_mont_mul_35(t[15], t[ 8], t[ 7], m, mp); - sp_4096_mont_sqr_35(t[16], t[ 8], m, mp); - sp_4096_mont_mul_35(t[17], t[ 9], t[ 8], m, mp); - sp_4096_mont_sqr_35(t[18], t[ 9], m, mp); - sp_4096_mont_mul_35(t[19], t[10], t[ 9], m, mp); - sp_4096_mont_sqr_35(t[20], t[10], m, mp); - sp_4096_mont_mul_35(t[21], t[11], t[10], m, mp); - sp_4096_mont_sqr_35(t[22], t[11], m, mp); - sp_4096_mont_mul_35(t[23], t[12], t[11], m, mp); - sp_4096_mont_sqr_35(t[24], t[12], m, mp); - sp_4096_mont_mul_35(t[25], t[13], t[12], m, mp); - sp_4096_mont_sqr_35(t[26], t[13], m, mp); - sp_4096_mont_mul_35(t[27], t[14], t[13], m, mp); - sp_4096_mont_sqr_35(t[28], t[14], m, mp); - sp_4096_mont_mul_35(t[29], t[15], t[14], m, mp); - sp_4096_mont_sqr_35(t[30], t[15], m, mp); - sp_4096_mont_mul_35(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 58) / 59) - 1; - c = bits % 59; - if (c == 0) { - c = 59; - } - if (i < 35) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (5 - c); - c += 59; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 70); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 5; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 54; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 5; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 59 - c; - } - - sp_4096_mont_sqr_35(rt, rt, m, mp); - sp_4096_mont_sqr_35(rt, rt, m, mp); - sp_4096_mont_sqr_35(rt, rt, m, mp); - sp_4096_mont_sqr_35(rt, rt, m, mp); - sp_4096_mont_sqr_35(rt, rt, m, mp); - - sp_4096_mont_mul_35(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_35(rt, m, mp); - n = sp_4096_cmp_35(rt, m); - sp_4096_cond_sub_35(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 70); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ - -/* 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_70(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 70; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_70(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i=0; i<69; i++) { - r[i] = 0x7ffffffffffffffL; - } - r[69] = 0x1ffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_70(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_70(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - for (i=69; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 58); - } - - 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_4096_cond_sub_70(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 70; i++) { - r[i] = a[i] - (b[i] & m); - } -} - -/* 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_4096_mul_add_70(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 68; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x7ffffffffffffffL); - t[1] += t[0] >> 59; - r[i+1] = (sp_digit)(t[1] & 0x7ffffffffffffffL); - t[2] += t[1] >> 59; - r[i+2] = (sp_digit)(t[2] & 0x7ffffffffffffffL); - t[3] += t[2] >> 59; - r[i+3] = (sp_digit)(t[3] & 0x7ffffffffffffffL); - t[0] = t[3] >> 59; - } - t[0] += (tb * a[68]) + r[68]; - t[1] = (tb * a[69]) + r[69]; - r[68] = (sp_digit)(t[0] & 0x7ffffffffffffffL); - t[1] += t[0] >> 59; - r[69] = (sp_digit)(t[1] & 0x7ffffffffffffffL); - r[70] += (sp_digit)(t[1] >> 59); -} - -/* Shift the result in the high 4096 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_70(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[69] >> 25; - n += ((sp_int128)a[70]) << 34; - - for (i = 0; i < 69; i++) { - r[i] = (sp_digit)(n & 0x7ffffffffffffffL); - n >>= 59; - n += ((sp_int128)a[71 + i]) << 34; - } - r[69] = (sp_digit)n; - XMEMSET(&r[70], 0, sizeof(*r) * 70U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_70(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_70(a + 70); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<69; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffffffffL); - sp_4096_mul_add_70(a+i, m, mu); - a[i+1] += a[i] >> 59; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffL); - sp_4096_mul_add_70(a+i, m, mu); - a[i+1] += a[i] >> 59; - a[i] &= 0x7ffffffffffffffL; - } - else { - for (i=0; i<69; i++) { - mu = (sp_digit)(a[i] & 0x7ffffffffffffffL); - sp_4096_mul_add_70(a+i, m, mu); - a[i+1] += a[i] >> 59; - } - mu = (sp_digit)(a[i] & 0x1ffffffL); - sp_4096_mul_add_70(a+i, m, mu); - a[i+1] += a[i] >> 59; - a[i] &= 0x7ffffffffffffffL; - } -#else - for (i=0; i<69; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7ffffffffffffffL); - sp_4096_mul_add_70(a+i, m, mu); - a[i+1] += a[i] >> 59; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffL); - sp_4096_mul_add_70(a+i, m, mu); - a[i+1] += a[i] >> 59; - a[i] &= 0x7ffffffffffffffL; -#endif - sp_4096_mont_shift_70(a, a); - over = a[69] - m[69]; - sp_4096_cond_sub_70(a, a, m, ~((over - 1) >> 63)); - sp_4096_norm_70(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_mul_70(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_4096_mul_70(r, a, b); - sp_4096_mont_reduce_70(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_4096_mont_sqr_70(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_4096_sqr_70(r, a); - sp_4096_mont_reduce_70(r, m, mp); -} - -/* 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_4096_mul_d_140(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 140; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x7ffffffffffffffL); - t >>= 59; - } - r[140] = (sp_digit)t; -} - -#ifdef 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_4096_cond_add_70(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 70; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#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. - */ -SP_NOINLINE static int sp_4096_add_70(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 70; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} - -SP_NOINLINE static void sp_4096_rshift_70(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<69; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (59 - n))) & 0x7ffffffffffffffL); - } - r[69] = a[69] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_70(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 59) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 59) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 59) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 59); - sp_digit t0 = (sp_digit)(d & 0x7ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 57; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 58) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 59); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 118) - (sp_digit)(d >> 118); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 59) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 28) + 1; - - t = (sp_digit)(d >> 56); - t = (t / dv) << 28; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 25); - t = t / (dv << 3); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_70(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_70(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 70 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 70 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 140 + 1; - sd = t2 + 70 + 1; - - sp_4096_mul_d_70(sd, d, (sp_digit)1 << 34); - sp_4096_mul_d_140(t1, a, (sp_digit)1 << 34); - dv = sd[69]; - t1[70 + 70] += t1[70 + 70 - 1] >> 59; - t1[70 + 70 - 1] &= 0x7ffffffffffffffL; - for (i=70; i>=0; i--) { - r1 = sp_4096_div_word_70(t1[70 + i], t1[70 + i - 1], dv); - - sp_4096_mul_d_70(t2, sd, r1); - (void)sp_4096_sub_70(&t1[i], &t1[i], t2); - sp_4096_norm_70(&t1[i]); - t1[70 + i] -= t2[70]; - t1[70 + i] += t1[70 + i - 1] >> 59; - t1[70 + i - 1] &= 0x7ffffffffffffffL; - r1 = sp_4096_div_word_70(-t1[70 + i], -t1[70 + i - 1], dv); - r1 -= t1[70 + i]; - sp_4096_mul_d_70(t2, sd, r1); - (void)sp_4096_add_70(&t1[i], &t1[i], t2); - t1[70 + i] += t1[70 + i - 1] >> 59; - t1[70 + i - 1] &= 0x7ffffffffffffffL; - } - t1[70 - 1] += t1[70 - 2] >> 59; - t1[70 - 2] &= 0x7ffffffffffffffL; - r1 = sp_4096_word_div_word_70(t1[70 - 1], dv); - - sp_4096_mul_d_70(t2, sd, r1); - sp_4096_sub_70(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 140U); - for (i=0; i<69; i++) { - r[i+1] += r[i] >> 59; - r[i] &= 0x7ffffffffffffffL; - } - sp_4096_cond_add_70(r, r, sd, r[69] >> 63); - - sp_4096_norm_70(r); - sp_4096_rshift_70(r, r, 34); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_70(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_70(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_70(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 140); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 140, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 70 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 70U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_70(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_70(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 70U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_70(t[1], t[1], norm); - err = sp_4096_mod_70(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 59; - c = bits % 59; - n = e[i--] << (59 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 59; - } - - y = (int)((n >> 58) & 1); - n <<= 1; - - sp_4096_mont_mul_70(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 70 * 2); - sp_4096_mont_sqr_70(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 70 * 2); - } - - sp_4096_mont_reduce_70(t[0], m, mp); - n = sp_4096_cmp_70(t[0], m); - sp_4096_cond_sub_70(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 70 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 140); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 140, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 70 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_70(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_70(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_70(t[1], t[1], norm); - err = sp_4096_mod_70(t[1], t[1], m); - } - } - else { - sp_4096_mul_70(t[1], a, norm); - err = sp_4096_mod_70(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 59; - c = bits % 59; - n = e[i--] << (59 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 59; - } - - y = (int)((n >> 58) & 1); - n <<= 1; - - sp_4096_mont_mul_70(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 70 * 2); - sp_4096_mont_sqr_70(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 70 * 2); - } - - sp_4096_mont_reduce_70(t[0], m, mp); - n = sp_4096_cmp_70(t[0], m); - sp_4096_cond_sub_70(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 70 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 140) + 140); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 140) + 140, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 140; - rt = td + 2240; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_70(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_70(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_70(t[1], t[1], norm); - err = sp_4096_mod_70(t[1], t[1], m); - } - } - else { - sp_4096_mul_70(t[1], a, norm); - err = sp_4096_mod_70(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_70(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_70(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_70(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_70(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_70(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_70(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_70(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_70(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_70(t[10], t[ 5], m, mp); - sp_4096_mont_mul_70(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_70(t[12], t[ 6], m, mp); - sp_4096_mont_mul_70(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_70(t[14], t[ 7], m, mp); - sp_4096_mont_mul_70(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 58) / 59) - 1; - c = bits % 59; - if (c == 0) { - c = 59; - } - if (i < 70) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (5 - c); - c += 59; - } - y = (int)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 140); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 5; - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c = 55; - } - else { - y = (byte)((n >> 60) & 0xf); - n = e[i--] << 5; - c = 4 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 59 - c; - } - - sp_4096_mont_sqr_70(rt, rt, m, mp); - sp_4096_mont_sqr_70(rt, rt, m, mp); - sp_4096_mont_sqr_70(rt, rt, m, mp); - sp_4096_mont_sqr_70(rt, rt, m, mp); - - sp_4096_mont_mul_70(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_70(rt, m, mp); - n = sp_4096_cmp_70(rt, m); - sp_4096_cond_sub_70(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 140); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#endif -} - -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 70 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 70 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 70 * 2; - m = r + 70 * 2; - norm = r; - - sp_4096_from_bin(a, 70, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_4096_from_mp(m, 70, mm); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_70(norm, m); - } - if (err == MP_OKAY) { - sp_4096_mul_70(a, a, norm); - err = sp_4096_mod_70(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 70 * 2); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_70(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_70(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_70(r, m, mp); - mp = sp_4096_cmp_70(r, m); - sp_4096_cond_sub_70(r, r, m, ~(mp >> 63)); - - sp_4096_to_bin_70(r, out); - *outLen = 512; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 70 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 70 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 70 * 2; - m = r + 70 * 2; - - sp_4096_from_bin(a, 70, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_4096_from_mp(m, 70, mm); - - if (e[0] == 0x3) { - sp_4096_sqr_70(r, a); - err = sp_4096_mod_70(r, r, m); - if (err == MP_OKAY) { - sp_4096_mul_70(r, a, r); - err = sp_4096_mod_70(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_70(norm, m); - - sp_4096_mul_70(a, a, norm); - err = sp_4096_mod_70(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 140U); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_70(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_70(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_70(r, m, mp); - mp = sp_4096_cmp_70(r, m); - sp_4096_cond_sub_70(r, r, m, ~(mp >> 63)); - } - } - } - - if (err == MP_OKAY) { - sp_4096_to_bin_70(r, out); - *outLen = 512; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 70 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 70 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 70; - m = a + 140; - r = a; - - sp_4096_from_bin(a, 70, in, inLen); - sp_4096_from_mp(d, 70, dm); - sp_4096_from_mp(m, 70, mm); - err = sp_4096_mod_exp_70(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_70(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 70, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 70 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 70 * 4, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d + 70; - m = a + 140; - r = a; - - sp_4096_from_bin(a, 70, in, inLen); - sp_4096_from_mp(d, 70, dm); - sp_4096_from_mp(m, 70, mm); - err = sp_4096_mod_exp_70(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_70(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 70, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 35 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 35 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 70; - qi = dq = dp = p + 35; - tmpa = qi + 35; - tmpb = tmpa + 70; - r = a; - - sp_4096_from_bin(a, 70, in, inLen); - sp_4096_from_mp(p, 35, pm); - sp_4096_from_mp(dp, 35, dpm); - err = sp_4096_mod_exp_35(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 35, qm); - sp_4096_from_mp(dq, 35, dqm); - err = sp_4096_mod_exp_35(tmpb, a, dq, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 35, pm); - (void)sp_4096_sub_35(tmpa, tmpa, tmpb); - sp_4096_norm_35(tmpa); - sp_4096_cond_add_35(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[34] >> 63)); - sp_4096_cond_add_35(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[34] >> 63)); - sp_4096_norm_35(tmpa); - - sp_4096_from_mp(qi, 35, qim); - sp_4096_mul_35(tmpa, tmpa, qi); - err = sp_4096_mod_35(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_from_mp(p, 35, qm); - sp_4096_mul_35(tmpa, p, tmpa); - (void)sp_4096_add_70(r, tmpb, tmpa); - sp_4096_norm_70(r); - - sp_4096_to_bin_70(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 35 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 35 * 13); - 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 35 * 13, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 70 * 2; - q = p + 35; - dp = q + 35; - dq = dp + 35; - qi = dq + 35; - tmpa = qi + 35; - tmpb = tmpa + 70; - r = a; - - sp_4096_from_bin(a, 70, in, inLen); - sp_4096_from_mp(p, 35, pm); - sp_4096_from_mp(q, 35, qm); - sp_4096_from_mp(dp, 35, dpm); - sp_4096_from_mp(dq, 35, dqm); - sp_4096_from_mp(qi, 35, qim); - - err = sp_4096_mod_exp_35(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - err = sp_4096_mod_exp_35(tmpb, a, dq, 2048, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_4096_sub_35(tmpa, tmpa, tmpb); - sp_4096_norm_35(tmpa); - sp_4096_cond_add_35(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[34] >> 63)); - sp_4096_cond_add_35(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[34] >> 63)); - sp_4096_norm_35(tmpa); - sp_4096_mul_35(tmpa, tmpa, qi); - err = sp_4096_mod_35(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_mul_35(tmpa, tmpa, q); - (void)sp_4096_add_70(r, tmpb, tmpa); - sp_4096_norm_70(r); - - sp_4096_to_bin_70(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 35 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_4096_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 59 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 70); - r->used = 70; - mp_clamp(r); -#elif DIGIT_BIT < 59 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 70; 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 <= 59) { - 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 = 59 - s; - } - r->used = (4096 + 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 < 70; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 59 >= 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 = 59 - s; - } - else { - s += 59; - } - } - r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 70 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 70 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 70 * 2; - m = e + 70; - r = b; - - sp_4096_from_mp(b, 70, base); - sp_4096_from_mp(e, 70, exp); - sp_4096_from_mp(m, 70, mod); - - err = sp_4096_mod_exp_70(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 70U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 70 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 70 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 70 * 2; - m = e + 70; - r = b; - - sp_4096_from_mp(b, 70, base); - sp_4096_from_mp(e, 70, exp); - sp_4096_from_mp(m, 70, mod); - - err = sp_4096_mod_exp_70(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 70U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_4096 -SP_NOINLINE static void sp_4096_lshift_70(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - r[70] = a[69] >> (59 - n); - for (i=69; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (59 - n))) & 0x7ffffffffffffffL); - } - r[0] = (sp_digit)((a[0] << n) & 0x7ffffffffffffffL); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_4096_mod_exp_2_70(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 211); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 211, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 140; - XMEMSET(td, 0, sizeof(sp_digit) * 211); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_70(norm, m); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 58) / 59) - 1; - c = bits % 59; - if (c == 0) { - c = 59; - } - if (i < 70) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (5 - c); - c += 59; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - sp_4096_lshift_70(r, norm, (byte)y); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 5; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 54; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 5; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 59 - c; - } - - sp_4096_mont_sqr_70(r, r, m, mp); - sp_4096_mont_sqr_70(r, r, m, mp); - sp_4096_mont_sqr_70(r, r, m, mp); - sp_4096_mont_sqr_70(r, r, m, mp); - sp_4096_mont_sqr_70(r, r, m, mp); - - sp_4096_lshift_70(r, r, (byte)y); - sp_4096_mul_d_70(tmp, norm, (r[70] << 34) + (r[69] >> 25)); - r[70] = 0; - r[69] &= 0x1ffffffL; - (void)sp_4096_add_70(r, r, tmp); - sp_4096_norm_70(r); - o = sp_4096_cmp_70(r, m); - sp_4096_cond_sub_70(r, r, m, ~(o >> 63)); - } - - sp_4096_mont_reduce_70(r, m, mp); - n = sp_4096_cmp_70(r, m); - sp_4096_cond_sub_70(r, r, m, (sp_digit)~(n >> 63)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_4096 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 70 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 70 * 4, NULL, DYNAMIC_TYPE_DH); - - if (err == MP_OKAY) { - e = b + 70 * 2; - m = e + 70; - r = b; - - sp_4096_from_mp(b, 70, base); - sp_4096_from_bin(e, 70, exp, expLen); - sp_4096_from_mp(m, 70, mod); - - #ifdef HAVE_FFDHE_4096 - if (base->used == 1 && base->dp[0] == 2U && - ((m[69] << 7) | (m[68] >> 52)) == 0xffffffffL) { - err = sp_4096_mod_exp_2_70(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_4096_mod_exp_70(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_4096 - } - #endif - } - - if (err == MP_OKAY) { - sp_4096_to_bin_70(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 70U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#else -/* 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_4096_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 >= 45U) { - r[j] &= 0x1fffffffffffffL; - s = 53U - 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; - } -} - -/* 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_4096_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 53 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 52); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 52); - } -#elif DIGIT_BIT > 53 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x1fffffffffffffL; - s = 53U - 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 + 53U) <= (word32)DIGIT_BIT) { - s += 53U; - r[j] &= 0x1fffffffffffffL; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 53) { - r[j] &= 0x1fffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 53 - 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 -} - -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 512 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_4096_to_bin_78(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<77; i++) { - r[i+1] += r[i] >> 53; - r[i] &= 0x1fffffffffffffL; - } - j = 4103 / 8 - 1; - a[j] = 0; - for (i=0; i<78 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 53) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 53); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* Normalize the values in each word to 53 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_39(sp_digit* a) -{ - int i; - for (i = 0; i < 32; i += 8) { - a[i+1] += a[i+0] >> 53; a[i+0] &= 0x1fffffffffffffL; - a[i+2] += a[i+1] >> 53; a[i+1] &= 0x1fffffffffffffL; - a[i+3] += a[i+2] >> 53; a[i+2] &= 0x1fffffffffffffL; - a[i+4] += a[i+3] >> 53; a[i+3] &= 0x1fffffffffffffL; - a[i+5] += a[i+4] >> 53; a[i+4] &= 0x1fffffffffffffL; - a[i+6] += a[i+5] >> 53; a[i+5] &= 0x1fffffffffffffL; - a[i+7] += a[i+6] >> 53; a[i+6] &= 0x1fffffffffffffL; - a[i+8] += a[i+7] >> 53; a[i+7] &= 0x1fffffffffffffL; - } - a[33] += a[32] >> 53; a[32] &= 0x1fffffffffffffL; - a[34] += a[33] >> 53; a[33] &= 0x1fffffffffffffL; - a[35] += a[34] >> 53; a[34] &= 0x1fffffffffffffL; - a[36] += a[35] >> 53; a[35] &= 0x1fffffffffffffL; - a[37] += a[36] >> 53; a[36] &= 0x1fffffffffffffL; - a[38] += a[37] >> 53; a[37] &= 0x1fffffffffffffL; -} - -#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ -/* Normalize the values in each word to 53 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_4096_norm_78(sp_digit* a) -{ - int i; - for (i = 0; i < 72; i += 8) { - a[i+1] += a[i+0] >> 53; a[i+0] &= 0x1fffffffffffffL; - a[i+2] += a[i+1] >> 53; a[i+1] &= 0x1fffffffffffffL; - a[i+3] += a[i+2] >> 53; a[i+2] &= 0x1fffffffffffffL; - a[i+4] += a[i+3] >> 53; a[i+3] &= 0x1fffffffffffffL; - a[i+5] += a[i+4] >> 53; a[i+4] &= 0x1fffffffffffffL; - a[i+6] += a[i+5] >> 53; a[i+5] &= 0x1fffffffffffffL; - a[i+7] += a[i+6] >> 53; a[i+6] &= 0x1fffffffffffffL; - a[i+8] += a[i+7] >> 53; a[i+7] &= 0x1fffffffffffffL; - } - a[73] += a[72] >> 53; a[72] &= 0x1fffffffffffffL; - a[74] += a[73] >> 53; a[73] &= 0x1fffffffffffffL; - a[75] += a[74] >> 53; a[74] &= 0x1fffffffffffffL; - a[76] += a[75] >> 53; a[75] &= 0x1fffffffffffffL; - a[77] += a[76] >> 53; a[76] &= 0x1fffffffffffffL; -} - -#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_4096_mul_13(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_uint128 t0; - sp_uint128 t1; - sp_digit t[13]; - - t0 = ((sp_uint128)a[ 0]) * b[ 0]; - t1 = ((sp_uint128)a[ 0]) * b[ 1] - + ((sp_uint128)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 0]) * b[ 2] - + ((sp_uint128)a[ 1]) * b[ 1] - + ((sp_uint128)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 0]) * b[ 3] - + ((sp_uint128)a[ 1]) * b[ 2] - + ((sp_uint128)a[ 2]) * b[ 1] - + ((sp_uint128)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 0]) * b[ 4] - + ((sp_uint128)a[ 1]) * b[ 3] - + ((sp_uint128)a[ 2]) * b[ 2] - + ((sp_uint128)a[ 3]) * b[ 1] - + ((sp_uint128)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 0]) * b[ 5] - + ((sp_uint128)a[ 1]) * b[ 4] - + ((sp_uint128)a[ 2]) * b[ 3] - + ((sp_uint128)a[ 3]) * b[ 2] - + ((sp_uint128)a[ 4]) * b[ 1] - + ((sp_uint128)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 0]) * b[ 6] - + ((sp_uint128)a[ 1]) * b[ 5] - + ((sp_uint128)a[ 2]) * b[ 4] - + ((sp_uint128)a[ 3]) * b[ 3] - + ((sp_uint128)a[ 4]) * b[ 2] - + ((sp_uint128)a[ 5]) * b[ 1] - + ((sp_uint128)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 0]) * b[ 7] - + ((sp_uint128)a[ 1]) * b[ 6] - + ((sp_uint128)a[ 2]) * b[ 5] - + ((sp_uint128)a[ 3]) * b[ 4] - + ((sp_uint128)a[ 4]) * b[ 3] - + ((sp_uint128)a[ 5]) * b[ 2] - + ((sp_uint128)a[ 6]) * b[ 1] - + ((sp_uint128)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 0]) * b[ 8] - + ((sp_uint128)a[ 1]) * b[ 7] - + ((sp_uint128)a[ 2]) * b[ 6] - + ((sp_uint128)a[ 3]) * b[ 5] - + ((sp_uint128)a[ 4]) * b[ 4] - + ((sp_uint128)a[ 5]) * b[ 3] - + ((sp_uint128)a[ 6]) * b[ 2] - + ((sp_uint128)a[ 7]) * b[ 1] - + ((sp_uint128)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 0]) * b[ 9] - + ((sp_uint128)a[ 1]) * b[ 8] - + ((sp_uint128)a[ 2]) * b[ 7] - + ((sp_uint128)a[ 3]) * b[ 6] - + ((sp_uint128)a[ 4]) * b[ 5] - + ((sp_uint128)a[ 5]) * b[ 4] - + ((sp_uint128)a[ 6]) * b[ 3] - + ((sp_uint128)a[ 7]) * b[ 2] - + ((sp_uint128)a[ 8]) * b[ 1] - + ((sp_uint128)a[ 9]) * b[ 0]; - t[ 8] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 0]) * b[10] - + ((sp_uint128)a[ 1]) * b[ 9] - + ((sp_uint128)a[ 2]) * b[ 8] - + ((sp_uint128)a[ 3]) * b[ 7] - + ((sp_uint128)a[ 4]) * b[ 6] - + ((sp_uint128)a[ 5]) * b[ 5] - + ((sp_uint128)a[ 6]) * b[ 4] - + ((sp_uint128)a[ 7]) * b[ 3] - + ((sp_uint128)a[ 8]) * b[ 2] - + ((sp_uint128)a[ 9]) * b[ 1] - + ((sp_uint128)a[10]) * b[ 0]; - t[ 9] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 0]) * b[11] - + ((sp_uint128)a[ 1]) * b[10] - + ((sp_uint128)a[ 2]) * b[ 9] - + ((sp_uint128)a[ 3]) * b[ 8] - + ((sp_uint128)a[ 4]) * b[ 7] - + ((sp_uint128)a[ 5]) * b[ 6] - + ((sp_uint128)a[ 6]) * b[ 5] - + ((sp_uint128)a[ 7]) * b[ 4] - + ((sp_uint128)a[ 8]) * b[ 3] - + ((sp_uint128)a[ 9]) * b[ 2] - + ((sp_uint128)a[10]) * b[ 1] - + ((sp_uint128)a[11]) * b[ 0]; - t[10] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 0]) * b[12] - + ((sp_uint128)a[ 1]) * b[11] - + ((sp_uint128)a[ 2]) * b[10] - + ((sp_uint128)a[ 3]) * b[ 9] - + ((sp_uint128)a[ 4]) * b[ 8] - + ((sp_uint128)a[ 5]) * b[ 7] - + ((sp_uint128)a[ 6]) * b[ 6] - + ((sp_uint128)a[ 7]) * b[ 5] - + ((sp_uint128)a[ 8]) * b[ 4] - + ((sp_uint128)a[ 9]) * b[ 3] - + ((sp_uint128)a[10]) * b[ 2] - + ((sp_uint128)a[11]) * b[ 1] - + ((sp_uint128)a[12]) * b[ 0]; - t[11] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 1]) * b[12] - + ((sp_uint128)a[ 2]) * b[11] - + ((sp_uint128)a[ 3]) * b[10] - + ((sp_uint128)a[ 4]) * b[ 9] - + ((sp_uint128)a[ 5]) * b[ 8] - + ((sp_uint128)a[ 6]) * b[ 7] - + ((sp_uint128)a[ 7]) * b[ 6] - + ((sp_uint128)a[ 8]) * b[ 5] - + ((sp_uint128)a[ 9]) * b[ 4] - + ((sp_uint128)a[10]) * b[ 3] - + ((sp_uint128)a[11]) * b[ 2] - + ((sp_uint128)a[12]) * b[ 1]; - t[12] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 2]) * b[12] - + ((sp_uint128)a[ 3]) * b[11] - + ((sp_uint128)a[ 4]) * b[10] - + ((sp_uint128)a[ 5]) * b[ 9] - + ((sp_uint128)a[ 6]) * b[ 8] - + ((sp_uint128)a[ 7]) * b[ 7] - + ((sp_uint128)a[ 8]) * b[ 6] - + ((sp_uint128)a[ 9]) * b[ 5] - + ((sp_uint128)a[10]) * b[ 4] - + ((sp_uint128)a[11]) * b[ 3] - + ((sp_uint128)a[12]) * b[ 2]; - r[13] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 3]) * b[12] - + ((sp_uint128)a[ 4]) * b[11] - + ((sp_uint128)a[ 5]) * b[10] - + ((sp_uint128)a[ 6]) * b[ 9] - + ((sp_uint128)a[ 7]) * b[ 8] - + ((sp_uint128)a[ 8]) * b[ 7] - + ((sp_uint128)a[ 9]) * b[ 6] - + ((sp_uint128)a[10]) * b[ 5] - + ((sp_uint128)a[11]) * b[ 4] - + ((sp_uint128)a[12]) * b[ 3]; - r[14] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 4]) * b[12] - + ((sp_uint128)a[ 5]) * b[11] - + ((sp_uint128)a[ 6]) * b[10] - + ((sp_uint128)a[ 7]) * b[ 9] - + ((sp_uint128)a[ 8]) * b[ 8] - + ((sp_uint128)a[ 9]) * b[ 7] - + ((sp_uint128)a[10]) * b[ 6] - + ((sp_uint128)a[11]) * b[ 5] - + ((sp_uint128)a[12]) * b[ 4]; - r[15] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 5]) * b[12] - + ((sp_uint128)a[ 6]) * b[11] - + ((sp_uint128)a[ 7]) * b[10] - + ((sp_uint128)a[ 8]) * b[ 9] - + ((sp_uint128)a[ 9]) * b[ 8] - + ((sp_uint128)a[10]) * b[ 7] - + ((sp_uint128)a[11]) * b[ 6] - + ((sp_uint128)a[12]) * b[ 5]; - r[16] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 6]) * b[12] - + ((sp_uint128)a[ 7]) * b[11] - + ((sp_uint128)a[ 8]) * b[10] - + ((sp_uint128)a[ 9]) * b[ 9] - + ((sp_uint128)a[10]) * b[ 8] - + ((sp_uint128)a[11]) * b[ 7] - + ((sp_uint128)a[12]) * b[ 6]; - r[17] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 7]) * b[12] - + ((sp_uint128)a[ 8]) * b[11] - + ((sp_uint128)a[ 9]) * b[10] - + ((sp_uint128)a[10]) * b[ 9] - + ((sp_uint128)a[11]) * b[ 8] - + ((sp_uint128)a[12]) * b[ 7]; - r[18] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[ 8]) * b[12] - + ((sp_uint128)a[ 9]) * b[11] - + ((sp_uint128)a[10]) * b[10] - + ((sp_uint128)a[11]) * b[ 9] - + ((sp_uint128)a[12]) * b[ 8]; - r[19] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[ 9]) * b[12] - + ((sp_uint128)a[10]) * b[11] - + ((sp_uint128)a[11]) * b[10] - + ((sp_uint128)a[12]) * b[ 9]; - r[20] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[10]) * b[12] - + ((sp_uint128)a[11]) * b[11] - + ((sp_uint128)a[12]) * b[10]; - r[21] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = ((sp_uint128)a[11]) * b[12] - + ((sp_uint128)a[12]) * b[11]; - r[22] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[12]) * b[12]; - r[23] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - r[24] = (sp_digit)(t0 & 0x1fffffffffffffL); - r[25] = (sp_digit)(t0 >> 53); - XMEMCPY(r, t, sizeof(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. - */ -SP_NOINLINE static int sp_4096_add_13(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]; - - 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_4096_sub_26(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] - b[24]; - r[25] = a[25] - b[25]; - - 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_4096_add_26(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 24; 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[24] = a[24] + b[24]; - r[25] = a[25] + b[25]; - - 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_4096_mul_39(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit p0[26]; - sp_digit p1[26]; - sp_digit p2[26]; - sp_digit p3[26]; - sp_digit p4[26]; - sp_digit p5[26]; - sp_digit t0[26]; - sp_digit t1[26]; - sp_digit t2[26]; - sp_digit a0[13]; - sp_digit a1[13]; - sp_digit a2[13]; - sp_digit b0[13]; - sp_digit b1[13]; - sp_digit b2[13]; - (void)sp_4096_add_13(a0, a, &a[13]); - (void)sp_4096_add_13(b0, b, &b[13]); - (void)sp_4096_add_13(a1, &a[13], &a[26]); - (void)sp_4096_add_13(b1, &b[13], &b[26]); - (void)sp_4096_add_13(a2, a0, &a[26]); - (void)sp_4096_add_13(b2, b0, &b[26]); - sp_4096_mul_13(p0, a, b); - sp_4096_mul_13(p2, &a[13], &b[13]); - sp_4096_mul_13(p4, &a[26], &b[26]); - sp_4096_mul_13(p1, a0, b0); - sp_4096_mul_13(p3, a1, b1); - sp_4096_mul_13(p5, a2, b2); - XMEMSET(r, 0, sizeof(*r)*2U*39U); - (void)sp_4096_sub_26(t0, p3, p2); - (void)sp_4096_sub_26(t1, p1, p2); - (void)sp_4096_sub_26(t2, p5, t0); - (void)sp_4096_sub_26(t2, t2, t1); - (void)sp_4096_sub_26(t0, t0, p4); - (void)sp_4096_sub_26(t1, t1, p0); - (void)sp_4096_add_26(r, r, p0); - (void)sp_4096_add_26(&r[13], &r[13], t1); - (void)sp_4096_add_26(&r[26], &r[26], t2); - (void)sp_4096_add_26(&r[39], &r[39], t0); - (void)sp_4096_add_26(&r[52], &r[52], 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_4096_add_39(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] + b[32]; - r[33] = a[33] + b[33]; - r[34] = a[34] + b[34]; - r[35] = a[35] + b[35]; - r[36] = a[36] + b[36]; - r[37] = a[37] + b[37]; - r[38] = a[38] + b[38]; - - 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_4096_add_78(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 72; 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[72] = a[72] + b[72]; - r[73] = a[73] + b[73]; - r[74] = a[74] + b[74]; - r[75] = a[75] + b[75]; - r[76] = a[76] + b[76]; - r[77] = a[77] + b[77]; - - 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_4096_sub_78(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 72; 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[72] = a[72] - b[72]; - r[73] = a[73] - b[73]; - r[74] = a[74] - b[74]; - r[75] = a[75] - b[75]; - r[76] = a[76] - b[76]; - r[77] = a[77] - b[77]; - - 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_4096_mul_78(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit* z0 = r; - sp_digit z1[78]; - sp_digit* a1 = z1; - sp_digit b1[39]; - sp_digit* z2 = r + 78; - (void)sp_4096_add_39(a1, a, &a[39]); - (void)sp_4096_add_39(b1, b, &b[39]); - sp_4096_mul_39(z2, &a[39], &b[39]); - sp_4096_mul_39(z0, a, b); - sp_4096_mul_39(z1, a1, b1); - (void)sp_4096_sub_78(z1, z1, z2); - (void)sp_4096_sub_78(z1, z1, z0); - (void)sp_4096_add_78(r + 39, r + 39, 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_4096_sqr_13(sp_digit* r, const sp_digit* a) -{ - sp_uint128 t0; - sp_uint128 t1; - sp_digit t[13]; - - t0 = ((sp_uint128)a[ 0]) * a[ 0]; - t1 = (((sp_uint128)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 0]) * a[ 2]) * 2 - + ((sp_uint128)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 0]) * a[ 3] - + ((sp_uint128)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 0]) * a[ 4] - + ((sp_uint128)a[ 1]) * a[ 3]) * 2 - + ((sp_uint128)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 0]) * a[ 5] - + ((sp_uint128)a[ 1]) * a[ 4] - + ((sp_uint128)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 0]) * a[ 6] - + ((sp_uint128)a[ 1]) * a[ 5] - + ((sp_uint128)a[ 2]) * a[ 4]) * 2 - + ((sp_uint128)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 0]) * a[ 7] - + ((sp_uint128)a[ 1]) * a[ 6] - + ((sp_uint128)a[ 2]) * a[ 5] - + ((sp_uint128)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 0]) * a[ 8] - + ((sp_uint128)a[ 1]) * a[ 7] - + ((sp_uint128)a[ 2]) * a[ 6] - + ((sp_uint128)a[ 3]) * a[ 5]) * 2 - + ((sp_uint128)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 0]) * a[ 9] - + ((sp_uint128)a[ 1]) * a[ 8] - + ((sp_uint128)a[ 2]) * a[ 7] - + ((sp_uint128)a[ 3]) * a[ 6] - + ((sp_uint128)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 0]) * a[10] - + ((sp_uint128)a[ 1]) * a[ 9] - + ((sp_uint128)a[ 2]) * a[ 8] - + ((sp_uint128)a[ 3]) * a[ 7] - + ((sp_uint128)a[ 4]) * a[ 6]) * 2 - + ((sp_uint128)a[ 5]) * a[ 5]; - t[ 9] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 0]) * a[11] - + ((sp_uint128)a[ 1]) * a[10] - + ((sp_uint128)a[ 2]) * a[ 9] - + ((sp_uint128)a[ 3]) * a[ 8] - + ((sp_uint128)a[ 4]) * a[ 7] - + ((sp_uint128)a[ 5]) * a[ 6]) * 2; - t[10] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 0]) * a[12] - + ((sp_uint128)a[ 1]) * a[11] - + ((sp_uint128)a[ 2]) * a[10] - + ((sp_uint128)a[ 3]) * a[ 9] - + ((sp_uint128)a[ 4]) * a[ 8] - + ((sp_uint128)a[ 5]) * a[ 7]) * 2 - + ((sp_uint128)a[ 6]) * a[ 6]; - t[11] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 1]) * a[12] - + ((sp_uint128)a[ 2]) * a[11] - + ((sp_uint128)a[ 3]) * a[10] - + ((sp_uint128)a[ 4]) * a[ 9] - + ((sp_uint128)a[ 5]) * a[ 8] - + ((sp_uint128)a[ 6]) * a[ 7]) * 2; - t[12] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 2]) * a[12] - + ((sp_uint128)a[ 3]) * a[11] - + ((sp_uint128)a[ 4]) * a[10] - + ((sp_uint128)a[ 5]) * a[ 9] - + ((sp_uint128)a[ 6]) * a[ 8]) * 2 - + ((sp_uint128)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 3]) * a[12] - + ((sp_uint128)a[ 4]) * a[11] - + ((sp_uint128)a[ 5]) * a[10] - + ((sp_uint128)a[ 6]) * a[ 9] - + ((sp_uint128)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 4]) * a[12] - + ((sp_uint128)a[ 5]) * a[11] - + ((sp_uint128)a[ 6]) * a[10] - + ((sp_uint128)a[ 7]) * a[ 9]) * 2 - + ((sp_uint128)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 5]) * a[12] - + ((sp_uint128)a[ 6]) * a[11] - + ((sp_uint128)a[ 7]) * a[10] - + ((sp_uint128)a[ 8]) * a[ 9]) * 2; - r[16] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 6]) * a[12] - + ((sp_uint128)a[ 7]) * a[11] - + ((sp_uint128)a[ 8]) * a[10]) * 2 - + ((sp_uint128)a[ 9]) * a[ 9]; - r[17] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 7]) * a[12] - + ((sp_uint128)a[ 8]) * a[11] - + ((sp_uint128)a[ 9]) * a[10]) * 2; - r[18] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[ 8]) * a[12] - + ((sp_uint128)a[ 9]) * a[11]) * 2 - + ((sp_uint128)a[10]) * a[10]; - r[19] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[ 9]) * a[12] - + ((sp_uint128)a[10]) * a[11]) * 2; - r[20] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = (((sp_uint128)a[10]) * a[12]) * 2 - + ((sp_uint128)a[11]) * a[11]; - r[21] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - t1 = (((sp_uint128)a[11]) * a[12]) * 2; - r[22] = (sp_digit)(t0 & 0x1fffffffffffffL); t1 += t0 >> 53; - t0 = ((sp_uint128)a[12]) * a[12]; - r[23] = (sp_digit)(t1 & 0x1fffffffffffffL); t0 += t1 >> 53; - r[24] = (sp_digit)(t0 & 0x1fffffffffffffL); - r[25] = (sp_digit)(t0 >> 53); - XMEMCPY(r, t, sizeof(t)); -} - -/* Square a into r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a) -{ - sp_digit p0[26]; - sp_digit p1[26]; - sp_digit p2[26]; - sp_digit p3[26]; - sp_digit p4[26]; - sp_digit p5[26]; - sp_digit t0[26]; - sp_digit t1[26]; - sp_digit t2[26]; - sp_digit a0[13]; - sp_digit a1[13]; - sp_digit a2[13]; - (void)sp_4096_add_13(a0, a, &a[13]); - (void)sp_4096_add_13(a1, &a[13], &a[26]); - (void)sp_4096_add_13(a2, a0, &a[26]); - sp_4096_sqr_13(p0, a); - sp_4096_sqr_13(p2, &a[13]); - sp_4096_sqr_13(p4, &a[26]); - sp_4096_sqr_13(p1, a0); - sp_4096_sqr_13(p3, a1); - sp_4096_sqr_13(p5, a2); - XMEMSET(r, 0, sizeof(*r)*2U*39U); - (void)sp_4096_sub_26(t0, p3, p2); - (void)sp_4096_sub_26(t1, p1, p2); - (void)sp_4096_sub_26(t2, p5, t0); - (void)sp_4096_sub_26(t2, t2, t1); - (void)sp_4096_sub_26(t0, t0, p4); - (void)sp_4096_sub_26(t1, t1, p0); - (void)sp_4096_add_26(r, r, p0); - (void)sp_4096_add_26(&r[13], &r[13], t1); - (void)sp_4096_add_26(&r[26], &r[26], t2); - (void)sp_4096_add_26(&r[39], &r[39], t0); - (void)sp_4096_add_26(&r[52], &r[52], p4); -} - -/* 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_4096_sqr_78(sp_digit* r, const sp_digit* a) -{ - sp_digit* z0 = r; - sp_digit z1[78]; - sp_digit* a1 = z1; - sp_digit* z2 = r + 78; - (void)sp_4096_add_39(a1, a, &a[39]); - sp_4096_sqr_39(z2, &a[39]); - sp_4096_sqr_39(z0, a); - sp_4096_sqr_39(z1, a1); - (void)sp_4096_sub_78(z1, z1, z2); - (void)sp_4096_sub_78(z1, z1, z0); - (void)sp_4096_add_78(r + 39, r + 39, z1); -} - -#endif /* !WOLFSSL_SP_SMALL */ -/* Calculate the bottom digit of -1/a mod 2^n. - * - * a A single precision number. - * rho Bottom word of inverse. - */ -static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) -{ - sp_digit x; - sp_digit b; - - b = a[0]; - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ - x &= 0x1fffffffffffffL; - - /* rho = -1/m mod b */ - *rho = ((sp_digit)1 << 53) - x; -} - -/* 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_4096_mul_d_78(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 76; 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 & 0x1fffffffffffffL); - t >>= 53; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 3] = (sp_digit)t2; - } - t += tb * a[76]; - r[76] = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - t += tb * a[77]; - r[77] = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[78] = (sp_digit)(t & 0x1fffffffffffffL); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) -/* 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_39(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] - b[32]; - r[33] = a[33] - b[33]; - r[34] = a[34] - b[34]; - r[35] = a[35] - b[35]; - r[36] = a[36] - b[36]; - r[37] = a[37] - b[37]; - r[38] = a[38] - b[38]; - - return 0; -} - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_39(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 32; i += 8) { - r[i + 0] = 0x1fffffffffffffL; - r[i + 1] = 0x1fffffffffffffL; - r[i + 2] = 0x1fffffffffffffL; - r[i + 3] = 0x1fffffffffffffL; - r[i + 4] = 0x1fffffffffffffL; - r[i + 5] = 0x1fffffffffffffL; - r[i + 6] = 0x1fffffffffffffL; - r[i + 7] = 0x1fffffffffffffL; - } - r[32] = 0x1fffffffffffffL; - r[33] = 0x1fffffffffffffL; - r[34] = 0x1fffffffffffffL; - r[35] = 0x1fffffffffffffL; - r[36] = 0x1fffffffffffffL; - r[37] = 0x1fffffffffffffL; - r[38] = 0x3ffffffffL; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_39(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_39(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[38] - b[38]) & (0 - (sp_digit)1); - r |= (a[37] - b[37]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[36] - b[36]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[35] - b[35]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[34] - b[34]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[33] - b[33]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[32] - b[32]) & ~(((sp_digit)0 - r) >> 52); - for (i = 24; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 52); - } - - 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_4096_cond_sub_39(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] - (b[32] & m); - r[33] = a[33] - (b[33] & m); - r[34] = a[34] - (b[34] & m); - r[35] = a[35] - (b[35] & m); - r[36] = a[36] - (b[36] & m); - r[37] = a[37] - (b[37] & m); - r[38] = a[38] - (b[38] & m); -} - -/* 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_4096_mul_add_39(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[8]; - int i; - - t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1fffffffffffffL); - for (i = 0; i < 32; i += 8) { - t[1] = tb * a[i+1]; - r[i+1] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); - t[2] = tb * a[i+2]; - r[i+2] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); - t[3] = tb * a[i+3]; - r[i+3] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); - t[4] = tb * a[i+4]; - r[i+4] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); - t[5] = tb * a[i+5]; - r[i+5] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); - t[6] = tb * a[i+6]; - r[i+6] += (sp_digit)((t[5] >> 53) + (t[6] & 0x1fffffffffffffL)); - t[7] = tb * a[i+7]; - r[i+7] += (sp_digit)((t[6] >> 53) + (t[7] & 0x1fffffffffffffL)); - t[0] = tb * a[i+8]; - r[i+8] += (sp_digit)((t[7] >> 53) + (t[0] & 0x1fffffffffffffL)); - } - t[1] = tb * a[33]; - r[33] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); - t[2] = tb * a[34]; - r[34] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); - t[3] = tb * a[35]; - r[35] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); - t[4] = tb * a[36]; - r[36] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); - t[5] = tb * a[37]; - r[37] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); - t[6] = tb * a[38]; - r[38] += (sp_digit)((t[5] >> 53) + (t[6] & 0x1fffffffffffffL)); - r[39] += (sp_digit)(t[6] >> 53); -} - -/* Shift the result in the high 2048 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_39(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[38] >> 34; - n += ((sp_int128)a[39]) << 19; - for (i = 0; i < 32; i += 8) { - r[i + 0] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 40]) << 19; - r[i + 1] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 41]) << 19; - r[i + 2] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 42]) << 19; - r[i + 3] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 43]) << 19; - r[i + 4] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 44]) << 19; - r[i + 5] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 45]) << 19; - r[i + 6] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 46]) << 19; - r[i + 7] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 47]) << 19; - } - r[32] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[72]) << 19; - r[33] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[73]) << 19; - r[34] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[74]) << 19; - r[35] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[75]) << 19; - r[36] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[76]) << 19; - r[37] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[77]) << 19; - r[38] = (sp_digit)n; - XMEMSET(&r[39], 0, sizeof(*r) * 39U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_39(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_39(a + 39); - - for (i=0; i<38; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffL); - sp_4096_mul_add_39(a+i, m, mu); - a[i+1] += a[i] >> 53; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x3ffffffffL); - 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); - over = a[38] - m[38]; - sp_4096_cond_sub_39(a, a, m, ~((over - 1) >> 63)); - sp_4096_norm_39(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_4096_mul_d_39(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 36; 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 & 0x1fffffffffffffL); - t >>= 53; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 3] = (sp_digit)t2; - } - t += tb * a[36]; - r[36] = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - t += tb * a[37]; - r[37] = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - t += tb * a[38]; - r[38] = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[39] = (sp_digit)(t & 0x1fffffffffffffL); -} - -#ifndef 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_4096_cond_add_39(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 32; 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[32] = a[32] + (b[32] & m); - r[33] = a[33] + (b[33] & m); - r[34] = a[34] + (b[34] & m); - r[35] = a[35] + (b[35] & m); - r[36] = a[36] + (b[36] & m); - r[37] = a[37] + (b[37] & m); - r[38] = a[38] + (b[38] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<32; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (53 - n)) & 0x1fffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (53 - n)) & 0x1fffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (53 - n)) & 0x1fffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (53 - n)) & 0x1fffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (53 - n)) & 0x1fffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (53 - n)) & 0x1fffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (53 - n)) & 0x1fffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (53 - n)) & 0x1fffffffffffffL); - } - r[32] = (a[32] >> n) | (sp_digit)((a[33] << (53 - n)) & 0x1fffffffffffffL); - r[33] = (a[33] >> n) | (sp_digit)((a[34] << (53 - n)) & 0x1fffffffffffffL); - r[34] = (a[34] >> n) | (sp_digit)((a[35] << (53 - n)) & 0x1fffffffffffffL); - r[35] = (a[35] >> n) | (sp_digit)((a[36] << (53 - n)) & 0x1fffffffffffffL); - r[36] = (a[36] >> n) | (sp_digit)((a[37] << (53 - n)) & 0x1fffffffffffffL); - r[37] = (a[37] >> n) | (sp_digit)((a[38] << (53 - n)) & 0x1fffffffffffffL); - r[38] = a[38] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 53) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 53) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 53) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 53); - sp_digit t0 = (sp_digit)(d & 0x1fffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 51; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 52) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 53); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 106) - (sp_digit)(d >> 106); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 53) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 22) + 1; - - t = (sp_digit)(d >> 44); - t = (t / dv) << 22; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 9); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_39(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 39 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 39 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 78 + 1; - sd = t2 + 39 + 1; - - sp_4096_mul_d_39(sd, d, (sp_digit)1 << 19); - sp_4096_mul_d_78(t1, a, (sp_digit)1 << 19); - dv = sd[38]; - t1[39 + 39] += t1[39 + 39 - 1] >> 53; - t1[39 + 39 - 1] &= 0x1fffffffffffffL; - for (i=39; i>=0; i--) { - r1 = sp_4096_div_word_39(t1[39 + i], t1[39 + i - 1], dv); - - sp_4096_mul_d_39(t2, sd, r1); - (void)sp_4096_sub_39(&t1[i], &t1[i], t2); - sp_4096_norm_39(&t1[i]); - t1[39 + i] -= t2[39]; - t1[39 + i] += t1[39 + i - 1] >> 53; - t1[39 + i - 1] &= 0x1fffffffffffffL; - r1 = sp_4096_div_word_39(-t1[39 + i], -t1[39 + i - 1], dv); - r1 -= t1[39 + i]; - sp_4096_mul_d_39(t2, sd, r1); - (void)sp_4096_add_39(&t1[i], &t1[i], t2); - t1[39 + i] += t1[39 + i - 1] >> 53; - t1[39 + i - 1] &= 0x1fffffffffffffL; - } - t1[39 - 1] += t1[39 - 2] >> 53; - t1[39 - 2] &= 0x1fffffffffffffL; - r1 = sp_4096_word_div_word_39(t1[39 - 1], dv); - - sp_4096_mul_d_39(t2, sd, r1); - sp_4096_sub_39(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 78U); - for (i=0; i<38; i++) { - r[i+1] += r[i] >> 53; - r[i] &= 0x1fffffffffffffL; - } - sp_4096_cond_add_39(r, r, sd, r[38] >> 63); - - sp_4096_norm_39(r); - sp_4096_rshift_39(r, r, 19); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_39(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_39(a, m, NULL, r); -} - -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 78); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 78, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 39 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 39U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_39(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_39(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 39U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_39(t[1], t[1], norm); - err = sp_4096_mod_39(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 53; - c = bits % 53; - n = e[i--] << (53 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 53; - } - - y = (int)((n >> 52) & 1); - n <<= 1; - - sp_4096_mont_mul_39(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 39 * 2); - sp_4096_mont_sqr_39(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 39 * 2); - } - - sp_4096_mont_reduce_39(t[0], m, mp); - n = sp_4096_cmp_39(t[0], m); - sp_4096_cond_sub_39(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 39 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 78); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 78, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 39 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_39(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_39(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_39(t[1], t[1], norm); - err = sp_4096_mod_39(t[1], t[1], m); - } - } - else { - sp_4096_mul_39(t[1], a, norm); - err = sp_4096_mod_39(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 53; - c = bits % 53; - n = e[i--] << (53 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 53; - } - - y = (int)((n >> 52) & 1); - n <<= 1; - - sp_4096_mont_mul_39(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 39 * 2); - sp_4096_mont_sqr_39(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 39 * 2); - } - - sp_4096_mont_reduce_39(t[0], m, mp); - n = sp_4096_cmp_39(t[0], m); - sp_4096_cond_sub_39(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 39 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (32 * 78) + 78); - sp_digit* t[32]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (32 * 78) + 78, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<32; i++) - t[i] = td + i * 78; - rt = td + 2496; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_39(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_39(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_39(t[1], t[1], norm); - err = sp_4096_mod_39(t[1], t[1], m); - } - } - else { - sp_4096_mul_39(t[1], a, norm); - err = sp_4096_mod_39(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_39(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_39(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_39(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_39(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_39(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_39(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_39(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_39(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_39(t[10], t[ 5], m, mp); - sp_4096_mont_mul_39(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_39(t[12], t[ 6], m, mp); - sp_4096_mont_mul_39(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_39(t[14], t[ 7], m, mp); - sp_4096_mont_mul_39(t[15], t[ 8], t[ 7], m, mp); - sp_4096_mont_sqr_39(t[16], t[ 8], m, mp); - sp_4096_mont_mul_39(t[17], t[ 9], t[ 8], m, mp); - sp_4096_mont_sqr_39(t[18], t[ 9], m, mp); - sp_4096_mont_mul_39(t[19], t[10], t[ 9], m, mp); - sp_4096_mont_sqr_39(t[20], t[10], m, mp); - sp_4096_mont_mul_39(t[21], t[11], t[10], m, mp); - sp_4096_mont_sqr_39(t[22], t[11], m, mp); - sp_4096_mont_mul_39(t[23], t[12], t[11], m, mp); - sp_4096_mont_sqr_39(t[24], t[12], m, mp); - sp_4096_mont_mul_39(t[25], t[13], t[12], m, mp); - sp_4096_mont_sqr_39(t[26], t[13], m, mp); - sp_4096_mont_mul_39(t[27], t[14], t[13], m, mp); - sp_4096_mont_sqr_39(t[28], t[14], m, mp); - sp_4096_mont_mul_39(t[29], t[15], t[14], m, mp); - sp_4096_mont_sqr_39(t[30], t[15], m, mp); - sp_4096_mont_mul_39(t[31], t[16], t[15], m, mp); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 52) / 53) - 1; - c = bits % 53; - if (c == 0) { - c = 53; - } - if (i < 39) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (11 - c); - c += 53; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 78); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 11; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 48; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 11; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 53 - c; - } - - sp_4096_mont_sqr_39(rt, rt, m, mp); - sp_4096_mont_sqr_39(rt, rt, m, mp); - sp_4096_mont_sqr_39(rt, rt, m, mp); - sp_4096_mont_sqr_39(rt, rt, m, mp); - sp_4096_mont_sqr_39(rt, rt, m, mp); - - sp_4096_mont_mul_39(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_39(rt, m, mp); - n = sp_4096_cmp_39(rt, m); - sp_4096_cond_sub_39(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 78); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ - -/* 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. - * - * r A single precision number. - * m A single precision number. - */ -static void sp_4096_mont_norm_78(sp_digit* r, const sp_digit* m) -{ - /* Set r = 2^n - 1. */ - int i; - - for (i = 0; i < 72; i += 8) { - r[i + 0] = 0x1fffffffffffffL; - r[i + 1] = 0x1fffffffffffffL; - r[i + 2] = 0x1fffffffffffffL; - r[i + 3] = 0x1fffffffffffffL; - r[i + 4] = 0x1fffffffffffffL; - r[i + 5] = 0x1fffffffffffffL; - r[i + 6] = 0x1fffffffffffffL; - r[i + 7] = 0x1fffffffffffffL; - } - r[72] = 0x1fffffffffffffL; - r[73] = 0x1fffffffffffffL; - r[74] = 0x1fffffffffffffL; - r[75] = 0x1fffffffffffffL; - r[76] = 0x1fffffffffffffL; - r[77] = 0x7fffL; - - /* r = (2^n - 1) mod n */ - (void)sp_4096_sub_78(r, r, m); - - /* Add one so r = 2^n mod m */ - r[0] += 1; -} - -/* 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_4096_cmp_78(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; - int i; - - r |= (a[77] - b[77]) & (0 - (sp_digit)1); - r |= (a[76] - b[76]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[75] - b[75]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[74] - b[74]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[73] - b[73]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[72] - b[72]) & ~(((sp_digit)0 - r) >> 52); - for (i = 64; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 52); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 52); - } - - 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_4096_cond_sub_78(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 72; 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[72] = a[72] - (b[72] & m); - r[73] = a[73] - (b[73] & m); - r[74] = a[74] - (b[74] & m); - r[75] = a[75] - (b[75] & m); - r[76] = a[76] - (b[76] & m); - r[77] = a[77] - (b[77] & m); -} - -/* 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_4096_mul_add_78(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t[8]; - int i; - - t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1fffffffffffffL); - for (i = 0; i < 72; i += 8) { - t[1] = tb * a[i+1]; - r[i+1] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); - t[2] = tb * a[i+2]; - r[i+2] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); - t[3] = tb * a[i+3]; - r[i+3] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); - t[4] = tb * a[i+4]; - r[i+4] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); - t[5] = tb * a[i+5]; - r[i+5] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); - t[6] = tb * a[i+6]; - r[i+6] += (sp_digit)((t[5] >> 53) + (t[6] & 0x1fffffffffffffL)); - t[7] = tb * a[i+7]; - r[i+7] += (sp_digit)((t[6] >> 53) + (t[7] & 0x1fffffffffffffL)); - t[0] = tb * a[i+8]; - r[i+8] += (sp_digit)((t[7] >> 53) + (t[0] & 0x1fffffffffffffL)); - } - t[1] = tb * a[73]; - r[73] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); - t[2] = tb * a[74]; - r[74] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); - t[3] = tb * a[75]; - r[75] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); - t[4] = tb * a[76]; - r[76] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); - t[5] = tb * a[77]; - r[77] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); - r[78] += (sp_digit)(t[5] >> 53); -} - -/* Shift the result in the high 4096 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_4096_mont_shift_78(sp_digit* r, const sp_digit* a) -{ - int i; - sp_int128 n = a[77] >> 15; - n += ((sp_int128)a[78]) << 38; - for (i = 0; i < 72; i += 8) { - r[i + 0] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 79]) << 38; - r[i + 1] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 80]) << 38; - r[i + 2] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 81]) << 38; - r[i + 3] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 82]) << 38; - r[i + 4] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 83]) << 38; - r[i + 5] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 84]) << 38; - r[i + 6] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 85]) << 38; - r[i + 7] = (sp_digit)(n & 0x1fffffffffffffL); - n >>= 53; n += ((sp_int128)a[i + 86]) << 38; - } - r[72] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[151]) << 38; - r[73] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[152]) << 38; - r[74] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[153]) << 38; - r[75] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[154]) << 38; - r[76] = (sp_digit)(n & 0x1fffffffffffffL); n >>= 53; n += ((sp_int128)a[155]) << 38; - r[77] = (sp_digit)n; - XMEMSET(&r[78], 0, sizeof(*r) * 78U); -} - -/* 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. - */ -static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_4096_norm_78(a + 78); - -#ifdef WOLFSSL_SP_DH - if (mp != 1) { - for (i=0; i<77; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffL); - sp_4096_mul_add_78(a+i, m, mu); - a[i+1] += a[i] >> 53; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7fffL); - sp_4096_mul_add_78(a+i, m, mu); - a[i+1] += a[i] >> 53; - a[i] &= 0x1fffffffffffffL; - } - else { - for (i=0; i<77; i++) { - mu = (sp_digit)(a[i] & 0x1fffffffffffffL); - sp_4096_mul_add_78(a+i, m, mu); - a[i+1] += a[i] >> 53; - } - mu = (sp_digit)(a[i] & 0x7fffL); - sp_4096_mul_add_78(a+i, m, mu); - a[i+1] += a[i] >> 53; - a[i] &= 0x1fffffffffffffL; - } -#else - for (i=0; i<77; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1fffffffffffffL); - sp_4096_mul_add_78(a+i, m, mu); - a[i+1] += a[i] >> 53; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7fffL); - sp_4096_mul_add_78(a+i, m, mu); - a[i+1] += a[i] >> 53; - a[i] &= 0x1fffffffffffffL; -#endif - sp_4096_mont_shift_78(a, a); - over = a[77] - m[77]; - sp_4096_cond_sub_78(a, a, m, ~((over - 1) >> 63)); - sp_4096_norm_78(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* 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_4096_mul_d_156(sp_digit* r, const sp_digit* a, - sp_digit b) -{ - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 156; 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 & 0x1fffffffffffffL); - t >>= 53; - r[i + 0] = (sp_digit)t2; - t += p[1]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 1] = (sp_digit)t2; - t += p[2]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 2] = (sp_digit)t2; - t += p[3]; - t2 = (sp_digit)(t & 0x1fffffffffffffL); - t >>= 53; - r[i + 3] = (sp_digit)t2; - } - r[156] = (sp_digit)(t & 0x1fffffffffffffL); -} - -#ifndef 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_4096_cond_add_78(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 72; 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[72] = a[72] + (b[72] & m); - r[73] = a[73] + (b[73] & m); - r[74] = a[74] + (b[74] & m); - r[75] = a[75] + (b[75] & m); - r[76] = a[76] + (b[76] & m); - r[77] = a[77] + (b[77] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - - for (i=0; i<72; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (53 - n)) & 0x1fffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (53 - n)) & 0x1fffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (53 - n)) & 0x1fffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (53 - n)) & 0x1fffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (53 - n)) & 0x1fffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (53 - n)) & 0x1fffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (53 - n)) & 0x1fffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (53 - n)) & 0x1fffffffffffffL); - } - r[72] = (a[72] >> n) | (sp_digit)((a[73] << (53 - n)) & 0x1fffffffffffffL); - r[73] = (a[73] >> n) | (sp_digit)((a[74] << (53 - n)) & 0x1fffffffffffffL); - r[74] = (a[74] >> n) | (sp_digit)((a[75] << (53 - n)) & 0x1fffffffffffffL); - r[75] = (a[75] >> n) | (sp_digit)((a[76] << (53 - n)) & 0x1fffffffffffffL); - r[76] = (a[76] >> n) | (sp_digit)((a[77] << (53 - n)) & 0x1fffffffffffffL); - r[77] = a[77] >> n; -} - -static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 53) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 53) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 53) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 53); - sp_digit t0 = (sp_digit)(d & 0x1fffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 51; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 52) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 53); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 106) - (sp_digit)(d >> 106); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 53) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 22) + 1; - - t = (sp_digit)(d >> 44); - t = (t / dv) << 22; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 13); - t = t / (dv << 9); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_4096_word_div_word_78(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 78 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 78 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 156 + 1; - sd = t2 + 78 + 1; - - sp_4096_mul_d_78(sd, d, (sp_digit)1 << 38); - sp_4096_mul_d_156(t1, a, (sp_digit)1 << 38); - dv = sd[77]; - t1[78 + 78] += t1[78 + 78 - 1] >> 53; - t1[78 + 78 - 1] &= 0x1fffffffffffffL; - for (i=78; i>=0; i--) { - r1 = sp_4096_div_word_78(t1[78 + i], t1[78 + i - 1], dv); - - sp_4096_mul_d_78(t2, sd, r1); - (void)sp_4096_sub_78(&t1[i], &t1[i], t2); - sp_4096_norm_78(&t1[i]); - t1[78 + i] -= t2[78]; - t1[78 + i] += t1[78 + i - 1] >> 53; - t1[78 + i - 1] &= 0x1fffffffffffffL; - r1 = sp_4096_div_word_78(-t1[78 + i], -t1[78 + i - 1], dv); - r1 -= t1[78 + i]; - sp_4096_mul_d_78(t2, sd, r1); - (void)sp_4096_add_78(&t1[i], &t1[i], t2); - t1[78 + i] += t1[78 + i - 1] >> 53; - t1[78 + i - 1] &= 0x1fffffffffffffL; - } - t1[78 - 1] += t1[78 - 2] >> 53; - t1[78 - 2] &= 0x1fffffffffffffL; - r1 = sp_4096_word_div_word_78(t1[78 - 1], dv); - - sp_4096_mul_d_78(t2, sd, r1); - sp_4096_sub_78(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 156U); - for (i=0; i<77; i++) { - r[i+1] += r[i] >> 53; - r[i] &= 0x1fffffffffffffL; - } - sp_4096_cond_add_78(r, r, sd, r[77] >> 63); - - sp_4096_norm_78(r); - sp_4096_rshift_78(r, r, 38); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_4096_mod_78(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_4096_div_78(a, m, NULL, r); -} - -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) -/* Modular exponentiate a to the e mod m. (r = a^e mod m) - * - * r A single precision number that is the result of the operation. - * a A single precision number being exponentiated. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even or exponent is 0. - */ -static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, - int bits, const sp_digit* m, int reduceA) -{ -#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) - SP_DECL_VAR(sp_digit, td, 3 * 156); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 156, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 78 * 2); - XMEMSET(t[i], 0, sizeof(sp_digit) * 78U * 2U); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_78(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_78(t[1], a, m); - } - else { - XMEMCPY(t[1], a, sizeof(sp_digit) * 78U); - } - } - if (err == MP_OKAY) { - sp_4096_mul_78(t[1], t[1], norm); - err = sp_4096_mod_78(t[1], t[1], m); - } - - if (err == MP_OKAY) { - i = bits / 53; - c = bits % 53; - n = e[i--] << (53 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 53; - } - - y = (int)((n >> 52) & 1); - n <<= 1; - - sp_4096_mont_mul_78(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 78 * 2); - sp_4096_mont_sqr_78(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 78 * 2); - } - - sp_4096_mont_reduce_78(t[0], m, mp); - n = sp_4096_cmp_78(t[0], m); - sp_4096_cond_sub_78(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 78 * 2); - - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#elif !defined(WC_NO_CACHE_RESISTANT) - SP_DECL_VAR(sp_digit, td, 3 * 156); - sp_digit* t[3] = {0, 0, 0}; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 3 * 156, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<3; i++) { - t[i] = td + (i * 78 * 2); - } - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_78(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_78(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_78(t[1], t[1], norm); - err = sp_4096_mod_78(t[1], t[1], m); - } - } - else { - sp_4096_mul_78(t[1], a, norm); - err = sp_4096_mod_78(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - i = bits / 53; - c = bits % 53; - n = e[i--] << (53 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) { - break; - } - - n = e[i--]; - c = 53; - } - - y = (int)((n >> 52) & 1); - n <<= 1; - - sp_4096_mont_mul_78(t[y^1], t[0], t[1], m, mp); - - XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), - sizeof(*t[2]) * 78 * 2); - sp_4096_mont_sqr_78(t[2], t[2], m, mp); - XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + - ((size_t)t[1] & addr_mask[y])), t[2], - sizeof(*t[2]) * 78 * 2); - } - - sp_4096_mont_reduce_78(t[0], m, mp); - n = sp_4096_cmp_78(t[0], m); - sp_4096_cond_sub_78(t[0], t[0], m, (sp_digit)~(n >> 63)); - XMEMCPY(r, t[0], sizeof(*r) * 78 * 2); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -#else - SP_DECL_VAR(sp_digit, td, (16 * 156) + 156); - sp_digit* t[16]; - sp_digit* rt = NULL; - sp_digit* norm = NULL; - sp_digit mp = 1; - sp_digit n; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, (16 * 156) + 156, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - for (i=0; i<16; i++) - t[i] = td + i * 156; - rt = td + 2496; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_78(norm, m); - - if (reduceA != 0) { - err = sp_4096_mod_78(t[1], a, m); - if (err == MP_OKAY) { - sp_4096_mul_78(t[1], t[1], norm); - err = sp_4096_mod_78(t[1], t[1], m); - } - } - else { - sp_4096_mul_78(t[1], a, norm); - err = sp_4096_mod_78(t[1], t[1], m); - } - } - - if (err == MP_OKAY) { - sp_4096_mont_sqr_78(t[ 2], t[ 1], m, mp); - sp_4096_mont_mul_78(t[ 3], t[ 2], t[ 1], m, mp); - sp_4096_mont_sqr_78(t[ 4], t[ 2], m, mp); - sp_4096_mont_mul_78(t[ 5], t[ 3], t[ 2], m, mp); - sp_4096_mont_sqr_78(t[ 6], t[ 3], m, mp); - sp_4096_mont_mul_78(t[ 7], t[ 4], t[ 3], m, mp); - sp_4096_mont_sqr_78(t[ 8], t[ 4], m, mp); - sp_4096_mont_mul_78(t[ 9], t[ 5], t[ 4], m, mp); - sp_4096_mont_sqr_78(t[10], t[ 5], m, mp); - sp_4096_mont_mul_78(t[11], t[ 6], t[ 5], m, mp); - sp_4096_mont_sqr_78(t[12], t[ 6], m, mp); - sp_4096_mont_mul_78(t[13], t[ 7], t[ 6], m, mp); - sp_4096_mont_sqr_78(t[14], t[ 7], m, mp); - sp_4096_mont_mul_78(t[15], t[ 8], t[ 7], m, mp); - - bits = ((bits + 3) / 4) * 4; - i = ((bits + 52) / 53) - 1; - c = bits % 53; - if (c == 0) { - c = 53; - } - if (i < 78) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 4) { - n |= e[i--] << (11 - c); - c += 53; - } - y = (int)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - XMEMCPY(rt, t[y], sizeof(sp_digit) * 156); - while ((i >= 0) || (c >= 4)) { - if (c >= 4) { - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c -= 4; - } - else if (c == 0) { - n = e[i--] << 11; - y = (byte)((n >> 60) & 0xf); - n <<= 4; - c = 49; - } - else { - y = (byte)((n >> 60) & 0xf); - n = e[i--] << 11; - c = 4 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 53 - c; - } - - sp_4096_mont_sqr_78(rt, rt, m, mp); - sp_4096_mont_sqr_78(rt, rt, m, mp); - sp_4096_mont_sqr_78(rt, rt, m, mp); - sp_4096_mont_sqr_78(rt, rt, m, mp); - - sp_4096_mont_mul_78(rt, rt, t[y], m, mp); - } - - sp_4096_mont_reduce_78(rt, m, mp); - n = sp_4096_cmp_78(rt, m); - sp_4096_cond_sub_78(rt, rt, m, (sp_digit)~(n >> 63)); - XMEMCPY(r, rt, sizeof(sp_digit) * 156); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 */ -#ifdef WOLFSSL_HAVE_SP_RSA -/* RSA public key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * em Public exponent. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, const mp_int* em, - const mp_int* mm, byte* out, word32* outLen) -{ -#ifdef WOLFSSL_SP_SMALL - SP_DECL_VAR(sp_digit, a, 78 * 5); - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_digit* norm = NULL; - sp_uint64 e[1] = {0}; - sp_digit mp = 0; - int i; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 78 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - r = a + 78 * 2; - m = r + 78 * 2; - norm = r; - - sp_4096_from_bin(a, 78, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - - if (err == MP_OKAY) { - sp_4096_from_mp(m, 78, mm); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_78(norm, m); - } - if (err == MP_OKAY) { - sp_4096_mul_78(a, a, norm); - err = sp_4096_mod_78(a, a, m); - } - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 78 * 2); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_78(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_78(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_78(r, m, mp); - mp = sp_4096_cmp_78(r, m); - sp_4096_cond_sub_78(r, r, m, ~(mp >> 63)); - - sp_4096_to_bin_78(r, out); - *outLen = 512; - } - - SP_FREE_VAR(a, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 78 * 5); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - sp_uint64 e[1] = {0}; - int err = MP_OKAY; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(em) > 64) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 78 * 5, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - a = d; - r = a + 78 * 2; - m = r + 78 * 2; - - sp_4096_from_bin(a, 78, in, inLen); -#if DIGIT_BIT >= 64 - e[0] = (sp_uint64)em->dp[0]; -#else - e[0] = (sp_uint64)em->dp[0]; - if (em->used > 1) { - e[0] |= ((sp_uint64)em->dp[1]) << DIGIT_BIT; - } -#endif - if (e[0] == 0) { - err = MP_EXPTMOD_E; - } - } - if (err == MP_OKAY) { - sp_4096_from_mp(m, 78, mm); - - if (e[0] == 0x3) { - sp_4096_sqr_78(r, a); - err = sp_4096_mod_78(r, r, m); - if (err == MP_OKAY) { - sp_4096_mul_78(r, a, r); - err = sp_4096_mod_78(r, r, m); - } - } - else { - sp_digit* norm = r; - int i; - sp_digit mp; - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_78(norm, m); - - sp_4096_mul_78(a, a, norm); - err = sp_4096_mod_78(a, a, m); - - if (err == MP_OKAY) { - for (i=63; i>=0; i--) { - if ((e[0] >> i) != 0) { - break; - } - } - - XMEMCPY(r, a, sizeof(sp_digit) * 156U); - for (i--; i>=0; i--) { - sp_4096_mont_sqr_78(r, r, m, mp); - - if (((e[0] >> i) & 1) == 1) { - sp_4096_mont_mul_78(r, r, a, m, mp); - } - } - sp_4096_mont_reduce_78(r, m, mp); - mp = sp_4096_cmp_78(r, m); - sp_4096_cond_sub_78(r, r, m, ~(mp >> 63)); - } - } - } - - if (err == MP_OKAY) { - sp_4096_to_bin_78(r, out); - *outLen = 512; - } - - SP_FREE_VAR(d, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -} - -#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 */ -/* RSA private key operation. - * - * in Array of bytes representing the number to exponentiate, base. - * inLen Number of bytes in base. - * dm Private exponent. - * pm First prime. - * qm Second prime. - * dpm First prime's CRT exponent. - * dqm Second prime's CRT exponent. - * qim Inverse of second prime mod p. - * mm Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Number of bytes in result. - * 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, 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) - SP_DECL_VAR(sp_digit, d, 78 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 78 * 4, NULL, DYNAMIC_TYPE_RSA); - 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); - err = sp_4096_mod_exp_78(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_78(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 78, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, d, 78 * 4); - sp_digit* a = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - - (void)pm; - (void)qm; - (void)dpm; - (void)dqm; - (void)qim; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (mp_count_bits(dm) > 4096) { - err = MP_READ_E; - } - else if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, d, 78 * 4, NULL, DYNAMIC_TYPE_RSA); - 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); - err = sp_4096_mod_exp_78(r, a, d, 4096, m, 0); - } - - if (err == MP_OKAY) { - sp_4096_to_bin_78(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR_ALT(sp_digit, d, a, 78, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#else -#if defined(WOLFSSL_SP_SMALL) - SP_DECL_VAR(sp_digit, a, 39 * 8); - sp_digit* p = 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 39 * 8, NULL, DYNAMIC_TYPE_RSA); - if (err == MP_OKAY) { - p = a + 78; - qi = dq = dp = p + 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(dp, 39, dpm); - err = sp_4096_mod_exp_39(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 39, qm); - sp_4096_from_mp(dq, 39, dqm); - err = sp_4096_mod_exp_39(tmpb, a, dq, 2048, p, 1); - } - if (err == MP_OKAY) { - sp_4096_from_mp(p, 39, pm); - (void)sp_4096_sub_39(tmpa, tmpa, tmpb); - sp_4096_norm_39(tmpa); - sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); - sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); - sp_4096_norm_39(tmpa); - - sp_4096_from_mp(qi, 39, qim); - sp_4096_mul_39(tmpa, tmpa, qi); - err = sp_4096_mod_39(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_from_mp(p, 39, qm); - sp_4096_mul_39(tmpa, p, tmpa); - (void)sp_4096_add_78(r, tmpb, tmpa); - sp_4096_norm_78(r); - - sp_4096_to_bin_78(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 39 * 8, NULL, DYNAMIC_TYPE_RSA); - - return err; -#else - SP_DECL_VAR(sp_digit, a, 39 * 13); - 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; - (void)mm; - - if (*outLen < 512U) { - err = MP_TO_E; - } - if (err == MP_OKAY) { - if (inLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mm) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mm)) { - err = MP_VAL; - } - else if (mp_iseven(pm)) { - err = MP_VAL; - } - else if (mp_iseven(qm)) { - err = MP_VAL; - } - } - - SP_ALLOC_VAR(sp_digit, a, 39 * 13, NULL, DYNAMIC_TYPE_RSA); - 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); - sp_4096_from_mp(dp, 39, dpm); - sp_4096_from_mp(dq, 39, dqm); - sp_4096_from_mp(qi, 39, qim); - - err = sp_4096_mod_exp_39(tmpa, a, dp, 2048, p, 1); - } - if (err == MP_OKAY) { - err = sp_4096_mod_exp_39(tmpb, a, dq, 2048, q, 1); - } - - if (err == MP_OKAY) { - (void)sp_4096_sub_39(tmpa, tmpa, tmpb); - sp_4096_norm_39(tmpa); - sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); - sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); - sp_4096_norm_39(tmpa); - sp_4096_mul_39(tmpa, tmpa, qi); - err = sp_4096_mod_39(tmpa, tmpa, p); - } - - if (err == MP_OKAY) { - sp_4096_mul_39(tmpa, tmpa, q); - (void)sp_4096_add_78(r, tmpb, tmpa); - sp_4096_norm_78(r); - - sp_4096_to_bin_78(r, out); - *outLen = 512; - } - - SP_ZEROFREE_VAR(sp_digit, a, 39 * 13, NULL, DYNAMIC_TYPE_RSA); - - return err; -#endif /* WOLFSSL_SP_SMALL */ -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ -} - -#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_4096_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 53 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 78); - r->used = 78; - mp_clamp(r); -#elif DIGIT_BIT < 53 - 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] &= ((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++] &= ((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 = 53 - s; - } - r->used = (4096 + 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 < 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] &= ((sp_digit)1 << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 53 - s; - } - else { - s += 53; - } - } - r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. MP integer. - * exp Exponent. MP integer. - * mod Modulus. 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_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_DECL_VAR(sp_digit, b, 78 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 78 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_4096_mod_exp_78(r, b, e, mp_count_bits(exp), m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 78U, NULL, DYNAMIC_TYPE_DH); - - return err; -#else - SP_DECL_VAR(sp_digit, b, 78 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - int err = MP_OKAY; - int expBits = mp_count_bits(exp); - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expBits > 4096) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 78 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - err = sp_4096_mod_exp_78(r, b, e, expBits, m, 0); - } - - if (err == MP_OKAY) { - err = sp_4096_to_mp(r, res); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 78U, NULL, DYNAMIC_TYPE_DH); - - return err; -#endif -} - -#ifdef WOLFSSL_HAVE_SP_DH - -#ifdef HAVE_FFDHE_4096 -SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, const sp_digit* a, - byte n) -{ - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[77]; - r[78] = s >> (53U - n); - s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); - r[77] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); - r[76] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); - r[75] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); - r[74] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); - r[73] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); - r[72] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); - r[71] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); - r[70] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); - r[69] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); - r[68] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); - r[67] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); - r[66] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); - r[65] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); - r[64] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); - r[63] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); - r[62] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); - r[61] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); - r[60] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); - r[59] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); - r[58] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); - r[57] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); - r[56] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); - r[55] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); - r[54] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); - r[53] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); - r[52] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); - r[51] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); - r[50] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); - r[49] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); - r[48] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); - r[47] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); - r[46] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); - r[45] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); - r[44] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); - r[43] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); - r[42] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); - r[41] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); - r[40] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); - r[39] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); - r[38] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); - r[37] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); - r[36] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); - r[35] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); - r[34] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); - r[33] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); - r[32] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); - r[31] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); - r[30] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); - r[29] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); - r[28] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); - r[27] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); - r[26] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); - r[25] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); - r[24] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); - r[23] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); - r[22] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); - r[21] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); - r[20] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); - r[19] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); - r[18] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL); - r[0] = (sp_digit)((a[0] << n) & 0x1fffffffffffffL); -} - -/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) - * - * r A single precision number that is the result of the operation. - * e A single precision number that is the exponent. - * bits The number of bits in the exponent. - * m A single precision number that is the modulus. - * returns 0 on success. - * returns MEMORY_E on dynamic memory allocation failure. - * returns MP_VAL when base is even. - */ -static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) -{ - SP_DECL_VAR(sp_digit, td, 235); - sp_digit* norm = NULL; - sp_digit* tmp = NULL; - sp_digit mp = 1; - sp_digit n; - sp_digit o; - int i; - int c; - byte y; - int err = MP_OKAY; - - if (bits == 0) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, td, 235, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - norm = td; - tmp = td + 156; - XMEMSET(td, 0, sizeof(sp_digit) * 235); - - sp_4096_mont_setup(m, &mp); - sp_4096_mont_norm_78(norm, m); - - bits = ((bits + 4) / 5) * 5; - i = ((bits + 52) / 53) - 1; - c = bits % 53; - if (c == 0) { - c = 53; - } - if (i < 78) { - n = e[i--] << (64 - c); - } - else { - n = 0; - i--; - } - if (c < 5) { - n |= e[i--] << (11 - c); - c += 53; - } - y = (int)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - sp_4096_lshift_78(r, norm, (byte)y); - while ((i >= 0) || (c >= 5)) { - if (c >= 5) { - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c -= 5; - } - else if (c == 0) { - n = e[i--] << 11; - y = (byte)((n >> 59) & 0x1f); - n <<= 5; - c = 48; - } - else { - y = (byte)((n >> 59) & 0x1f); - n = e[i--] << 11; - c = 5 - c; - y |= (byte)((n >> (64 - c)) & ((1 << c) - 1)); - n <<= c; - c = 53 - c; - } - - sp_4096_mont_sqr_78(r, r, m, mp); - sp_4096_mont_sqr_78(r, r, m, mp); - sp_4096_mont_sqr_78(r, r, m, mp); - sp_4096_mont_sqr_78(r, r, m, mp); - sp_4096_mont_sqr_78(r, r, m, mp); - - sp_4096_lshift_78(r, r, (byte)y); - sp_4096_mul_d_78(tmp, norm, (r[78] << 38) + (r[77] >> 15)); - r[78] = 0; - r[77] &= 0x7fffL; - (void)sp_4096_add_78(r, r, tmp); - sp_4096_norm_78(r); - o = sp_4096_cmp_78(r, m); - sp_4096_cond_sub_78(r, r, m, ~(o >> 63)); - } - - sp_4096_mont_reduce_78(r, m, mp); - n = sp_4096_cmp_78(r, m); - sp_4096_cond_sub_78(r, r, m, (sp_digit)~(n >> 63)); - } - - SP_FREE_VAR(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return err; -} - -#endif /* HAVE_FFDHE_4096 */ - -/* Perform the modular exponentiation for Diffie-Hellman. - * - * base Base. - * exp Array of bytes that is the exponent. - * expLen Length of data, in bytes, in exponent. - * mod Modulus. - * out Buffer to hold big-endian bytes of exponentiation result. - * Must be at least 512 bytes long. - * outLen Length, in bytes, of exponentiation result. - * 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(const mp_int* base, const byte* exp, word32 expLen, - const mp_int* mod, byte* out, word32* outLen) -{ - SP_DECL_VAR(sp_digit, b, 78 * 4); - sp_digit* e = NULL; - sp_digit* m = NULL; - sp_digit* r = NULL; - word32 i; - int err = MP_OKAY; - - if (mp_count_bits(base) > 4096) { - err = MP_READ_E; - } - else if (expLen > 512U) { - err = MP_READ_E; - } - else if (mp_count_bits(mod) != 4096) { - err = MP_READ_E; - } - else if (mp_iseven(mod)) { - err = MP_VAL; - } - - SP_ALLOC_VAR(sp_digit, b, 78 * 4, NULL, DYNAMIC_TYPE_DH); - - 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); - - #ifdef HAVE_FFDHE_4096 - if (base->used == 1 && base->dp[0] == 2U && - ((m[77] << 17) | (m[76] >> 36)) == 0xffffffffL) { - err = sp_4096_mod_exp_2_78(r, e, expLen * 8U, m); - } - else { - #endif - err = sp_4096_mod_exp_78(r, b, e, expLen * 8U, m, 0); - #ifdef HAVE_FFDHE_4096 - } - #endif - } - - if (err == MP_OKAY) { - sp_4096_to_bin_78(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); - } - - SP_ZEROFREE_VAR_ALT(sp_digit, b, e, 78U, NULL, DYNAMIC_TYPE_DH); - - return err; -} -#endif /* WOLFSSL_HAVE_SP_DH */ - -#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ - -#endif /* WOLFSSL_SP_SMALL */ -#endif /* WOLFSSL_SP_4096 */ - -#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; - -/* The modulus (prime) of the curve P256. */ -static const sp_digit p256_mod[5] = { - 0xfffffffffffffL,0x00fffffffffffL,0x0000000000000L,0x0001000000000L, - 0x0ffffffff0000L -}; -/* The Montgomery normalizer for modulus of the curve P256. */ -static const sp_digit p256_norm_mod[5] = { - 0x0000000000001L,0xff00000000000L,0xfffffffffffffL,0xfffefffffffffL, - 0x000000000ffffL -}; -/* The Montgomery multiplier for modulus of the curve P256. */ -static const sp_digit p256_mp_mod = 0x0000000000001; -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -/* The order of the curve P256. */ -static const sp_digit p256_order[5] = { - 0x9cac2fc632551L,0xada7179e84f3bL,0xfffffffbce6faL,0x0000fffffffffL, - 0x0ffffffff0000L -}; -#endif -#ifndef WC_NO_RNG -/* The order of the curve P256 minus 2. */ -static const sp_digit p256_order2[5] = { - 0x9cac2fc63254fL,0xada7179e84f3bL,0xfffffffbce6faL,0x0000fffffffffL, - 0x0ffffffff0000L -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery normalizer for order of the curve P256. */ -static const sp_digit p256_norm_order[5] = { - 0x6353d039cdaafL,0x5258e8617b0c4L,0x0000000431905L,0xffff000000000L, - 0x000000000ffffL -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery multiplier for order of the curve P256. */ -static const sp_digit p256_mp_order = 0x1c8aaee00bc4fL; -#endif -/* The base point of curve P256. */ -static const sp_point_256 p256_base = { - /* X ordinate */ - { - 0x13945d898c296L,0x812deb33a0f4aL,0x3a440f277037dL,0x4247f8bce6e56L, - 0x06b17d1f2e12cL, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Y ordinate */ - { - 0x6406837bf51f5L,0x576b315ececbbL,0xc0f9e162bce33L,0x7f9b8ee7eb4a7L, - 0x04fe342e2fe1aL, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Z ordinate */ - { - 0x0000000000001L,0x0000000000000L,0x0000000000000L,0x0000000000000L, - 0x0000000000000L, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) || \ - defined(HAVE_COMP_KEY) -static const sp_digit p256_b[5] = { - 0xe3c3e27d2604bL,0xb0cc53b0f63bcL,0x69886bc651d06L,0x93e7b3ebbd557L, - 0x05ac635d8aa3aL -}; -#endif - -#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. - */ -SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[4]) * b[4]; - r[9] = (sp_digit)(c >> 52); - c &= 0xfffffffffffffL; - for (k = 7; k >= 0; k--) { - if (k >= 5) { - i = k - 4; - imax = 4; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 52; - r[k + 2] += (sp_digit)(c >> 52); - r[k + 1] = (sp_digit)(c & 0xfffffffffffffL); - c = lo & 0xfffffffffffffL; - } - r[0] = (sp_digit)c; -} - -#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_256_mul_5(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_int128 t0 = ((sp_int128)a[ 0]) * b[ 0]; - sp_int128 t1 = ((sp_int128)a[ 0]) * b[ 1] - + ((sp_int128)a[ 1]) * b[ 0]; - sp_int128 t2 = ((sp_int128)a[ 0]) * b[ 2] - + ((sp_int128)a[ 1]) * b[ 1] - + ((sp_int128)a[ 2]) * b[ 0]; - sp_int128 t3 = ((sp_int128)a[ 0]) * b[ 3] - + ((sp_int128)a[ 1]) * b[ 2] - + ((sp_int128)a[ 2]) * b[ 1] - + ((sp_int128)a[ 3]) * b[ 0]; - sp_int128 t4 = ((sp_int128)a[ 0]) * b[ 4] - + ((sp_int128)a[ 1]) * b[ 3] - + ((sp_int128)a[ 2]) * b[ 2] - + ((sp_int128)a[ 3]) * b[ 1] - + ((sp_int128)a[ 4]) * b[ 0]; - sp_int128 t5 = ((sp_int128)a[ 1]) * b[ 4] - + ((sp_int128)a[ 2]) * b[ 3] - + ((sp_int128)a[ 3]) * b[ 2] - + ((sp_int128)a[ 4]) * b[ 1]; - sp_int128 t6 = ((sp_int128)a[ 2]) * b[ 4] - + ((sp_int128)a[ 3]) * b[ 3] - + ((sp_int128)a[ 4]) * b[ 2]; - sp_int128 t7 = ((sp_int128)a[ 3]) * b[ 4] - + ((sp_int128)a[ 4]) * b[ 3]; - sp_int128 t8 = ((sp_int128)a[ 4]) * b[ 4]; - - t1 += t0 >> 52; r[ 0] = (sp_digit)(t0 & 0xfffffffffffffL); - t2 += t1 >> 52; r[ 1] = (sp_digit)(t1 & 0xfffffffffffffL); - t3 += t2 >> 52; r[ 2] = (sp_digit)(t2 & 0xfffffffffffffL); - t4 += t3 >> 52; r[ 3] = (sp_digit)(t3 & 0xfffffffffffffL); - t5 += t4 >> 52; r[ 4] = (sp_digit)(t4 & 0xfffffffffffffL); - t6 += t5 >> 52; r[ 5] = (sp_digit)(t5 & 0xfffffffffffffL); - t7 += t6 >> 52; r[ 6] = (sp_digit)(t6 & 0xfffffffffffffL); - t8 += t7 >> 52; r[ 7] = (sp_digit)(t7 & 0xfffffffffffffL); - r[9] = (sp_digit)(t8 >> 52); - r[8] = (sp_digit)(t8 & 0xfffffffffffffL); -} - -#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 imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[4]) * a[4]; - r[9] = (sp_digit)(c >> 52); - c = (c & 0xfffffffffffffL) << 52; - for (k = 7; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 4) { - imax = k; - } - else { - imax = 4; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - 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) -{ - sp_int128 t0 = ((sp_int128)a[ 0]) * a[ 0]; - sp_int128 t1 = (((sp_int128)a[ 0]) * a[ 1]) * 2; - sp_int128 t2 = (((sp_int128)a[ 0]) * a[ 2]) * 2 - + ((sp_int128)a[ 1]) * a[ 1]; - sp_int128 t3 = (((sp_int128)a[ 0]) * a[ 3] - + ((sp_int128)a[ 1]) * a[ 2]) * 2; - sp_int128 t4 = (((sp_int128)a[ 0]) * a[ 4] - + ((sp_int128)a[ 1]) * a[ 3]) * 2 - + ((sp_int128)a[ 2]) * a[ 2]; - sp_int128 t5 = (((sp_int128)a[ 1]) * a[ 4] - + ((sp_int128)a[ 2]) * a[ 3]) * 2; - sp_int128 t6 = (((sp_int128)a[ 2]) * a[ 4]) * 2 - + ((sp_int128)a[ 3]) * a[ 3]; - sp_int128 t7 = (((sp_int128)a[ 3]) * a[ 4]) * 2; - sp_int128 t8 = ((sp_int128)a[ 4]) * a[ 4]; - - t1 += t0 >> 52; r[ 0] = (sp_digit)(t0 & 0xfffffffffffffL); - t2 += t1 >> 52; r[ 1] = (sp_digit)(t1 & 0xfffffffffffffL); - t3 += t2 >> 52; r[ 2] = (sp_digit)(t2 & 0xfffffffffffffL); - t4 += t3 >> 52; r[ 3] = (sp_digit)(t3 & 0xfffffffffffffL); - t5 += t4 >> 52; r[ 4] = (sp_digit)(t4 & 0xfffffffffffffL); - t6 += t5 >> 52; r[ 5] = (sp_digit)(t5 & 0xfffffffffffffL); - t7 += t6 >> 52; r[ 6] = (sp_digit)(t6 & 0xfffffffffffffL); - t8 += t7 >> 52; r[ 7] = (sp_digit)(t7 & 0xfffffffffffffL); - r[9] = (sp_digit)(t8 >> 52); - r[8] = (sp_digit)(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 i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 51); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 51); - } -#elif DIGIT_BIT > 52 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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; -} - -/* 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_256_cmp_5(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=4; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 51); - } -#else - r |= (a[ 4] - b[ 4]) & (0 - (sp_digit)1); - r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 51); - r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 51); - r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 51); - r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 51); -#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_256_cond_sub_5(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 < 5; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - r[ 0] = a[ 0] - (b[ 0] & m); - r[ 1] = a[ 1] - (b[ 1] & m); - r[ 2] = a[ 2] - (b[ 2] & m); - r[ 3] = a[ 3] - (b[ 3] & m); - r[ 4] = a[ 4] - (b[ 4] & 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_256_mul_add_5(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 4; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0xfffffffffffffL); - t[1] += t[0] >> 52; - r[i+1] = (sp_digit)(t[1] & 0xfffffffffffffL); - t[2] += t[1] >> 52; - r[i+2] = (sp_digit)(t[2] & 0xfffffffffffffL); - t[3] += t[2] >> 52; - r[i+3] = (sp_digit)(t[3] & 0xfffffffffffffL); - t[0] = t[3] >> 52; - } - t[0] += (tb * a[4]) + r[4]; - r[4] = (sp_digit)(t[0] & 0xfffffffffffffL); - r[5] += (sp_digit)(t[0] >> 52); -#else - sp_int128 tb = b; - sp_int128 t[5]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - r[ 0] += (sp_digit) (t[ 0] & 0xfffffffffffffL); - r[ 1] += (sp_digit)((t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffL)); - r[ 2] += (sp_digit)((t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffL)); - r[ 3] += (sp_digit)((t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffL)); - r[ 4] += (sp_digit)((t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffL)); - r[ 5] += (sp_digit) (t[ 4] >> 52); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Normalize the values in each word to 52 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_256_norm_5(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 4; i++) { - a[i+1] += a[i] >> 52; - a[i] &= 0xfffffffffffffL; - } -#else - a[1] += a[0] >> 52; a[0] &= 0xfffffffffffffL; - a[2] += a[1] >> 52; a[1] &= 0xfffffffffffffL; - a[3] += a[2] >> 52; a[2] &= 0xfffffffffffffL; - a[4] += a[3] >> 52; a[3] &= 0xfffffffffffffL; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Shift the result in the high 256 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_256_mont_shift_5(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_uint64 n; - - n = a[4] >> 48; - for (i = 0; i < 4; i++) { - n += (sp_uint64)a[5 + i] << 4; - r[i] = (sp_digit)(n & 0xfffffffffffffL); - n >>= 52; - } - n += (sp_uint64)a[9] << 4; - r[4] = n; -#else - sp_uint64 n; - - n = a[4] >> 48; - n += (sp_uint64)a[ 5] << 4U; r[ 0] = (sp_digit)(n & 0xfffffffffffffUL); n >>= 52U; - n += (sp_uint64)a[ 6] << 4U; r[ 1] = (sp_digit)(n & 0xfffffffffffffUL); n >>= 52U; - n += (sp_uint64)a[ 7] << 4U; r[ 2] = (sp_digit)(n & 0xfffffffffffffUL); n >>= 52U; - n += (sp_uint64)a[ 8] << 4U; r[ 3] = (sp_digit)(n & 0xfffffffffffffUL); n >>= 52U; - n += (sp_uint64)a[ 9] << 4U; r[ 4] = n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[5], 0, sizeof(*r) * 5U); -} - -/* 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. - */ -static void sp_256_mont_reduce_order_5(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_256_norm_5(a + 5); - - for (i=0; i<4; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xfffffffffffffL); - sp_256_mul_add_5(a+i, m, mu); - a[i+1] += a[i] >> 52; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0xffffffffffffL); - sp_256_mul_add_5(a+i, m, mu); - a[i+1] += a[i] >> 52; - a[i] &= 0xfffffffffffffL; - sp_256_mont_shift_5(a, a); - over = a[4] >> 48; - sp_256_cond_sub_5(a, a, m, ~((over - 1) >> 63)); - sp_256_norm_5(a); -} - -/* 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. - */ -static void sp_256_mont_reduce_5(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_int128 t; - sp_digit am; - - (void)m; - (void)mp; - - for (i = 0; i < 4; i++) { - am = (sp_digit)(a[i] & 0xfffffffffffffL); - /* Fifth word of modulus word */ - t = am; t *= 0x0ffffffff0000L; - - a[i + 1] += (sp_digit)((am << 44) & 0xfffffffffffffL); - a[i + 2] += am >> 8; - a[i + 3] += (sp_digit)((am << 36) & 0xfffffffffffffL); - a[i + 4] += (am >> 16) + (sp_digit)(t & 0xfffffffffffffL); - a[i + 5] += t >> 52; - - a[i + 1] += a[i] >> 52; - } - am = (sp_digit)(a[4] & 0xffffffffffff); - /* Fifth word of modulus word */ - t = am; t *= 0x0ffffffff0000L; - - a[4 + 1] += (sp_digit)((am << 44) & 0xfffffffffffffL); - a[4 + 2] += am >> 8; - a[4 + 3] += (sp_digit)((am << 36) & 0xfffffffffffffL); - a[4 + 4] += (am >> 16) + (sp_digit)(t & 0xfffffffffffffL); - a[4 + 5] += t >> 52; - - a[0] = (a[4] >> 48) + (sp_digit)((a[5] << 4) & 0xfffffffffffffL); - a[1] = (a[5] >> 48) + (sp_digit)((a[6] << 4) & 0xfffffffffffffL); - a[2] = (a[6] >> 48) + (sp_digit)((a[7] << 4) & 0xfffffffffffffL); - a[3] = (a[7] >> 48) + (sp_digit)((a[8] << 4) & 0xfffffffffffffL); - a[4] = (a[8] >> 48) + (a[9] << 4); - - a[1] += a[0] >> 52; a[0] &= 0xfffffffffffffL; - a[2] += a[1] >> 52; a[1] &= 0xfffffffffffffL; - a[3] += a[2] >> 52; a[2] &= 0xfffffffffffffL; - a[4] += a[3] >> 52; a[3] &= 0xfffffffffffffL; - - /* Get the bit over, if any. */ - am = a[4] >> 48; - /* Create mask. */ - am = 0 - am; - - a[0] -= (sp_digit)(0x000fffffffffffffL & am); - a[1] -= (sp_digit)(0x00000fffffffffffL & am); - /* p256_mod[2] is zero */ - a[3] -= (sp_digit)(0x0000001000000000L & am); - a[4] -= (sp_digit)(0x0000ffffffff0000L & am); - - a[1] += a[0] >> 52; a[0] &= 0xfffffffffffffL; - a[2] += a[1] >> 52; a[1] &= 0xfffffffffffffL; - a[3] += a[2] >> 52; a[2] &= 0xfffffffffffffL; - a[4] += a[3] >> 52; a[3] &= 0xfffffffffffffL; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) -/* Square the Montgomery form number a number of times. (r = a ^ n mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * n Number of times to square. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_256_mont_sqr_n_5(sp_digit* r, - const sp_digit* a, int n, const sp_digit* m, sp_digit mp) -{ - sp_256_mont_sqr_5(r, a, m, mp); - for (; n > 1; n--) { - sp_256_mont_sqr_5(r, r, m, mp); - } -} - -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ -#ifdef WOLFSSL_SP_SMALL -/* Mod-2 for the P256 curve. */ -static const word64 p256_mod_minus_2[4] = { - 0xfffffffffffffffdU,0x00000000ffffffffU,0x0000000000000000U, - 0xffffffff00000001U -}; -#endif /* !WOLFSSL_SP_SMALL */ - -/* Invert the number, in Montgomery form, modulo the modulus (prime) of the - * P256 curve. (r = 1 / a mod m) - * - * r Inverse result. - * a Number to invert. - * td Temporary data. - */ -static void sp_256_mont_inv_5(sp_digit* r, const sp_digit* a, sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 5); - for (i=254; i>=0; i--) { - sp_256_mont_sqr_5(t, t, p256_mod, p256_mp_mod); - if (p256_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) - sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod); - } - XMEMCPY(r, t, sizeof(sp_digit) * 5); -#else - sp_digit* t1 = td; - sp_digit* t2 = td + 2 * 5; - sp_digit* t3 = td + 4 * 5; - /* 0x2 */ - sp_256_mont_sqr_5(t1, a, p256_mod, p256_mp_mod); - /* 0x3 */ - sp_256_mont_mul_5(t2, t1, a, p256_mod, p256_mp_mod); - /* 0xc */ - sp_256_mont_sqr_n_5(t1, t2, 2, p256_mod, p256_mp_mod); - /* 0xd */ - sp_256_mont_mul_5(t3, t1, a, p256_mod, p256_mp_mod); - /* 0xf */ - sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xf0 */ - sp_256_mont_sqr_n_5(t1, t2, 4, p256_mod, p256_mp_mod); - /* 0xfd */ - sp_256_mont_mul_5(t3, t3, t1, p256_mod, p256_mp_mod); - /* 0xff */ - sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xff00 */ - sp_256_mont_sqr_n_5(t1, t2, 8, p256_mod, p256_mp_mod); - /* 0xfffd */ - sp_256_mont_mul_5(t3, t3, t1, p256_mod, p256_mp_mod); - /* 0xffff */ - sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xffff0000 */ - sp_256_mont_sqr_n_5(t1, t2, 16, p256_mod, p256_mp_mod); - /* 0xfffffffd */ - sp_256_mont_mul_5(t3, t3, t1, p256_mod, p256_mp_mod); - /* 0xffffffff */ - sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xffffffff00000000 */ - sp_256_mont_sqr_n_5(t1, t2, 32, p256_mod, p256_mp_mod); - /* 0xffffffffffffffff */ - sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); - /* 0xffffffff00000001 */ - sp_256_mont_mul_5(r, t1, a, p256_mod, p256_mp_mod); - /* 0xffffffff000000010000000000000000000000000000000000000000 */ - sp_256_mont_sqr_n_5(r, r, 160, p256_mod, p256_mp_mod); - /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ - sp_256_mont_mul_5(r, r, t2, p256_mod, p256_mp_mod); - /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ - sp_256_mont_sqr_n_5(r, r, 32, p256_mod, p256_mp_mod); - /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ - sp_256_mont_mul_5(r, r, t3, p256_mod, p256_mp_mod); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_5(sp_point_256* r, const sp_point_256* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*5; - sp_int64 n; - - sp_256_mont_inv_5(t1, p->z, t + 2*5); - - sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod); - - /* x /= z^2 */ - sp_256_mont_mul_5(r->x, p->x, t2, p256_mod, p256_mp_mod); - XMEMSET(r->x + 5, 0, sizeof(sp_digit) * 5U); - sp_256_mont_reduce_5(r->x, p256_mod, p256_mp_mod); - /* Reduce x to less than modulus */ - n = sp_256_cmp_5(r->x, p256_mod); - sp_256_cond_sub_5(r->x, r->x, p256_mod, (sp_digit)~(n >> 51)); - sp_256_norm_5(r->x); - - /* y /= z^3 */ - sp_256_mont_mul_5(r->y, p->y, t1, p256_mod, p256_mp_mod); - XMEMSET(r->y + 5, 0, sizeof(sp_digit) * 5U); - sp_256_mont_reduce_5(r->y, p256_mod, p256_mp_mod); - /* Reduce y to less than modulus */ - n = sp_256_cmp_5(r->y, p256_mod); - sp_256_cond_sub_5(r->y, r->y, p256_mod, (sp_digit)~(n >> 51)); - sp_256_norm_5(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_add_5(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - sp_digit over; - (void)sp_256_add_5(r, a, b); - sp_256_norm_5(r); - over = r[4] >> 48; - sp_256_cond_sub_5(r, r, m, ~((over - 1) >> 63)); - sp_256_norm_5(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_dbl_5(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_256_add_5(r, a, a); - sp_256_norm_5(r); - over = r[4] >> 48; - sp_256_cond_sub_5(r, r, m, ~((over - 1) >> 63)); - sp_256_norm_5(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_tpl_5(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_256_add_5(r, a, a); - sp_256_norm_5(r); - over = r[4] >> 48; - sp_256_cond_sub_5(r, r, m, ~((over - 1) >> 63)); - sp_256_norm_5(r); - (void)sp_256_add_5(r, r, a); - sp_256_norm_5(r); - over = r[4] >> 48; - sp_256_cond_sub_5(r, r, m, ~((over - 1) >> 63)); - sp_256_norm_5(r); -} - -#ifdef 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_256_cond_add_5(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 5; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_256_cond_add_5(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - r[ 0] = a[ 0] + (b[ 0] & m); - r[ 1] = a[ 1] + (b[ 1] & m); - r[ 2] = a[ 2] + (b[ 2] & m); - r[ 3] = a[ 3] + (b[ 3] & m); - r[ 4] = a[ 4] + (b[ 4] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_256_mont_sub_5(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_256_sub_5(r, a, b); - sp_256_norm_5(r); - sp_256_cond_add_5(r, r, m, r[4] >> 48); - sp_256_norm_5(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -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) + (sp_digit)((a[i + 1] << 51) & 0xfffffffffffffL); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 51) & 0xfffffffffffffL); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 51) & 0xfffffffffffffL); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 51) & 0xfffffffffffffL); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 51) & 0xfffffffffffffL); -#endif - r[4] = a[4] >> 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_256_mont_div2_5(sp_digit* r, const sp_digit* a, - const sp_digit* m) -{ - sp_256_cond_add_5(r, a, m, 0 - (a[0] & 1)); - sp_256_norm_5(r); - sp_256_rshift1_5(r, r); -} - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static void sp_256_proj_point_dbl_5(sp_point_256* r, const sp_point_256* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*5; - 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_256_mont_sqr_5(t1, p->z, p256_mod, p256_mp_mod); - /* Z = Y * Z */ - sp_256_mont_mul_5(z, p->y, p->z, p256_mod, p256_mp_mod); - /* Z = 2Z */ - sp_256_mont_dbl_5(z, z, p256_mod); - /* T2 = X - T1 */ - sp_256_mont_sub_5(t2, p->x, t1, p256_mod); - /* T1 = X + T1 */ - sp_256_mont_add_5(t1, p->x, t1, p256_mod); - /* T2 = T1 * T2 */ - sp_256_mont_mul_5(t2, t1, t2, p256_mod, p256_mp_mod); - /* T1 = 3T2 */ - sp_256_mont_tpl_5(t1, t2, p256_mod); - /* Y = 2Y */ - sp_256_mont_dbl_5(y, p->y, p256_mod); - /* Y = Y * Y */ - sp_256_mont_sqr_5(y, y, p256_mod, p256_mp_mod); - /* T2 = Y * Y */ - sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); - /* T2 = T2/2 */ - sp_256_mont_div2_5(t2, t2, p256_mod); - /* Y = Y * X */ - sp_256_mont_mul_5(y, y, p->x, p256_mod, p256_mp_mod); - /* X = T1 * T1 */ - sp_256_mont_sqr_5(x, t1, p256_mod, p256_mp_mod); - /* X = X - Y */ - sp_256_mont_sub_5(x, x, y, p256_mod); - /* X = X - Y */ - sp_256_mont_sub_5(x, x, y, p256_mod); - /* Y = Y - X */ - sp_256_mont_sub_5(y, y, x, p256_mod); - /* Y = Y * T1 */ - sp_256_mont_mul_5(y, y, t1, p256_mod, p256_mp_mod); - /* Y = Y - T2 */ - sp_256_mont_sub_5(y, y, t2, p256_mod); -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_256_proj_point_dbl_5_ctx { - int state; - sp_digit* t1; - sp_digit* t2; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_256_proj_point_dbl_5_ctx; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static int sp_256_proj_point_dbl_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_point_256* p, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_256_proj_point_dbl_5_ctx* ctx = (sp_256_proj_point_dbl_5_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - ctx->t1 = t; - ctx->t2 = t + 2*5; - 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_256_mont_sqr_5(ctx->t1, p->z, p256_mod, p256_mp_mod); - ctx->state = 2; - break; - case 2: - /* Z = Y * Z */ - sp_256_mont_mul_5(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); - ctx->state = 3; - break; - case 3: - /* Z = 2Z */ - sp_256_mont_dbl_5(ctx->z, ctx->z, p256_mod); - ctx->state = 4; - break; - case 4: - /* T2 = X - T1 */ - sp_256_mont_sub_5(ctx->t2, p->x, ctx->t1, p256_mod); - ctx->state = 5; - break; - case 5: - /* T1 = X + T1 */ - sp_256_mont_add_5(ctx->t1, p->x, ctx->t1, p256_mod); - ctx->state = 6; - break; - case 6: - /* T2 = T1 * T2 */ - sp_256_mont_mul_5(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 7; - break; - case 7: - /* T1 = 3T2 */ - sp_256_mont_tpl_5(ctx->t1, ctx->t2, p256_mod); - ctx->state = 8; - break; - case 8: - /* Y = 2Y */ - sp_256_mont_dbl_5(ctx->y, p->y, p256_mod); - ctx->state = 9; - break; - case 9: - /* Y = Y * Y */ - sp_256_mont_sqr_5(ctx->y, ctx->y, p256_mod, p256_mp_mod); - ctx->state = 10; - break; - case 10: - /* T2 = Y * Y */ - sp_256_mont_sqr_5(ctx->t2, ctx->y, p256_mod, p256_mp_mod); - ctx->state = 11; - break; - case 11: - /* T2 = T2/2 */ - sp_256_mont_div2_5(ctx->t2, ctx->t2, p256_mod); - ctx->state = 12; - break; - case 12: - /* Y = Y * X */ - sp_256_mont_mul_5(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); - ctx->state = 13; - break; - case 13: - /* X = T1 * T1 */ - sp_256_mont_sqr_5(ctx->x, ctx->t1, p256_mod, p256_mp_mod); - ctx->state = 14; - break; - case 14: - /* X = X - Y */ - sp_256_mont_sub_5(ctx->x, ctx->x, ctx->y, p256_mod); - ctx->state = 15; - break; - case 15: - /* X = X - Y */ - sp_256_mont_sub_5(ctx->x, ctx->x, ctx->y, p256_mod); - ctx->state = 16; - break; - case 16: - /* Y = Y - X */ - sp_256_mont_sub_5(ctx->y, ctx->y, ctx->x, p256_mod); - ctx->state = 17; - break; - case 17: - /* Y = Y * T1 */ - sp_256_mont_mul_5(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); - ctx->state = 18; - break; - case 18: - /* Y = Y - T2 */ - sp_256_mont_sub_5(ctx->y, ctx->y, ctx->t2, p256_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 */ -/* 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_256_cmp_equal_5(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])) == 0; -} - -/* 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_256_iszero_5(const sp_digit* a) -{ - return (a[0] | a[1] | a[2] | a[3] | a[4]) == 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. - */ -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) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*5; - sp_digit* t2 = t + 4*5; - sp_digit* t3 = t + 6*5; - sp_digit* t4 = t + 8*5; - sp_digit* t5 = t + 10*5; - - /* U1 = X1*Z2^2 */ - sp_256_mont_sqr_5(t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t3, t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t1, t1, p->x, p256_mod, p256_mp_mod); - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_5(t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t4, t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_256_mont_mul_5(t3, t3, p->y, p256_mod, p256_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_256_cmp_equal_5(t2, t1) & - sp_256_cmp_equal_5(t4, t3)) { - sp_256_proj_point_dbl_5(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* H = U2 - U1 */ - sp_256_mont_sub_5(t2, t2, t1, p256_mod); - /* R = S2 - S1 */ - sp_256_mont_sub_5(t4, t4, t3, p256_mod); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(y, t1, t5, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod); - /* Z3 = H*Z1*Z2 */ - sp_256_mont_mul_5(z, p->z, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(z, z, q->z, p256_mod, p256_mp_mod); - sp_256_mont_sqr_5(x, t4, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(x, x, t5, p256_mod); - sp_256_mont_mul_5(t5, t5, t3, p256_mod, p256_mp_mod); - sp_256_mont_dbl_5(t3, y, p256_mod); - sp_256_mont_sub_5(x, x, t3, p256_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_256_mont_sub_5(y, y, x, p256_mod); - sp_256_mont_mul_5(y, y, t4, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(y, y, t5, p256_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 5; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 5; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 5; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_256_proj_point_add_5_ctx { - int state; - sp_256_proj_point_dbl_5_ctx dbl_ctx; - const sp_point_256* ap[2]; - sp_point_256* rp[2]; - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; - sp_digit* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_256_proj_point_add_5_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -static int sp_256_proj_point_add_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_point_256* p, const sp_point_256* q, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_256_proj_point_add_5_ctx* ctx = (sp_256_proj_point_add_5_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_256_proj_point_add_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_256* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*5; - ctx->t2 = t + 4*5; - ctx->t3 = t + 6*5; - ctx->t4 = t + 8*5; - ctx->t5 = t + 10*5; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_256_mont_sqr_5(ctx->t1, q->z, p256_mod, p256_mp_mod); - ctx->state = 2; - break; - case 2: - sp_256_mont_mul_5(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); - ctx->state = 3; - break; - case 3: - sp_256_mont_mul_5(ctx->t1, ctx->t1, p->x, p256_mod, p256_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_5(ctx->t2, p->z, p256_mod, p256_mp_mod); - ctx->state = 5; - break; - case 5: - sp_256_mont_mul_5(ctx->t4, ctx->t2, p->z, p256_mod, p256_mp_mod); - ctx->state = 6; - break; - case 6: - sp_256_mont_mul_5(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_256_mont_mul_5(ctx->t3, ctx->t3, p->y, p256_mod, p256_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_5(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_256_cmp_equal_5(ctx->t2, ctx->t1) & - sp_256_cmp_equal_5(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_256_proj_point_dbl_5(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_256_mont_sub_5(ctx->t2, ctx->t2, ctx->t1, p256_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_256_mont_sub_5(ctx->t4, ctx->t4, ctx->t3, p256_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_256_mont_sqr_5(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 13; - break; - case 13: - sp_256_mont_mul_5(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); - ctx->state = 14; - break; - case 14: - sp_256_mont_mul_5(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_256_mont_mul_5(ctx->z, p->z, ctx->t2, p256_mod, p256_mp_mod); - ctx->state = 16; - break; - case 16: - sp_256_mont_mul_5(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); - ctx->state = 17; - break; - case 17: - sp_256_mont_sqr_5(ctx->x, ctx->t4, p256_mod, p256_mp_mod); - ctx->state = 18; - break; - case 18: - sp_256_mont_sub_5(ctx->x, ctx->x, ctx->t5, p256_mod); - ctx->state = 19; - break; - case 19: - sp_256_mont_mul_5(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); - ctx->state = 20; - break; - case 20: - sp_256_mont_dbl_5(ctx->t3, ctx->y, p256_mod); - sp_256_mont_sub_5(ctx->x, ctx->x, ctx->t3, p256_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_256_mont_sub_5(ctx->y, ctx->y, ctx->x, p256_mod); - ctx->state = 22; - break; - case 22: - sp_256_mont_mul_5(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); - ctx->state = 23; - break; - case 23: - sp_256_mont_sub_5(ctx->y, ctx->y, ctx->t5, p256_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 5; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 5; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 5; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -/* Multiply a number by Montgomery 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) -{ - SP_DECL_VAR(int64_t, t, 2 * 8); - int64_t* a32 = NULL; - int64_t o; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(int64_t, t, 2 * 8, NULL, DYNAMIC_TYPE_ECC); - 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; - } - - SP_FREE_VAR(t, NULL, DYNAMIC_TYPE_ECC); - - 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. - * 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_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_256, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 5 * 6); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_256, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 5 * 6, heap, DYNAMIC_TYPE_ECC); - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_256) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); - } - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); - - if (err == MP_OKAY) { - i = 4; - c = 48; - n = k[i--] << (52 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 52; - } - - y = (n >> 51) & 1; - n <<= 1; - - sp_256_proj_point_add_5(&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_256)); - sp_256_proj_point_dbl_5(&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_256)); - } - - if (map != 0) { - sp_256_map_5(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_256)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 5 * 6, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_256, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_256_ecc_mulmod_5_ctx { - int state; - union { - sp_256_proj_point_dbl_5_ctx dbl_ctx; - sp_256_proj_point_add_5_ctx add_ctx; - }; - sp_point_256 t[3]; - sp_digit tmp[2 * 5 * 6]; - sp_digit n; - int i; - int c; - int y; -} sp_256_ecc_mulmod_5_ctx; - -static int sp_256_ecc_mulmod_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_256_ecc_mulmod_5_ctx* ctx = (sp_256_ecc_mulmod_5_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_5_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_256) * 3); - ctx->i = 4; - ctx->c = 48; - ctx->n = k[ctx->i--] << (52 - 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_256_mod_mul_norm_5(ctx->t[1].x, g->x, p256_mod); - ctx->state = 2; - break; - case 2: /* T1Y */ - err = sp_256_mod_mul_norm_5(ctx->t[1].y, g->y, p256_mod); - ctx->state = 3; - break; - case 3: /* T1Z */ - err = sp_256_mod_mul_norm_5(ctx->t[1].z, g->z, p256_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 = 52; - } - ctx->y = (ctx->n >> 51) & 1; - ctx->n <<= 1; - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 5; - break; - case 5: /* ADD */ - err = sp_256_proj_point_add_5_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_256)); - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 6; - } - break; - case 6: /* DBL */ - err = sp_256_proj_point_dbl_5_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_256)); - ctx->state = 4; - ctx->c--; - } - break; - case 7: /* MAP */ - if (map != 0) { - sp_256_map_5(r, &ctx->t[0], ctx->tmp); - } - else { - XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256)); - } - 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 */ - -#else -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_256 { - sp_digit x[5]; - sp_digit y[5]; -} sp_table_entry_256; - -/* 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_256_cond_copy_5(sp_digit* r, const sp_digit* a, const sp_digit m) -{ - sp_digit t[5]; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i = 0; i < 5; i++) { - t[i] = r[i] ^ a[i]; - } - for (i = 0; i < 5; 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]; - 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; -#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_256_proj_point_dbl_n_5(sp_point_256* p, int i, - sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*5; - sp_digit* b = t + 4*5; - sp_digit* t1 = t + 6*5; - sp_digit* t2 = t + 8*5; - sp_digit* x; - sp_digit* y; - sp_digit* z; - volatile int n = i - 1; - - x = p->x; - y = p->y; - z = p->z; - - /* Y = 2*Y */ - sp_256_mont_dbl_5(y, y, p256_mod); - /* 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); -#ifndef WOLFSSL_SP_SMALL - while (n > 0) -#else - while (n >= 0) -#endif - { - /* 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); - sp_256_mont_tpl_5(a, t1, p256_mod); - /* B = X*Y^2 */ - sp_256_mont_sqr_5(t1, y, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(b, t1, x, p256_mod, p256_mp_mod); - /* X = A^2 - 2B */ - sp_256_mont_sqr_5(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_5(t2, b, p256_mod); - sp_256_mont_sub_5(x, x, t2, p256_mod); - /* B = 2.(B - X) */ - sp_256_mont_sub_5(t2, b, x, p256_mod); - sp_256_mont_dbl_5(b, t2, p256_mod); - /* Z = Z*Y */ - sp_256_mont_mul_5(z, z, y, p256_mod, p256_mp_mod); - /* t1 = Y^4 */ - sp_256_mont_sqr_5(t1, t1, p256_mod, p256_mp_mod); -#ifdef WOLFSSL_SP_SMALL - if (n != 0) -#endif - { - /* W = W*Y^4 */ - sp_256_mont_mul_5(w, w, t1, p256_mod, p256_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_mul_5(y, b, a, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(y, y, t1, p256_mod); - n = n - 1; - } -#ifndef WOLFSSL_SP_SMALL - /* 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); - sp_256_mont_tpl_5(a, t1, p256_mod); - /* B = X*Y^2 */ - sp_256_mont_sqr_5(t1, y, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(b, t1, x, p256_mod, p256_mp_mod); - /* X = A^2 - 2B */ - sp_256_mont_sqr_5(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_5(t2, b, p256_mod); - sp_256_mont_sub_5(x, x, t2, p256_mod); - /* B = 2.(B - X) */ - sp_256_mont_sub_5(t2, b, x, p256_mod); - sp_256_mont_dbl_5(b, t2, p256_mod); - /* Z = Z*Y */ - sp_256_mont_mul_5(z, z, y, p256_mod, p256_mp_mod); - /* t1 = Y^4 */ - sp_256_mont_sqr_5(t1, t1, p256_mod, p256_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_mul_5(y, b, a, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(y, y, t1, p256_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_256_mont_div2_5(y, y, p256_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_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; - sp_digit* b = t + 4*5; - sp_digit* t1 = t + 6*5; - sp_digit* t2 = t + 8*5; - sp_digit* x = r[2*m].x; - sp_digit* y = r[(1<x[i]; - } - for (i=0; i<5; i++) { - y[i] = p->y[i]; - } - for (i=0; i<5; i++) { - z[i] = p->z[i]; - } - - /* Y = 2*Y */ - sp_256_mont_dbl_5(y, y, p256_mod); - /* 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); - sp_256_mont_tpl_5(a, t1, p256_mod); - /* B = X*Y^2 */ - sp_256_mont_sqr_5(t1, y, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(b, t1, x, p256_mod, p256_mp_mod); - x = r[j].x; - /* X = A^2 - 2B */ - sp_256_mont_sqr_5(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_5(t2, b, p256_mod); - sp_256_mont_sub_5(x, x, t2, p256_mod); - /* B = 2.(B - X) */ - sp_256_mont_sub_5(t2, b, x, p256_mod); - sp_256_mont_dbl_5(b, t2, p256_mod); - /* Z = Z*Y */ - sp_256_mont_mul_5(r[j].z, z, y, p256_mod, p256_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_256_mont_sqr_5(t1, t1, p256_mod, p256_mp_mod); - if (i != n) { - /* W = W*Y^4 */ - sp_256_mont_mul_5(w, w, t1, p256_mod, p256_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_mul_5(y, b, a, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(y, y, t1, p256_mod); - /* Y = Y/2 */ - sp_256_mont_div2_5(r[j].y, y, p256_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_256_proj_point_add_sub_5(sp_point_256* ra, - sp_point_256* rs, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*5; - sp_digit* t3 = t + 4*5; - sp_digit* t4 = t + 6*5; - sp_digit* t5 = t + 8*5; - sp_digit* t6 = t + 10*5; - sp_digit* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, p->z, sizeof(p->z) / 2); - ra->infinity = 0; - rs->infinity = 0; - - /* U1 = X1*Z2^2 */ - sp_256_mont_sqr_5(t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t3, t1, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t1, t1, xa, p256_mod, p256_mp_mod); - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_5(t2, za, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t4, t2, za, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_256_mont_mul_5(t3, t3, ya, p256_mod, p256_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); - /* H = U2 - U1 */ - sp_256_mont_sub_5(t2, t2, t1, p256_mod); - /* RS = S2 + S1 */ - sp_256_mont_add_5(t6, t4, t3, p256_mod); - /* R = S2 - S1 */ - sp_256_mont_sub_5(t4, t4, t3, p256_mod); - /* Z3 = H*Z1*Z2 */ - /* ZS = H*Z1*Z2 */ - sp_256_mont_mul_5(za, za, q->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(za, za, t2, p256_mod, p256_mp_mod); - XMEMCPY(zs, za, sizeof(p->z)/2); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - /* XS = RS^2 - H^3 - 2*U1*H^2 */ - sp_256_mont_sqr_5(xa, t4, p256_mod, p256_mp_mod); - sp_256_mont_sqr_5(xs, t6, p256_mod, p256_mp_mod); - sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(ya, t1, t5, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(xa, xa, t5, p256_mod); - sp_256_mont_sub_5(xs, xs, t5, p256_mod); - sp_256_mont_dbl_5(t1, ya, p256_mod); - sp_256_mont_sub_5(xa, xa, t1, p256_mod); - sp_256_mont_sub_5(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_5(ys, ya, xs, p256_mod); - sp_256_mont_sub_5(ya, ya, xa, p256_mod); - sp_256_mont_mul_5(ya, ya, t4, p256_mod, p256_mp_mod); - sp_256_sub_5(t6, p256_mod, t6); - sp_256_mont_mul_5(ys, ys, t6, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t5, t5, t3, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(ya, ya, t5, p256_mod); - sp_256_mont_sub_5(ys, ys, t5, p256_mod); -} - -/* Structure used to describe recoding of scalar multiplication. */ -typedef struct ecc_recode_256 { - /* Index into pre-computation table. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_256; - -/* The index into pre-computation table to use. */ -static const word8 recode_index_5_6[66] = { - 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, 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 word8 recode_neg_5_6[66] = { - 0, 0, 0, 0, 0, 0, 0, 0, 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, - 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_256_ecc_recode_6_5(const sp_digit* k, ecc_recode_256* v) -{ - int i; - int j; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<43; i++) { - y = (word8)(int8_t)n; - if (o + 6 < 52) { - y &= 0x3f; - n >>= 6; - o += 6; - } - else if (o + 6 == 52) { - n >>= 6; - if (++j < 5) - n = k[j]; - o = 0; - } - else if (++j < 5) { - n = k[j]; - y |= (word8)((n << (52 - o)) & 0x3f); - o -= 46; - n >>= o; - } - - y = (word8)(y + carry); - v[i].i = recode_index_5_6[y]; - v[i].neg = recode_neg_5_6[y]; - carry = (y >> 6) + v[i].neg; - } -} - -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible point that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_256_get_point_33_5(sp_point_256* r, const sp_point_256* 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->y[0] = 0; - r->y[1] = 0; - r->y[2] = 0; - r->y[3] = 0; - r->y[4] = 0; - r->z[0] = 0; - r->z[1] = 0; - r->z[2] = 0; - r->z[3] = 0; - r->z[4] = 0; - for (i = 1; i < 33; i++) { - mask = (sp_digit)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->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->z[0] |= mask & table[i].z[0]; - r->z[1] |= mask & table[i].z[1]; - r->z[2] |= mask & table[i].z[2]; - r->z[3] |= mask & table[i].z[3]; - r->z[4] |= mask & table[i].z[4]; - } -} -#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. - * - * Window technique of 6 bits. (Add-Sub variation.) - * Calculate 0..32 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_256_ecc_mulmod_win_add_sub_5(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_256, t, 33+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 5 * 6); - sp_point_256* rt = NULL; - sp_point_256* p = NULL; - sp_digit* negy; - int i; - ecc_recode_256 v[43]; - int err = MP_OKAY; - - /* Constant time used for cache attack resistance implementation. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_256, t, 33+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 5 * 6, heap, DYNAMIC_TYPE_ECC); - 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_5(t[1].x, g->x, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); - } - - if (err == MP_OKAY) { - t[1].infinity = 0; - /* t[2] ... t[32] */ - sp_256_proj_point_dbl_n_store_5(t, &t[ 1], 5, 1, tmp); - sp_256_proj_point_add_5(&t[ 3], &t[ 2], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[ 6], &t[ 3], tmp); - sp_256_proj_point_add_sub_5(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[10], &t[ 5], tmp); - sp_256_proj_point_add_sub_5(&t[11], &t[ 9], &t[10], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[12], &t[ 6], tmp); - sp_256_proj_point_dbl_5(&t[14], &t[ 7], tmp); - sp_256_proj_point_add_sub_5(&t[15], &t[13], &t[14], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[18], &t[ 9], tmp); - sp_256_proj_point_add_sub_5(&t[19], &t[17], &t[18], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[20], &t[10], tmp); - sp_256_proj_point_dbl_5(&t[22], &t[11], tmp); - sp_256_proj_point_add_sub_5(&t[23], &t[21], &t[22], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[24], &t[12], tmp); - sp_256_proj_point_dbl_5(&t[26], &t[13], tmp); - sp_256_proj_point_add_sub_5(&t[27], &t[25], &t[26], &t[ 1], tmp); - sp_256_proj_point_dbl_5(&t[28], &t[14], tmp); - sp_256_proj_point_dbl_5(&t[30], &t[15], tmp); - sp_256_proj_point_add_sub_5(&t[31], &t[29], &t[30], &t[ 1], tmp); - - negy = t[0].y; - - sp_256_ecc_recode_6_5(k, v); - - i = 42; - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_point_33_5(rt, t, v[i].i); - rt->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_256)); - } - for (--i; i>=0; i--) { - sp_256_proj_point_dbl_n_5(rt, 6, tmp); - - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_point_33_5(p, t, v[i].i); - p->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256)); - } - sp_256_sub_5(negy, p256_mod, p->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); - } - - if (map != 0) { - sp_256_map_5(r, rt, tmp); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_256)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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_256_proj_point_add_qz1_5(sp_point_256* r, - const sp_point_256* p, const sp_point_256* q, sp_digit* t) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*5; - sp_digit* t6 = t + 4*5; - sp_digit* t1 = t + 6*5; - sp_digit* t4 = t + 8*5; - sp_digit* t5 = t + 10*5; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_256_mont_sqr_5(t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t4, t2, p->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); - - if ((~p->infinity) & (~q->infinity) & - sp_256_cmp_equal_5(p->x, t2) & - sp_256_cmp_equal_5(p->y, t4)) { - sp_256_proj_point_dbl_5(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_256_mont_sub_5(t2, t2, p->x, p256_mod); - /* R = S2 - Y1 */ - sp_256_mont_sub_5(t4, t4, p->y, p256_mod); - /* Z3 = H*Z1 */ - sp_256_mont_mul_5(z, p->z, t2, p256_mod, p256_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_256_mont_sqr_5(t1, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t3, p->x, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); - sp_256_mont_sqr_5(t2, t4, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(t2, t2, t1, p256_mod); - sp_256_mont_dbl_5(t5, t3, p256_mod); - sp_256_mont_sub_5(x, t2, t5, p256_mod); - /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_256_mont_sub_5(t3, t3, x, p256_mod); - sp_256_mont_mul_5(t3, t3, t4, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t1, t1, p->y, p256_mod, p256_mp_mod); - sp_256_mont_sub_5(y, t3, t1, p256_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 5; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 5; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 5; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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_5(sp_point_256* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 5; - sp_digit* tmp = t + 4 * 5; - - sp_256_mont_inv_5(t1, a->z, tmp); - - sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod); - - sp_256_mont_mul_5(a->x, a->x, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(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 = 8 - * 256 entries - * 32 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_256_gen_stripe_table_5(const sp_point_256* a, - sp_table_entry_256* table, sp_digit* tmp, void* heap) -{ - SP_DECL_VAR(sp_point_256, t, 3); - sp_point_256* s1 = NULL; - sp_point_256* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_256, t, 3, heap, DYNAMIC_TYPE_ECC); - 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) { - err = sp_256_mod_mul_norm_5(t->y, a->y, p256_mod); - } - if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_5(t->z, a->z, p256_mod); - } - if (err == MP_OKAY) { - t->infinity = 0; - sp_256_proj_to_affine_5(t, tmp); - - XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); - s1->infinity = 0; - XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); - s2->infinity = 0; - - /* table[0] = {0, 0, infinity} */ - XMEMSET(&table[0], 0, sizeof(sp_table_entry_256)); - /* 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_256_proj_point_dbl_n_5(t, 32, tmp); - sp_256_proj_to_affine_5(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_256_proj_point_add_qz1_5(t, s1, s2, tmp); - sp_256_proj_to_affine_5(t, tmp); - XMEMCPY(table[j].x, t->x, sizeof(table->x)); - XMEMCPY(table[j].y, t->y, sizeof(table->y)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible entry that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_256_get_entry_256_5(sp_point_256* r, - const sp_table_entry_256* 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->y[0] = 0; - r->y[1] = 0; - r->y[2] = 0; - r->y[3] = 0; - r->y[4] = 0; - for (i = 1; i < 256; i++) { - sp_digit gte = (sp_digit)((((sp_uint64)i - (sp_uint64)idx) >> 63) - 1); - sp_digit lte = (sp_digit)((((sp_uint64)idx - (sp_uint64)i) >> 63) - 1); - mask = gte & lte; - 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->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]; - } -} -#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^32, ... - * 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_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) -{ - SP_DECL_VAR(sp_point_256, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 5 * 6); - sp_point_256* 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; - - - SP_ALLOC_VAR(sp_point_256, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 5 * 6, heap, DYNAMIC_TYPE_ECC); - 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; - 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) { - sp_256_get_entry_256_5(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=30; i>=0; i--) { - y = 0; - 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); - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_256_get_entry_256_5(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_256_proj_point_add_qz1_5(rt, rt, p, t); - } - - if (map != 0) { - sp_256_map_5(r, rt, t); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_256)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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_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. */ - word32 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 - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_256 = 0; - #endif - static wolfSSL_Mutex sp_cache_256_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_256_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * 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; - int j; - word32 least; - - if (sp_cache_256_inited == 0) { - for (i=0; ix, sp_cache_256[i].x) & - sp_256_cmp_equal_5(g->y, sp_cache_256[i].y)) { - sp_cache_256[i].cnt++; - break; - } - } - - /* No match. */ - if (i == FP_ENTRIES) { - /* Find empty entry. */ - i = (sp_cache_256_last + 1) % FP_ENTRIES; - for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { - if (!sp_cache_256[i].set) { - break; - } - } - - /* Evict least used. */ - if (i == sp_cache_256_last) { - least = sp_cache_256[0].cnt; - for (j=1; jx, sizeof(sp_cache_256[i].x)); - XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); - sp_cache_256[i].set = 1; - sp_cache_256[i].cnt = 1; - } - - *cache = &sp_cache_256[i]; - sp_cache_256_last = i; -} -#endif /* FP_ECC */ - -/* Multiply the base point of P256 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_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#ifndef FP_ECC - return sp_256_ecc_mulmod_win_add_sub_5(r, g, k, map, ct, heap); -#else - SP_DECL_VAR(sp_digit, tmp, 2 * 5 * 6); - sp_cache_256_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 5 * 6, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_256 == 0) { - wc_InitMutex(&sp_cache_256_lock); - initCacheMutex_256 = 1; - } - #endif - if (wc_LockMutex(&sp_cache_256_lock) != 0) { - err = BAD_MUTEX_E; - } - } -#endif /* HAVE_THREAD_LS */ - - if (err == MP_OKAY) { - sp_ecc_get_cache_256(g, &cache); - if (cache->cnt == 2) - sp_256_gen_stripe_table_5(g, cache->table, tmp, heap); - -#ifndef HAVE_THREAD_LS - wc_UnLockMutex(&sp_cache_256_lock); -#endif /* HAVE_THREAD_LS */ - - if (cache->cnt < 2) { - err = sp_256_ecc_mulmod_win_add_sub_5(r, g, k, map, ct, heap); - } - else { - err = sp_256_ecc_mulmod_stripe_5(r, g, cache->table, k, - map, ct, heap); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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_256(const mp_int* km, const ecc_point* gm, ecc_point* r, - int map, void* heap) -{ - SP_DECL_VAR(sp_point_256, point, 1); - SP_DECL_VAR(sp_digit, k, 5); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 5, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(k, 5, km); - sp_256_point_from_ecc_point_5(point, gm); - - err = sp_256_ecc_mulmod_5(point, point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_5(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_256, point, 2); - SP_DECL_VAR(sp_digit, k, 5 + 5 * 2 * 6); - sp_point_256* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 5 + 5 * 2 * 6, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef 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. - * - * 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_256_ecc_mulmod_base_5(sp_point_256* r, const sp_digit* k, - int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_256_ecc_mulmod_5(r, &p256_base, k, map, ct, heap); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_256_ecc_mulmod_base_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_256_ecc_mulmod_5_nb(sp_ctx, r, &p256_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#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 } }, - /* 1 */ - { { 0x730d418a9143cL,0xfc5fedb60179eL,0x762251075ba95L,0x55c679fb732b7L, - 0x018905f76a537L }, - { 0x25357ce95560aL,0xe4ba19e45cddfL,0xd21f3258b4ab8L,0x5d85d2e88688dL, - 0x08571ff182588L } }, - /* 2 */ - { { 0x886024147519aL,0xac26b372f0202L,0x785ebc8d0981eL,0x58e9a9d4a7caaL, - 0x0d953c50ddbdfL }, - { 0x361ccfd590f8fL,0x6b44e6c9179d6L,0x2eb64cf72e962L,0x88f37fd961102L, - 0x0863ebb7e9eb2L } }, - /* 3 */ - { { 0x6b6235cdb6485L,0xa22f0a2f97785L,0xf7e300b808f0eL,0x80a03e68d9544L, - 0x000076055b5ffL }, - { 0x4eb9b838d2010L,0xbb3243708a763L,0x42a660654014fL,0x3ee0e0e47d398L, - 0x0830877613437L } }, - /* 4 */ - { { 0x22fc516a0d2bbL,0x6c1a6234994f9L,0x7c62c8b0d5cc1L,0x667f9241cf3a5L, - 0x02f5e6961fd1bL }, - { 0x5c70bf5a01797L,0x4d609561925c1L,0x71fdb523d20b4L,0x0f7b04911b370L, - 0x0f648f9168d6fL } }, - /* 5 */ - { { 0x66847e137bbbcL,0x9e8a6a0bec9e5L,0x9d73463e43446L,0x0015b1c427617L, - 0x05abe0285133dL }, - { 0xa837cc04c7dabL,0x4c43260c0792aL,0x8e6cc37573d9fL,0x73830c9315627L, - 0x094bb725b6b6fL } }, - /* 6 */ - { { 0x9b48f720f141cL,0xcd2df5bc74bbfL,0x11045c46199b3L,0xc4efdc3f61294L, - 0x0cdd6bbcb2f7dL }, - { 0x6700beaf436fdL,0x6db99326beccaL,0x14f25226f647fL,0xe5f60c0fa7920L, - 0x0a361bebd4bdaL } }, - /* 7 */ - { { 0xa2558597c13c7L,0x5f50b7c3e128aL,0x3c09d1dc38d63L,0x292c07039aecfL, - 0x0ba12ca09c4b5L }, - { 0x08fa459f91dfdL,0x66ceea07fb9e4L,0xd780b293af43bL,0xef4b1eceb0899L, - 0x053ebb99d701fL } }, - /* 8 */ - { { 0x7ee31b0e63d34L,0x72a9e54fab4feL,0x5e7b5a4f46005L,0x4831c0493334dL, - 0x08589fb9206d5L }, - { 0x0f5cc6583553aL,0x4ae25649e5aa7L,0x0044652087909L,0x1c4fcc9045071L, - 0x0ebb0696d0254L } }, - /* 9 */ - { { 0x6ca15ac1647c5L,0x47c4cf5799461L,0x64dfbacb8127dL,0x7da3dc666aa37L, - 0x0eb2820cbd1b2L }, - { 0x6f8d86a87e008L,0x9d922378f3940L,0x0ccecb2d87dfaL,0xda1d56ed2e428L, - 0x01f28289b55a7L } }, - /* 10 */ - { { 0xaa0c03b89da99L,0x9eb8284022abbL,0x81c05e8a6f2d7L,0x4d6327847862bL, - 0x0337a4b5905e5L }, - { 0x7500d21f7794aL,0xb77d6d7f613c6L,0x4cfd6e8207005L,0xfbd60a5a37810L, - 0x00d65e0d5f4c2L } }, - /* 11 */ - { { 0x09bbeb5275d38L,0x450be0a358d9dL,0x73eb2654268a7L,0xa232f0762ff49L, - 0x0c23da24252f4L }, - { 0x1b84f0b94520cL,0x63b05bd78e5daL,0x4d29ea1096667L,0xcff13a4dcb869L, - 0x019de3b8cc790L } }, - /* 12 */ - { { 0xa716c26c5fe04L,0x0b3bba1bdb183L,0x4cb712c3b28deL,0xcbfd7432c586aL, - 0x0e34dcbd491fcL }, - { 0x8d46baaa58403L,0x8682e97a53b40L,0x6aaa8af9a6974L,0x0f7f9e3901273L, - 0x0e7641f447b4eL } }, - /* 13 */ - { { 0x53941df64ba59L,0xec0b0242fc7d7L,0x1581859d33f10L,0x57bf4f06dfc6aL, - 0x04a12df57052aL }, - { 0x6338f9439dbd0L,0xd4bde53e1fbfaL,0x1f1b314d3c24bL,0xea46fd5e4ffa2L, - 0x06af5aa93bb5bL } }, - /* 14 */ - { { 0x0b69910c91999L,0x402a580491da1L,0x8cc20900a24b4L,0x40133e0094b4bL, - 0x05fe3475a66a4L }, - { 0x8cabdf93e7b4bL,0x1a7c23f91ab0fL,0xd1e6263292b50L,0xa91642e889aecL, - 0x0b544e308ecfeL } }, - /* 15 */ - { { 0x8c6e916ddfdceL,0x66f89179e6647L,0xd4e67e12c3291L,0xc20b4e8d6e764L, - 0x0e0b6b2bda6b0L }, - { 0x12df2bb7efb57L,0xde790c40070d3L,0x79bc9441aac0dL,0x3774f90336ad6L, - 0x071c023de25a6L } }, - /* 16 */ - { { 0x8c244bfe20925L,0xc38fdce86762aL,0xd38706391c19aL,0x24f65a96a5d5dL, - 0x061d587d421d3L }, - { 0x673a2a37173eaL,0x0853778b65e87L,0x5bab43e238480L,0xefbe10f8441e0L, - 0x0fa11fe124621L } }, - /* 17 */ - { { 0x91f2b2cb19ffdL,0x5bb1923c231c8L,0xac5ca8e01ba8dL,0xbedcb6d03d678L, - 0x0586eb04c1f13L }, - { 0x5c6e527e8ed09L,0x3c1819ede20c3L,0x6c652fa1e81a3L,0x4f11278fd6c05L, - 0x019d5ac087086L } }, - /* 18 */ - { { 0x9f581309a4e1fL,0x1be92700741e9L,0xfd28d20ab7de7L,0x563f26a5ef0beL, - 0x0e7c0073f7f9cL }, - { 0xd663a0ef59f76L,0x5420fcb0501f6L,0xa6602d4669b3bL,0x3c0ac08c1f7a7L, - 0x0e08504fec65bL } }, - /* 19 */ - { { 0x8f68da031b3caL,0x9ee6da6d66f09L,0x4f246e86d1cabL,0x96b45bfd81fa9L, - 0x078f018825b09L }, - { 0xefde43a25787fL,0x0d1dccac9bb7eL,0x35bfc368016f8L,0x747a0cea4877bL, - 0x043a773b87e94L } }, - /* 20 */ - { { 0x77734d2b533d5L,0xf6a1bdddc0625L,0x79ec293673b8aL,0x66b1577e7c9aaL, - 0x0bb6de651c3b2L }, - { 0x9303ab65259b3L,0xd3d03a7480e7eL,0xb3cfc27d6a0afL,0xb99bc5ac83d19L, - 0x060b4619a5d18L } }, - /* 21 */ - { { 0xa38e11ae5aa1cL,0x2b49e73658bd6L,0xe5f87edb8b765L,0xffcd0b130014eL, - 0x09d0f27b2aeebL }, - { 0x246317a730a55L,0x2fddbbc83aca9L,0xc019a719c955bL,0xc48d07c1dfe0aL, - 0x0244a566d356eL } }, - /* 22 */ - { { 0x0394aeacf1f96L,0xa9024c271c6dbL,0x2cbd3b99f2122L,0xef692626ac1b8L, - 0x045e58c873581L }, - { 0xf479da38f9dbcL,0x46e888a040d3fL,0x6e0bed7a8aaf1L,0xb7a4945adfb24L, - 0x0c040e21cc1e4L } }, - /* 23 */ - { { 0xaf0006f8117b6L,0xff73a35433847L,0xd9475eb651969L,0x6ec7482b35761L, - 0x01cdf5c97682cL }, - { 0x775b411f04839L,0xf448de16987dbL,0x70b32197dbeacL,0xff3db2921dd1bL, - 0x0046755f8a92dL } }, - /* 24 */ - { { 0xac5d2bce8ffcdL,0x8b2fe61a82cc8L,0x202d6c70d53c4L,0xa5f3f6f161727L, - 0x0046e5e113b83L }, - { 0x8ff64d8007f01L,0x125af43183e7bL,0x5e1a03c7fb1efL,0x005b045c5ea63L, - 0x06e0106c3303dL } }, - /* 25 */ - { { 0x7358488dd73b1L,0x8f995ed0d948cL,0x56a2ab7767070L,0xcf1f38385ea8cL, - 0x0442594ede901L }, - { 0xaa2c912d4b65bL,0x3b96c90c37f8fL,0xe978d1f94c234L,0xe68ed326e4a15L, - 0x0a796fa514c2eL } }, - /* 26 */ - { { 0xfb604823addd7L,0x83e56693b3359L,0xcbf3c809e2a61L,0x66e9f885b78e3L, - 0x0e4ad2da9c697L }, - { 0xf7f428e048a61L,0x8cc092d9a0357L,0x03ed8ef082d19L,0x5143fc3a1af4cL, - 0x0c5e94046c37bL } }, - /* 27 */ - { { 0xa538c2be75f9eL,0xe8cb123a78476L,0x109c04b6fd1a9L,0x4747d85e4df0bL, - 0x063283dafdb46L }, - { 0x28cf7baf2df15L,0x550ad9a7f4ce7L,0x834bcc3e592c4L,0xa938fab226adeL, - 0x068bd19ab1981L } }, - /* 28 */ - { { 0xead511887d659L,0xf4b359305ac08L,0xfe74fe33374d5L,0xdfd696986981cL, - 0x0495292f53c6fL }, - { 0x78c9e1acec896L,0x10ec5b44844a8L,0x64d60a7d964b2L,0x68376696f7e26L, - 0x00ec7530d2603L } }, - /* 29 */ - { { 0x13a05ad2687bbL,0x6af32e21fa2daL,0xdd4607ba1f83bL,0x3f0b390f5ef51L, - 0x00f6207a66486L }, - { 0x7e3bb0f138233L,0x6c272aa718bd6L,0x6ec88aedd66b9L,0x6dcf8ed004072L, - 0x0ff0db07208edL } }, - /* 30 */ - { { 0xfa1014c95d553L,0xfd5d680a8a749L,0xf3b566fa44052L,0x0ea3183b4317fL, - 0x0313b513c8874L }, - { 0x2e2ac08d11549L,0x0bb4dee21cb40L,0x7f2320e071ee1L,0x9f8126b987dd4L, - 0x02d3abcf986f1L } }, - /* 31 */ - { { 0x88501815581a2L,0x56632211af4c2L,0xcab2e999a0a6dL,0x8cdf19ba7a0f0L, - 0x0c036fa10ded9L }, - { 0xe08bac1fbd009L,0x9006d1581629aL,0xb9e0d8f0b68b1L,0x0194c2eb32779L, - 0x0a6b2a2c4b6d4L } }, - /* 32 */ - { { 0x3e50f6d3549cfL,0x6ffacd665ed43L,0xe11fcb46f3369L,0x9860695bfdaccL, - 0x0810ee252af7cL }, - { 0x50fe17159bb2cL,0xbe758b357b654L,0x69fea72f7dfbeL,0x17452b057e74dL, - 0x0d485717a9273L } }, - /* 33 */ - { { 0x41a8af0cb5a98L,0x931f3110bf117L,0xb382adfd3da8fL,0x604e1994e2cbaL, - 0x06a6045a72f9aL }, - { 0xc0d3fa2b2411dL,0x3e510e96e0170L,0x865b3ccbe0eb8L,0x57903bcc9f738L, - 0x0d3e45cfaf9e1L } }, - /* 34 */ - { { 0xf69bbe83f7669L,0x8272877d6bce1L,0x244278d09f8aeL,0xc19c9548ae543L, - 0x0207755dee3c2L }, - { 0xd61d96fef1945L,0xefb12d28c387bL,0x2df64aa18813cL,0xb00d9fbcd1d67L, - 0x048dc5ee57154L } }, - /* 35 */ - { { 0x790bff7e5a199L,0xcf989ccbb7123L,0xa519c79e0efb8L,0xf445c27a2bfe0L, - 0x0f2fb0aeddff6L }, - { 0x09575f0b5025fL,0xd740fa9f2241cL,0x80bfbd0550543L,0xd5258fa3c8ad3L, - 0x0a13e9015db28L } }, - /* 36 */ - { { 0x7a350a2b65cbcL,0x722a464226f9fL,0x23f07a10b04b9L,0x526f265ce241eL, - 0x02bf0d6b01497L }, - { 0x4dd3f4b216fb7L,0x67fbdda26ad3dL,0x708505cf7d7b8L,0xe89faeb7b83f6L, - 0x042a94a5a162fL } }, - /* 37 */ - { { 0x6ad0beaadf191L,0x9025a268d7584L,0x94dc1f60f8a48L,0xde3de86030504L, - 0x02c2dd969c65eL }, - { 0x2171d93849c17L,0xba1da250dd6d0L,0xc3a5485460488L,0x6dbc4810c7063L, - 0x0f437fa1f42c5L } }, - /* 38 */ - { { 0x0d7144a0f7dabL,0x931776e9ac6aaL,0x5f397860f0497L,0x7aa852c0a050fL, - 0x0aaf45b335470L }, - { 0x37c33c18d364aL,0x063e49716585eL,0x5ec5444d40b9bL,0x72bcf41716811L, - 0x0cdf6310df4f2L } }, - /* 39 */ - { { 0x3c6238ea8b7efL,0x1885bc2287747L,0xbda8e3408e935L,0x2ff2419567722L, - 0x0f0d008bada9eL }, - { 0x2671d2414d3b1L,0x85b019ea76291L,0x53bcbdbb37549L,0x7b8b5c61b96d4L, - 0x05bd5c2f5ca88L } }, - /* 40 */ - { { 0xf469ef49a3154L,0x956e2b2e9aef0L,0xa924a9c3e85a5L,0x471945aaec1eaL, - 0x0aa12dfc8a09eL }, - { 0x272274df69f1dL,0x2ca2ff5e7326fL,0x7a9dd44e0e4c8L,0xa901b9d8ce73bL, - 0x06c036e73e48cL } }, - /* 41 */ - { { 0xae12a0f6e3138L,0x0025ad345a5cfL,0x5672bc56966efL,0xbe248993c64b4L, - 0x0292ff65896afL }, - { 0x50d445e213402L,0x274392c9fed52L,0xa1c72e8f6580eL,0x7276097b397fdL, - 0x0644e0c90311bL } }, - /* 42 */ - { { 0x421e1a47153f0L,0x79920418c9e1eL,0x05d7672b86c3bL,0x9a7793bdce877L, - 0x0f25ae793cab7L }, - { 0x194a36d869d0cL,0x824986c2641f3L,0x96e945e9d55c8L,0x0a3e49fb5ea30L, - 0x039b8e65313dbL } }, - /* 43 */ - { { 0x54200b6fd2e59L,0x669255c98f377L,0xe2a573935e2c0L,0xdb06d9dab21a0L, - 0x039122f2f0f19L }, - { 0xce1e003cad53cL,0x0fe65c17e3cfbL,0xaa13877225b2cL,0xff8d72baf1d29L, - 0x08de80af8ce80L } }, - /* 44 */ - { { 0xea8d9207bbb76L,0x7c21782758afbL,0xc0436b1921c7eL,0x8c04dfa2b74b1L, - 0x0871949062e36L }, - { 0x928bba3993df5L,0xb5f3b3d26ab5fL,0x5b55050639d75L,0xfde1011aa78a8L, - 0x0fc315e6a5b74L } }, - /* 45 */ - { { 0xfd41ae8d6ecfaL,0xf61aec7f86561L,0x924741d5f8c44L,0x908898452a7b4L, - 0x0e6d4a7adee38L }, - { 0x52ed14593c75dL,0xa4dd271162605L,0xba2c7db70a70dL,0xae57d2aede937L, - 0x035dfaf9a9be2L } }, - /* 46 */ - { { 0x56fcdaa736636L,0x97ae2cab7e6b9L,0xf34996609f51dL,0x0d2bfb10bf410L, - 0x01da5c7d71c83L }, - { 0x1e4833cce6825L,0x8ff9573c3b5c4L,0x23036b815ad11L,0xb9d6a28552c7fL, - 0x07077c0fddbf4L } }, - /* 47 */ - { { 0x3ff8d46b9661cL,0x6b0d2cfd71bf6L,0x847f8f7a1dfd3L,0xfe440373e140aL, - 0x053a8632ee50eL }, - { 0x6ff68696d8051L,0x95c74f468a097L,0xe4e26bddaec0cL,0xfcc162994dc35L, - 0x0028ca76d34e1L } }, - /* 48 */ - { { 0xd47dcfc9877eeL,0x10801d0002d11L,0x4c260b6c8b362L,0xf046d002c1175L, - 0x004c17cd86962L }, - { 0xbd094b0daddf5L,0x7524ce55c06d9L,0x2da03b5bea235L,0x7474663356e67L, - 0x0f7ba4de9fed9L } }, - /* 49 */ - { { 0xbfa34ebe1263fL,0x3571ae7ce6d0dL,0x2a6f523557637L,0x1c41d24405538L, - 0x0e31f96005213L }, - { 0xb9216ea6b6ec6L,0x2e73c2fc44d1bL,0x9d0a29437a1d1L,0xd47bc10e7eac8L, - 0x0aa3a6259ce34L } }, - /* 50 */ - { { 0xf9df536f3dcd3L,0x50d2bf7360fbcL,0xf504f5b6cededL,0xdaee491710fadL, - 0x02398dd627e79L }, - { 0x705a36d09569eL,0xbb5149f769cf4L,0x5f6034cea0619L,0x6210ff9c03773L, - 0x05717f5b21c04L } }, - /* 51 */ - { { 0x229c921dd895eL,0x0040c284519feL,0xd637ecd8e5185L,0x28defa13d2391L, - 0x0660a2c560e3cL }, - { 0xa88aed67fcbd0L,0x780ea9f0969ccL,0x2e92b4dc84724L,0x245332b2f4817L, - 0x0624ee54c4f52L } }, - /* 52 */ - { { 0x49ce4d897ecccL,0xd93f9880aa095L,0x43a7c204d49d1L,0xfbc0723c24230L, - 0x04f392afb92bdL }, - { 0x9f8fa7de44fd9L,0xe457b32156696L,0x68ebc3cb66cfbL,0x399cdb2fa8033L, - 0x08a3e7977ccdbL } }, - /* 53 */ - { { 0x1881f06c4b125L,0x00f6e3ca8cddeL,0xc7a13e9ae34e3L,0x4404ef6999de5L, - 0x03888d02370c2L }, - { 0x8035644f91081L,0x615f015504762L,0x32cd36e3d9fcfL,0x23361827edc86L, - 0x0a5e62e471810L } }, - /* 54 */ - { { 0x25ee32facd6c8L,0x5454bcbc661a8L,0x8df9931699c63L,0x5adc0ce3edf79L, - 0x02c4768e6466aL }, - { 0x6ff8c90a64bc9L,0x20e4779f5cb34L,0xc05e884630a60L,0x52a0d949d064bL, - 0x07b5e6441f9e6L } }, - /* 55 */ - { { 0x9422c1d28444aL,0xd8be136a39216L,0xb0c7fcee996c5L,0x744a2387afe5fL, - 0x0b8af73cb0c8dL }, - { 0xe83aa338b86fdL,0x58a58a5cff5fdL,0x0ac9433fee3f1L,0x0895c9ee8f6f2L, - 0x0a036395f7f3fL } }, - /* 56 */ - { { 0x3c6bba10f7770L,0x81a12a0e248c7L,0x1bc2b9fa6f16dL,0xb533100df6825L, - 0x04be36b01875fL }, - { 0x6086e9fb56dbbL,0x8b07e7a4f8922L,0x6d52f20306fefL,0x00c0eeaccc056L, - 0x08cbc9a871bdcL } }, - /* 57 */ - { { 0x1895cc0dac4abL,0x40712ff112e13L,0xa1cee57a874a4L,0x35f86332ae7c6L, - 0x044e7553e0c08L }, - { 0x03fff7734002dL,0x8b0b34425c6d5L,0xe8738b59d35cbL,0xfc1895f702760L, - 0x0470a683a5eb8L } }, - /* 58 */ - { { 0x761dc90513482L,0x2a01e9276a81bL,0xce73083028720L,0xc6efcda441ee0L, - 0x016410690c63dL }, - { 0x34a066d06a2edL,0x45189b100bf50L,0xb8218c9dd4d77L,0xbb4fd914ae72aL, - 0x0d73479fd7abcL } }, - /* 59 */ - { { 0xefb165ad4c6e5L,0x8f5b06d04d7edL,0x575cb14262cf0L,0x666b12ed5bb18L, - 0x0816469e30771L }, - { 0xb9d79561e291eL,0x22c1de1661d7aL,0x35e0513eb9dafL,0x3f9cf49827eb1L, - 0x00a36dd23f0ddL } }, - /* 60 */ - { { 0xd32c741d5533cL,0x9e8684628f098L,0x349bd117c5f5aL,0xb11839a228adeL, - 0x0e331dfd6fdbaL }, - { 0x0ab686bcc6ed8L,0xbdef7a260e510L,0xce850d77160c3L,0x33899063d9a7bL, - 0x0d3b4782a492eL } }, - /* 61 */ - { { 0x9b6e8f3821f90L,0xed66eb7aada14L,0xa01311692edd9L,0xa5bd0bb669531L, - 0x07281275a4c86L }, - { 0x858f7d3ff47e5L,0xbc61016441503L,0xdfd9bb15e1616L,0x505962b0f11a7L, - 0x02c062e7ece14L } }, - /* 62 */ - { { 0xf996f0159ac2eL,0x36cbdb2713a76L,0x8e46047281e77L,0x7ef12ad6d2880L, - 0x0282a35f92c4eL }, - { 0x54b1ec0ce5cd2L,0xc91379c2299c3L,0xe82c11ecf99efL,0x2abd992caf383L, - 0x0c71cd513554dL } }, - /* 63 */ - { { 0x5de9c09b578f4L,0x58e3affa7a488L,0x9182f1f1884e2L,0xf3a38f76b1b75L, - 0x0c50f6740cf47L }, - { 0x4adf3374b68eaL,0x2369965fe2a9cL,0x5a53050a406f3L,0x58dc2f86a2228L, - 0x0b9ecb3a72129L } }, - /* 64 */ - { { 0x8410ef4f8b16aL,0xfec47b266a56fL,0xd9c87c197241aL,0xab1b0a406b8e6L, - 0x0803f3e02cd42L }, - { 0x309a804dbec69L,0xf73bbad05f7f0L,0xd8e197fa83b85L,0xadc1c6097273aL, - 0x0c097440e5067L } }, - /* 65 */ - { { 0xa56f2c379ab34L,0x8b841df8d1846L,0x76c68efa8ee06L,0x1f30203144591L, - 0x0f1af32d5915fL }, - { 0x375315d75bd50L,0xbaf72f67bc99cL,0x8d7723f837cffL,0x1c8b0613a4184L, - 0x023d0f130e2d4L } }, - /* 66 */ - { { 0xab6edf41500d9L,0xe5fcbeada8857L,0x97259510d890aL,0xfadd52fe86488L, - 0x0b0288dd6c0a3L }, - { 0x20f30650bcb08L,0x13695d6e16853L,0x989aa7671af63L,0xc8d231f520a7bL, - 0x0ffd3724ff408L } }, - /* 67 */ - { { 0x68e64b458e6cbL,0x20317a5d28539L,0xaa75f56992dadL,0x26df3814ae0b7L, - 0x0f5590f4ad78cL }, - { 0x24bd3cf0ba55aL,0x4a0c778bae0fcL,0x83b674a0fc472L,0x4a201ce9864f6L, - 0x018d6da54f6f7L } }, - /* 68 */ - { { 0x3e225d5be5a2bL,0x835934f3c6ed9L,0x2626ffc6fe799L,0x216a431409262L, - 0x050bbb4d97990L }, - { 0x191c6e57ec63eL,0x40181dcdb2378L,0x236e0f665422cL,0x49c341a8099b0L, - 0x02b10011801feL } }, - /* 69 */ - { { 0x8b5c59b391593L,0xa2598270fcfc6L,0x19adcbbc385f5L,0xae0c7144f3aadL, - 0x0dd55899983fbL }, - { 0x88b8e74b82ff4L,0x4071e734c993bL,0x3c0322ad2e03cL,0x60419a7a9eaf4L, - 0x0e6e4c551149dL } }, - /* 70 */ - { { 0x655bb1e9af288L,0x64f7ada93155fL,0xb2820e5647e1aL,0x56ff43697e4bcL, - 0x051e00db107edL }, - { 0x169b8771c327eL,0x0b4a96c2ad43dL,0xdeb477929cdb2L,0x9177c07d51f53L, - 0x0e22f42414982L } }, - /* 71 */ - { { 0x5e8f4635f1abbL,0xb568538874cd4L,0x5a8034d7edc0cL,0x48c9c9472c1fbL, - 0x0f709373d52dcL }, - { 0x966bba8af30d6L,0x4af137b69c401L,0x361c47e95bf5fL,0x5b113966162a9L, - 0x0bd52d288e727L } }, - /* 72 */ - { { 0x55c7a9c5fa877L,0x727d3a3d48ab1L,0x3d189d817dad6L,0x77a643f43f9e7L, - 0x0a0d0f8e4c8aaL }, - { 0xeafd8cc94f92dL,0xbe0c4ddb3a0bbL,0x82eba14d818c8L,0x6a0022cc65f8bL, - 0x0a56c78c7946dL } }, - /* 73 */ - { { 0x2391b0dd09529L,0xa63daddfcf296L,0xb5bf481803e0eL,0x367a2c77351f5L, - 0x0d8befdf8731aL }, - { 0x19d42fc0157f4L,0xd7fec8e650ab9L,0x2d48b0af51caeL,0x6478cdf9cb400L, - 0x0854a68a5ce9fL } }, - /* 74 */ - { { 0x5f67b63506ea5L,0x89a4fe0d66dc3L,0xe95cd4d9286c4L,0x6a953f101d3bfL, - 0x05cacea0b9884L }, - { 0xdf60c9ceac44dL,0xf4354d1c3aa90L,0xd5dbabe3db29aL,0xefa908dd3de8aL, - 0x0e4982d1235e4L } }, - /* 75 */ - { { 0x04a22c34cd55eL,0xb32680d132231L,0xfa1d94358695bL,0x0499fb345afa1L, - 0x08046b7f616b2L }, - { 0x3581e38e7d098L,0x8df46f0b70b53L,0x4cb78c4d7f61eL,0xaf5530dea9ea4L, - 0x0eb17ca7b9082L } }, - /* 76 */ - { { 0x1b59876a145b9L,0x0fc1bc71ec175L,0x92715bba5cf6bL,0xe131d3e035653L, - 0x0097b00bafab5L }, - { 0x6c8e9565f69e1L,0x5ab5be5199aa6L,0xa4fd98477e8f7L,0xcc9e6033ba11dL, - 0x0f95c747bafdbL } }, - /* 77 */ - { { 0xf01d3bebae45eL,0xf0c4bc6955558L,0xbc64fc6a8ebe9L,0xd837aeb705b1dL, - 0x03512601e566eL }, - { 0x6f1e1fa1161cdL,0xd54c65ef87933L,0x24f21e5328ab8L,0xab6b4757eee27L, - 0x00ef971236068L } }, - /* 78 */ - { { 0x98cf754ca4226L,0x38f8642c8e025L,0x68e17905eede1L,0xbc9548963f744L, - 0x0fc16d9333b4fL }, - { 0x6fb31e7c800caL,0x312678adaabe9L,0xff3e8b5138063L,0x7a173d6244976L, - 0x014ca4af1b95dL } }, - /* 79 */ - { { 0x771babd2f81d5L,0x6901f7d1967a4L,0xad9c9071a5f9dL,0x231dd898bef7cL, - 0x04057b063f59cL }, - { 0xd82fe89c05c0aL,0x6f1dc0df85bffL,0x35a16dbe4911cL,0x0b133befccaeaL, - 0x01c3b5d64f133L } }, - /* 80 */ - { { 0x14bfe80ec21feL,0x6ac255be825feL,0xf4a5d67f6ce11L,0x63af98bc5a072L, - 0x0fad27148db7eL }, - { 0x0b6ac29ab05b3L,0x3c4e251ae690cL,0x2aade7d37a9a8L,0x1a840a7dc875cL, - 0x077387de39f0eL } }, - /* 81 */ - { { 0xecc49a56c0dd7L,0xd846086c741e9L,0x505aecea5cffcL,0xc47e8f7a1408fL, - 0x0b37b85c0bef0L }, - { 0x6b6e4cc0e6a8fL,0xbf6b388f23359L,0x39cef4efd6d4bL,0x28d5aba453facL, - 0x09c135ac8f9f6L } }, - /* 82 */ - { { 0xa320284e35743L,0xb185a3cdef32aL,0xdf19819320d6aL,0x851fb821b1761L, - 0x05721361fc433L }, - { 0xdb36a71fc9168L,0x735e5c403c1f0L,0x7bcd8f55f98baL,0x11bdf64ca87e3L, - 0x0dcbac3c9e6bbL } }, - /* 83 */ - { { 0xd99684518cbe2L,0x189c9eb04ef01L,0x47feebfd242fcL,0x6862727663c7eL, - 0x0b8c1c89e2d62L }, - { 0x58bddc8e1d569L,0xc8b7d88cd051aL,0x11f31eb563809L,0x22d426c27fd9fL, - 0x05d23bbda2f94L } }, - /* 84 */ - { { 0xc729495c8f8beL,0x803bf362bf0a1L,0xf63d4ac2961c4L,0xe9009e418403dL, - 0x0c109f9cb91ecL }, - { 0x095d058945705L,0x96ddeb85c0c2dL,0xa40449bb9083dL,0x1ee184692b8d7L, - 0x09bc3344f2eeeL } }, - /* 85 */ - { { 0xae35642913074L,0x2748a542b10d5L,0x310732a55491bL,0x4cc1469ca665bL, - 0x029591d525f1aL }, - { 0xf5b6bb84f983fL,0x419f5f84e1e76L,0x0baa189be7eefL,0x332c1200d4968L, - 0x06376551f18efL } }, - /* 86 */ - { { 0x5f14e562976ccL,0xe60ef12c38bdaL,0xcca985222bca3L,0x987abbfa30646L, - 0x0bdb79dc808e2L }, - { 0xcb5c9cb06a772L,0xaafe536dcefd2L,0xc2b5db838f475L,0xc14ac2a3e0227L, - 0x08ee86001add3L } }, - /* 87 */ - { { 0x96981a4ade873L,0x4dc4fba48ccbeL,0xa054ba57ee9aaL,0xaa4b2cee28995L, - 0x092e51d7a6f77L }, - { 0xbafa87190a34dL,0x5bf6bd1ed1948L,0xcaf1144d698f7L,0xaaaad00ee6e30L, - 0x05182f86f0a56L } }, - /* 88 */ - { { 0x6212c7a4cc99cL,0x683e6d9ca1fbaL,0xac98c5aff609bL,0xa6f25dbb27cb5L, - 0x091dcab5d4073L }, - { 0x6cc3d5f575a70L,0x396f8d87fa01bL,0x99817360cb361L,0x4f2b165d4e8c8L, - 0x017a0cedb9797L } }, - /* 89 */ - { { 0x61e2a076c8d3aL,0x39210f924b388L,0x3a835d9701aadL,0xdf4194d0eae41L, - 0x02e8ce36c7f4cL }, - { 0x73dab037a862bL,0xb760e4c8fa912L,0x3baf2dd01ba9bL,0x68f3f96453883L, - 0x0f4ccc6cb34f6L } }, - /* 90 */ - { { 0xf525cf1f79687L,0x9592efa81544eL,0x5c78d297c5954L,0xf3c9e1231741aL, - 0x0ac0db4889a0dL }, - { 0xfc711df01747fL,0x58ef17df1386bL,0xccb6bb5592b93L,0x74a2e5880e4f5L, - 0x095a64a6194c9L } }, - /* 91 */ - { { 0x1efdac15a4c93L,0x738258514172cL,0x6cb0bad40269bL,0x06776a8dfb1c1L, - 0x0231e54ba2921L }, - { 0xdf9178ae6d2dcL,0x3f39112918a70L,0xe5b72234d6aa6L,0x31e1f627726b5L, - 0x0ab0be032d8a7L } }, - /* 92 */ - { { 0xad0e98d131f2dL,0xe33b04f101097L,0x5e9a748637f09L,0xa6791ac86196dL, - 0x0f1bcc8802cf6L }, - { 0x69140e8daacb4L,0x5560f6500925cL,0x77937a63c4e40L,0xb271591cc8fc4L, - 0x0851694695aebL } }, - /* 93 */ - { { 0x5c143f1dcf593L,0x29b018be3bde3L,0xbdd9d3d78202bL,0x55d8e9cdadc29L, - 0x08f67d9d2daadL }, - { 0x116567481ea5fL,0xe9e34c590c841L,0x5053fa8e7d2ddL,0x8b5dffdd43f40L, - 0x0f84572b9c072L } }, - /* 94 */ - { { 0xa7a7197af71c9L,0x447a7365655e1L,0xe1d5063a14494L,0x2c19a1b4ae070L, - 0x0edee2710616bL }, - { 0x034f511734121L,0x554a25e9f0b2fL,0x40c2ecf1cac6eL,0xd7f48dc148f3aL, - 0x09fd27e9b44ebL } }, - /* 95 */ - { { 0x7658af6e2cb16L,0x2cfe5919b63ccL,0x68d5583e3eb7dL,0xf3875a8c58161L, - 0x0a40c2fb6958fL }, - { 0xec560fedcc158L,0xc655f230568c9L,0xa307e127ad804L,0xdecfd93967049L, - 0x099bc9bb87dc6L } }, - /* 96 */ - { { 0x9521d927dafc6L,0x695c09cd1984aL,0x9366dde52c1fbL,0x7e649d9581a0fL, - 0x09abe210ba16dL }, - { 0xaf84a48915220L,0x6a4dd816c6480L,0x681ca5afa7317L,0x44b0c7d539871L, - 0x07881c25787f3L } }, - /* 97 */ - { { 0x99b51e0bcf3ffL,0xc5127f74f6933L,0xd01d9680d02cbL,0x89408fb465a2dL, - 0x015e6e319a30eL }, - { 0xd6e0d3e0e05f4L,0xdc43588404646L,0x4f850d3fad7bdL,0x72cebe61c7d1cL, - 0x00e55facf1911L } }, - /* 98 */ - { { 0xd9806f8787564L,0x2131e85ce67e9L,0x819e8d61a3317L,0x65776b0158cabL, - 0x0d73d09766fe9L }, - { 0x834251eb7206eL,0x0fc618bb42424L,0xe30a520a51929L,0xa50b5dcbb8595L, - 0x09250a3748f15L } }, - /* 99 */ - { { 0xf08f8be577410L,0x035077a8c6cafL,0xc0a63a4fd408aL,0x8c0bf1f63289eL, - 0x077414082c1ccL }, - { 0x40fa6eb0991cdL,0x6649fdc29605aL,0x324fd40c1ca08L,0x20b93a68a3c7bL, - 0x08cb04f4d12ebL } }, - /* 100 */ - { { 0x2d0556906171cL,0xcdb0240c3fb1cL,0x89068419073e9L,0x3b51db8e6b4fdL, - 0x0e4e429ef4712L }, - { 0xdd53c38ec36f4L,0x01ff4b6a270b8L,0x79a9a48f9d2dcL,0x65525d066e078L, - 0x037bca2ff3c6eL } }, - /* 101 */ - { { 0x2e3c7df562470L,0xa2c0964ac94cdL,0x0c793be44f272L,0xb22a7c6d5df98L, - 0x059913edc3002L }, - { 0x39a835750592aL,0x80e783de027a1L,0xa05d64f99e01dL,0xe226cf8c0375eL, - 0x043786e4ab013L } }, - /* 102 */ - { { 0x2b0ed9e56b5a6L,0xa6d9fc68f9ff3L,0x97846a70750d9L,0x9e7aec15e8455L, - 0x08638ca98b7e7L }, - { 0xae0960afc24b2L,0xaf4dace8f22f5L,0xecba78f05398eL,0xa6f03b765dd0aL, - 0x01ecdd36a7b3aL } }, - /* 103 */ - { { 0xacd626c5ff2f3L,0xc02873a9785d3L,0x2110d54a2d516L,0xf32dad94c9fadL, - 0x0d85d0f85d459L }, - { 0x00b8d10b11da3L,0x30a78318c49f7L,0x208decdd2c22cL,0x3c62556988f49L, - 0x0a04f19c3b4edL } }, - /* 104 */ - { { 0x924c8ed7f93bdL,0x5d392f51f6087L,0x21b71afcb64acL,0x50b07cae330a8L, - 0x092b2eeea5c09L }, - { 0xc4c9485b6e235L,0xa92936c0f085aL,0x0508891ab2ca4L,0x276c80faa6b3eL, - 0x01ee782215834L } }, - /* 105 */ - { { 0xa2e00e63e79f7L,0xb2f399d906a60L,0x607c09df590e7L,0xe1509021054a6L, - 0x0f3f2ced857a6L }, - { 0x510f3f10d9b55L,0xacd8642648200L,0x8bd0e7c9d2fcfL,0xe210e5631aa7eL, - 0x00f56a4543da3L } }, - /* 106 */ - { { 0x1bffa1043e0dfL,0xcc9c007e6d5b2L,0x4a8517a6c74b6L,0xe2631a656ec0dL, - 0x0bd8f17411969L }, - { 0xbbb86beb7494aL,0x6f45f3b8388a9L,0x4e5a79a1567d4L,0xfa09df7a12a7aL, - 0x02d1a1c3530ccL } }, - /* 107 */ - { { 0xe3813506508daL,0xc4a1d795a7192L,0xa9944b3336180L,0xba46cddb59497L, - 0x0a107a65eb91fL }, - { 0x1d1c50f94d639L,0x758a58b7d7e6dL,0xd37ca1c8b4af3L,0x9af21a7c5584bL, - 0x0183d760af87aL } }, - /* 108 */ - { { 0x697110dde59a4L,0x070e8bef8729dL,0xf2ebe78f1ad8dL,0xd754229b49634L, - 0x01d44179dc269L }, - { 0xdc0cf8390d30eL,0x530de8110cb32L,0xbc0339a0a3b27L,0xd26231af1dc52L, - 0x0771f9cc29606L } }, - /* 109 */ - { { 0x93e7785040739L,0xb98026a939999L,0x5f8fc2644539dL,0x718ecf40f6f2fL, - 0x064427a310362L }, - { 0xf2d8785428aa8L,0x3febfb49a84f4L,0x23d01ac7b7adcL,0x0d6d201b2c6dfL, - 0x049d9b7496ae9L } }, - /* 110 */ - { { 0x8d8bc435d1099L,0x4e8e8d1a08cc7L,0xcb68a412adbcdL,0x544502c2e2a02L, - 0x09037d81b3f60L }, - { 0xbac27074c7b61L,0xab57bfd72e7cdL,0x96d5352fe2031L,0x639c61ccec965L, - 0x008c3de6a7cc0L } }, - /* 111 */ - { { 0xdd020f6d552abL,0x9805cd81f120fL,0x135129156baffL,0x6b2f06fb7c3e9L, - 0x0c69094424579L }, - { 0x3ae9c41231bd1L,0x875cc5820517bL,0x9d6a1221eac6eL,0x3ac0208837abfL, - 0x03fa3db02cafeL } }, - /* 112 */ - { { 0xa3e6505058880L,0xef643943f2d75L,0xab249257da365L,0x08ff4147861cfL, - 0x0c5c4bdb0fdb8L }, - { 0x13e34b272b56bL,0x9511b9043a735L,0x8844969c8327eL,0xb6b5fd8ce37dfL, - 0x02d56db9446c2L } }, - /* 113 */ - { { 0x1782fff46ac6bL,0x2607a2e425246L,0x9a48de1d19f79L,0xba42fafea3c40L, - 0x00f56bd9de503L }, - { 0xd4ed1345cda49L,0xfc816f299d137L,0xeb43402821158L,0xb5f1e7c6a54aaL, - 0x04003bb9d1173L } }, - /* 114 */ - { { 0xe8189a0803387L,0xf539cbd4043b8L,0x2877f21ece115L,0x2f9e4297208ddL, - 0x053765522a07fL }, - { 0x80a21a8a4182dL,0x7a3219df79a49L,0xa19a2d4a2bbd0L,0x4549674d0a2e1L, - 0x07a056f586c5dL } }, - /* 115 */ - { { 0xb25589d8a2a47L,0x48c3df2773646L,0xbf0d5395b5829L,0x267551ec000eaL, - 0x077d482f17a1aL }, - { 0x1bd9587853948L,0xbd6cfbffeeb8aL,0x0681e47a6f817L,0xb0e4ab6ec0578L, - 0x04115012b2b38L } }, - /* 116 */ - { { 0x3f0f46de28cedL,0x609b13ec473c7L,0xe5c63921d5da7L,0x094661b8ce9e6L, - 0x0cdf04572fbeaL }, - { 0x3c58b6c53c3b0L,0x10447b843c1cbL,0xcb9780e97fe3cL,0x3109fb2b8ae12L, - 0x0ee703dda9738L } }, - /* 117 */ - { { 0x15140ff57e43aL,0xd3b1b811b8345L,0xf42b986d44660L,0xce212b3b5dff8L, - 0x02a0ad89da162L }, - { 0x4a6946bc277baL,0x54c141c27664eL,0xabf6274c788c9L,0x4659141aa64ccL, - 0x0d62d0b67ac2bL } }, - /* 118 */ - { { 0x5d87b2c054ac4L,0x59f27df78839cL,0x18128d6570058L,0x2426edf7cbf3bL, - 0x0b39a23f2991cL }, - { 0x84a15f0b16ae5L,0xb1a136f51b952L,0x27007830c6a05L,0x4cc51d63c137fL, - 0x004ed0092c067L } }, - /* 119 */ - { { 0x185d19ae90393L,0x294a3d64e61f4L,0x854fc143047b4L,0xc387ae0001a69L, - 0x0a0a91fc10177L }, - { 0xa3f01ae2c831eL,0x822b727e16ff0L,0xa3075b4bb76aeL,0x0c418f12c8a15L, - 0x0084cf9889ed2L } }, - /* 120 */ - { { 0x509defca6becfL,0x807dffb328d98L,0x778e8b92fceaeL,0xf77e5d8a15c44L, - 0x0d57955b273abL }, - { 0xda79e31b5d4f1L,0x4b3cfa7a1c210L,0xc27c20baa52f0L,0x41f1d4d12089dL, - 0x08e14ea4202d1L } }, - /* 121 */ - { { 0x50345f2897042L,0x1f43402c4aeedL,0x8bdfb218d0533L,0xd158c8d9c194cL, - 0x0597e1a372aa4L }, - { 0x7ec1acf0bd68cL,0xdcab024945032L,0x9fe3e846d4be0L,0x4dea5b9c8d7acL, - 0x0ca3f0236199bL } }, - /* 122 */ - { { 0xa10b56170bd20L,0xf16d3f5de7592L,0x4b2ade20ea897L,0x07e4a3363ff14L, - 0x0bde7fd7e309cL }, - { 0xbb6d2b8f5432cL,0xcbe043444b516L,0x8f95b5a210dc1L,0xd1983db01e6ffL, - 0x0b623ad0e0a7dL } }, - /* 123 */ - { { 0xbd67560c7b65bL,0x9023a4a289a75L,0x7b26795ab8c55L,0x137bf8220fd0dL, - 0x0d6aa2e4658ecL }, - { 0xbc00b5138bb85L,0x21d833a95c10aL,0x702a32e8c31d1L,0x513ab24ff00b1L, - 0x0111662e02dccL } }, - /* 124 */ - { { 0x14015efb42b87L,0x701b6c4dff781L,0x7d7c129bd9f5dL,0x50f866ecccd7aL, - 0x0db3ee1cb94b7L }, - { 0xf3db0f34837cfL,0x8bb9578d4fb26L,0xc56657de7eed1L,0x6a595d2cdf937L, - 0x0886a64425220L } }, - /* 125 */ - { { 0x34cfb65b569eaL,0x41f72119c13c2L,0x15a619e200111L,0x17bc8badc85daL, - 0x0a70cf4eb018aL }, - { 0xf97ae8c4a6a65L,0x270134378f224L,0xf7e096036e5cfL,0x7b77be3a609e4L, - 0x0aa4772abd174L } }, - /* 126 */ - { { 0x761317aa60cc0L,0x610368115f676L,0xbc1bb5ac79163L,0xf974ded98bb4bL, - 0x0611a6ddc30faL }, - { 0x78cbcc15ee47aL,0x824e0d96a530eL,0xdd9ed882e8962L,0x9c8836f35adf3L, - 0x05cfffaf81642L } }, - /* 127 */ - { { 0x54cff9b7a99cdL,0x9d843c45a1c0dL,0x2c739e17bf3b9L,0x994c038a908f6L, - 0x06e5a6b237dc1L }, - { 0xb454e0ba5db77L,0x7facf60d63ef8L,0x6608378b7b880L,0xabcce591c0c67L, - 0x0481a238d242dL } }, - /* 128 */ - { { 0x17bc035d0b34aL,0x6b8327c0a7e34L,0xc0362d1440b38L,0xf9438fb7262daL, - 0x02c41114ce0cdL }, - { 0x5cef1ad95a0b1L,0xa867d543622baL,0x1e486c9c09b37L,0x929726d6cdd20L, - 0x020477abf42ffL } }, - /* 129 */ - { { 0x5173c18d65dbfL,0x0e339edad82f7L,0xcf1001c77bf94L,0x96b67022d26bdL, - 0x0ac66409ac773L }, - { 0xbb36fc6261cc3L,0xc9190e7e908b0L,0x45e6c10213f7bL,0x2f856541cebaaL, - 0x0ce8e6975cc12L } }, - /* 130 */ - { { 0x21b41bc0a67d2L,0x0a444d248a0f1L,0x59b473762d476L,0xb4a80e044f1d6L, - 0x008fde365250bL }, - { 0xec3da848bf287L,0x82d3369d6eaceL,0x2449482c2a621L,0x6cd73582dfdc9L, - 0x02f7e2fd2565dL } }, - /* 131 */ - { { 0xb92dbc3770fa7L,0x5c379043f9ae4L,0x7761171095e8dL,0x02ae54f34e9d1L, - 0x0c65be92e9077L }, - { 0x8a303f6fd0a40L,0xe3bcce784b275L,0xf9767bfe7d822L,0x3b3a7ae4f5854L, - 0x04bff8e47d119L } }, - /* 132 */ - { { 0x1d21f00ff1480L,0x7d0754db16cd4L,0xbe0f3ea2ab8fbL,0x967dac81d2efbL, - 0x03e4e4ae65772L }, - { 0x8f36d3c5303e6L,0x4b922623977e1L,0x324c3c03bd999L,0x60289ed70e261L, - 0x05388aefd58ecL } }, - /* 133 */ - { { 0x317eb5e5d7713L,0xee75de49daad1L,0x74fb26109b985L,0xbe0e32f5bc4fcL, - 0x05cf908d14f75L }, - { 0x435108e657b12L,0xa5b96ed9e6760L,0x970ccc2bfd421L,0x0ce20e29f51f8L, - 0x0a698ba4060f0L } }, - /* 134 */ - { { 0xb1686ef748fecL,0xa27e9d2cf973dL,0xe265effe6e755L,0xad8d630b6544cL, - 0x0b142ef8a7aebL }, - { 0x1af9f17d5770aL,0x672cb3412fad3L,0xf3359de66af3bL,0x50756bd60d1bdL, - 0x0d1896a965851L } }, - /* 135 */ - { { 0x957ab33c41c08L,0xac5468e2e1ec5L,0xc472f6c87de94L,0xda3918816b73aL, - 0x0267b0e0b7981L }, - { 0x54e5d8e62b988L,0x55116d21e76e5L,0xd2a6f99d8ddc7L,0x93934610faf03L, - 0x0b54e287aa111L } }, - /* 136 */ - { { 0x122b5178a876bL,0xff085104b40a0L,0x4f29f7651ff96L,0xd4e6050b31ab1L, - 0x084abb28b5f87L }, - { 0xd439f8270790aL,0x9d85e3f46bd5eL,0xc1e22122d6cb5L,0x564075f55c1b6L, - 0x0e5436f671765L } }, - /* 137 */ - { { 0x9025e2286e8d5L,0xb4864453be53fL,0x408e3a0353c95L,0xe99ed832f5bdeL, - 0x00404f68b5b9cL }, - { 0x33bdea781e8e5L,0x18163c2f5bcadL,0x119caa33cdf50L,0xc701575769600L, - 0x03a4263df0ac1L } }, - /* 138 */ - { { 0x65ecc9aeb596dL,0xe7023c92b4c29L,0xe01396101ea03L,0xa3674704b4b62L, - 0x00ca8fd3f905eL }, - { 0x23a42551b2b61L,0x9c390fcd06925L,0x392a63e1eb7a8L,0x0c33e7f1d2be0L, - 0x096dca2644ddbL } }, - /* 139 */ - { { 0xbb43a387510afL,0xa8a9a36a01203L,0xf950378846feaL,0x59dcd23a57702L, - 0x04363e2123aadL }, - { 0x3a1c740246a47L,0xd2e55dd24dca4L,0xd8faf96b362b8L,0x98c4f9b086045L, - 0x0840e115cd8bbL } }, - /* 140 */ - { { 0x205e21023e8a7L,0xcdd8dc7a0bf12L,0x63a5ddfc808a8L,0xd6d4e292a2721L, - 0x05e0d6abd30deL }, - { 0x721c27cfc0f64L,0x1d0e55ed8807aL,0xd1f9db242eec0L,0xa25a26a7bef91L, - 0x07dea48f42945L } }, - /* 141 */ - { { 0xf6f1ce5060a81L,0x72f8f95615abdL,0x6ac268be79f9cL,0x16d1cfd36c540L, - 0x0abc2a2beebfdL }, - { 0x66f91d3e2eac7L,0x63d2dd04668acL,0x282d31b6f10baL,0xefc16790e3770L, - 0x04ea353946c7eL } }, - /* 142 */ - { { 0xa2f8d5266309dL,0xc081945a3eed8L,0x78c5dc10a51c6L,0xffc3cecaf45a5L, - 0x03a76e6891c94L }, - { 0xce8a47d7b0d0fL,0x968f584a5f9aaL,0xe697fbe963aceL,0x646451a30c724L, - 0x08212a10a465eL } }, - /* 143 */ - { { 0xc61c3cfab8caaL,0x840e142390ef7L,0xe9733ca18eb8eL,0xb164cd1dff677L, - 0x0aa7cab71599cL }, - { 0xc9273bc837bd1L,0xd0c36af5d702fL,0x423da49c06407L,0x17c317621292fL, - 0x040e38073fe06L } }, - /* 144 */ - { { 0x80824a7bf9b7cL,0x203fbe30d0f4fL,0x7cf9ce3365d23L,0x5526bfbe53209L, - 0x0e3604700b305L }, - { 0xb99116cc6c2c7L,0x08ba4cbee64dcL,0x37ad9ec726837L,0xe15fdcded4346L, - 0x06542d677a3deL } }, - /* 145 */ - { { 0x2b6d07b6c377aL,0x47903448be3f3L,0x0da8af76cb038L,0x6f21d6fdd3a82L, - 0x0a6534aee09bbL }, - { 0x1780d1035facfL,0x339dcb47e630aL,0x447f39335e55aL,0xef226ea50fe1cL, - 0x0f3cb672fdc9aL } }, - /* 146 */ - { { 0x719fe3b55fd83L,0x6c875ddd10eb3L,0x5cea784e0d7a4L,0x70e733ac9fa90L, - 0x07cafaa2eaae8L }, - { 0x14d041d53b338L,0xa0ef87e6c69b8L,0x1672b0fe0acc0L,0x522efb93d1081L, - 0x00aab13c1b9bdL } }, - /* 147 */ - { { 0xce278d2681297L,0xb1b509546addcL,0x661aaf2cb350eL,0x12e92dc431737L, - 0x04b91a6028470L }, - { 0xf109572f8ddcfL,0x1e9a911af4dcfL,0x372430e08ebf6L,0x1cab48f4360acL, - 0x049534c537232L } }, - /* 148 */ - { { 0xf7d71f07b7e9dL,0xa313cd516f83dL,0xc047ee3a478efL,0xc5ee78ef264b6L, - 0x0caf46c4fd65aL }, - { 0xd0c7792aa8266L,0x66913684bba04L,0xe4b16b0edf454L,0x770f56e65168aL, - 0x014ce9e5704c6L } }, - /* 149 */ - { { 0x45e3e965e8f91L,0xbacb0f2492994L,0x0c8a0a0d3aca1L,0x9a71d31cc70f9L, - 0x01bb708a53e4cL }, - { 0xa9e69558bdd7aL,0x08018a26b1d5cL,0xc9cf1ec734a05L,0x0102b093aa714L, - 0x0f9d126f2da30L } }, - /* 150 */ - { { 0xbca7aaff9563eL,0xfeb49914a0749L,0xf5f1671dd077aL,0xcc69e27a0311bL, - 0x0807afcb9729eL }, - { 0xa9337c9b08b77L,0x85443c7e387f8L,0x76fd8ba86c3a7L,0xcd8c85fafa594L, - 0x0751adcd16568L } }, - /* 151 */ - { { 0xa38b410715c0dL,0x718f7697f78aeL,0x3fbf06dd113eaL,0x743f665eab149L, - 0x029ec44682537L }, - { 0x4719cb50bebbcL,0xbfe45054223d9L,0xd2dedb1399ee5L,0x077d90cd5b3a8L, - 0x0ff9370e392a4L } }, - /* 152 */ - { { 0x2d69bc6b75b65L,0xd5266651c559aL,0xde9d7d24188f8L,0xd01a28a9f33e3L, - 0x09776478ba2a9L }, - { 0x2622d929af2c7L,0x6d4e690923885L,0x89a51e9334f5dL,0x82face6cc7e5aL, - 0x074a6313fac2fL } }, - /* 153 */ - { { 0x4dfddb75f079cL,0x9518e36fbbb2fL,0x7cd36dd85b07cL,0x863d1b6cfcf0eL, - 0x0ab75be150ff4L }, - { 0x367c0173fc9b7L,0x20d2594fd081bL,0x4091236b90a74L,0x59f615fdbf03cL, - 0x04ebeac2e0b44L } }, - /* 154 */ - { { 0xc5fe75c9f2c53L,0x118eae9411eb6L,0x95ac5d8d25220L,0xaffcc8887633fL, - 0x0df99887b2c1bL }, - { 0x8eed2850aaecbL,0x1b01d6a272bb7L,0x1cdbcac9d4918L,0x4058978dd511bL, - 0x027b040a7779fL } }, - /* 155 */ - { { 0x05db7f73b2eb2L,0x088e1b2118904L,0x962327ee0df85L,0xa3f5501b71525L, - 0x0b393dd37e4cfL }, - { 0x30e7b3fd75165L,0xc2bcd33554a12L,0xf7b5022d66344L,0x34196c36f1be0L, - 0x009588c12d046L } }, - /* 156 */ - { { 0x6093f02601c3bL,0xf8cf5c335fe08L,0x94aff28fb0252L,0x648b955cf2808L, - 0x081c879a9db9fL }, - { 0xe687cc6f56c51L,0x693f17618c040L,0x059353bfed471L,0x1bc444f88a419L, - 0x0fa0d48f55fc1L } }, - /* 157 */ - { { 0xe1c9de1608e4dL,0x113582822cbc6L,0x57ec2d7010ddaL,0x67d6f6b7ddc11L, - 0x08ea0e156b6a3L }, - { 0x4e02f2383b3b4L,0x943f01f53ca35L,0xde03ca569966bL,0xb5ac4ff6632b2L, - 0x03f5ab924fa00L } }, - /* 158 */ - { { 0xbb0d959739efbL,0xf4e7ebec0d337L,0x11a67d1c751b0L,0x256e2da52dd64L, - 0x08bc768872b74L }, - { 0xe3b7282d3d253L,0xa1f58d779fa5bL,0x16767bba9f679L,0xf34fa1cac168eL, - 0x0b386f19060fcL } }, - /* 159 */ - { { 0x3c1352fedcfc2L,0x6262f8af0d31fL,0x57288c25396bfL,0x9c4d9a02b4eaeL, - 0x04cb460f71b06L }, - { 0x7b4d35b8095eaL,0x596fc07603ae6L,0x614a16592bbf8L,0x5223e1475f66bL, - 0x052c0d50895efL } }, - /* 160 */ - { { 0xc210e15339848L,0xe870778c8d231L,0x956e170e87a28L,0x9c0b9d1de6616L, - 0x04ac3c9382bb0L }, - { 0xe05516998987dL,0xc4ae09f4d619bL,0xa3f933d8b2376L,0x05f41de0b7651L, - 0x0380d94c7e397L } }, - /* 161 */ - { { 0x355aa81542e75L,0xa1ee01b9b701aL,0x24d708796c724L,0x37af6b3a29776L, - 0x02ce3e171de26L }, - { 0xfeb49f5d5bc1aL,0x7e2777e2b5cfeL,0x513756ca65560L,0x4e4d4feaac2f9L, - 0x02e6cd8520b62L } }, - /* 162 */ - { { 0x5954b8c31c31dL,0x005bf21a0c368L,0x5c79ec968533dL,0x9d540bd7626e7L, - 0x0ca17754742c6L }, - { 0xedafff6d2dbb2L,0xbd174a9d18cc6L,0xa4578e8fd0d8cL,0x2ce6875e8793aL, - 0x0a976a7139cabL } }, - /* 163 */ - { { 0x51f1b93fb353dL,0x8b57fcfa720a6L,0x1b15281d75cabL,0x4999aa88cfa73L, - 0x08720a7170a1fL }, - { 0xe8d37693e1b90L,0x0b16f6dfc38c3L,0x52a8742d345dcL,0x893c8ea8d00abL, - 0x09719ef29c769L } }, - /* 164 */ - { { 0xeed8d58e35909L,0xdc33ddc116820L,0xe2050269366d8L,0x04c1d7f999d06L, - 0x0a5072976e157L }, - { 0xa37eac4e70b2eL,0x576890aa8a002L,0x45b2a5c84dcf6L,0x7725cd71bf186L, - 0x099389c9df7b7L } }, - /* 165 */ - { { 0xc08f27ada7a4bL,0x03fd389366238L,0x66f512c3abe9dL,0x82e46b672e897L, - 0x0a88806aa202cL }, - { 0x2044ad380184eL,0xc4126a8b85660L,0xd844f17a8cb78L,0xdcfe79d670c0aL, - 0x00043bffb4738L } }, - /* 166 */ - { { 0x9b5dc36d5192eL,0xd34590b2af8d5L,0x1601781acf885L,0x486683566d0a1L, - 0x052f3ef01ba6cL }, - { 0x6732a0edcb64dL,0x238068379f398L,0x040f3090a482cL,0x7e7516cbe5fa7L, - 0x03296bd899ef2L } }, - /* 167 */ - { { 0xaba89454d81d7L,0xef51eb9b3c476L,0x1c579869eade7L,0x71e9619a21cd8L, - 0x03b90febfaee5L }, - { 0x3023e5496f7cbL,0xd87fb51bc4939L,0x9beb5ce55be41L,0x0b1803f1dd489L, - 0x06e88069d9f81L } }, - /* 168 */ - { { 0x7ab11b43ea1dbL,0xa95259d292ce3L,0xf84f1860a7ff1L,0xad13851b02218L, - 0x0a7222beadefaL }, - { 0xc78ec2b0a9144L,0x51f2fa59c5a2aL,0x147ce385a0240L,0xc69091d1eca56L, - 0x0be94d523bc2aL } }, - /* 169 */ - { { 0x4945e0b226ce7L,0x47967e8b7072fL,0x5a6c63eb8afd7L,0xc766edea46f18L, - 0x07782defe9be8L }, - { 0xd2aa43db38626L,0x8776f67ad1760L,0x4499cdb460ae7L,0x2e4b341b86fc5L, - 0x003838567a289L } }, - /* 170 */ - { { 0xdaefd79ec1a0fL,0xfdceb39c972d8L,0x8f61a953bbcd6L,0xb420f5575ffc5L, - 0x0dbd986c4adf7L }, - { 0xa881415f39eb7L,0xf5b98d976c81aL,0xf2f717d6ee2fcL,0xbbd05465475dcL, - 0x08e24d3c46860L } }, - /* 171 */ - { { 0xd8e549a587390L,0x4f0cbec588749L,0x25983c612bb19L,0xafc846e07da4bL, - 0x0541a99c4407bL }, - { 0x41692624c8842L,0x2ad86c05ffdb2L,0xf7fcf626044c1L,0x35d1c59d14b44L, - 0x0c0092c49f57dL } }, - /* 172 */ - { { 0xc75c3df2e61efL,0xc82e1b35cad3cL,0x09f29f47e8841L,0x944dc62d30d19L, - 0x075e406347286L }, - { 0x41fc5bbc237d0L,0xf0ec4f01c9e7dL,0x82bd534c9537bL,0x858691c51a162L, - 0x05b7cb658c784L } }, - /* 173 */ - { { 0xa70848a28ead1L,0x08fd3b47f6964L,0x67e5b39802dc5L,0x97a19ae4bfd17L, - 0x07ae13eba8df0L }, - { 0x16ef8eadd384eL,0xd9b6b2ff06fd2L,0xbcdb5f30361a2L,0xe3fd204b98784L, - 0x0787d8074e2a8L } }, - /* 174 */ - { { 0x25d6b757fbb1cL,0xb2ca201debc5eL,0xd2233ffe47bddL,0x84844a55e9a36L, - 0x05c2228199ef2L }, - { 0xd4a8588315250L,0x2b827097c1773L,0xef5d33f21b21aL,0xf2b0ab7c4ea1dL, - 0x0e45d37abbaf0L } }, - /* 175 */ - { { 0xf1e3428511c8aL,0xc8bdca6cd3d2dL,0x27c39a7ebb229L,0xb9d3578a71a76L, - 0x0ed7bc12284dfL }, - { 0x2a6df93dea561L,0x8dd48f0ed1cf2L,0xbad23e85443f1L,0x6d27d8b861405L, - 0x0aac97cc945caL } }, - /* 176 */ - { { 0x4ea74a16bd00aL,0xadf5c0bcc1eb5L,0xf9bfc06d839e9L,0xdc4e092bb7f11L, - 0x0318f97b31163L }, - { 0x0c5bec30d7138L,0x23abc30220eccL,0x022360644e8dfL,0xff4d2bb7972fbL, - 0x0fa41faa19a84L } }, - /* 177 */ - { { 0x2d974a6642269L,0xce9bb783bd440L,0x941e60bc81814L,0xe9e2398d38e47L, - 0x038bb6b2c1d26L }, - { 0xe4a256a577f87L,0x53dc11fe1cc64L,0x22807288b52d2L,0x01a5ff336abf6L, - 0x094dd0905ce76L } }, - /* 178 */ - { { 0xcf7dcde93f92aL,0xcb89b5f315156L,0x995e750a01333L,0x2ae902404df9cL, - 0x092077867d25cL }, - { 0x71e010bf39d44L,0x2096bb53d7e24L,0xc9c3d8f5f2c90L,0xeb514c44b7b35L, - 0x081e8428bd29bL } }, - /* 179 */ - { { 0x9c2bac477199fL,0xee6b5ecdd96ddL,0xe40fd0e8cb8eeL,0xa4b18af7db3feL, - 0x01b94ab62dbbfL }, - { 0x0d8b3ce47f143L,0xfc63f4616344fL,0xc59938351e623L,0x90eef18f270fcL, - 0x006a38e280555L } }, - /* 180 */ - { { 0xb0139b3355b49L,0x60b4ebf99b2e5L,0x269f3dc20e265L,0xd4f8c08ffa6bdL, - 0x0a7b36c2083d9L }, - { 0x15c3a1b3e8830L,0xe1a89f9c0b64dL,0x2d16930d5fceaL,0x2a20cfeee4a2eL, - 0x0be54c6b4a282L } }, - /* 181 */ - { { 0xdb3df8d91167cL,0x79e7a6625ed6cL,0x46ac7f4517c3fL,0x22bb7105648f3L, - 0x0bf30a5abeae0L }, - { 0x785be93828a68L,0x327f3ef0368e7L,0x92146b25161c3L,0xd13ae11b5feb5L, - 0x0d1c820de2732L } }, - /* 182 */ - { { 0xe13479038b363L,0x546b05e519043L,0x026cad158c11fL,0x8da34fe57abe6L, - 0x0b7d17bed68a1L }, - { 0xa5891e29c2559L,0x765bfffd8444cL,0x4e469484f7a03L,0xcc64498de4af7L, - 0x03997fd5e6412L } }, - /* 183 */ - { { 0x746828bd61507L,0xd534a64d2af20L,0xa8a15e329e132L,0x13e8ffeddfb08L, - 0x00eeb89293c6cL }, - { 0x69a3ea7e259f8L,0xe6d13e7e67e9bL,0xd1fa685ce1db7L,0xb6ef277318f6aL, - 0x0228916f8c922L } }, - /* 184 */ - { { 0xae25b0a12ab5bL,0x1f957bc136959L,0x16e2b0ccc1117L,0x097e8058429edL, - 0x0ec05ad1d6e93L }, - { 0xba5beac3f3708L,0x3530b59d77157L,0x18234e531baf9L,0x1b3747b552371L, - 0x07d3141567ff1L } }, - /* 185 */ - { { 0x9c05cf6dfefabL,0x68dcb377077bdL,0xa38bb95be2f22L,0xd7a3e53ead973L, - 0x0e9ce66fc9bc1L }, - { 0xa15766f6a02a1L,0xdf60e600ed75aL,0x8cdc1b938c087L,0x0651f8947f346L, - 0x0d9650b017228L } }, - /* 186 */ - { { 0xb4c4a5a057e60L,0xbe8def25e4504L,0x7c1ccbdcbccc3L,0xb7a2a63532081L, - 0x014d6699a804eL }, - { 0xa8415db1f411aL,0x0bf80d769c2c8L,0xc2f77ad09fbafL,0x598ab4deef901L, - 0x06f4c68410d43L } }, - /* 187 */ - { { 0x6df4e96c24a96L,0x85fcbd99a3872L,0xb2ae30a534dbcL,0x9abb3c466ef28L, - 0x04c4350fd6118L }, - { 0x7f716f855b8daL,0x94463c38a1296L,0xae9334341a423L,0x18b5c37e1413eL, - 0x0a726d2425a31L } }, - /* 188 */ - { { 0x6b3ee948c1086L,0x3dcbd3a2e1daeL,0x3d022f3f1de50L,0xf3923f35ed3f0L, - 0x013639e82cc6cL }, - { 0x938fbcdafaa86L,0xfb2654a2589acL,0x5051329f45bc5L,0x35a31963b26e4L, - 0x0ca9365e1c1a3L } }, - /* 189 */ - { { 0x5ac754c3b2d20L,0x17904e241b361L,0xc9d071d742a54L,0x72a5b08521c4cL, - 0x09ce29c34970bL }, - { 0x81f736d3e0ad6L,0x9ef2f8434c8ccL,0xce862d98060daL,0xaf9835ed1d1a6L, - 0x048c4abd7ab42L } }, - /* 190 */ - { { 0x1b0cc40c7485aL,0xbbe5274dbfd22L,0x263d2e8ead455L,0x33cb493c76989L, - 0x078017c32f67bL }, - { 0x35769930cb5eeL,0x940c408ed2b9dL,0x72f1a4dc0d14eL,0x1c04f8b7bf552L, - 0x053cd0454de5cL } }, - /* 191 */ - { { 0x585fa5d28ccacL,0x56005b746ebcdL,0xd0123aa5f823eL,0xfa8f7c79f0a1cL, - 0x0eea465c1d3d7L }, - { 0x0659f0551803bL,0x9f7ce6af70781L,0x9288e706c0b59L,0x91934195a7702L, - 0x01b6e42a47ae6L } }, - /* 192 */ - { { 0x0937cf67d04c3L,0xe289eeb8112e8L,0x2594d601e312bL,0xbd3d56b5d8879L, - 0x00224da14187fL }, - { 0xbb8630c5fe36fL,0x604ef51f5f87aL,0x3b429ec580f3cL,0xff33964fb1bfbL, - 0x060838ef042bfL } }, - /* 193 */ - { { 0xcb2f27e0bbe99L,0xf304aa39ee432L,0xfa939037bda44L,0x16435f497c7a9L, - 0x0636eb2022d33L }, - { 0xd0e6193ae00aaL,0xfe31ae6d2ffcfL,0xf93901c875a00L,0x8bacf43658a29L, - 0x08844eeb63921L } }, - /* 194 */ - { { 0x171d26b3bae58L,0x7117e39f3e114L,0x1a8eada7db3dfL,0x789ecd37bc7f8L, - 0x027ba83dc51fbL }, - { 0xf439ffbf54de5L,0x0bb5fe1a71a7dL,0xb297a48727703L,0xa4ab42ee8e35dL, - 0x0adb62d3487f3L } }, - /* 195 */ - { { 0x168a2a175df2aL,0x4f618c32e99b1L,0x46b0916082aa0L,0xc8b2c9e4f2e71L, - 0x0b990fd7675e7L }, - { 0x9d96b4df37313L,0x79d0b40789082L,0x80877111c2055L,0xd18d66c9ae4a7L, - 0x081707ef94d10L } }, - /* 196 */ - { { 0x7cab203d6ff96L,0xfc0d84336097dL,0x042db4b5b851bL,0xaa5c268823c4dL, - 0x03792daead5a8L }, - { 0x18865941afa0bL,0x4142d83671528L,0xbe4e0a7f3e9e7L,0x01ba17c825275L, - 0x05abd635e94b0L } }, - /* 197 */ - { { 0xfa84e0ac4927cL,0x35a7c8cf23727L,0xadca0dfe38860L,0xb610a4bcd5ea4L, - 0x05995bf21846aL }, - { 0xf860b829dfa33L,0xae958fc18be90L,0x8630366caafe2L,0x411e9b3baf447L, - 0x044c32ca2d483L } }, - /* 198 */ - { { 0xa97f1e40ed80cL,0xb131d2ca82a74L,0xc2d6ad95f938cL,0xa54c53f2124b7L, - 0x01f2162fb8082L }, - { 0x67cc5720b173eL,0x66085f12f97e4L,0xc9d65dc40e8a6L,0x07c98cebc20e4L, - 0x08f1d402bc3e9L } }, - /* 199 */ - { { 0x92f9cfbc4058aL,0xb6292f56704f5L,0xc1d8c57b15e14L,0xdbf9c55cfe37bL, - 0x0b1980f43926eL }, - { 0x33e0932c76b09L,0x9d33b07f7898cL,0x63bb4611df527L,0x8e456f08ead48L, - 0x02828ad9b3744L } }, - /* 200 */ - { { 0x722c4c4cf4ac5L,0x3fdde64afb696L,0x0890832f5ac1aL,0xb3900551baa2eL, - 0x04973f1275a14L }, - { 0xd8335322eac5dL,0xf50bd9b568e59L,0x25883935e07eeL,0x8ac7ab36720faL, - 0x06dac8ed0db16L } }, - /* 201 */ - { { 0x545aeeda835efL,0xd21d10ed51f7bL,0x3741b094aa113L,0xde4c035a65e01L, - 0x04b23ef5920b9L }, - { 0xbb6803c4c7341L,0x6d3f58bc37e82L,0x51e3ee8d45770L,0x9a4e73527863aL, - 0x04dd71534ddf4L } }, - /* 202 */ - { { 0x4467295476cd9L,0x2fe31a725bbf9L,0xc4b67e0648d07L,0x4dbb1441c8b8fL, - 0x0fd3170002f4aL }, - { 0x43ff48995d0e1L,0xd10ef729aa1cbL,0x179898276e695L,0xf365e0d5f9764L, - 0x014fac58c9569L } }, - /* 203 */ - { { 0xa0065f312ae18L,0xc0fcc93fc9ad9L,0xa7d284651958dL,0xda50d9a142408L, - 0x0ed7c765136abL }, - { 0x70f1a25d4abbcL,0xf3f1a113ea462L,0xb51952f9b5dd8L,0x9f53c609b0755L, - 0x0fefcb7f74d2eL } }, - /* 204 */ - { { 0x9497aba119185L,0x30aac45ba4bd0L,0xa521179d54e8cL,0xd80b492479deaL, - 0x01801a57e87e0L }, - { 0xd3f8dfcafffb0L,0x0bae255240073L,0xb5fdfbc6cf33cL,0x1064781d763b5L, - 0x09f8fc11e1eadL } }, - /* 205 */ - { { 0x3a1715e69544cL,0x67f04b7813158L,0x78a4c320eaf85L,0x69a91e22a8fd2L, - 0x0a9d3809d3d3aL }, - { 0xc2c2c59a2da3bL,0xf61895c847936L,0x3d5086938ccbcL,0x8ef75e65244e6L, - 0x03006b9aee117L } }, - /* 206 */ - { { 0x1f2b0c9eead28L,0x5d89f4dfbc0bbL,0x2ce89397eef63L,0xf761074757fdbL, - 0x00ab85fd745f8L }, - { 0xa7c933e5b4549L,0x5c97922f21ecdL,0x43b80404be2bbL,0x42c2261a1274bL, - 0x0b122d67511e9L } }, - /* 207 */ - { { 0x607be66a5ae7aL,0xfa76adcbe33beL,0xeb6e5c501e703L,0xbaecaf9043014L, - 0x09f599dc1097dL }, - { 0x5b7180ff250edL,0x74349a20dc6d7L,0x0b227a38eb915L,0x4b78425605a41L, - 0x07d5528e08a29L } }, - /* 208 */ - { { 0x58f6620c26defL,0xea582b2d1ef0fL,0x1ce3881025585L,0x1730fbe7d79b0L, - 0x028ccea01303fL }, - { 0xabcd179644ba5L,0xe806fff0b8d1dL,0x6b3e17b1fc643L,0x13bfa60a76fc6L, - 0x0c18baf48a1d0L } }, - /* 209 */ - { { 0x638c85dc4216dL,0x67206142ac34eL,0x5f5064a00c010L,0x596bd453a1719L, - 0x09def809db7a9L }, - { 0x8642e67ab8d2cL,0x336237a2b641eL,0x4c4218bb42404L,0x8ce57d506a6d6L, - 0x00357f8b06880L } }, - /* 210 */ - { { 0xdbe644cd2cc88L,0x8df0b8f39d8e9L,0xd30a0c8cc61c2L,0x98874a309874cL, - 0x0e4a01add1b48L }, - { 0x1eeacf57cd8f9L,0x3ebd594c482edL,0xbd2f7871b767dL,0xcc30a7295c717L, - 0x0466d7d79ce10L } }, - /* 211 */ - { { 0x318929dada2c7L,0xc38f9aa27d47dL,0x20a59e14fa0a6L,0xad1a90e4fd288L, - 0x0c672a522451eL }, - { 0x07cc85d86b655L,0x3bf9ad4af1306L,0x71172a6f0235dL,0x751399a086805L, - 0x05e3d64faf2a6L } }, - /* 212 */ - { { 0x410c79b3b4416L,0x85eab26d99aa6L,0xb656a74cd8fcfL,0x42fc5ebff74adL, - 0x06c8a7a95eb8eL }, - { 0x60ba7b02a63bdL,0x038b8f004710cL,0x12d90b06b2f23L,0xca918c6c37383L, - 0x0348ae422ad82L } }, - /* 213 */ - { { 0x746635ccda2fbL,0xa18e0726d27f4L,0x92b1f2022accaL,0x2d2e85adf7824L, - 0x0c1074de0d9efL }, - { 0x3ce44ae9a65b3L,0xac05d7151bfcfL,0xe6a9788fd71e4L,0x4ffcd4711f50cL, - 0x0fbadfbdbc9e5L } }, - /* 214 */ - { { 0x3f1cd20a99363L,0x8f6cf22775171L,0x4d359b2b91565L,0x6fcd968175cd2L, - 0x0b7f976b48371L }, - { 0x8e24d5d6dbf74L,0xfd71c3af36575L,0x243dfe38d23baL,0xc80548f477600L, - 0x0f4d41b2ecafcL } }, - /* 215 */ - { { 0x1cf28fdabd48dL,0x3632c078a451fL,0x17146e9ce81beL,0x0f106ace29741L, - 0x0180824eae016L }, - { 0x7698b66e58358L,0x52ce6ca358038L,0xe41e6c5635687L,0x6d2582380e345L, - 0x067e5f63983cfL } }, - /* 216 */ - { { 0xccb8dcf4899efL,0xf09ebb44c0f89L,0x2598ec9949015L,0x1fc6546f9276bL, - 0x09fef789a04c1L }, - { 0x67ecf53d2a071L,0x7fa4519b096d3L,0x11e2eefb10e1aL,0x4e20ca6b3fb06L, - 0x0bc80c181a99cL } }, - /* 217 */ - { { 0x536f8e5eb82e6L,0xc7f56cb920972L,0x0b5da5e1a484fL,0xdf10c78e21715L, - 0x049270e629f8cL }, - { 0x9b7bbea6b50adL,0xc1a2388ffc1a3L,0x107197b9a0284L,0x2f7f5403eb178L, - 0x0d2ee52f96137L } }, - /* 218 */ - { { 0xcd28588e0362aL,0xa78fa5d94dd37L,0x434a526442fa8L,0xb733aff836e5aL, - 0x0dfb478bee5abL }, - { 0xf1ce7673eede6L,0xd42b5b2f04a91L,0x530da2fa5390aL,0x473a5e66f7bf5L, - 0x0d9a140b408dfL } }, - /* 219 */ - { { 0x221b56e8ea498L,0x293563ee090e0L,0x35d2ade623478L,0x4b1ae06b83913L, - 0x0760c058d623fL }, - { 0x9b58cc198aa79L,0xd2f07aba7f0b8L,0xde2556af74890L,0x04094e204110fL, - 0x07141982d8f19L } }, - /* 220 */ - { { 0xa0e334d4b0f45L,0x38392a94e16f0L,0x3c61d5ed9280bL,0x4e473af324c6bL, - 0x03af9d1ce89d5L }, - { 0xf798120930371L,0x4c21c17097fd8L,0xc42309beda266L,0x7dd60e9545dcdL, - 0x0b1f815c37395L } }, - /* 221 */ - { { 0xaa78e89fec44aL,0x473caa4caf84fL,0x1b6a624c8c2aeL,0xf052691c807dcL, - 0x0a41aed141543L }, - { 0x353997d5ffe04L,0xdf625b6e20424L,0x78177758bacb2L,0x60ef85d660be8L, - 0x0d6e9c1dd86fbL } }, - /* 222 */ - { { 0x2e97ec6853264L,0xb7e2304a0b3aaL,0x8eae9be771533L,0xf8c21b912bb7bL, - 0x09c9c6e10ae9bL }, - { 0x09a59e030b74cL,0x4d6a631e90a23L,0x49b79f24ed749L,0x61b689f44b23aL, - 0x0566bd59640faL } }, - /* 223 */ - { { 0xc0118c18061f3L,0xd37c83fc70066L,0x7273245190b25L,0x345ef05fc8e02L, - 0x0cf2c7390f525L }, - { 0xbceb410eb30cfL,0xba0d77703aa09L,0x50ff255cfd2ebL,0x0979e842c43a1L, - 0x002f517558aa2L } }, - /* 224 */ - { { 0xef794addb7d07L,0x4224455500396L,0x78aa3ce0b4fc7L,0xd97dfaff8eaccL, - 0x014e9ada5e8d4L }, - { 0x480a12f7079e2L,0xcde4b0800edaaL,0x838157d45baa3L,0x9ae801765e2d7L, - 0x0a0ad4fab8e9dL } }, - /* 225 */ - { { 0xb76214a653618L,0x3c31eaaa5f0bfL,0x4949d5e187281L,0xed1e1553e7374L, - 0x0bcd530b86e56L }, - { 0xbe85332e9c47bL,0xfeb50059ab169L,0x92bfbb4dc2776L,0x341dcdba97611L, - 0x0909283cf6979L } }, - /* 226 */ - { { 0x0032476e81a13L,0x996217123967bL,0x32e19d69bee1aL,0x549a08ed361bdL, - 0x035eeb7c9ace1L }, - { 0x0ae5a7e4e5bdcL,0xd3b6ceec6e128L,0xe266bc12dcd2cL,0xe86452e4224c6L, - 0x09a8b2cf4448aL } }, - /* 227 */ - { { 0x71bf209d03b59L,0xa3b65af2abf64L,0xbd5eec9c90e62L,0x1379ff7ff168eL, - 0x06bdb60f4d449L }, - { 0xafebc8a55bc30L,0x1610097fe0dadL,0xc1e3bddc79eadL,0x08a942e197414L, - 0x001ec3cfd94baL } }, - /* 228 */ - { { 0x277ebdc9485c2L,0x7922fb10c7ba6L,0x0a28d8a48cc9aL,0x64f64f61d60f7L, - 0x0d1acb1c04754L }, - { 0x902b126f36612L,0x4ee0618d8bd26L,0x08357ee59c3a4L,0x26c24df8a8133L, - 0x07dcd079d4056L } }, - /* 229 */ - { { 0x7d4d3f05a4b48L,0x52372307725ceL,0x12a915aadcd29L,0x19b8d18f79718L, - 0x00bf53589377dL }, - { 0xcd95a6c68ea73L,0xca823a584d35eL,0x473a723c7f3bbL,0x86fc9fb674c6fL, - 0x0d28be4d9e166L } }, - /* 230 */ - { { 0xb990638fa8e4bL,0x6e893fd8fc5d2L,0x36fb6fc559f18L,0x88ce3a6de2aa4L, - 0x0d76007aa510fL }, - { 0x0aab6523a4988L,0x4474dd02732d1L,0x3407278b455cfL,0xbb017f467082aL, - 0x0f2b52f68b303L } }, - /* 231 */ - { { 0x7eafa9835b4caL,0xfcbb669cbc0d5L,0x66431982d2232L,0xed3a8eeeb680cL, - 0x0d8dbe98ecc5aL }, - { 0x9be3fc5a02709L,0xe5f5ba1fa8cbaL,0x10ea85230be68L,0x9705febd43cdfL, - 0x0e01593a3ee55L } }, - /* 232 */ - { { 0x5af50ea75a0a6L,0xac57858033d3eL,0x0176406512226L,0xef066fe6d50fdL, - 0x0afec07b1aeb8L }, - { 0x9956780bb0a31L,0xcc37309aae7fbL,0x1abf3896f1af3L,0xbfdd9153a15a0L, - 0x0a71b93546e2dL } }, - /* 233 */ - { { 0xe12e018f593d2L,0x28a078122bbf8L,0xba4f2add1a904L,0x23d9150505db0L, - 0x053a2005c6285L }, - { 0x8b639e7f2b935L,0x5ac182961a07cL,0x518ca2c2bff97L,0x8e3d86bceea77L, - 0x0bf47d19b3d58L } }, - /* 234 */ - { { 0x967a7dd7665d5L,0x572f2f4de5672L,0x0d4903f4e3030L,0xa1b6144005ae8L, - 0x0001c2c7f39c9L }, - { 0xa801469efc6d6L,0xaa7bc7a724143L,0x78150a4c810bdL,0xb99b5f65670baL, - 0x0fdadf8e786ffL } }, - /* 235 */ - { { 0x8cb88ffc00785L,0x913b48eb67fd3L,0xf368fbc77fa75L,0x3c940454d055bL, - 0x03a838e4d5aa4L }, - { 0x663293e97bb9aL,0x63441d94d9561L,0xadb2a839eb933L,0x1da3515591a60L, - 0x03cdb8257873eL } }, - /* 236 */ - { { 0x140a97de77eabL,0x0d41648109137L,0xeb1d0dff7e1c5L,0x7fba762dcad2cL, - 0x05a60cc89f1f5L }, - { 0x3638240d45673L,0x195913c65580bL,0xd64b7411b82beL,0x8fc0057284b8dL, - 0x0922ff56fdbfdL } }, - /* 237 */ - { { 0x65deec9a129a1L,0x57cc284e041b2L,0xebfbe3ca5b1ceL,0xcd6204380c46cL, - 0x072919a7df6c5L }, - { 0xf453a8fb90f9aL,0x0b88e4031b298L,0x96f1856d719c0L,0x089ae32c0e777L, - 0x05e7917803624L } }, - /* 238 */ - { { 0x6ec557f63cdfbL,0x71f1cae4fd5c1L,0x60597ca8e6a35L,0x2fabfce26bea5L, - 0x04e0a5371e24cL }, - { 0xa40d3a5765357L,0x440d73a2b4276L,0x1d11a323c89afL,0x04eeb8f370ae4L, - 0x0f5ff7818d566L } }, - /* 239 */ - { { 0x3e3fe1a09df21L,0x8ee66e8e47fbfL,0x9c8901526d5d2L,0x5e642096bd0a2L, - 0x0e41df0e9533fL }, - { 0xfda40b3ba9e3fL,0xeb2604d895305L,0xf0367c7f2340cL,0x155f0866e1927L, - 0x08edd7d6eac4fL } }, - /* 240 */ - { { 0x1dc0e0bfc8ff3L,0x2be936f42fc9aL,0xca381ef14efd8L,0xee9667016f7ccL, - 0x01432c1caed8aL }, - { 0x8482970b23c26L,0x730735b273ec6L,0xaef0f5aa64fe8L,0xd2c6e389f6e5eL, - 0x0caef480b5ac8L } }, - /* 241 */ - { { 0x5c97875315922L,0x713063cca5524L,0x64ef2cbd82951L,0xe236f3ce60d0bL, - 0x0d0ba177e8efaL }, - { 0x9ae8fb1b3af60L,0xe53d2da20e53aL,0xf9eef281a796aL,0xae1601d63605dL, - 0x0f31c957c1c54L } }, - /* 242 */ - { { 0x58d5249cc4597L,0xb0bae0a028c0fL,0x34a814adc5015L,0x7c3aefc5fc557L, - 0x0013404cb96e1L }, - { 0xe2585c9a824bfL,0x5e001eaed7b29L,0x1ef68acd59318L,0x3e6c8d6ee6826L, - 0x06f377c4b9193L } }, - /* 243 */ - { { 0x3bad1a8333fd2L,0x025a2a95b89f9L,0xaf75acea89302L,0x9506211e5037eL, - 0x06dba3e4ed2d0L }, - { 0xef98cd04399cdL,0x6ee6b73adea48L,0x17ecaf31811c6L,0xf4a772f60752cL, - 0x0f13cf3423becL } }, - /* 244 */ - { { 0xb9ec0a919e2ebL,0x95f62c0f68ceeL,0xaba229983a9a1L,0xbad3cfba3bb67L, - 0x0c83fa9a9274bL }, - { 0xd1b0b62fa1ce0L,0xf53418efbf0d7L,0x2706f04e58b60L,0x2683bfa8ef9e5L, - 0x0b49d70f45d70L } }, - /* 245 */ - { { 0xc7510fad5513bL,0xecb1751e2d914L,0x9fb9d5905f32eL,0xf1cf6d850418dL, - 0x059cfadbb0c30L }, - { 0x7ac2355cb7fd6L,0xb8820426a3e16L,0x0a78864249367L,0x4b67eaeec58c9L, - 0x05babf362354aL } }, - /* 246 */ - { { 0x981d1ee424865L,0x78f2e5577f37cL,0x9e0c0588b0028L,0xc8f0702970f1bL, - 0x06188c6a79026L }, - { 0x9a19bd0f244daL,0x5cfb08087306fL,0xf2136371eccedL,0xb9d935470f9b9L, - 0x0993fe475df50L } }, - /* 247 */ - { { 0x31cdf9b2c3609L,0xc02c46d4ea68eL,0xa77510184eb19L,0x616b7ac9ec1a9L, - 0x081f764664c80L }, - { 0xc2a5a75fbe978L,0xd3f183b3561d7L,0x01dd2bf6743feL,0x060d838d1f045L, - 0x0564a812a5fe9L } }, - /* 248 */ - { { 0xa64f4fa817d1dL,0x44bea82e0f7a5L,0xd57f9aa55f968L,0x1d6cb5ff5a0fcL, - 0x0226bf3cf00e5L }, - { 0x1a9f92f2833cfL,0x5a4f4f89a8d6dL,0xf3f7f7720a0a3L,0x783611536c498L, - 0x068779f47ff25L } }, - /* 249 */ - { { 0x0c1c173043d08L,0x741fc020fa79bL,0xa6d26d0a54467L,0x2e0bd3767e289L, - 0x097bcb0d1eb09L }, - { 0x6eaa8f32ed3c3L,0x51b281bc482abL,0xfa178f3c8a4f1L,0x46554d1bf4f3bL, - 0x0a872ffe80a78L } }, - /* 250 */ - { { 0xb7935a32b2086L,0x0e8160f486b1aL,0xb6ae6bee1eb71L,0xa36a9bd0cd913L, - 0x002812bfcb732L }, - { 0xfd7cacf605318L,0x50fdfd6d1da63L,0x102d619646e5dL,0x96afa1d683982L, - 0x007391cc9fe53L } }, - /* 251 */ - { { 0x157f08b80d02bL,0xd162877f7fc50L,0x8d542ae6b8333L,0x2a087aca1af87L, - 0x0355d2adc7e6dL }, - { 0xf335a287386e1L,0x94f8e43275b41L,0x79989eafd272aL,0x3a79286ca2cdeL, - 0x03dc2b1e37c2aL } }, - /* 252 */ - { { 0x9d21c04581352L,0x25376782bed68L,0xfed701f0a00c8L,0x846b203bd5909L, - 0x0c47869103ccdL }, - { 0xa770824c768edL,0x026841f6575dbL,0xaccce0e72feeaL,0x4d3273313ed56L, - 0x0ccc42968d5bbL } }, - /* 253 */ - { { 0x50de13d7620b9L,0x8a5992a56a94eL,0x75487c9d89a5cL,0x71cfdc0076406L, - 0x0e147eb42aa48L }, - { 0xab4eeacf3ae46L,0xfb50350fbe274L,0x8c840eafd4936L,0x96e3df2afe474L, - 0x0239ac047080eL } }, - /* 254 */ - { { 0xd1f352bfee8d4L,0xcffa7b0fec481L,0xce9af3cce80b5L,0xe59d105c4c9e2L, - 0x0c55fa1a3f5f7L }, - { 0x6f14e8257c227L,0x3f342be00b318L,0xa904fb2c5b165L,0xb69909afc998aL, - 0x0094cd99cd4f4L } }, - /* 255 */ - { { 0x81c84d703bebaL,0x5032ceb2918a9L,0x3bd49ec8631d1L,0xad33a445f2c9eL, - 0x0b90a30b642abL }, - { 0x5404fb4a5abf9L,0xc375db7603b46L,0xa35d89f004750L,0x24f76f9a42cccL, - 0x0019f8b9a1b79L } }, -}; - -/* 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. - * 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_256_ecc_mulmod_base_5(sp_point_256* r, const sp_digit* k, - int map, int ct, void* heap) -{ - return sp_256_ecc_mulmod_stripe_5(r, &p256_base, p256_table, - k, map, ct, heap); -} - -#endif - -/* Multiply the base point of P256 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_256(const mp_int* km, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_256, point, 1); - SP_DECL_VAR(sp_digit, k, 5); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 5, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(k, 5, km); - - err = sp_256_ecc_mulmod_base_5(point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_5(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_256, point, 2); - SP_DECL_VAR(sp_digit, k, 5 + 5 * 2 * 6); - sp_point_256* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 5 + 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ -#ifndef WC_NO_RNG -/* Add 1 to a. (a = a + 1) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_add_one_5(sp_digit* a) -{ - a[0]++; - sp_256_norm_5(a); -} - -#endif -/* 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_256_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 >= 44U) { - r[j] &= 0xfffffffffffffL; - s = 52U - 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; - } -} - -/* Generates a scalar that is in the range 1..order-1. - * - * rng Random number generator. - * k Scalar value. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. - */ -static int sp_256_ecc_gen_k_5(WC_RNG* rng, sp_digit* k) -{ -#ifndef WC_NO_RNG - int err; - byte buf[32]; - - do { - err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); - if (err == 0) { - sp_256_from_bin(k, 5, buf, (int)sizeof(buf)); - if (sp_256_cmp_5(k, p256_order2) <= 0) { - sp_256_add_one_5(k); - break; - } - } - } - while (err == 0); - - return err; -#else - (void)rng; - (void)k; - return NOT_COMPILED_IN; -#endif -} - -/* Makes a random EC key pair. - * - * rng Random number generator. - * priv Generated private value. - * pub Generated public point. - * heap Heap to use for allocation. - * returns ECC_INF_E when the point does not have the correct order, RNG - * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) -{ -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_DECL_VAR(sp_point_256, point, 2); -#else - SP_DECL_VAR(sp_point_256, point, 1); -#endif - SP_DECL_VAR(sp_digit, k, 5); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256* infinity = NULL; -#endif - int err = MP_OKAY; - - - (void)heap; - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_ALLOC_VAR(sp_point_256, point, 2, heap, DYNAMIC_TYPE_ECC); -#else - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); -#endif - SP_ALLOC_VAR(sp_digit, k, 5, heap, DYNAMIC_TYPE_ECC); - 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) { - err = sp_256_ecc_mulmod_base_5(point, k, 1, 1, NULL); - } - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_5(infinity, point, p256_order, 1, 1, NULL); - } - if (err == MP_OKAY) { - if (sp_256_iszero_5(point->x) || sp_256_iszero_5(point->y)) { - err = ECC_INF_E; - } - } -#endif - - if (err == MP_OKAY) { - err = sp_256_to_mp(k, priv); - } - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_5(point, pub); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - /* point is not sensitive, so no need to zeroize */ - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_key_gen_256_ctx { - int state; - sp_256_ecc_mulmod_5_ctx mulmod_ctx; - sp_digit k[5]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 point[2]; -#else - sp_point_256 point[1]; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ -} sp_ecc_key_gen_256_ctx; - -int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, - ecc_point* pub, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256* infinity = ctx->point + 1; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - - typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) - >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - err = sp_256_ecc_gen_k_5(rng, ctx->k); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - ctx->state = 1; - } - break; - case 1: - err = sp_256_ecc_mulmod_base_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - #else - ctx->state = 3; - #endif - } - break; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - case 2: - err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p256_order, 1, 1); - if (err == MP_OKAY) { - if (sp_256_iszero_5(ctx->point->x) || - sp_256_iszero_5(ctx->point->y)) { - err = ECC_INF_E; - } - else { - err = FP_WOULDBLOCK; - ctx->state = 3; - } - } - break; - #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - case 3: - err = sp_256_to_mp(ctx->k, priv); - if (err == MP_OKAY) { - err = sp_256_point_to_ecc_point_5(ctx->point, pub); - } - break; - } - - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#ifdef HAVE_ECC_DHE -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 32 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_256_to_bin_5(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<4; i++) { - r[i+1] += r[i] >> 52; - r[i] &= 0xfffffffffffffL; - } - j = 263 / 8 - 1; - a[j] = 0; - for (i=0; i<5 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 52) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 52); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Multiply the point by the scalar and serialize the X ordinate. - * The number is 0 padded to maximum size on output. - * - * priv Scalar to multiply the point by. - * pub Point to multiply. - * out Buffer to hold X ordinate. - * outLen On entry, size of the buffer in bytes. - * On exit, length of data in buffer in bytes. - * heap Heap to use for allocation. - * 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(const mp_int* priv, const ecc_point* pub, byte* out, - word32* outLen, void* heap) -{ - SP_DECL_VAR(sp_point_256, point, 1); - SP_DECL_VAR(sp_digit, k, 5); - int err = MP_OKAY; - - if (*outLen < 32U) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 5, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_256_from_mp(k, 5, priv); - sp_256_point_from_ecc_point_5(point, pub); - err = sp_256_ecc_mulmod_5(point, point, k, 1, 1, heap); - } - if (err == MP_OKAY) { - sp_256_to_bin_5(point->x, out); - *outLen = 32; - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sec_gen_256_ctx { - int state; - union { - sp_256_ecc_mulmod_5_ctx mulmod_ctx; - }; - sp_digit k[5]; - sp_point_256 point; -} sp_ecc_sec_gen_256_ctx; - -int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, - const ecc_point* pub, byte* out, word32* outLen, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - if (*outLen < 32U) { - err = BUFFER_E; - } - - switch (ctx->state) { - case 0: - sp_256_from_mp(ctx->k, 5, priv); - sp_256_point_from_ecc_point_5(&ctx->point, pub); - ctx->state = 1; - break; - case 1: - err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - sp_256_to_bin_5(ctx->point.x, out); - *outLen = 32; - } - break; - } - - if (err == MP_OKAY && ctx->state != 1) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_DHE */ - -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -SP_NOINLINE static void sp_256_rshift_5(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<4; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (52 - n))) & 0xfffffffffffffL); - } -#else - for (i=0; i<0; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (52 - n)) & 0xfffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (52 - n)) & 0xfffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (52 - n)) & 0xfffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (52 - n)) & 0xfffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (52 - n)) & 0xfffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (52 - n)) & 0xfffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (52 - n)) & 0xfffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (52 - n)) & 0xfffffffffffffL); - } - r[0] = (a[0] >> n) | (sp_digit)((a[1] << (52 - n)) & 0xfffffffffffffL); - r[1] = (a[1] >> n) | (sp_digit)((a[2] << (52 - n)) & 0xfffffffffffffL); - r[2] = (a[2] >> n) | (sp_digit)((a[3] << (52 - n)) & 0xfffffffffffffL); - r[3] = (a[3] >> n) | (sp_digit)((a[4] << (52 - n)) & 0xfffffffffffffL); -#endif /* WOLFSSL_SP_SMALL */ - r[4] = a[4] >> n; -} - -/* 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_256_mul_d_5(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 5; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0xfffffffffffffL); - t >>= 52; - } - r[5] = (sp_digit)t; -#else - sp_int128 tb = b; - sp_int128 t[5]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - r[ 0] = (sp_digit) (t[ 0] & 0xfffffffffffffL); - r[ 1] = (sp_digit)((t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffL)); - r[ 2] = (sp_digit)((t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffL)); - r[ 3] = (sp_digit)((t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffL)); - r[ 4] = (sp_digit)((t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffL)); - r[ 5] = (sp_digit) (t[ 4] >> 52); -#endif /* WOLFSSL_SP_SMALL */ -} - -SP_NOINLINE static void sp_256_lshift_10(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[10] = a[9] >> (52 - n); - for (i=9; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (52 - n))) & 0xfffffffffffffL); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[9]; - r[10] = s >> (52U - n); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (52U - n))) & 0xfffffffffffffUL); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0xfffffffffffffL); -} - -/* 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. - * - * Simplified based on top word of divisor being very large. - * - * 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, - const sp_digit* m, sp_digit* r) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 5 + 3); - int i; - sp_digit r1; - sp_digit mask; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 5 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 10 + 1; - sd = t2 + 5 + 1; - - sp_256_mul_d_5(sd, d, (sp_digit)1 << 4); - sp_256_lshift_10(t1, a, 4); - t1[5 + 5] += t1[5 + 5 - 1] >> 52; - t1[5 + 5 - 1] &= 0xfffffffffffffL; - for (i=4; i>=0; i--) { - r1 = t1[5 + i]; - sp_256_mul_d_5(t2, sd, r1); - (void)sp_256_sub_5(&t1[i], &t1[i], t2); - t1[5 + i] -= t2[5]; - sp_256_norm_5(&t1[i + 1]); - - r1 = t1[5 + i]; - sp_256_mul_d_5(t2, sd, r1); - (void)sp_256_sub_5(&t1[i], &t1[i], t2); - t1[5 + i] -= t2[5]; - sp_256_norm_5(&t1[i + 1]); - - mask = ~((t1[5 + i] - 1) >> 63); - sp_256_cond_sub_5(t1 + i, t1 + i, sd, mask); - sp_256_norm_5(&t1[i + 1]); - } - sp_256_norm_5(t1); - sp_256_rshift_5(r, t1, 4); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_256_mod_5(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_256_div_5(a, m, NULL, r); -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply two number mod the order of P256 curve. (r = a * b mod order) - * - * r Result of the multiplication. - * a First operand of the multiplication. - * b Second operand of the multiplication. - */ -static void sp_256_mont_mul_order_5(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_256_mul_5(r, a, b); - sp_256_mont_reduce_order_5(r, p256_order, p256_mp_order); -} - -#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL)) -#ifdef WOLFSSL_SP_SMALL -/* Order-2 for the P256 curve. */ -static const word64 p256_order_minus_2[4] = { - 0xf3b9cac2fc63254fU,0xbce6faada7179e84U,0xffffffffffffffffU, - 0xffffffff00000000U -}; -#else -/* The low half of the order-2 of the P256 curve. */ -static const sp_int_digit p256_order_low[2] = { - 0xf3b9cac2fc63254fU,0xbce6faada7179e84U -}; -#endif /* WOLFSSL_SP_SMALL */ - -/* Square number mod the order of P256 curve. (r = a * a mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_256_mont_sqr_order_5(sp_digit* r, const sp_digit* a) -{ - sp_256_sqr_5(r, a); - sp_256_mont_reduce_order_5(r, p256_order, p256_mp_order); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square number mod the order of P256 curve a number of times. - * (r = a ^ n mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_256_mont_sqr_n_order_5(sp_digit* r, const sp_digit* a, int n) -{ - int i; - - sp_256_mont_sqr_order_5(r, a); - for (i=1; i= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - XMEMCPY(t, a, sizeof(sp_digit) * 5); - ctx->i = 254; - ctx->state = 1; - break; - case 1: - sp_256_mont_sqr_order_5(t, t); - ctx->state = 2; - break; - case 2: - if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { - sp_256_mont_mul_order_5(t, t, a); - } - ctx->i--; - ctx->state = (ctx->i >= 0) ? 1 : 3; - break; - case 3: - XMEMCPY(r, t, sizeof(sp_digit) * 5U); - err = MP_OKAY; - break; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, - sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 5); - for (i=254; i>=0; i--) { - sp_256_mont_sqr_order_5(t, t); - if ((p256_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_256_mont_mul_order_5(t, t, a); - } - } - XMEMCPY(r, t, sizeof(sp_digit) * 5U); -#else - sp_digit* t = td; - sp_digit* t2 = td + 2 * 5; - sp_digit* t3 = td + 4 * 5; - int i; - - /* t = a^2 */ - sp_256_mont_sqr_order_5(t, a); - /* t = a^3 = t * a */ - sp_256_mont_mul_order_5(t, t, a); - /* t2= a^c = t ^ 2 ^ 2 */ - sp_256_mont_sqr_n_order_5(t2, t, 2); - /* t3= a^f = t2 * t */ - sp_256_mont_mul_order_5(t3, t2, t); - /* t2= a^f0 = t3 ^ 2 ^ 4 */ - sp_256_mont_sqr_n_order_5(t2, t3, 4); - /* t = a^ff = t2 * t3 */ - sp_256_mont_mul_order_5(t, t2, t3); - /* t2= a^ff00 = t ^ 2 ^ 8 */ - sp_256_mont_sqr_n_order_5(t2, t, 8); - /* t = a^ffff = t2 * t */ - sp_256_mont_mul_order_5(t, t2, t); - /* t2= a^ffff0000 = t ^ 2 ^ 16 */ - sp_256_mont_sqr_n_order_5(t2, t, 16); - /* t = a^ffffffff = t2 * t */ - sp_256_mont_mul_order_5(t, t2, t); - /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ - sp_256_mont_sqr_n_order_5(t2, t, 64); - /* t2= a^ffffffff00000000ffffffff = t2 * t */ - sp_256_mont_mul_order_5(t2, t2, t); - /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ - sp_256_mont_sqr_n_order_5(t2, t2, 32); - /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ - sp_256_mont_mul_order_5(t2, t2, t); - /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ - sp_256_mont_sqr_order_5(t2, t2); - sp_256_mont_mul_order_5(t2, t2, a); - sp_256_mont_sqr_n_order_5(t2, t2, 5); - sp_256_mont_mul_order_5(t2, t2, t3); - for (i=121; i>=112; i--) { - sp_256_mont_sqr_order_5(t2, t2); - if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_256_mont_mul_order_5(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ - sp_256_mont_sqr_n_order_5(t2, t2, 4); - sp_256_mont_mul_order_5(t2, t2, t3); - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ - for (i=107; i>=64; i--) { - sp_256_mont_sqr_order_5(t2, t2); - if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_256_mont_mul_order_5(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ - sp_256_mont_sqr_n_order_5(t2, t2, 4); - sp_256_mont_mul_order_5(t2, t2, t3); - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ - for (i=59; i>=32; i--) { - sp_256_mont_sqr_order_5(t2, t2); - if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_256_mont_mul_order_5(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ - sp_256_mont_sqr_n_order_5(t2, t2, 4); - sp_256_mont_mul_order_5(t2, t2, t3); - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ - for (i=27; i>=0; i--) { - sp_256_mont_sqr_order_5(t2, t2); - if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_256_mont_mul_order_5(t2, t2, a); - } - } - /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ - sp_256_mont_sqr_n_order_5(t2, t2, 4); - /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ - sp_256_mont_mul_order_5(r, t2, t3); -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */ -#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; - sp_int64 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, - (sp_digit)0 - (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 - * s = (r * x + e) / k mod order - * The hash is truncated to the first 256 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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. - */ -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) -{ - SP_DECL_VAR(sp_digit, e, 7 * 2 * 5); - SP_DECL_VAR(sp_point_256, point, 1); - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, e, 7 * 2 * 5, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - x = e + 2 * 5; - k = e + 4 * 5; - r = e + 6 * 5; - tmp = e + 8 * 5; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_5(rng, k); - } - else { - sp_256_from_mp(k, 5, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_5(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 5U); - sp_256_norm_5(r); - c = sp_256_cmp_5(r, p256_order); - sp_256_cond_sub_5(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_5(r); - - if (!sp_256_iszero_5(r)) { - /* x is modified in calculation of s. */ - sp_256_from_mp(x, 5, priv); - /* s ptr == e ptr, e is modified in calculation of s. */ - sp_256_from_bin(e, 5, hash, (int)hashLen); - - err = sp_256_calc_s_5(s, r, k, x, e, tmp); - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (!sp_256_iszero_5(s))) { - break; - } - } - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - - SP_ZEROFREE_VAR(sp_point_256, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_digit, e, 7 * 2 * 5, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sign_256_ctx { - int state; - union { - sp_256_ecc_mulmod_5_ctx mulmod_ctx; - sp_256_mont_inv_order_5_ctx mont_inv_order_ctx; - }; - sp_digit e[2*5]; - sp_digit x[2*5]; - sp_digit k[2*5]; - sp_digit r[2*5]; - sp_digit tmp[3 * 2*5]; - sp_point_256 point; - sp_digit* s; - sp_digit* kInv; - 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 err = FP_WOULDBLOCK; - sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - ctx->s = ctx->e; - ctx->kInv = ctx->k; - - ctx->i = SP_ECC_MAX_SIG_GEN; - ctx->state = 1; - break; - case 1: /* GEN */ - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_5(rng, ctx->k); - } - else { - sp_256_from_mp(ctx->k, 5, km); - mp_zero(km); - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - break; - case 2: /* MULMOD */ - err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &p256_base, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - ctx->state = 3; - } - break; - case 3: /* MODORDER */ - { - sp_int64 c; - /* r = point->x mod order */ - XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 5U); - sp_256_norm_5(ctx->r); - c = sp_256_cmp_5(ctx->r, p256_order); - sp_256_cond_sub_5(ctx->r, ctx->r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_5(ctx->r); - - if (hashLen > 32U) { - hashLen = 32U; - } - sp_256_from_mp(ctx->x, 5, priv); - sp_256_from_bin(ctx->e, 5, hash, (int)hashLen); - ctx->state = 4; - break; - } - case 4: /* KMODORDER */ - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_5(ctx->k, ctx->k, p256_norm_order); - err = sp_256_mod_5(ctx->k, ctx->k, p256_order); - if (err == MP_OKAY) { - sp_256_norm_5(ctx->k); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 5; - } - break; - case 5: /* KINV */ - /* kInv = 1/k mod order */ - err = sp_256_mont_inv_order_5_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); - if (err == MP_OKAY) { - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 6; - } - break; - case 6: /* KINVNORM */ - sp_256_norm_5(ctx->kInv); - ctx->state = 7; - break; - case 7: /* R */ - /* s = r * x + e */ - sp_256_mul_5(ctx->x, ctx->x, ctx->r); - ctx->state = 8; - break; - case 8: /* S1 */ - err = sp_256_mod_5(ctx->x, ctx->x, p256_order); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* S2 */ - { - sp_digit carry; - sp_int64 c; - sp_256_norm_5(ctx->x); - carry = sp_256_add_5(ctx->s, ctx->e, ctx->x); - sp_256_cond_sub_5(ctx->s, ctx->s, - p256_order, 0 - carry); - sp_256_norm_5(ctx->s); - c = sp_256_cmp_5(ctx->s, p256_order); - sp_256_cond_sub_5(ctx->s, ctx->s, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_5(ctx->s); - - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_5(ctx->s, ctx->s, ctx->kInv); - sp_256_norm_5(ctx->s); - - /* Check that signature is usable. */ - if (sp_256_iszero_5(ctx->s) == 0) { - ctx->state = 10; - break; - } - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - ctx->i = 1; - #endif - - /* not usable gen, try again */ - ctx->i--; - if (ctx->i == 0) { - err = RNG_FAILURE_E; - } - ctx->state = 1; - break; - } - case 10: /* RES */ - err = sp_256_to_mp(ctx->r, rm); - if (err == MP_OKAY) { - err = sp_256_to_mp(ctx->s, sm); - } - break; - } - - if (err == MP_OKAY && ctx->state != 10) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 5U); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_SIGN */ - -#ifndef WOLFSSL_SP_SMALL -static const char sp_256_tab64_5[64] = { - 64, 1, 59, 2, 60, 48, 54, 3, - 61, 40, 49, 28, 55, 34, 43, 4, - 62, 52, 38, 41, 50, 19, 29, 21, - 56, 31, 35, 12, 44, 15, 23, 5, - 63, 58, 47, 53, 39, 27, 33, 42, - 51, 37, 18, 20, 30, 11, 14, 22, - 57, 46, 26, 32, 36, 17, 10, 13, - 45, 25, 16, 9, 24, 8, 7, 6}; - -static int sp_256_num_bits_52_5(sp_digit v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - return sp_256_tab64_5[((word64)((v - (v >> 1))*0x07EDD5E59A4E28C2)) >> 58]; -} - -static int sp_256_num_bits_5(const sp_digit* a) -{ - int i; - int r = 0; - - for (i = 4; i >= 0; i--) { - if (a[i] != 0) { - r = sp_256_num_bits_52_5(a[i]); - r += i * 52; - break; - } - } - - return r; -} - -/* 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. - * @return MEMEORY_E when dynamic memory allocation fails. - */ -static int sp_256_mod_inv_5(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int err = MP_OKAY; - SP_DECL_VAR(sp_digit, u, 5 * 4); - sp_digit* v = NULL; - sp_digit* b = NULL; - sp_digit* d = NULL; - int ut; - int vt; - - SP_ALLOC_VAR(sp_digit, u, 5 * 4, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - v = u + 5; - b = u + 2 * 5; - d = u + 3 * 5; - - XMEMCPY(u, m, sizeof(sp_digit) * 5); - XMEMCPY(v, a, sizeof(sp_digit) * 5); - - ut = sp_256_num_bits_5(u); - vt = sp_256_num_bits_5(v); - - XMEMSET(b, 0, sizeof(sp_digit) * 5); - if ((v[0] & 1) == 0) { - sp_256_rshift1_5(v, v); - XMEMCPY(d, m, sizeof(sp_digit) * 5); - d[0]++; - sp_256_rshift1_5(d, d); - vt--; - - while ((v[0] & 1) == 0) { - sp_256_rshift1_5(v, v); - if (d[0] & 1) - sp_256_add_5(d, d, m); - sp_256_rshift1_5(d, d); - vt--; - } - } - else { - XMEMSET(d+1, 0, sizeof(sp_digit) * (5 - 1)); - d[0] = 1; - } - - while (ut > 1 && vt > 1) { - if ((ut > vt) || ((ut == vt) && - (sp_256_cmp_5(u, v) >= 0))) { - sp_256_sub_5(u, u, v); - sp_256_norm_5(u); - - sp_256_sub_5(b, b, d); - sp_256_norm_5(b); - if (b[4] < 0) - sp_256_add_5(b, b, m); - sp_256_norm_5(b); - ut = sp_256_num_bits_5(u); - - do { - sp_256_rshift1_5(u, u); - if (b[0] & 1) - sp_256_add_5(b, b, m); - sp_256_rshift1_5(b, b); - ut--; - } - while (ut > 0 && (u[0] & 1) == 0); - } - else { - sp_256_sub_5(v, v, u); - sp_256_norm_5(v); - - sp_256_sub_5(d, d, b); - sp_256_norm_5(d); - if (d[4] < 0) - sp_256_add_5(d, d, m); - sp_256_norm_5(d); - vt = sp_256_num_bits_5(v); - - do { - sp_256_rshift1_5(v, v); - if (d[0] & 1) - sp_256_add_5(d, d, m); - sp_256_rshift1_5(d, d); - vt--; - } - while (vt > 0 && (v[0] & 1) == 0); - } - } - - if (ut == 1) - XMEMCPY(r, b, sizeof(sp_digit) * 5); - else - XMEMCPY(r, d, sizeof(sp_digit) * 5); - } - SP_FREE_VAR(u, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#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 Temporary 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 - err = sp_256_mod_inv_5(s, s, p256_order); - if (err == MP_OKAY) -#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) - * u1 = e/s mod order - * u2 = r/s mod order - * r == (u1.G + u2.Q)->x mod order - * Optimization: Leave point in projective form. - * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') - * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' - * The hash is truncated to the first 256 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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 MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -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) -{ - SP_DECL_VAR(sp_digit, u1, 18 * 5); - SP_DECL_VAR(sp_point_256, p1, 2); - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, u1, 18 * 5, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p1, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - 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, 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); - - err = sp_256_calc_vfy_point_5(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (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, rm); - err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_5(p1->z, p1->z, p256_mod, p256_mp_mod); - 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) { - /* Reload r and add order. */ - 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) { - sp_256_norm_5(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_5(u2, p256_mod); - } - } - 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); - } - } - } - - SP_FREE_VAR(p1, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(u1, heap, DYNAMIC_TYPE_ECC); - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_verify_256_ctx { - int state; - union { - sp_256_ecc_mulmod_5_ctx mulmod_ctx; - sp_256_mont_inv_order_5_ctx mont_inv_order_ctx; - sp_256_proj_point_dbl_5_ctx dbl_ctx; - sp_256_proj_point_add_5_ctx add_ctx; - }; - sp_digit u1[2*5]; - sp_digit u2[2*5]; - sp_digit s[2*5]; - sp_digit tmp[2*5 * 6]; - sp_point_256 p1; - 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, 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; - - typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(ctx->u1, 5, hash, (int)hashLen); - 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); - sp_256_from_mp(ctx->p2.z, 5, pZ); - ctx->state = 1; - break; - case 1: /* NORMS0 */ - sp_256_mul_5(ctx->s, ctx->s, p256_norm_order); - err = sp_256_mod_5(ctx->s, ctx->s, p256_order); - if (err == MP_OKAY) - ctx->state = 2; - break; - case 2: /* NORMS1 */ - sp_256_norm_5(ctx->s); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 3; - break; - case 3: /* NORMS2 */ - err = sp_256_mont_inv_order_5_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 4; - } - break; - case 4: /* NORMS3 */ - sp_256_mont_mul_order_5(ctx->u1, ctx->u1, ctx->s); - ctx->state = 5; - break; - case 5: /* NORMS4 */ - sp_256_mont_mul_order_5(ctx->u2, ctx->u2, ctx->s); - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 6; - break; - case 6: /* MULBASE */ - err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_256_iszero_5(ctx->p1.z)) { - ctx->p1.infinity = 1; - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 7; - } - break; - case 7: /* MULMOD */ - err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_256_iszero_5(ctx->p2.z)) { - ctx->p2.infinity = 1; - } - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 8; - } - break; - case 8: /* ADD */ - err = sp_256_proj_point_add_5_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); - if (err == MP_OKAY) - ctx->state = 9; - break; - 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, rm); - err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) - ctx->state = 10; - break; - 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 = 11; - break; - case 11: /* MUL */ - sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 12; - break; - case 12: /* RES */ - { - sp_int64 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; - - /* Reload r and add order. */ - 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) { - sp_256_norm_5(ctx->u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_5(ctx->u2, p256_mod); - } - } - 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 != 12) { - err = FP_WOULDBLOCK; - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_VERIFY */ - -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* Check that the x and y ordinates 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_256_ecc_is_point_5(const sp_point_256* point, - void* heap) -{ - SP_DECL_VAR(sp_digit, t1, 5 * 4); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 5 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 5; - - /* y^2 - x^3 - a.x = b */ - sp_256_sqr_5(t1, point->y); - (void)sp_256_mod_5(t1, t1, p256_mod); - sp_256_sqr_5(t2, point->x); - (void)sp_256_mod_5(t2, t2, p256_mod); - sp_256_mul_5(t2, t2, point->x); - (void)sp_256_mod_5(t2, t2, p256_mod); - sp_256_mont_sub_5(t1, t1, t2, p256_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - sp_256_mont_add_5(t1, t1, point->x, p256_mod); - sp_256_mont_add_5(t1, t1, point->x, p256_mod); - sp_256_mont_add_5(t1, t1, point->x, p256_mod); - - - if (sp_256_cmp_5(t1, p256_b) != 0) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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_256(const mp_int* pX, const mp_int* pY) -{ - SP_DECL_VAR(sp_point_256, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_256, pub, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - 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)); - - err = sp_256_ecc_is_point_5(pub, NULL); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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_256(const mp_int* pX, const mp_int* pY, - const mp_int* privm, void* heap) -{ - SP_DECL_VAR(sp_digit, priv, 5); - SP_DECL_VAR(sp_point_256, pub, 2); - 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 (((mp_count_bits(pX) > 256) || - (mp_count_bits(pY) > 256) || - ((privm != NULL) && (mp_count_bits(privm) > 256)))) { - err = ECC_OUT_OF_RANGE_E; - } - - SP_ALLOC_VAR(sp_digit, priv, 5, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, pub, 2, heap, DYNAMIC_TYPE_ECC); - 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)); - if (privm) - sp_256_from_mp(priv, 5, privm); - - /* Check point at infinitiy. */ - if ((sp_256_iszero_5(pub->x) != 0) && - (sp_256_iszero_5(pub->y) != 0)) { - err = ECC_INF_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) { - /* Check point is on curve */ - err = sp_256_ecc_is_point_5(pub, heap); - } - - if (err == MP_OKAY) { - /* Point * order = infinity */ - err = sp_256_ecc_mulmod_5(p, pub, p256_order, 1, 1, heap); - } - /* 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) { - if (err == MP_OKAY) { - /* Base * private = point */ - err = sp_256_ecc_mulmod_base_5(p, priv, 1, 1, heap); - } - /* 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; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL -/* Add two projective EC points together. - * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) - * - * pX First EC point's X ordinate. - * pY First EC point's Y ordinate. - * pZ First EC point's Z ordinate. - * qX Second EC point's X ordinate. - * qY Second EC point's Y ordinate. - * qZ Second EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 5 * 6); - SP_DECL_VAR(sp_point_256, p, 2); - sp_point_256* q = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 5 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p, 2, NULL, DYNAMIC_TYPE_ECC); - 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); - sp_256_from_mp(q->x, 5, qX); - sp_256_from_mp(q->y, 5, qY); - sp_256_from_mp(q->z, 5, qZ); - p->infinity = sp_256_iszero_5(p->x) & - sp_256_iszero_5(p->y); - q->infinity = sp_256_iszero_5(q->x) & - sp_256_iszero_5(q->y); - - sp_256_proj_point_add_5(p, p, q, tmp); - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Double a projective EC point. - * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 5 * 2); - SP_DECL_VAR(sp_point_256, p, 1); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 5 * 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - p->infinity = sp_256_iszero_5(p->x) & - sp_256_iszero_5(p->y); - - sp_256_proj_point_dbl_5(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Map a projective EC point to affine in place. - * pZ will be one. - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 5 * 4); - SP_DECL_VAR(sp_point_256, p, 1); - int err = MP_OKAY; - - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 5 * 4, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_256, p, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - p->infinity = sp_256_iszero_5(p->x) & - sp_256_iszero_5(p->y); - - sp_256_map_5(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(p->x, pX); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, pY); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, pZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifdef HAVE_COMP_KEY -/* Find the square root of a number mod the prime of the curve. - * - * y The number to operate on and the result. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -static int sp_256_mont_sqrt_5(sp_digit* y) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 5); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 5, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 5; - - { - /* t2 = y ^ 0x2 */ - sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); - /* t1 = y ^ 0x3 */ - sp_256_mont_mul_5(t1, t2, y, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xc */ - sp_256_mont_sqr_n_5(t2, t1, 2, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xf */ - sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xf0 */ - sp_256_mont_sqr_n_5(t2, t1, 4, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xff */ - sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xff00 */ - sp_256_mont_sqr_n_5(t2, t1, 8, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffff */ - sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); - /* t2 = y ^ 0xffff0000 */ - sp_256_mont_sqr_n_5(t2, t1, 16, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff */ - sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000000 */ - sp_256_mont_sqr_n_5(t1, t1, 32, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000001 */ - sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ - sp_256_mont_sqr_n_5(t1, t1, 96, p256_mod, p256_mp_mod); - /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ - sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); - sp_256_mont_sqr_n_5(y, t1, 94, p256_mod, p256_mp_mod); - } - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - - -/* Uncompress the point given the X ordinate. - * - * xm X ordinate. - * odd Whether the Y ordinate is odd. - * ym Calculated Y ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) -{ - SP_DECL_VAR(sp_digit, x, 4 * 5); - sp_digit* y = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, x, 4 * 5, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - y = x + 2 * 5; - - sp_256_from_mp(x, 5, xm); - err = sp_256_mod_mul_norm_5(x, x, p256_mod); - } - if (err == MP_OKAY) { - /* y = x^3 */ - { - sp_256_mont_sqr_5(y, x, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod); - } - /* y = x^3 - 3x */ - sp_256_mont_sub_5(y, y, x, p256_mod); - sp_256_mont_sub_5(y, y, x, p256_mod); - sp_256_mont_sub_5(y, y, x, p256_mod); - /* y = x^3 - 3x + b */ - err = sp_256_mod_mul_norm_5(x, p256_b, p256_mod); - } - if (err == MP_OKAY) { - sp_256_mont_add_5(y, y, x, p256_mod); - /* y = sqrt(x^3 - 3x + b) */ - err = sp_256_mont_sqrt_5(y); - } - if (err == MP_OKAY) { - XMEMSET(y + 5, 0, 5U * sizeof(sp_digit)); - sp_256_mont_reduce_5(y, p256_mod, p256_mp_mod); - if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { - sp_256_mont_sub_5(y, p256_mod, y, p256_mod); - } - - err = sp_256_to_mp(y, ym); - } - - SP_FREE_VAR(x, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* !WOLFSSL_SP_NO_256 */ -#ifdef WOLFSSL_SP_384 - -/* 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; - -/* The modulus (prime) of the curve P384. */ -static const sp_digit p384_mod[7] = { - 0x000000ffffffffL,0x7ffe0000000000L,0x7ffffffffbffffL,0x7fffffffffffffL, - 0x7fffffffffffffL,0x7fffffffffffffL,0x3fffffffffffffL -}; -/* The Montgomery normalizer for modulus of the curve P384. */ -static const sp_digit p384_norm_mod[7] = { - 0x7fffff00000001L,0x0001ffffffffffL,0x00000000040000L,0x00000000000000L, - 0x00000000000000L,0x00000000000000L,0x00000000000000L -}; -/* The Montgomery multiplier for modulus of the curve P384. */ -static const sp_digit p384_mp_mod = 0x0000100000001; -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -/* The order of the curve P384. */ -static const sp_digit p384_order[7] = { - 0x6c196accc52973L,0x1b6491614ef5d9L,0x07d0dcb77d6068L,0x7ffffffe3b1a6cL, - 0x7fffffffffffffL,0x7fffffffffffffL,0x3fffffffffffffL -}; -#endif -#ifndef WC_NO_RNG -/* The order of the curve P384 minus 2. */ -static const sp_digit p384_order2[7] = { - 0x6c196accc52971L,0x1b6491614ef5d9L,0x07d0dcb77d6068L,0x7ffffffe3b1a6cL, - 0x7fffffffffffffL,0x7fffffffffffffL,0x3fffffffffffffL -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery normalizer for order of the curve P384. */ -static const sp_digit p384_norm_order[7] = { - 0x13e695333ad68dL,0x649b6e9eb10a26L,0x782f2348829f97L,0x00000001c4e593L, - 0x00000000000000L,0x00000000000000L,0x00000000000000L -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery multiplier for order of the curve P384. */ -static const 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, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0 - }, - /* Y ordinate */ - { - 0x431d7c90ea0e5fL,0x639c3afd033af4L,0x4ed7c2e3002982L,0x44d0a3e74ed188L, - 0x2dc29f8f41dbd2L,0x0debb3d317f252L,0x0d85f792a5898bL, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0 - }, - /* Z ordinate */ - { - 0x00000000000001L,0x00000000000000L,0x00000000000000L,0x00000000000000L, - 0x00000000000000L,0x00000000000000L,0x00000000000000L, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) || \ - defined(HAVE_COMP_KEY) -static const sp_digit p384_b[7] = { - 0x05c8edd3ec2aefL,0x731b145da33a55L,0x3d404e1d6b1958L,0x740a089018a044L, - 0x02d19181d9c6efL,0x7c9311c0ad7c7fL,0x2ccc4be9f88fb9L -}; -#endif - -#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. - */ -SP_NOINLINE static void sp_384_mul_7(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[6]) * b[6]; - r[13] = (sp_digit)(c >> 55); - c &= 0x7fffffffffffffL; - for (k = 11; k >= 0; k--) { - if (k >= 7) { - i = k - 6; - imax = 6; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 55; - r[k + 2] += (sp_digit)(c >> 55); - r[k + 1] = (sp_digit)(c & 0x7fffffffffffffL); - c = lo & 0x7fffffffffffffL; - } - r[0] = (sp_digit)c; -} - -#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_384_mul_7(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_int128 t0 = ((sp_int128)a[ 0]) * b[ 0]; - sp_int128 t1 = ((sp_int128)a[ 0]) * b[ 1] - + ((sp_int128)a[ 1]) * b[ 0]; - sp_int128 t2 = ((sp_int128)a[ 0]) * b[ 2] - + ((sp_int128)a[ 1]) * b[ 1] - + ((sp_int128)a[ 2]) * b[ 0]; - sp_int128 t3 = ((sp_int128)a[ 0]) * b[ 3] - + ((sp_int128)a[ 1]) * b[ 2] - + ((sp_int128)a[ 2]) * b[ 1] - + ((sp_int128)a[ 3]) * b[ 0]; - sp_int128 t4 = ((sp_int128)a[ 0]) * b[ 4] - + ((sp_int128)a[ 1]) * b[ 3] - + ((sp_int128)a[ 2]) * b[ 2] - + ((sp_int128)a[ 3]) * b[ 1] - + ((sp_int128)a[ 4]) * b[ 0]; - sp_int128 t5 = ((sp_int128)a[ 0]) * b[ 5] - + ((sp_int128)a[ 1]) * b[ 4] - + ((sp_int128)a[ 2]) * b[ 3] - + ((sp_int128)a[ 3]) * b[ 2] - + ((sp_int128)a[ 4]) * b[ 1] - + ((sp_int128)a[ 5]) * b[ 0]; - sp_int128 t6 = ((sp_int128)a[ 0]) * b[ 6] - + ((sp_int128)a[ 1]) * b[ 5] - + ((sp_int128)a[ 2]) * b[ 4] - + ((sp_int128)a[ 3]) * b[ 3] - + ((sp_int128)a[ 4]) * b[ 2] - + ((sp_int128)a[ 5]) * b[ 1] - + ((sp_int128)a[ 6]) * b[ 0]; - sp_int128 t7 = ((sp_int128)a[ 1]) * b[ 6] - + ((sp_int128)a[ 2]) * b[ 5] - + ((sp_int128)a[ 3]) * b[ 4] - + ((sp_int128)a[ 4]) * b[ 3] - + ((sp_int128)a[ 5]) * b[ 2] - + ((sp_int128)a[ 6]) * b[ 1]; - sp_int128 t8 = ((sp_int128)a[ 2]) * b[ 6] - + ((sp_int128)a[ 3]) * b[ 5] - + ((sp_int128)a[ 4]) * b[ 4] - + ((sp_int128)a[ 5]) * b[ 3] - + ((sp_int128)a[ 6]) * b[ 2]; - sp_int128 t9 = ((sp_int128)a[ 3]) * b[ 6] - + ((sp_int128)a[ 4]) * b[ 5] - + ((sp_int128)a[ 5]) * b[ 4] - + ((sp_int128)a[ 6]) * b[ 3]; - sp_int128 t10 = ((sp_int128)a[ 4]) * b[ 6] - + ((sp_int128)a[ 5]) * b[ 5] - + ((sp_int128)a[ 6]) * b[ 4]; - sp_int128 t11 = ((sp_int128)a[ 5]) * b[ 6] - + ((sp_int128)a[ 6]) * b[ 5]; - sp_int128 t12 = ((sp_int128)a[ 6]) * b[ 6]; - - t1 += t0 >> 55; r[ 0] = (sp_digit)(t0 & 0x7fffffffffffffL); - t2 += t1 >> 55; r[ 1] = (sp_digit)(t1 & 0x7fffffffffffffL); - t3 += t2 >> 55; r[ 2] = (sp_digit)(t2 & 0x7fffffffffffffL); - t4 += t3 >> 55; r[ 3] = (sp_digit)(t3 & 0x7fffffffffffffL); - t5 += t4 >> 55; r[ 4] = (sp_digit)(t4 & 0x7fffffffffffffL); - t6 += t5 >> 55; r[ 5] = (sp_digit)(t5 & 0x7fffffffffffffL); - t7 += t6 >> 55; r[ 6] = (sp_digit)(t6 & 0x7fffffffffffffL); - t8 += t7 >> 55; r[ 7] = (sp_digit)(t7 & 0x7fffffffffffffL); - t9 += t8 >> 55; r[ 8] = (sp_digit)(t8 & 0x7fffffffffffffL); - t10 += t9 >> 55; r[ 9] = (sp_digit)(t9 & 0x7fffffffffffffL); - t11 += t10 >> 55; r[10] = (sp_digit)(t10 & 0x7fffffffffffffL); - t12 += t11 >> 55; r[11] = (sp_digit)(t11 & 0x7fffffffffffffL); - r[13] = (sp_digit)(t12 >> 55); - r[12] = (sp_digit)(t12 & 0x7fffffffffffffL); -} - -#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 imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[6]) * a[6]; - r[13] = (sp_digit)(c >> 55); - c = (c & 0x7fffffffffffffL) << 55; - for (k = 11; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 6) { - imax = k; - } - else { - imax = 6; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - 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) -{ - sp_int128 t0 = ((sp_int128)a[ 0]) * a[ 0]; - sp_int128 t1 = (((sp_int128)a[ 0]) * a[ 1]) * 2; - sp_int128 t2 = (((sp_int128)a[ 0]) * a[ 2]) * 2 - + ((sp_int128)a[ 1]) * a[ 1]; - sp_int128 t3 = (((sp_int128)a[ 0]) * a[ 3] - + ((sp_int128)a[ 1]) * a[ 2]) * 2; - sp_int128 t4 = (((sp_int128)a[ 0]) * a[ 4] - + ((sp_int128)a[ 1]) * a[ 3]) * 2 - + ((sp_int128)a[ 2]) * a[ 2]; - sp_int128 t5 = (((sp_int128)a[ 0]) * a[ 5] - + ((sp_int128)a[ 1]) * a[ 4] - + ((sp_int128)a[ 2]) * a[ 3]) * 2; - sp_int128 t6 = (((sp_int128)a[ 0]) * a[ 6] - + ((sp_int128)a[ 1]) * a[ 5] - + ((sp_int128)a[ 2]) * a[ 4]) * 2 - + ((sp_int128)a[ 3]) * a[ 3]; - sp_int128 t7 = (((sp_int128)a[ 1]) * a[ 6] - + ((sp_int128)a[ 2]) * a[ 5] - + ((sp_int128)a[ 3]) * a[ 4]) * 2; - sp_int128 t8 = (((sp_int128)a[ 2]) * a[ 6] - + ((sp_int128)a[ 3]) * a[ 5]) * 2 - + ((sp_int128)a[ 4]) * a[ 4]; - sp_int128 t9 = (((sp_int128)a[ 3]) * a[ 6] - + ((sp_int128)a[ 4]) * a[ 5]) * 2; - sp_int128 t10 = (((sp_int128)a[ 4]) * a[ 6]) * 2 - + ((sp_int128)a[ 5]) * a[ 5]; - sp_int128 t11 = (((sp_int128)a[ 5]) * a[ 6]) * 2; - sp_int128 t12 = ((sp_int128)a[ 6]) * a[ 6]; - - t1 += t0 >> 55; r[ 0] = (sp_digit)(t0 & 0x7fffffffffffffL); - t2 += t1 >> 55; r[ 1] = (sp_digit)(t1 & 0x7fffffffffffffL); - t3 += t2 >> 55; r[ 2] = (sp_digit)(t2 & 0x7fffffffffffffL); - t4 += t3 >> 55; r[ 3] = (sp_digit)(t3 & 0x7fffffffffffffL); - t5 += t4 >> 55; r[ 4] = (sp_digit)(t4 & 0x7fffffffffffffL); - t6 += t5 >> 55; r[ 5] = (sp_digit)(t5 & 0x7fffffffffffffL); - t7 += t6 >> 55; r[ 6] = (sp_digit)(t6 & 0x7fffffffffffffL); - t8 += t7 >> 55; r[ 7] = (sp_digit)(t7 & 0x7fffffffffffffL); - t9 += t8 >> 55; r[ 8] = (sp_digit)(t8 & 0x7fffffffffffffL); - t10 += t9 >> 55; r[ 9] = (sp_digit)(t9 & 0x7fffffffffffffL); - t11 += t10 >> 55; r[10] = (sp_digit)(t10 & 0x7fffffffffffffL); - t12 += t11 >> 55; r[11] = (sp_digit)(t11 & 0x7fffffffffffffL); - r[13] = (sp_digit)(t12 >> 55); - r[12] = (sp_digit)(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 i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 54); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 54); - } -#elif DIGIT_BIT > 55 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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; -} - -/* 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_384_cmp_7(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=6; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 54); - } -#else - r |= (a[ 6] - b[ 6]) & (0 - (sp_digit)1); - r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 54); - r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 54); - r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 54); - r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 54); - r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 54); - r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 54); -#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_384_cond_sub_7(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 < 7; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - r[ 0] = a[ 0] - (b[ 0] & m); - r[ 1] = a[ 1] - (b[ 1] & m); - r[ 2] = a[ 2] - (b[ 2] & m); - r[ 3] = a[ 3] - (b[ 3] & m); - r[ 4] = a[ 4] - (b[ 4] & m); - r[ 5] = a[ 5] - (b[ 5] & m); - r[ 6] = a[ 6] - (b[ 6] & 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_384_mul_add_7(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 4; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x7fffffffffffffL); - t[1] += t[0] >> 55; - r[i+1] = (sp_digit)(t[1] & 0x7fffffffffffffL); - t[2] += t[1] >> 55; - r[i+2] = (sp_digit)(t[2] & 0x7fffffffffffffL); - t[3] += t[2] >> 55; - r[i+3] = (sp_digit)(t[3] & 0x7fffffffffffffL); - t[0] = t[3] >> 55; - } - t[0] += (tb * a[4]) + r[4]; - t[1] = (tb * a[5]) + r[5]; - t[2] = (tb * a[6]) + r[6]; - r[4] = (sp_digit)(t[0] & 0x7fffffffffffffL); - t[1] += t[0] >> 55; - r[5] = (sp_digit)(t[1] & 0x7fffffffffffffL); - t[2] += t[1] >> 55; - r[6] = (sp_digit)(t[2] & 0x7fffffffffffffL); - r[7] += (sp_digit)(t[2] >> 55); -#else - sp_int128 tb = b; - sp_int128 t[7]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - r[ 0] += (sp_digit) (t[ 0] & 0x7fffffffffffffL); - r[ 1] += (sp_digit)((t[ 0] >> 55) + (t[ 1] & 0x7fffffffffffffL)); - r[ 2] += (sp_digit)((t[ 1] >> 55) + (t[ 2] & 0x7fffffffffffffL)); - r[ 3] += (sp_digit)((t[ 2] >> 55) + (t[ 3] & 0x7fffffffffffffL)); - r[ 4] += (sp_digit)((t[ 3] >> 55) + (t[ 4] & 0x7fffffffffffffL)); - r[ 5] += (sp_digit)((t[ 4] >> 55) + (t[ 5] & 0x7fffffffffffffL)); - r[ 6] += (sp_digit)((t[ 5] >> 55) + (t[ 6] & 0x7fffffffffffffL)); - r[ 7] += (sp_digit) (t[ 6] >> 55); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Normalize the values in each word to 55 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_384_norm_7(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 6; i++) { - a[i+1] += a[i] >> 55; - a[i] &= 0x7fffffffffffffL; - } -#else - a[1] += a[0] >> 55; a[0] &= 0x7fffffffffffffL; - a[2] += a[1] >> 55; a[1] &= 0x7fffffffffffffL; - a[3] += a[2] >> 55; a[2] &= 0x7fffffffffffffL; - a[4] += a[3] >> 55; a[3] &= 0x7fffffffffffffL; - a[5] += a[4] >> 55; a[4] &= 0x7fffffffffffffL; - a[6] += a[5] >> 55; a[5] &= 0x7fffffffffffffL; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Shift the result in the high 384 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_384_mont_shift_7(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_uint64 n; - - n = a[6] >> 54; - for (i = 0; i < 6; i++) { - n += (sp_uint64)a[7 + i] << 1; - r[i] = (sp_digit)(n & 0x7fffffffffffffL); - n >>= 55; - } - n += (sp_uint64)a[13] << 1; - r[6] = n; -#else - sp_uint64 n; - - n = a[6] >> 54; - n += (sp_uint64)a[ 7] << 1U; r[ 0] = (sp_digit)(n & 0x7fffffffffffffUL); n >>= 55U; - n += (sp_uint64)a[ 8] << 1U; r[ 1] = (sp_digit)(n & 0x7fffffffffffffUL); n >>= 55U; - n += (sp_uint64)a[ 9] << 1U; r[ 2] = (sp_digit)(n & 0x7fffffffffffffUL); n >>= 55U; - n += (sp_uint64)a[10] << 1U; r[ 3] = (sp_digit)(n & 0x7fffffffffffffUL); n >>= 55U; - n += (sp_uint64)a[11] << 1U; r[ 4] = (sp_digit)(n & 0x7fffffffffffffUL); n >>= 55U; - n += (sp_uint64)a[12] << 1U; r[ 5] = (sp_digit)(n & 0x7fffffffffffffUL); n >>= 55U; - n += (sp_uint64)a[13] << 1U; r[ 6] = n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[7], 0, sizeof(*r) * 7U); -} - -/* 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. - */ -static void sp_384_mont_reduce_order_7(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_384_norm_7(a + 7); - - for (i=0; i<6; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x7fffffffffffffL); - sp_384_mul_add_7(a+i, m, mu); - a[i+1] += a[i] >> 55; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x3fffffffffffffL); - 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); - over = a[6] >> 54; - sp_384_cond_sub_7(a, a, m, ~((over - 1) >> 63)); - sp_384_norm_7(a); -} - -/* 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. - */ -static void sp_384_mont_reduce_7(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit am; - - (void)m; - (void)mp; - - for (i = 0; i < 6; i++) { - am = (sp_digit)((a[i] * 0x100000001) & 0x7fffffffffffffL); - a[i + 0] += (sp_digit)((am << 32) & 0x7fffffffffffffL); - a[i + 1] += (am >> 23) - (sp_digit)((am << 41) & 0x7fffffffffffffL); - a[i + 2] += -(am >> 14) - ((sp_digit)(am << 18) & 0x7fffffffffffffL); - a[i + 3] += -(am >> 37); - a[i + 6] += ((sp_digit)(am << 54) & 0x7fffffffffffffL); - a[i + 7] += am >> 1; - - a[i + 1] += a[i] >> 55; - } - am = (sp_digit)((a[6] * 0x100000001) & 0x3fffffffffffff); - a[6 + 0] += (sp_digit)((am << 32) & 0x7fffffffffffffL); - a[6 + 1] += (am >> 23) - (sp_digit)((am << 41) & 0x7fffffffffffffL); - a[6 + 2] += -(am >> 14) - (sp_digit)((am << 18) & 0x7fffffffffffffL); - a[6 + 3] += -(am >> 37); - a[6 + 6] += (sp_digit)((am << 54) & 0x7fffffffffffffL); - a[6 + 7] += am >> 1; - - a[0] = (a[6] >> 54) + (sp_digit)((a[7] << 1) & 0x7fffffffffffffL); - a[1] = (a[7] >> 54) + (sp_digit)((a[8] << 1) & 0x7fffffffffffffL); - a[2] = (a[8] >> 54) + (sp_digit)((a[9] << 1) & 0x7fffffffffffffL); - a[3] = (a[9] >> 54) + (sp_digit)((a[10] << 1) & 0x7fffffffffffffL); - a[4] = (a[10] >> 54) + (sp_digit)((a[11] << 1) & 0x7fffffffffffffL); - a[5] = (a[11] >> 54) + (sp_digit)((a[12] << 1) & 0x7fffffffffffffL); - a[6] = (a[12] >> 54) + (a[13] << 1); - - a[1] += a[0] >> 55; a[0] &= 0x7fffffffffffffL; - a[2] += a[1] >> 55; a[1] &= 0x7fffffffffffffL; - a[3] += a[2] >> 55; a[2] &= 0x7fffffffffffffL; - a[4] += a[3] >> 55; a[3] &= 0x7fffffffffffffL; - a[5] += a[4] >> 55; a[4] &= 0x7fffffffffffffL; - a[6] += a[5] >> 55; a[5] &= 0x7fffffffffffffL; - - /* Get the bit over, if any. */ - am = a[6] >> 54; - /* Create mask. */ - am = 0 - am; - - a[0] -= (sp_digit)(0x00000000ffffffffL & am); - a[1] -= (sp_digit)(0x007ffe0000000000L & am); - a[2] -= (sp_digit)(0x007ffffffffbffffL & am); - a[3] -= (sp_digit)(0x007fffffffffffffL & am); - a[4] -= (sp_digit)(0x007fffffffffffffL & am); - a[5] -= (sp_digit)(0x007fffffffffffffL & am); - a[6] -= (sp_digit)(0x003fffffffffffffL & am); - - a[1] += a[0] >> 55; a[0] &= 0x7fffffffffffffL; - a[2] += a[1] >> 55; a[1] &= 0x7fffffffffffffL; - a[3] += a[2] >> 55; a[2] &= 0x7fffffffffffffL; - a[4] += a[3] >> 55; a[3] &= 0x7fffffffffffffL; - a[5] += a[4] >> 55; a[4] &= 0x7fffffffffffffL; - a[6] += a[5] >> 55; a[5] &= 0x7fffffffffffffL; -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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); -} - -#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) -/* Square the Montgomery form number a number of times. (r = a ^ n mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * n Number of times to square. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_384_mont_sqr_n_7(sp_digit* r, - const sp_digit* a, int n, const sp_digit* m, sp_digit mp) -{ - sp_384_mont_sqr_7(r, a, m, mp); - for (; n > 1; n--) { - sp_384_mont_sqr_7(r, r, m, mp); - } -} - -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ -#ifdef WOLFSSL_SP_SMALL -/* Mod-2 for the P384 curve. */ -static const word64 p384_mod_minus_2[6] = { - 0x00000000fffffffdU,0xffffffff00000000U,0xfffffffffffffffeU, - 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU -}; -#endif /* !WOLFSSL_SP_SMALL */ - -/* Invert the number, in Montgomery form, modulo the modulus (prime) of the - * P384 curve. (r = 1 / a mod m) - * - * r Inverse result. - * a Number to invert. - * td Temporary data. - */ -static void sp_384_mont_inv_7(sp_digit* r, const sp_digit* a, sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 7); - for (i=382; i>=0; i--) { - sp_384_mont_sqr_7(t, t, p384_mod, p384_mp_mod); - if (p384_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) - sp_384_mont_mul_7(t, t, a, p384_mod, p384_mp_mod); - } - XMEMCPY(r, t, sizeof(sp_digit) * 7); -#else - sp_digit* t1 = td; - sp_digit* t2 = td + 2 * 7; - sp_digit* t3 = td + 4 * 7; - sp_digit* t4 = td + 6 * 7; - sp_digit* t5 = td + 8 * 7; - - /* 0x2 */ - sp_384_mont_sqr_7(t1, a, p384_mod, p384_mp_mod); - /* 0x3 */ - sp_384_mont_mul_7(t5, t1, a, p384_mod, p384_mp_mod); - /* 0xc */ - sp_384_mont_sqr_n_7(t1, t5, 2, p384_mod, p384_mp_mod); - /* 0xf */ - sp_384_mont_mul_7(t2, t5, t1, p384_mod, p384_mp_mod); - /* 0x1e */ - sp_384_mont_sqr_7(t1, t2, p384_mod, p384_mp_mod); - /* 0x1f */ - sp_384_mont_mul_7(t4, t1, a, p384_mod, p384_mp_mod); - /* 0x3e0 */ - sp_384_mont_sqr_n_7(t1, t4, 5, p384_mod, p384_mp_mod); - /* 0x3ff */ - sp_384_mont_mul_7(t2, t4, t1, p384_mod, p384_mp_mod); - /* 0x7fe0 */ - sp_384_mont_sqr_n_7(t1, t2, 5, p384_mod, p384_mp_mod); - /* 0x7fff */ - sp_384_mont_mul_7(t4, t4, t1, p384_mod, p384_mp_mod); - /* 0x3fff8000 */ - sp_384_mont_sqr_n_7(t1, t4, 15, p384_mod, p384_mp_mod); - /* 0x3fffffff */ - sp_384_mont_mul_7(t2, t4, t1, p384_mod, p384_mp_mod); - /* 0xfffffffc */ - sp_384_mont_sqr_n_7(t3, t2, 2, p384_mod, p384_mp_mod); - /* 0xfffffffd */ - sp_384_mont_mul_7(r, t3, a, p384_mod, p384_mp_mod); - /* 0xffffffff */ - sp_384_mont_mul_7(t3, t5, t3, p384_mod, p384_mp_mod); - /* 0xfffffffc0000000 */ - sp_384_mont_sqr_n_7(t1, t2, 30, p384_mod, p384_mp_mod); - /* 0xfffffffffffffff */ - sp_384_mont_mul_7(t2, t2, t1, p384_mod, p384_mp_mod); - /* 0xfffffffffffffff000000000000000 */ - sp_384_mont_sqr_n_7(t1, t2, 60, p384_mod, p384_mp_mod); - /* 0xffffffffffffffffffffffffffffff */ - sp_384_mont_mul_7(t2, t2, t1, p384_mod, p384_mp_mod); - /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ - sp_384_mont_sqr_n_7(t1, t2, 120, p384_mod, p384_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_7(t2, t2, t1, p384_mod, p384_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ - sp_384_mont_sqr_n_7(t1, t2, 15, p384_mod, p384_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_7(t2, t4, t1, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ - sp_384_mont_sqr_n_7(t1, t2, 33, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ - sp_384_mont_mul_7(t2, t3, t1, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ - sp_384_mont_sqr_n_7(t1, t2, 96, p384_mod, p384_mp_mod); - /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ - sp_384_mont_mul_7(r, r, t1, p384_mod, p384_mp_mod); - -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_7(sp_point_384* r, const sp_point_384* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*7; - sp_int64 n; - - sp_384_mont_inv_7(t1, p->z, t + 2*7); - - sp_384_mont_sqr_7(t2, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t1, t2, t1, p384_mod, p384_mp_mod); - - /* x /= z^2 */ - sp_384_mont_mul_7(r->x, p->x, t2, p384_mod, p384_mp_mod); - XMEMSET(r->x + 7, 0, sizeof(sp_digit) * 7U); - sp_384_mont_reduce_7(r->x, p384_mod, p384_mp_mod); - /* Reduce x to less than modulus */ - n = sp_384_cmp_7(r->x, p384_mod); - sp_384_cond_sub_7(r->x, r->x, p384_mod, (sp_digit)~(n >> 54)); - sp_384_norm_7(r->x); - - /* y /= z^3 */ - sp_384_mont_mul_7(r->y, p->y, t1, p384_mod, p384_mp_mod); - XMEMSET(r->y + 7, 0, sizeof(sp_digit) * 7U); - sp_384_mont_reduce_7(r->y, p384_mod, p384_mp_mod); - /* Reduce y to less than modulus */ - n = sp_384_cmp_7(r->y, p384_mod); - sp_384_cond_sub_7(r->y, r->y, p384_mod, (sp_digit)~(n >> 54)); - sp_384_norm_7(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_add_7(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - sp_digit over; - (void)sp_384_add_7(r, a, b); - sp_384_norm_7(r); - over = r[6] >> 54; - sp_384_cond_sub_7(r, r, m, ~((over - 1) >> 63)); - sp_384_norm_7(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_dbl_7(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_384_add_7(r, a, a); - sp_384_norm_7(r); - over = r[6] >> 54; - sp_384_cond_sub_7(r, r, m, ~((over - 1) >> 63)); - sp_384_norm_7(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_tpl_7(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_384_add_7(r, a, a); - sp_384_norm_7(r); - over = r[6] >> 54; - sp_384_cond_sub_7(r, r, m, ~((over - 1) >> 63)); - sp_384_norm_7(r); - (void)sp_384_add_7(r, r, a); - sp_384_norm_7(r); - over = r[6] >> 54; - sp_384_cond_sub_7(r, r, m, ~((over - 1) >> 63)); - sp_384_norm_7(r); -} - -#ifdef 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_384_cond_add_7(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 7; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_384_cond_add_7(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - r[ 0] = a[ 0] + (b[ 0] & m); - r[ 1] = a[ 1] + (b[ 1] & m); - r[ 2] = a[ 2] + (b[ 2] & m); - r[ 3] = a[ 3] + (b[ 3] & m); - r[ 4] = a[ 4] + (b[ 4] & m); - r[ 5] = a[ 5] + (b[ 5] & m); - r[ 6] = a[ 6] + (b[ 6] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_384_mont_sub_7(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_384_sub_7(r, a, b); - sp_384_norm_7(r); - sp_384_cond_add_7(r, r, m, r[6] >> 54); - sp_384_norm_7(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -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) + (sp_digit)((a[i + 1] << 54) & 0x7fffffffffffffL); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 54) & 0x7fffffffffffffL); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 54) & 0x7fffffffffffffL); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 54) & 0x7fffffffffffffL); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 54) & 0x7fffffffffffffL); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 54) & 0x7fffffffffffffL); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 54) & 0x7fffffffffffffL); -#endif - r[6] = a[6] >> 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_384_mont_div2_7(sp_digit* r, const sp_digit* a, - const sp_digit* m) -{ - sp_384_cond_add_7(r, a, m, 0 - (a[0] & 1)); - sp_384_norm_7(r); - sp_384_rshift1_7(r, r); -} - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static void sp_384_proj_point_dbl_7(sp_point_384* r, const sp_point_384* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*7; - 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_384_mont_sqr_7(t1, p->z, p384_mod, p384_mp_mod); - /* Z = Y * Z */ - sp_384_mont_mul_7(z, p->y, p->z, p384_mod, p384_mp_mod); - /* Z = 2Z */ - sp_384_mont_dbl_7(z, z, p384_mod); - /* T2 = X - T1 */ - sp_384_mont_sub_7(t2, p->x, t1, p384_mod); - /* T1 = X + T1 */ - sp_384_mont_add_7(t1, p->x, t1, p384_mod); - /* T2 = T1 * T2 */ - sp_384_mont_mul_7(t2, t1, t2, p384_mod, p384_mp_mod); - /* T1 = 3T2 */ - sp_384_mont_tpl_7(t1, t2, p384_mod); - /* Y = 2Y */ - sp_384_mont_dbl_7(y, p->y, p384_mod); - /* Y = Y * Y */ - sp_384_mont_sqr_7(y, y, p384_mod, p384_mp_mod); - /* T2 = Y * Y */ - sp_384_mont_sqr_7(t2, y, p384_mod, p384_mp_mod); - /* T2 = T2/2 */ - sp_384_mont_div2_7(t2, t2, p384_mod); - /* Y = Y * X */ - sp_384_mont_mul_7(y, y, p->x, p384_mod, p384_mp_mod); - /* X = T1 * T1 */ - sp_384_mont_sqr_7(x, t1, p384_mod, p384_mp_mod); - /* X = X - Y */ - sp_384_mont_sub_7(x, x, y, p384_mod); - /* X = X - Y */ - sp_384_mont_sub_7(x, x, y, p384_mod); - /* Y = Y - X */ - sp_384_mont_sub_7(y, y, x, p384_mod); - /* Y = Y * T1 */ - sp_384_mont_mul_7(y, y, t1, p384_mod, p384_mp_mod); - /* Y = Y - T2 */ - sp_384_mont_sub_7(y, y, t2, p384_mod); -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_384_proj_point_dbl_7_ctx { - int state; - sp_digit* t1; - sp_digit* t2; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_384_proj_point_dbl_7_ctx; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static int sp_384_proj_point_dbl_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_point_384* p, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_384_proj_point_dbl_7_ctx* ctx = (sp_384_proj_point_dbl_7_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - ctx->t1 = t; - ctx->t2 = t + 2*7; - 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_384_mont_sqr_7(ctx->t1, p->z, p384_mod, p384_mp_mod); - ctx->state = 2; - break; - case 2: - /* Z = Y * Z */ - sp_384_mont_mul_7(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); - ctx->state = 3; - break; - case 3: - /* Z = 2Z */ - sp_384_mont_dbl_7(ctx->z, ctx->z, p384_mod); - ctx->state = 4; - break; - case 4: - /* T2 = X - T1 */ - sp_384_mont_sub_7(ctx->t2, p->x, ctx->t1, p384_mod); - ctx->state = 5; - break; - case 5: - /* T1 = X + T1 */ - sp_384_mont_add_7(ctx->t1, p->x, ctx->t1, p384_mod); - ctx->state = 6; - break; - case 6: - /* T2 = T1 * T2 */ - sp_384_mont_mul_7(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 7; - break; - case 7: - /* T1 = 3T2 */ - sp_384_mont_tpl_7(ctx->t1, ctx->t2, p384_mod); - ctx->state = 8; - break; - case 8: - /* Y = 2Y */ - sp_384_mont_dbl_7(ctx->y, p->y, p384_mod); - ctx->state = 9; - break; - case 9: - /* Y = Y * Y */ - sp_384_mont_sqr_7(ctx->y, ctx->y, p384_mod, p384_mp_mod); - ctx->state = 10; - break; - case 10: - /* T2 = Y * Y */ - sp_384_mont_sqr_7(ctx->t2, ctx->y, p384_mod, p384_mp_mod); - ctx->state = 11; - break; - case 11: - /* T2 = T2/2 */ - sp_384_mont_div2_7(ctx->t2, ctx->t2, p384_mod); - ctx->state = 12; - break; - case 12: - /* Y = Y * X */ - sp_384_mont_mul_7(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); - ctx->state = 13; - break; - case 13: - /* X = T1 * T1 */ - sp_384_mont_sqr_7(ctx->x, ctx->t1, p384_mod, p384_mp_mod); - ctx->state = 14; - break; - case 14: - /* X = X - Y */ - sp_384_mont_sub_7(ctx->x, ctx->x, ctx->y, p384_mod); - ctx->state = 15; - break; - case 15: - /* X = X - Y */ - sp_384_mont_sub_7(ctx->x, ctx->x, ctx->y, p384_mod); - ctx->state = 16; - break; - case 16: - /* Y = Y - X */ - sp_384_mont_sub_7(ctx->y, ctx->y, ctx->x, p384_mod); - ctx->state = 17; - break; - case 17: - /* Y = Y * T1 */ - sp_384_mont_mul_7(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); - ctx->state = 18; - break; - case 18: - /* Y = Y - T2 */ - sp_384_mont_sub_7(ctx->y, ctx->y, ctx->t2, p384_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 */ -/* 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_384_cmp_equal_7(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])) == 0; -} - -/* 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_384_iszero_7(const sp_digit* a) -{ - return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6]) == 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. - */ -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) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*7; - sp_digit* t2 = t + 4*7; - sp_digit* t3 = t + 6*7; - sp_digit* t4 = t + 8*7; - sp_digit* t5 = t + 10*7; - - /* U1 = X1*Z2^2 */ - sp_384_mont_sqr_7(t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t3, t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t1, t1, p->x, p384_mod, p384_mp_mod); - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_7(t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t4, t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t2, t2, q->x, p384_mod, p384_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_384_mont_mul_7(t3, t3, p->y, p384_mod, p384_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_7(t4, t4, q->y, p384_mod, p384_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_384_cmp_equal_7(t2, t1) & - sp_384_cmp_equal_7(t4, t3)) { - sp_384_proj_point_dbl_7(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* H = U2 - U1 */ - sp_384_mont_sub_7(t2, t2, t1, p384_mod); - /* R = S2 - S1 */ - sp_384_mont_sub_7(t4, t4, t3, p384_mod); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_384_mont_sqr_7(t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(y, t1, t5, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t5, t5, t2, p384_mod, p384_mp_mod); - /* Z3 = H*Z1*Z2 */ - sp_384_mont_mul_7(z, p->z, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(z, z, q->z, p384_mod, p384_mp_mod); - sp_384_mont_sqr_7(x, t4, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(x, x, t5, p384_mod); - sp_384_mont_mul_7(t5, t5, t3, p384_mod, p384_mp_mod); - sp_384_mont_dbl_7(t3, y, p384_mod); - sp_384_mont_sub_7(x, x, t3, p384_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_384_mont_sub_7(y, y, x, p384_mod); - sp_384_mont_mul_7(y, y, t4, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(y, y, t5, p384_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 7; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 7; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 7; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_384_proj_point_add_7_ctx { - int state; - sp_384_proj_point_dbl_7_ctx dbl_ctx; - const sp_point_384* ap[2]; - sp_point_384* rp[2]; - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; - sp_digit* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_384_proj_point_add_7_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -static int sp_384_proj_point_add_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_point_384* p, const sp_point_384* q, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_384_proj_point_add_7_ctx* ctx = (sp_384_proj_point_add_7_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_384_proj_point_add_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_384* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*7; - ctx->t2 = t + 4*7; - ctx->t3 = t + 6*7; - ctx->t4 = t + 8*7; - ctx->t5 = t + 10*7; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_384_mont_sqr_7(ctx->t1, q->z, p384_mod, p384_mp_mod); - ctx->state = 2; - break; - case 2: - sp_384_mont_mul_7(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); - ctx->state = 3; - break; - case 3: - sp_384_mont_mul_7(ctx->t1, ctx->t1, p->x, p384_mod, p384_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_7(ctx->t2, p->z, p384_mod, p384_mp_mod); - ctx->state = 5; - break; - case 5: - sp_384_mont_mul_7(ctx->t4, ctx->t2, p->z, p384_mod, p384_mp_mod); - ctx->state = 6; - break; - case 6: - sp_384_mont_mul_7(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_384_mont_mul_7(ctx->t3, ctx->t3, p->y, p384_mod, p384_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_7(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_384_cmp_equal_7(ctx->t2, ctx->t1) & - sp_384_cmp_equal_7(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_384_proj_point_dbl_7(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_384_mont_sub_7(ctx->t2, ctx->t2, ctx->t1, p384_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_384_mont_sub_7(ctx->t4, ctx->t4, ctx->t3, p384_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_384_mont_sqr_7(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 13; - break; - case 13: - sp_384_mont_mul_7(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); - ctx->state = 14; - break; - case 14: - sp_384_mont_mul_7(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_384_mont_mul_7(ctx->z, p->z, ctx->t2, p384_mod, p384_mp_mod); - ctx->state = 16; - break; - case 16: - sp_384_mont_mul_7(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); - ctx->state = 17; - break; - case 17: - sp_384_mont_sqr_7(ctx->x, ctx->t4, p384_mod, p384_mp_mod); - ctx->state = 18; - break; - case 18: - sp_384_mont_sub_7(ctx->x, ctx->x, ctx->t5, p384_mod); - ctx->state = 19; - break; - case 19: - sp_384_mont_mul_7(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); - ctx->state = 20; - break; - case 20: - sp_384_mont_dbl_7(ctx->t3, ctx->y, p384_mod); - sp_384_mont_sub_7(ctx->x, ctx->x, ctx->t3, p384_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_384_mont_sub_7(ctx->y, ctx->y, ctx->x, p384_mod); - ctx->state = 22; - break; - case 22: - sp_384_mont_mul_7(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); - ctx->state = 23; - break; - case 23: - sp_384_mont_sub_7(ctx->y, ctx->y, ctx->t5, p384_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 7; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 7; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 7; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -/* Multiply a number by Montgomery 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) -{ - SP_DECL_VAR(int64_t, t, 2 * 12); - int64_t* a32 = NULL; - int64_t o; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(int64_t, t, 2 * 12, NULL, DYNAMIC_TYPE_ECC); - 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; - } - - SP_FREE_VAR(t, NULL, DYNAMIC_TYPE_ECC); - - 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. - * 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_7(sp_point_384* r, const sp_point_384* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_384, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 7 * 6); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_384, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 7 * 6, heap, DYNAMIC_TYPE_ECC); - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_384) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_384_mod_mul_norm_7(t[1].x, g->x, p384_mod); - } - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); - - if (err == MP_OKAY) { - i = 6; - c = 54; - n = k[i--] << (55 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 55; - } - - y = (n >> 54) & 1; - n <<= 1; - - sp_384_proj_point_add_7(&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_384)); - sp_384_proj_point_dbl_7(&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_384)); - } - - if (map != 0) { - sp_384_map_7(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_384)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 7 * 6, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_384, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_384_ecc_mulmod_7_ctx { - int state; - union { - sp_384_proj_point_dbl_7_ctx dbl_ctx; - sp_384_proj_point_add_7_ctx add_ctx; - }; - sp_point_384 t[3]; - sp_digit tmp[2 * 7 * 6]; - sp_digit n; - int i; - int c; - int y; -} sp_384_ecc_mulmod_7_ctx; - -static int sp_384_ecc_mulmod_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_384_ecc_mulmod_7_ctx* ctx = (sp_384_ecc_mulmod_7_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_7_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_384) * 3); - ctx->i = 6; - ctx->c = 54; - ctx->n = k[ctx->i--] << (55 - 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_384_mod_mul_norm_7(ctx->t[1].x, g->x, p384_mod); - ctx->state = 2; - break; - case 2: /* T1Y */ - err = sp_384_mod_mul_norm_7(ctx->t[1].y, g->y, p384_mod); - ctx->state = 3; - break; - case 3: /* T1Z */ - err = sp_384_mod_mul_norm_7(ctx->t[1].z, g->z, p384_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 = 55; - } - ctx->y = (ctx->n >> 54) & 1; - ctx->n <<= 1; - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 5; - break; - case 5: /* ADD */ - err = sp_384_proj_point_add_7_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_384)); - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 6; - } - break; - case 6: /* DBL */ - err = sp_384_proj_point_dbl_7_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_384)); - ctx->state = 4; - ctx->c--; - } - break; - case 7: /* MAP */ - if (map != 0) { - sp_384_map_7(r, &ctx->t[0], ctx->tmp); - } - else { - XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384)); - } - 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 */ - -#else -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_384 { - sp_digit x[7]; - sp_digit y[7]; -} sp_table_entry_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. - */ -static void sp_384_cond_copy_7(sp_digit* r, const sp_digit* a, const sp_digit m) -{ - sp_digit t[7]; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i = 0; i < 7; i++) { - t[i] = r[i] ^ a[i]; - } - for (i = 0; i < 7; 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]; - 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; -#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_384_proj_point_dbl_n_7(sp_point_384* p, int i, - sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*7; - sp_digit* b = t + 4*7; - sp_digit* t1 = t + 6*7; - sp_digit* t2 = t + 8*7; - sp_digit* x; - sp_digit* y; - sp_digit* z; - volatile int n = i - 1; - - x = p->x; - y = p->y; - z = p->z; - - /* Y = 2*Y */ - sp_384_mont_dbl_7(y, y, p384_mod); - /* 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); -#ifndef WOLFSSL_SP_SMALL - while (n > 0) -#else - while (n >= 0) -#endif - { - /* 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); - sp_384_mont_tpl_7(a, t1, p384_mod); - /* B = X*Y^2 */ - sp_384_mont_sqr_7(t1, y, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(b, t1, x, p384_mod, p384_mp_mod); - /* X = A^2 - 2B */ - sp_384_mont_sqr_7(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_7(t2, b, p384_mod); - sp_384_mont_sub_7(x, x, t2, p384_mod); - /* B = 2.(B - X) */ - sp_384_mont_sub_7(t2, b, x, p384_mod); - sp_384_mont_dbl_7(b, t2, p384_mod); - /* Z = Z*Y */ - sp_384_mont_mul_7(z, z, y, p384_mod, p384_mp_mod); - /* t1 = Y^4 */ - sp_384_mont_sqr_7(t1, t1, p384_mod, p384_mp_mod); -#ifdef WOLFSSL_SP_SMALL - if (n != 0) -#endif - { - /* W = W*Y^4 */ - sp_384_mont_mul_7(w, w, t1, p384_mod, p384_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_mul_7(y, b, a, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(y, y, t1, p384_mod); - n = n - 1; - } -#ifndef WOLFSSL_SP_SMALL - /* 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); - sp_384_mont_tpl_7(a, t1, p384_mod); - /* B = X*Y^2 */ - sp_384_mont_sqr_7(t1, y, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(b, t1, x, p384_mod, p384_mp_mod); - /* X = A^2 - 2B */ - sp_384_mont_sqr_7(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_7(t2, b, p384_mod); - sp_384_mont_sub_7(x, x, t2, p384_mod); - /* B = 2.(B - X) */ - sp_384_mont_sub_7(t2, b, x, p384_mod); - sp_384_mont_dbl_7(b, t2, p384_mod); - /* Z = Z*Y */ - sp_384_mont_mul_7(z, z, y, p384_mod, p384_mp_mod); - /* t1 = Y^4 */ - sp_384_mont_sqr_7(t1, t1, p384_mod, p384_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_mul_7(y, b, a, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(y, y, t1, p384_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_384_mont_div2_7(y, y, p384_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_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; - sp_digit* b = t + 4*7; - sp_digit* t1 = t + 6*7; - sp_digit* t2 = t + 8*7; - sp_digit* x = r[2*m].x; - sp_digit* y = r[(1<x[i]; - } - for (i=0; i<7; i++) { - y[i] = p->y[i]; - } - for (i=0; i<7; i++) { - z[i] = p->z[i]; - } - - /* Y = 2*Y */ - sp_384_mont_dbl_7(y, y, p384_mod); - /* 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); - sp_384_mont_tpl_7(a, t1, p384_mod); - /* B = X*Y^2 */ - sp_384_mont_sqr_7(t1, y, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(b, t1, x, p384_mod, p384_mp_mod); - x = r[j].x; - /* X = A^2 - 2B */ - sp_384_mont_sqr_7(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_7(t2, b, p384_mod); - sp_384_mont_sub_7(x, x, t2, p384_mod); - /* B = 2.(B - X) */ - sp_384_mont_sub_7(t2, b, x, p384_mod); - sp_384_mont_dbl_7(b, t2, p384_mod); - /* Z = Z*Y */ - sp_384_mont_mul_7(r[j].z, z, y, p384_mod, p384_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_384_mont_sqr_7(t1, t1, p384_mod, p384_mp_mod); - if (i != n) { - /* W = W*Y^4 */ - sp_384_mont_mul_7(w, w, t1, p384_mod, p384_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_mul_7(y, b, a, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(y, y, t1, p384_mod); - /* Y = Y/2 */ - sp_384_mont_div2_7(r[j].y, y, p384_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_384_proj_point_add_sub_7(sp_point_384* ra, - sp_point_384* rs, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*7; - sp_digit* t3 = t + 4*7; - sp_digit* t4 = t + 6*7; - sp_digit* t5 = t + 8*7; - sp_digit* t6 = t + 10*7; - sp_digit* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, p->z, sizeof(p->z) / 2); - ra->infinity = 0; - rs->infinity = 0; - - /* U1 = X1*Z2^2 */ - sp_384_mont_sqr_7(t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t3, t1, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t1, t1, xa, p384_mod, p384_mp_mod); - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_7(t2, za, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t4, t2, za, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t2, t2, q->x, p384_mod, p384_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_384_mont_mul_7(t3, t3, ya, p384_mod, p384_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_7(t4, t4, q->y, p384_mod, p384_mp_mod); - /* H = U2 - U1 */ - sp_384_mont_sub_7(t2, t2, t1, p384_mod); - /* RS = S2 + S1 */ - sp_384_mont_add_7(t6, t4, t3, p384_mod); - /* R = S2 - S1 */ - sp_384_mont_sub_7(t4, t4, t3, p384_mod); - /* Z3 = H*Z1*Z2 */ - /* ZS = H*Z1*Z2 */ - sp_384_mont_mul_7(za, za, q->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(za, za, t2, p384_mod, p384_mp_mod); - XMEMCPY(zs, za, sizeof(p->z)/2); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - /* XS = RS^2 - H^3 - 2*U1*H^2 */ - sp_384_mont_sqr_7(xa, t4, p384_mod, p384_mp_mod); - sp_384_mont_sqr_7(xs, t6, p384_mod, p384_mp_mod); - sp_384_mont_sqr_7(t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(ya, t1, t5, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t5, t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(xa, xa, t5, p384_mod); - sp_384_mont_sub_7(xs, xs, t5, p384_mod); - sp_384_mont_dbl_7(t1, ya, p384_mod); - sp_384_mont_sub_7(xa, xa, t1, p384_mod); - sp_384_mont_sub_7(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_7(ys, ya, xs, p384_mod); - sp_384_mont_sub_7(ya, ya, xa, p384_mod); - sp_384_mont_mul_7(ya, ya, t4, p384_mod, p384_mp_mod); - sp_384_sub_7(t6, p384_mod, t6); - sp_384_mont_mul_7(ys, ys, t6, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t5, t5, t3, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(ya, ya, t5, p384_mod); - sp_384_mont_sub_7(ys, ys, t5, p384_mod); -} - -/* Structure used to describe recoding of scalar multiplication. */ -typedef struct ecc_recode_384 { - /* Index into pre-computation table. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_384; - -/* The index into pre-computation table to use. */ -static const word8 recode_index_7_6[66] = { - 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, 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 word8 recode_neg_7_6[66] = { - 0, 0, 0, 0, 0, 0, 0, 0, 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, - 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_6_7(const sp_digit* k, ecc_recode_384* v) -{ - int i; - int j; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<65; i++) { - y = (word8)(int8_t)n; - if (o + 6 < 55) { - y &= 0x3f; - n >>= 6; - o += 6; - } - else if (o + 6 == 55) { - n >>= 6; - if (++j < 7) - n = k[j]; - o = 0; - } - else if (++j < 7) { - n = k[j]; - y |= (word8)((n << (55 - o)) & 0x3f); - o -= 49; - n >>= o; - } - - y = (word8)(y + carry); - v[i].i = recode_index_7_6[y]; - v[i].neg = recode_neg_7_6[y]; - carry = (y >> 6) + v[i].neg; - } -} - -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible point that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_384_get_point_33_7(sp_point_384* r, const sp_point_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->x[6] = 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; - r->y[6] = 0; - r->z[0] = 0; - r->z[1] = 0; - r->z[2] = 0; - r->z[3] = 0; - r->z[4] = 0; - r->z[5] = 0; - r->z[6] = 0; - for (i = 1; i < 33; i++) { - mask = (sp_digit)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->x[6] |= mask & table[i].x[6]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->z[0] |= mask & table[i].z[0]; - r->z[1] |= mask & table[i].z[1]; - r->z[2] |= mask & table[i].z[2]; - r->z[3] |= mask & table[i].z[3]; - r->z[4] |= mask & table[i].z[4]; - r->z[5] |= mask & table[i].z[5]; - r->z[6] |= mask & table[i].z[6]; - } -} -#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. - * - * Window technique of 6 bits. (Add-Sub variation.) - * Calculate 0..32 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_384_ecc_mulmod_win_add_sub_7(sp_point_384* r, const sp_point_384* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_384, t, 33+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 7 * 6); - sp_point_384* rt = NULL; - sp_point_384* p = NULL; - sp_digit* negy; - int i; - ecc_recode_384 v[65]; - int err = MP_OKAY; - - /* Constant time used for cache attack resistance implementation. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_384, t, 33+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 7 * 6, heap, DYNAMIC_TYPE_ECC); - 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_7(t[1].x, g->x, p384_mod); - } - if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); - } - if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); - } - - if (err == MP_OKAY) { - t[1].infinity = 0; - /* t[2] ... t[32] */ - sp_384_proj_point_dbl_n_store_7(t, &t[ 1], 5, 1, tmp); - sp_384_proj_point_add_7(&t[ 3], &t[ 2], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[ 6], &t[ 3], tmp); - sp_384_proj_point_add_sub_7(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[10], &t[ 5], tmp); - sp_384_proj_point_add_sub_7(&t[11], &t[ 9], &t[10], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[12], &t[ 6], tmp); - sp_384_proj_point_dbl_7(&t[14], &t[ 7], tmp); - sp_384_proj_point_add_sub_7(&t[15], &t[13], &t[14], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[18], &t[ 9], tmp); - sp_384_proj_point_add_sub_7(&t[19], &t[17], &t[18], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[20], &t[10], tmp); - sp_384_proj_point_dbl_7(&t[22], &t[11], tmp); - sp_384_proj_point_add_sub_7(&t[23], &t[21], &t[22], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[24], &t[12], tmp); - sp_384_proj_point_dbl_7(&t[26], &t[13], tmp); - sp_384_proj_point_add_sub_7(&t[27], &t[25], &t[26], &t[ 1], tmp); - sp_384_proj_point_dbl_7(&t[28], &t[14], tmp); - sp_384_proj_point_dbl_7(&t[30], &t[15], tmp); - sp_384_proj_point_add_sub_7(&t[31], &t[29], &t[30], &t[ 1], tmp); - - negy = t[0].y; - - sp_384_ecc_recode_6_7(k, v); - - i = 64; - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_point_33_7(rt, t, v[i].i); - rt->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384)); - } - for (--i; i>=0; i--) { - sp_384_proj_point_dbl_n_7(rt, 6, tmp); - - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_point_33_7(p, t, v[i].i); - p->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384)); - } - sp_384_sub_7(negy, p384_mod, p->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); - } - - if (map != 0) { - sp_384_map_7(r, rt, tmp); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_384)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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_384_proj_point_add_qz1_7(sp_point_384* r, - const sp_point_384* p, const sp_point_384* q, sp_digit* t) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*7; - sp_digit* t6 = t + 4*7; - sp_digit* t1 = t + 6*7; - sp_digit* t4 = t + 8*7; - sp_digit* t5 = t + 10*7; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_384_mont_sqr_7(t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t4, t2, p->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t2, t2, q->x, p384_mod, p384_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_384_mont_mul_7(t4, t4, q->y, p384_mod, p384_mp_mod); - - if ((~p->infinity) & (~q->infinity) & - sp_384_cmp_equal_7(p->x, t2) & - sp_384_cmp_equal_7(p->y, t4)) { - sp_384_proj_point_dbl_7(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_384_mont_sub_7(t2, t2, p->x, p384_mod); - /* R = S2 - Y1 */ - sp_384_mont_sub_7(t4, t4, p->y, p384_mod); - /* Z3 = H*Z1 */ - sp_384_mont_mul_7(z, p->z, t2, p384_mod, p384_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_384_mont_sqr_7(t1, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t3, p->x, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t1, t1, t2, p384_mod, p384_mp_mod); - sp_384_mont_sqr_7(t2, t4, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(t2, t2, t1, p384_mod); - sp_384_mont_dbl_7(t5, t3, p384_mod); - sp_384_mont_sub_7(x, t2, t5, p384_mod); - /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_384_mont_sub_7(t3, t3, x, p384_mod); - sp_384_mont_mul_7(t3, t3, t4, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t1, t1, p->y, p384_mod, p384_mp_mod); - sp_384_mont_sub_7(y, t3, t1, p384_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 7; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 7; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 7; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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_7(sp_point_384* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 7; - sp_digit* tmp = t + 4 * 7; - - sp_384_mont_inv_7(t1, a->z, tmp); - - sp_384_mont_sqr_7(t2, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(t1, t2, t1, p384_mod, p384_mp_mod); - - sp_384_mont_mul_7(a->x, a->x, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(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 = 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_7(const sp_point_384* a, - sp_table_entry_384* table, sp_digit* tmp, void* heap) -{ - SP_DECL_VAR(sp_point_384, t, 3); - sp_point_384* s1 = NULL; - sp_point_384* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_384, t, 3, heap, DYNAMIC_TYPE_ECC); - 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) { - err = sp_384_mod_mul_norm_7(t->y, a->y, p384_mod); - } - if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_7(t->z, a->z, p384_mod); - } - if (err == MP_OKAY) { - t->infinity = 0; - sp_384_proj_to_affine_7(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_7(t, 48, tmp); - sp_384_proj_to_affine_7(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_7(t, s1, s2, tmp); - sp_384_proj_to_affine_7(t, tmp); - XMEMCPY(table[j].x, t->x, sizeof(table->x)); - XMEMCPY(table[j].y, t->y, sizeof(table->y)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible entry that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_384_get_entry_256_7(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->x[6] = 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; - r->y[6] = 0; - for (i = 1; i < 256; i++) { - sp_digit gte = (sp_digit)((((sp_uint64)i - (sp_uint64)idx) >> 63) - 1); - sp_digit lte = (sp_digit)((((sp_uint64)idx - (sp_uint64)i) >> 63) - 1); - mask = gte & lte; - 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->x[6] |= mask & table[i].x[6]; - 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]; - r->y[6] |= mask & table[i].y[6]; - } -} -#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_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) -{ - SP_DECL_VAR(sp_point_384, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 7 * 6); - 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; - - - SP_ALLOC_VAR(sp_point_384, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 7 * 6, heap, DYNAMIC_TYPE_ECC); - 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 / 55] >> (x % 55)) & 1) << j); - x += 48; - } - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_entry_256_7(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 / 55] >> (x % 55)) & 1) << j); - x += 48; - } - - sp_384_proj_point_dbl_7(rt, rt, t); - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_384_get_entry_256_7(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_7(rt, rt, p, t); - } - - if (map != 0) { - sp_384_map_7(r, rt, t); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_384)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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_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. */ - word32 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 - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_384 = 0; - #endif - static wolfSSL_Mutex sp_cache_384_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_384_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * 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; - word32 least; - - if (sp_cache_384_inited == 0) { - for (i=0; ix, sp_cache_384[i].x) & - sp_384_cmp_equal_7(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_7(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_7(r, g, k, map, ct, heap); -#else - SP_DECL_VAR(sp_digit, tmp, 2 * 7 * 7); - sp_cache_384_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 7 * 7, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_384 == 0) { - wc_InitMutex(&sp_cache_384_lock); - initCacheMutex_384 = 1; - } - #endif - 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_7(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_7(r, g, k, map, ct, heap); - } - else { - err = sp_384_ecc_mulmod_stripe_7(r, g, cache->table, k, - map, ct, heap); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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_384(const mp_int* km, const ecc_point* gm, ecc_point* r, - int map, void* heap) -{ - SP_DECL_VAR(sp_point_384, point, 1); - SP_DECL_VAR(sp_digit, k, 7); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 7, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_384_from_mp(k, 7, km); - sp_384_point_from_ecc_point_7(point, gm); - - err = sp_384_ecc_mulmod_7(point, point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_7(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_384, point, 2); - SP_DECL_VAR(sp_digit, k, 7 + 7 * 2 * 6); - sp_point_384* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 7 + 7 * 2 * 6, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef 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. - * - * 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_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, - int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_384_ecc_mulmod_7(r, &p384_base, k, map, ct, heap); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_384_ecc_mulmod_base_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_384_ecc_mulmod_7_nb(sp_ctx, r, &p384_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#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 } }, - /* 1 */ - { { 0x50756649c0b528L,0x71c541ad9c707bL,0x71506d35b8838dL, - 0x4d1877fc3ce1d7L,0x6de2b645486845L,0x227025fee46c29L, - 0x134eab708a6785L }, - { 0x043dad4b03a4feL,0x517ef769535846L,0x58ba0ec14286feL, - 0x47a7fecc5d6f3aL,0x1a840c6c352196L,0x3d3bb00044c72dL, - 0x0ade2af0968571L } }, - /* 2 */ - { { 0x0647532b0c535bL,0x52a6e0a0c52c53L,0x5085aae6b24375L, - 0x7096bb501c66b5L,0x47bdb3df9b7b7bL,0x11227e9b2f0be6L, - 0x088b172704fa51L }, - { 0x0e796f2680dc64L,0x796eb06a482ebfL,0x2b441d02e04839L, - 0x19bef7312a5aecL,0x02247c38b8efb5L,0x099ed1185c329eL, - 0x1ed71d7cdb096fL } }, - /* 3 */ - { { 0x6a3cc39edffea5L,0x7a386fafd3f9c4L,0x366f78fbd8d6efL, - 0x529c7ad7873b80L,0x79eb30380eb471L,0x07c5d3b51760b7L, - 0x36ee4f1cc69183L }, - { 0x5ba260f526b605L,0x2f1dfaf0aa6e6fL,0x6bb5ca812a5752L, - 0x3002d8d1276bc9L,0x01f82269483777L,0x1df33eaaf733cdL, - 0x2b97e555f59255L } }, - /* 4 */ - { { 0x480c57f26feef9L,0x4d28741c248048L,0x0c9cf8af1f0c68L, - 0x778f6a639a8016L,0x148e88c42e9c53L,0x464051757ecfe9L, - 0x1a940bd0e2a5e1L }, - { 0x713a46b74536feL,0x1757b153e1d7ebL,0x30dc8c9da07486L, - 0x3b7460c1879b5eL,0x4b766c5317b315L,0x1b9de3aaf4d377L, - 0x245f124c2cf8f5L } }, - /* 5 */ - { { 0x426e2ee349ddd0L,0x7df3365f84a022L,0x03b005d29a7c45L, - 0x422c2337f9b5a4L,0x060494f4bde761L,0x5245e5db6da0b0L, - 0x22b71d744677f2L }, - { 0x19d097b7d5a7ceL,0x6bcb468823d34cL,0x1c3692d3be1d09L, - 0x3c80ec7aa01f02L,0x7170f2ebaafd97L,0x06cbcc7d79d4e8L, - 0x04a8da511fe760L } }, - /* 6 */ - { { 0x79c07a4fc52870L,0x6e9034a752c251L,0x603860a367382cL, - 0x56d912d6aa87d0L,0x0a348a24abaf76L,0x6c5a23da14adcbL, - 0x3cf60479a522b2L }, - { 0x18dd774c61ed22L,0x0ff30168f93b0cL,0x3f79ae15642eddL, - 0x40510f4915fbcbL,0x2c9ddfdfd1c6d6L,0x67b81b62aee55eL, - 0x2824de79b07a43L } }, - /* 7 */ - { { 0x6c66efe085c629L,0x48c212b7913470L,0x4480fd2d057f0aL, - 0x725ec7a89a9eb1L,0x78ce97ca1972b7L,0x54760ee70154fbL, - 0x362a40e27b9f93L }, - { 0x474dc7e7b14461L,0x602819389ef037L,0x1a13bc284370b2L, - 0x0193ff1295a59dL,0x79615bde6ea5d2L,0x2e76e3d886acc1L, - 0x3bb796812e2b60L } }, - /* 8 */ - { { 0x04cbb3893b9a2dL,0x4c16010a18baabL,0x19f7cb50f60831L, - 0x084f400a0936c1L,0x72f1cdd5bbbf00L,0x1b30b725dc6702L, - 0x182753e4fcc50cL }, - { 0x059a07eadaf9d6L,0x26d81e24bf603cL,0x45583c839dc399L, - 0x5579d4d6b1103aL,0x2e14ea59489ae7L,0x492f6e1c5ecc97L, - 0x03740dc05db420L } }, - /* 9 */ - { { 0x413be88510521fL,0x3753ee49982e99L,0x6cd4f7098e1cc5L, - 0x613c92bda4ec1dL,0x495378b677efe0L,0x132a2143839927L, - 0x0cf8c336291c0bL }, - { 0x7fc89d2208353fL,0x751b9da85657e1L,0x349b8a97d405c3L, - 0x65a964b048428fL,0x1adf481276455eL,0x5560c8d89c2ffcL, - 0x144fc11fac21a3L } }, - /* 10 */ - { { 0x7611f4df5bdf53L,0x634eb16234db80L,0x3c713b8e51174cL, - 0x52c3c68ac4b2edL,0x53025ba8bebe75L,0x7175d98143105bL, - 0x33ca8e266a48faL }, - { 0x0c9281d24fd048L,0x76b3177604bbf3L,0x3b26ae754e106fL, - 0x7f782275c6efc6L,0x36662538a4cb67L,0x0ca1255843e464L, - 0x2a4674e142d9bcL } }, - /* 11 */ - { { 0x303b4085d480d8L,0x68f23650f4fa7bL,0x552a3ceeba3367L, - 0x6da0c4947926e3L,0x6e0f5482eb8003L,0x0de717f3d6738aL, - 0x22e5dcc826a477L }, - { 0x1b05b27209cfc2L,0x7f0a0b65b6e146L,0x63586549ed3126L, - 0x7d628dd2b23124L,0x383423fe510391L,0x57ff609eabd569L, - 0x301f04370131baL } }, - /* 12 */ - { { 0x22fe4cdb32f048L,0x7f228ebdadbf5aL,0x02a99adb2d7c8eL, - 0x01a02e05286706L,0x62d6adf627a89fL,0x49c6ce906fbf2bL, - 0x0207256dae90b9L }, - { 0x23e036e71d6cebL,0x199ed8d604e3d7L,0x0c1a11c076d16fL, - 0x389291fb3da3f3L,0x47adc60f8f942eL,0x177048468e4b9aL, - 0x20c09f5e61d927L } }, - /* 13 */ - { { 0x129ea63615b0b8L,0x03fb4a9b588367L,0x5ad6da8da2d051L, - 0x33f782f44caeaaL,0x5a27fa80d45291L,0x6d1ed796942da4L, - 0x08435a931ef556L }, - { 0x004abb25351130L,0x6d33207c6fd7e7L,0x702130972074b7L, - 0x0e34748af900f7L,0x762a531a28c87aL,0x3a903b5a4a6ac7L, - 0x1775b79c35b105L } }, - /* 14 */ - { { 0x7470fd846612ceL,0x7dd9b431b32e53L,0x04bcd2be1a61bcL, - 0x36ed7c5b5c260bL,0x6795f5ef0a4084L,0x46e2880b401c93L, - 0x17d246c5aa8bdeL }, - { 0x707ae4db41b38dL,0x233c31f7f9558fL,0x585110ec67bdf4L, - 0x4d0cc931d0c703L,0x26fbe4356841a7L,0x64323e95239c44L, - 0x371dc9230f3221L } }, - /* 15 */ - { { 0x70ff1ae4b1ec9dL,0x7c1dcfddee0daaL,0x53286782188748L, - 0x6a5d9381e6f207L,0x3aa6c7d6523c4cL,0x6c02d83e0d97e2L, - 0x16a9c916b45312L }, - { 0x78146744b74de8L,0x742ec415269c6fL,0x237a2c6a860e79L, - 0x186baf17ba68a7L,0x4261e8789fa51fL,0x3dc136480a5903L, - 0x1953899e0cf159L } }, - /* 16 */ - { { 0x0205de2f9fbe67L,0x1706fee51c886fL,0x31a0b803c712bfL, - 0x0a6aa11ede7603L,0x2463ef2a145c31L,0x615403b30e8f4aL, - 0x3f024d6c5f5c5eL }, - { 0x53bc4fd4d01f95L,0x7d512ac15a692cL,0x72be38fcfe6aa0L, - 0x437f0b77bbca1eL,0x7fdcf70774a10eL,0x392d6c5cde37f3L, - 0x229cbce79621d1L } }, - /* 17 */ - { { 0x2de4da2341c342L,0x5ca9d4e08844e7L,0x60dd073bcf74c9L, - 0x4f30aa499b63ecL,0x23efd1eafa00d5L,0x7c99a7db1257b3L, - 0x00febc9b3171b1L }, - { 0x7e2fcf3045f8acL,0x2a642e9e3ce610L,0x23f82be69c5299L, - 0x66e49ad967c279L,0x1c895ddfd7a842L,0x798981e22f6d25L, - 0x0d595cb59322f3L } }, - /* 18 */ - { { 0x4bac017d8c1bbaL,0x73872161e7aafdL,0x0fd865f43d8163L, - 0x019d89457708b7L,0x1b983c4dd70684L,0x095e109b74d841L, - 0x25f1f0b3e0c76fL }, - { 0x4e61ddf96010e8L,0x1c40a53f542e5eL,0x01a74dfc8365f9L, - 0x69b36b92773333L,0x08e0fccc139ed3L,0x266d216ddc4269L, - 0x1f2b47717ce9b5L } }, - /* 19 */ - { { 0x0a9a81da57a41fL,0x0825d800736cccL,0x2d7876b4579d28L, - 0x3340ea6211a1e3L,0x49e89284f3ff54L,0x6276a210fe2c6eL, - 0x01c3c8f31be7cbL }, - { 0x2211da5d186e14L,0x1e6ffbb61bfea8L,0x536c7d060211d2L, - 0x320168720d1d55L,0x5835525ed667baL,0x5125e52495205eL, - 0x16113b9f3e9129L } }, - /* 20 */ - { { 0x3086073f3b236fL,0x283b03c443b5f5L,0x78e49ed0a067a7L, - 0x2a878fb79fb2b8L,0x662f04348a9337L,0x57ee2cf732d50bL, - 0x18b50dd65fd514L }, - { 0x5feb9ef2955926L,0x2c3edbef06a7b0L,0x32728dad651029L, - 0x116d00b1c4b347L,0x13254052bf1a1aL,0x3e77bf7fee5ec1L, - 0x253943ca388882L } }, - /* 21 */ - { { 0x32e5b33062e8afL,0x46ebd147a6d321L,0x2c8076dec6a15cL, - 0x7328d511ff0d80L,0x10ad7e926def0eL,0x4e8ca85937d736L, - 0x02638c26e8bf2fL }, - { 0x1deeb3fff1d63fL,0x5014417fa6e8efL,0x6e1da3de5c8f43L, - 0x7ca942b42295d9L,0x23faacf75bb4d1L,0x4a71fcd680053dL, - 0x04af4f90204dceL } }, - /* 22 */ - { { 0x23780d104cbba5L,0x4e8ff46bba9980L,0x2072a6da8d881fL, - 0x3cc3d881ae11c9L,0x2eee84ff19be89L,0x69b708ed77f004L, - 0x2a82928534eef9L }, - { 0x794331187d4543L,0x70e0f3edc0cc41L,0x3ab1fa0b84c854L, - 0x1478355c1d87baL,0x6f35fa7748ba28L,0x37b8be0531584dL, - 0x03c3141c23a69fL } }, - /* 23 */ - { { 0x5c244cdef029ddL,0x0d0f0a0cc37018L,0x17f8476604f6afL, - 0x13a6dd6ccc95c3L,0x5a242e9801b8f6L,0x211ca9cc632131L, - 0x264a6a46a4694fL }, - { 0x3ffd7235285887L,0x284be28302046fL,0x57f4b9b882f1d6L, - 0x5e21772c940661L,0x7619a735c600cfL,0x2f76f5a50c9106L, - 0x28d89c8c69de31L } }, - /* 24 */ - { { 0x799b5c91361ed8L,0x36ead8c66cd95cL,0x046c9969a91f5cL, - 0x46bbdba2a66ea9L,0x29db0e0215a599L,0x26c8849b36f756L, - 0x22c3feb31ff679L }, - { 0x585d1237b5d9efL,0x5ac57f522e8e8dL,0x617e66e8b56c41L, - 0x68826f276823cfL,0x0983f0e6f39231L,0x4e1075099084bdL, - 0x2a541f82be0416L } }, - /* 25 */ - { { 0x468a6e14cf381cL,0x4f7b845c6399edL,0x36aa29732ebe74L, - 0x19c726911ab46aL,0x2ad1fe431eec0eL,0x301e35051fd1eaL, - 0x36da815e7a1ab3L }, - { 0x05672e4507832aL,0x4ebf10fca51251L,0x6015843421cff0L, - 0x3affad832fc013L,0x712b58d9b45540L,0x1e4751d1f6213eL, - 0x0e7c2b218bafa7L } }, - /* 26 */ - { { 0x7abf784c52edf5L,0x6fcb4b135ca7b1L,0x435e46ac5f735cL, - 0x67f8364ca48c5fL,0x46d45b5fbd956bL,0x10deda6065db94L, - 0x0b37fdf85068f9L }, - { 0x74b3ba61f47ec8L,0x42c7ddf08c10ccL,0x1531a1fe422a20L, - 0x366f913d12be38L,0x6a846e30cb2edfL,0x2785898c994fedL, - 0x061be85f331af3L } }, - /* 27 */ - { { 0x23f5361dfcb91eL,0x3c26c8da6b1491L,0x6e444a1e620d65L, - 0x0c3babd5e8ac13L,0x573723ce612b82L,0x2d10e62a142c37L, - 0x3d1a114c2d98bdL }, - { 0x33950b401896f6L,0x7134efe7c12110L,0x31239fd2978472L, - 0x30333bf5978965L,0x79f93313dd769fL,0x457fb9e11662caL, - 0x190a73b251ae3cL } }, - /* 28 */ - { { 0x04dd54bb75f9a4L,0x0d7253a76ae093L,0x08f5b930792bbcL, - 0x041f79adafc265L,0x4a9ff24c61c11bL,0x0019c94e724725L, - 0x21975945d9cc2aL }, - { 0x3dfe76722b4a2bL,0x17f2f6107c1d94L,0x546e1ae2944b01L, - 0x53f1f06401e72dL,0x2dbe43fc7632d6L,0x5639132e185903L, - 0x0f2f34eb448385L } }, - /* 29 */ - { { 0x7b4cc7ec30ce93L,0x58fb6e4e4145f7L,0x5d1ed5540043b5L, - 0x19ffbe1f633adfL,0x5bfc0907259033L,0x6378f872e7ca0eL, - 0x2c127b2c01eb3cL }, - { 0x076eaf4f58839cL,0x2db54560bc9f68L,0x42ad0319b84062L, - 0x46c325d1fb019dL,0x76d2a19ee9eebcL,0x6fbd6d9e2aa8f7L, - 0x2396a598fe0991L } }, - /* 30 */ - { { 0x662fddf7fbd5e1L,0x7ca8ed22563ad3L,0x5b4768efece3b3L, - 0x643786a422d1eaL,0x36ce80494950e1L,0x1a30795b7f2778L, - 0x107f395c93f332L }, - { 0x7939c28332c144L,0x491610e3c8dc0bL,0x099ba2bfdac5fcL, - 0x5c2e3149ec29a7L,0x31b731d06f1dc3L,0x1cbb60d465d462L, - 0x3ca5461362cfd9L } }, - /* 31 */ - { { 0x653ff736ddc103L,0x7c6f2bdec0dfb2L,0x73f81b73a097d0L, - 0x05b775f84f180fL,0x56b2085af23413L,0x0d6f36256a61feL, - 0x26d3ed267fa68fL }, - { 0x54f89251d27ac2L,0x4fc6ad94a71202L,0x7ebf01969b4cc5L, - 0x7ba364dbc14760L,0x4f8370959a2587L,0x7b7631e37c6188L, - 0x29e51845f104cbL } }, - /* 32 */ - { { 0x426b775e3c647bL,0x327319e0a69180L,0x0c5cb034f6ff2fL, - 0x73aa39b98e9897L,0x7ee615f49fde6eL,0x3f712aa61e0db4L, - 0x33ca06c2ba2ce9L }, - { 0x14973541b8a543L,0x4b4e6101ba61faL,0x1d94e4233d0698L, - 0x501513c715d570L,0x1b8f8c3d01436bL,0x52f41a0445cf64L, - 0x3f709c3a75fb04L } }, - /* 33 */ - { { 0x073c0cbc7f41d6L,0x227c36f5ac8201L,0x508e110fef65d8L, - 0x0f317229529b7fL,0x45fc6030d00e24L,0x118a65d30cebeaL, - 0x3340cc4223a448L }, - { 0x204c999797612cL,0x7c05dd4ce9c5a3L,0x7b865d0a8750e4L, - 0x2f82c876ab7d34L,0x2243ddd2ab4808L,0x6834b9df8a4914L, - 0x123319ed950e0fL } }, - /* 34 */ - { { 0x50430efc14ab48L,0x7e9e4ce0d4e89cL,0x2332207fd8656dL, - 0x4a2809e97f4511L,0x2162bb1b968e2dL,0x29526d54af2972L, - 0x13edd9adcd939dL }, - { 0x793bca31e1ff7fL,0x6b959c9e4d2227L,0x628ac27809a5baL, - 0x2c71ffc7fbaa5fL,0x0c0b058f13c9ceL,0x5676eae68de2cfL, - 0x35508036ea19a4L } }, - /* 35 */ - { { 0x030bbd6dda1265L,0x67f9d12e31bb34L,0x7e4d8196e3ded3L, - 0x7b9120e5352498L,0x75857bce72d875L,0x4ead976a396caeL, - 0x31c5860553a64dL }, - { 0x1a0f792ee32189L,0x564c4efb8165d0L,0x7adc7d1a7fbcbeL, - 0x7ed7c2ccf327b7L,0x35df1b448ce33dL,0x6f67eb838997cdL, - 0x3ee37ec0077917L } }, - /* 36 */ - { { 0x345fa74d5bb921L,0x097c9a56ccfd8eL,0x00a0b5e8f971f8L, - 0x723d95223f69d4L,0x08e2e5c2777f87L,0x68b13676200109L, - 0x26ab5df0acbad6L }, - { 0x01bca7daac34aeL,0x49ca4d5f664dadL,0x110687b850914bL, - 0x1203d6f06443c9L,0x7a2ac743b04d4cL,0x40d96bd3337f82L, - 0x13728be0929c06L } }, - /* 37 */ - { { 0x631ca61127bc1aL,0x2b362fd5a77cd1L,0x17897d68568fb7L, - 0x21070af33db5b2L,0x6872e76221794aL,0x436f29fb076963L, - 0x1f2acfc0ecb7b3L }, - { 0x19bf15ca9b3586L,0x32489a4a17aee2L,0x2b31af3c929551L, - 0x0db7c420b9b19fL,0x538c39bd308c2bL,0x438775c0dea88fL, - 0x1537304d7cd07fL } }, - /* 38 */ - { { 0x53598d943caf0dL,0x1d5244bfe266adL,0x7158feb7ab3811L, - 0x1f46e13cf6fb53L,0x0dcab632eb9447L,0x46302968cfc632L, - 0x0b53d3cc5b6ec7L }, - { 0x69811ca143b7caL,0x5865bcf9f2a11aL,0x74ded7fa093b06L, - 0x1c878ec911d5afL,0x04610e82616e49L,0x1e157fe9640eb0L, - 0x046e6f8561d6c2L } }, - /* 39 */ - { { 0x631a3d3bbe682cL,0x3a4ce9dde5ba95L,0x28f11f7502f1f1L, - 0x0a55cf0c957e88L,0x495e4ec7e0a3bcL,0x30ad4d87ba365cL, - 0x0217b97a4c26f3L }, - { 0x01a9088c2e67fdL,0x7501c4c3d5e5e7L,0x265b7bb854c820L, - 0x729263c87e6b52L,0x308b9e3b8fb035L,0x33f1b86c1b23abL, - 0x0e81b8b21fc99cL } }, - /* 40 */ - { { 0x59f5a87237cac0L,0x6b3a86b0cf28b9L,0x13a53db13a4fc2L, - 0x313c169a1c253bL,0x060158304ed2bbL,0x21e171b71679bcL, - 0x10cdb754d76f86L }, - { 0x44355392ab473aL,0x64eb7cbda08caeL,0x3086426a900c71L, - 0x49016ed9f3c33cL,0x7e6354ab7e04f9L,0x17c4c91a40cd2eL, - 0x3509f461024c66L } }, - /* 41 */ - { { 0x2848f50f9b5a31L,0x68d1755b6c5504L,0x48cd5d5672ec00L, - 0x4d77421919d023L,0x1e1e349ef68807L,0x4ab5130cf415d7L, - 0x305464c6c7dbe6L }, - { 0x64eb0bad74251eL,0x64c6957e52bda4L,0x6c12583440dee6L, - 0x6d3bee05b00490L,0x186970de53dbc4L,0x3be03b37567a56L, - 0x2b553b1ebdc55bL } }, - /* 42 */ - { { 0x74dc3579efdc58L,0x26d29fed1bb71cL,0x334c825a9515afL, - 0x433c1e839273a6L,0x0d8a4e41cff423L,0x3454098fe42f8eL, - 0x1046674bf98686L }, - { 0x09a3e029c05dd2L,0x54d7cfc7fb53a7L,0x35f0ad37e14d7cL, - 0x73a294a13767b9L,0x3f519678275f4fL,0x788c63393993a4L, - 0x0781680b620123L } }, - /* 43 */ - { { 0x4c8e2ed4d5ffe8L,0x112db7d42fe4ebL,0x433b8f2d2be2edL, - 0x23e30b29a82cbcL,0x35d2f4c06ee85aL,0x78ff31ffe4b252L, - 0x0d31295c8cbff5L }, - { 0x314806ea0376a2L,0x4ea09e22bc0589L,0x0879575f00ba97L, - 0x188226d2996bb7L,0x7799368dc9411fL,0x7ab24e5c8cae36L, - 0x2b6a8e2ee4ea33L } }, - /* 44 */ - { { 0x70c7127d4ed72aL,0x24c9743ef34697L,0x2fd30e7a93683aL, - 0x538a89c246012cL,0x6c660a5394ed82L,0x79a95ea239d7e0L, - 0x3f3af3bbfb170dL }, - { 0x3b75aa779ae8c1L,0x33995a3cc0dde4L,0x7489d5720b7bfdL, - 0x599677ef9fa937L,0x3defd64c5ab44bL,0x27d52dc234522bL, - 0x2ac65d1a8450e0L } }, - /* 45 */ - { { 0x478585ec837d7dL,0x5f7971dc174887L,0x67576ed7bb296dL, - 0x5a78e529a74926L,0x640f73f4fa104bL,0x7d42a8b16e4730L, - 0x108c7eaa75fd01L }, - { 0x60661ef96e6896L,0x18d3a0761f3aa7L,0x6e71e163455539L, - 0x165827d6a7e583L,0x4e7f77e9527935L,0x790bebe2ae912eL, - 0x0b8fe9561adb55L } }, - /* 46 */ - { { 0x4d48036a9951a8L,0x371084f255a085L,0x66aeca69cea2c5L, - 0x04c99f40c745e7L,0x08dc4bfd9a0924L,0x0b0ec146b29df7L, - 0x05106218d01c91L }, - { 0x2a56ee99caedc7L,0x5d9b23a203922cL,0x1ce4c80b6a3ec4L, - 0x2666bcb75338cbL,0x185a81aac8c4aaL,0x2b4fb60a06c39eL, - 0x0327e1b3633f42L } }, - /* 47 */ - { { 0x72814710b2a556L,0x52c864f6e16534L,0x4978de66ddd9f2L, - 0x151f5950276cf0L,0x450ac6781d2dc2L,0x114b7a22dd61b2L, - 0x3b32b07f29faf8L }, - { 0x68444fdc2d6e94L,0x68526bd9e437bcL,0x0ca780e8b0d887L, - 0x69f3f850a716aaL,0x500b953e42cd57L,0x4e57744d812e7dL, - 0x000a5f0e715f48L } }, - /* 48 */ - { { 0x2aab10b8243a7dL,0x727d1f4b18b675L,0x0e6b9fdd91bbbbL, - 0x0d58269fc337e5L,0x45d6664105a266L,0x11946af1b14072L, - 0x2c2334f91e46e1L }, - { 0x6dc5f8756d2411L,0x21b34eaa25188bL,0x0d2797da83529eL, - 0x324df55616784bL,0x7039ec66d267dfL,0x2de79cdb2d108cL, - 0x14011b1ad0bde0L } }, - /* 49 */ - { { 0x2e160266425043L,0x55fbe11b712125L,0x7e3c58b3947fd9L, - 0x67aacc79c37ad3L,0x4a18e18d2dea0fL,0x5eef06e5674351L, - 0x37c3483ae33439L }, - { 0x5d5e1d75bb4045L,0x0f9d72db296efdL,0x60b1899dd894a9L, - 0x06e8818ded949aL,0x747fd853c39434L,0x0953b937d9efabL, - 0x09f08c0beeb901L } }, - /* 50 */ - { { 0x1d208a8f2d49ceL,0x54042c5be1445aL,0x1c2681fd943646L, - 0x219c8094e2e674L,0x442cddf07238b8L,0x574a051c590832L, - 0x0b72f4d61c818aL }, - { 0x7bc3cbe4680967L,0x0c8b3f25ae596bL,0x0445b0da74a9efL, - 0x0bbf46c40363b7L,0x1df575c50677a3L,0x016ea6e73d68adL, - 0x0b5207bd8db0fdL } }, - /* 51 */ - { { 0x2d39fdfea1103eL,0x2b252bf0362e34L,0x63d66c992baab9L, - 0x5ac97706de8550L,0x0cca390c39c1acL,0x0d9bec5f01b2eaL, - 0x369360a0f7e5f3L }, - { 0x6dd3461e201067L,0x70b2d3f63ed614L,0x487580487c54c7L, - 0x6020e48a44af2aL,0x1ccf80b21aab04L,0x3cf3b12d88d798L, - 0x349368eccc506fL } }, - /* 52 */ - { { 0x5a053753b0a354L,0x65e818dbb9b0aeL,0x7d5855ee50e4bfL, - 0x58dc06885c7467L,0x5ee15073e57bd3L,0x63254ebc1e07fdL, - 0x1d48e0392aa39bL }, - { 0x4e227c6558ffe9L,0x0c3033d8a82a3eL,0x7bde65c214e8d2L, - 0x6e23561559c16aL,0x5094c5e6deaffdL,0x78dca2880f1f91L, - 0x3d9d3f947d838dL } }, - /* 53 */ - { { 0x387ae5af63408fL,0x6d539aeb4e6edfL,0x7f3d3186368e70L, - 0x01a6446bc19989L,0x35288fbcd4482fL,0x39288d34ec2736L, - 0x1de9c47159ad76L }, - { 0x695dc7944f8d65L,0x3eca2c35575094L,0x0c918059a79b69L, - 0x4573a48c32a74eL,0x580d8bc8b93f52L,0x190be3a3d071eaL, - 0x2333e686b3a8cbL } }, - /* 54 */ - { { 0x2b110c7196fee2L,0x3ac70e99128a51L,0x20a6bb6b75d5e6L, - 0x5f447fa513149aL,0x560d69714cc7b2L,0x1d3ee25279fab1L, - 0x369adb2ccca959L }, - { 0x3fddb13dd821c2L,0x70bf21ba647be8L,0x64121227e3cbc9L, - 0x12633a4c892320L,0x3c15c61660f26dL,0x1932c3b3d19900L, - 0x18c718563eab71L } }, - /* 55 */ - { { 0x72ebe0fd752366L,0x681c2737d11759L,0x143c805e7ae4f0L, - 0x78ed3c2cc7b324L,0x5c16e14820254fL,0x226a4f1c4ec9f0L, - 0x2891bb915eaac6L }, - { 0x061eb453763b33L,0x07f88b81781a87L,0x72b5ac7a87127cL, - 0x7ea4e4cd7ff8b5L,0x5e8c3ce33908b6L,0x0bcb8a3d37feffL, - 0x01da9e8e7fc50bL } }, - /* 56 */ - { { 0x639dfe9e338d10L,0x32dfe856823608L,0x46a1d73bca3b9aL, - 0x2da685d4b0230eL,0x6e0bc1057b6d69L,0x7144ec724a5520L, - 0x0b067c26b87083L }, - { 0x0fc3f0eef4c43dL,0x63500f509552b7L,0x220d74af6f8b86L, - 0x038996eafa2aa9L,0x7f6750f4aee4d2L,0x3e1d3f06718720L, - 0x1ea1d37243814cL } }, - /* 57 */ - { { 0x322d4597c27050L,0x1beeb3ce17f109L,0x15e5ce2e6ef42eL, - 0x6c8be27da6b3a0L,0x66e3347f4d5f5cL,0x7172133899c279L, - 0x250aff4e548743L }, - { 0x28f0f6a43b566dL,0x0cd2437fefbca0L,0x5b1108cb36bdbaL, - 0x48a834d41fb7c2L,0x6cb8565680579fL,0x42da2412b45d9fL, - 0x33dfc1abb6c06eL } }, - /* 58 */ - { { 0x56e3c48ef96c80L,0x65667bb6c1381eL,0x09f70514375487L, - 0x1548ff115f4a08L,0x237de2d21a0710L,0x1425cdee9f43dfL, - 0x26a6a42e055b0aL }, - { 0x4ea9ea9dc7dfcbL,0x4df858583ac58aL,0x1d274f819f1d39L, - 0x26e9c56cf91fcbL,0x6cee31c7c3a465L,0x0bb8e00b108b28L, - 0x226158da117301L } }, - /* 59 */ - { { 0x5a7cd4fce73946L,0x7b6a462d0ac653L,0x732ea4bb1a3da5L, - 0x7c8e9f54711af4L,0x0a6cd55d4655f9L,0x341e6d13e4754aL, - 0x373c87098879a8L }, - { 0x7bc82e61b818bfL,0x5f2db48f44879fL,0x2a2f06833f1d28L, - 0x494e5b691a74c0L,0x17d6cf35fd6b57L,0x5f7028d1c25dfcL, - 0x377a9ab9562cb6L } }, - /* 60 */ - { { 0x4de8877e787b2eL,0x183e7352621a52L,0x2ab0509974962bL, - 0x045a450496cb8aL,0x3bf7118b5591c7L,0x7724f98d761c35L, - 0x301607e8d5a0c1L }, - { 0x0f58a3f24d4d58L,0x3771c19c464f3cL,0x06746f9c0bfafaL, - 0x56564c9c8feb52L,0x0d66d9a7d8a45fL,0x403578141193caL, - 0x00b0d0bdc19260L } }, - /* 61 */ - { { 0x571407157bdbc2L,0x138d5a1c2c0b99L,0x2ee4a8057dcbeaL, - 0x051ff2b58e9ed1L,0x067378ad9e7cdaL,0x7cc2c1db97a49eL, - 0x1e7536ccd849d6L }, - { 0x531fd95f3497c4L,0x55dc08325f61a7L,0x144e942bce32bfL, - 0x642d572f09e53aL,0x556ff188261678L,0x3e79c0d9d513d6L, - 0x0bbbc6656f6d52L } }, - /* 62 */ - { { 0x57d3eb50596edcL,0x26c520a487451dL,0x0a92db40aea8d6L, - 0x27df6345109616L,0x7733d611fd727cL,0x61d14171fef709L, - 0x36169ae417c36bL }, - { 0x6899f5d4091cf7L,0x56ce5dfe4ed0c1L,0x2c430ce5913fbcL, - 0x1b13547e0f8caeL,0x4840a8275d3699L,0x59b8ef209e81adL, - 0x22362dff5ea1a2L } }, - /* 63 */ - { { 0x7237237bd98425L,0x73258e162a9d0bL,0x0a59a1e8bb5118L, - 0x4190a7ee5d8077L,0x13684905fdbf7cL,0x31c4033a52626bL, - 0x010a30e4fbd448L }, - { 0x47623f981e909aL,0x670af7c325b481L,0x3d004241fa4944L, - 0x0905a2ca47f240L,0x58f3cdd7a187c3L,0x78b93aee05b43fL, - 0x19b91d4ef8d63bL } }, - /* 64 */ - { { 0x0d34e116973cf4L,0x4116fc9e69ee0eL,0x657ae2b4a482bbL, - 0x3522eed134d7cdL,0x741e0dde0a036aL,0x6554316a51cc7bL, - 0x00f31c6ca89837L }, - { 0x26770aa06b1dd7L,0x38233a4ceba649L,0x065a1110c96feaL, - 0x18d367839e0f15L,0x794543660558d1L,0x39b605139065dcL, - 0x29abbec071b637L } }, - /* 65 */ - { { 0x1464b401ab5245L,0x16db891b27ff74L,0x724eb49cb26e34L, - 0x74fee3bc9cc33eL,0x6a8bdbebe085eaL,0x5c2e75ca207129L, - 0x1d03f2268e6b08L }, - { 0x28b0a328e23b23L,0x645dc26209a0bcL,0x62c28990348d49L, - 0x4dd9be1fa333d0L,0x6183aac74a72e4L,0x1d6f3ee69e1d03L, - 0x2fff96db0ff670L } }, - /* 66 */ - { { 0x2358f5c6a2123fL,0x5b2bfc51bedb63L,0x4fc6674be649ecL, - 0x51fc16e44b813aL,0x2ffe10a73754c1L,0x69a0c7a053aeefL, - 0x150e605fb6b9b4L }, - { 0x179eef6b8b83c4L,0x64293b28ad05efL,0x331795fab98572L, - 0x09823eec78727dL,0x36508042b89b81L,0x65f1106adb927eL, - 0x2fc0234617f47cL } }, - /* 67 */ - { { 0x12aa244e8068dbL,0x0c834ae5348f00L,0x310fc1a4771cb3L, - 0x6c90a2f9e19ef9L,0x77946fa0573471L,0x37f5df81e5f72fL, - 0x204f5d72cbe048L }, - { 0x613c724383bba6L,0x1ce14844967e0aL,0x797c85e69aa493L, - 0x4fb15b0f2ce765L,0x5807978e2e8aa7L,0x52c75859876a75L, - 0x1554635c763d3eL } }, - /* 68 */ - { { 0x4f292200623f3bL,0x6222be53d7fe07L,0x1e02a9a08c2571L, - 0x22c6058216b912L,0x1ec20044c7ba17L,0x53f94c5efde12bL, - 0x102b8aadfe32a4L }, - { 0x45377aa927b102L,0x0d41b8062ee371L,0x77085a9018e62aL, - 0x0c69980024847cL,0x14739b423a73a9L,0x52ec6961fe3c17L, - 0x38a779c94b5a7dL } }, - /* 69 */ - { { 0x4d14008435af04L,0x363bfd8325b4e8L,0x48cdb715097c95L, - 0x1b534540f8bee0L,0x4ca1e5c90c2a76L,0x4b52c193d6eee0L, - 0x277a33c79becf5L }, - { 0x0fee0d511d3d06L,0x4627f3d6a58f8cL,0x7c81ac245119b8L, - 0x0c8d526ba1e07aL,0x3dbc242f55bac2L,0x2399df8f91fffdL, - 0x353e982079ba3bL } }, - /* 70 */ - { { 0x6405d3b0ab9645L,0x7f31abe3ee236bL,0x456170a9babbb1L, - 0x09634a2456a118L,0x5b1c6045acb9e5L,0x2c75c20d89d521L, - 0x2e27ccf5626399L }, - { 0x307cd97fed2ce4L,0x1c2fbb02b64087L,0x542a068d27e64dL, - 0x148c030b3bc6a6L,0x671129e616ade5L,0x123f40db60dafcL, - 0x07688f3c621220L } }, - /* 71 */ - { { 0x1c46b342f2c4b5L,0x27decc0b3c8f04L,0x0d9bd433464c54L, - 0x1f3d893b818572L,0x2536043b536c94L,0x57e00c4b19ebf9L, - 0x3938fb9e5ad55eL }, - { 0x6b390024c8b22fL,0x4583f97e20a976L,0x2559d24abcbad7L, - 0x67a9cabc9bd8c6L,0x73a56f09432e4aL,0x79eb0beb53a3b7L, - 0x3e19d47f6f8221L } }, - /* 72 */ - { { 0x7399cb9d10e0b2L,0x32acc1b8a36e2aL,0x287d60c2407035L, - 0x42c82420ea4b5cL,0x13f286658bc268L,0x3c91181156e064L, - 0x234b83dcdeb963L }, - { 0x79bc95486cfee6L,0x4d8fd3cb78af36L,0x07362ba5e80da8L, - 0x79d024a0d681b0L,0x6b58406907f87fL,0x4b40f1e977e58fL, - 0x38dcc6fd5fa342L } }, - /* 73 */ - { { 0x72282be1cd0abeL,0x02bd0fdfdf44e5L,0x19b0e0d2f753e4L, - 0x4514e76ce8c4c0L,0x02ebc9c8cdcc1bL,0x6ac0c0373e9fddL, - 0x0dc414af1c81a9L }, - { 0x7a109246f32562L,0x26982e6a3768edL,0x5ecd8daed76ab5L, - 0x2eaa70061eb261L,0x09e7c038a8c514L,0x2a2603cc300658L, - 0x25d93ab9e55cd4L } }, - /* 74 */ - { { 0x11b19fcbd5256aL,0x41e4d94274770fL,0x0133c1a411001fL, - 0x360bac481dbca3L,0x45908b18a9c22bL,0x1e34396fafb03aL, - 0x1b84fea7486edaL }, - { 0x183c62a71e6e16L,0x5f1dc30e93da8eL,0x6cb97b502573c3L, - 0x3708bf0964e3fcL,0x35a7f042eeacceL,0x56370da902c27fL, - 0x3a873c3b72797fL } }, - /* 75 */ - { { 0x6573c9cea4cc9bL,0x2c3b5f9d91e6dcL,0x2a90e2dbd9505eL, - 0x66a75444025f81L,0x1571fb894b03cdL,0x5d1a1f00fd26f3L, - 0x0d19a9fd618855L }, - { 0x659acd56515664L,0x7279478bd616a3L,0x09a909e76d56c3L, - 0x2fd70474250358L,0x3a1a25c850579cL,0x11b9e0f71b74ccL, - 0x1268daef3d1bffL } }, - /* 76 */ - { { 0x7f5acc46d93106L,0x5bc15512f939c8L,0x504b5f92f996deL, - 0x25965549be7a64L,0x357a3a2ae9b80dL,0x3f2bcf9c139cc0L, - 0x0a7ddd99f23b35L }, - { 0x6868f5a8a0b1c5L,0x319ec52f15b1beL,0x0770000a849021L, - 0x7f4d50287bd608L,0x62c971d28a9d7fL,0x164e89309acb72L, - 0x2a29f002cf4a32L } }, - /* 77 */ - { { 0x58a852ae11a338L,0x27e3a35f2dcef8L,0x494d5731ce9e18L, - 0x49516f33f4bb3eL,0x386b26ba370097L,0x4e8fac1ec30248L, - 0x2ac26d4c44455dL }, - { 0x20484198eb9dd0L,0x75982a0e06512bL,0x152271b9279b05L, - 0x5908a9857e36d2L,0x6a933ab45a60abL,0x58d8b1acb24fafL, - 0x28fbcf19425590L } }, - /* 78 */ - { { 0x5420e9df010879L,0x4aba72aec2f313L,0x438e544eda7494L, - 0x2e8e189ce6f7eaL,0x2f771e4efe45bdL,0x0d780293bce7efL, - 0x1569ad3d0d02acL }, - { 0x325251ebeaf771L,0x02510f1a8511e2L,0x3863816bf8aad1L, - 0x60fdb15fe6ac19L,0x4792aef52a348cL,0x38e57a104e9838L, - 0x0d171611a1df1bL } }, - /* 79 */ - { { 0x15ceb0bea65e90L,0x6e56482db339bcL,0x37f618f7b0261fL, - 0x6351abc226dabcL,0x0e999f617b74baL,0x37d3cc57af5b69L, - 0x21df2b987aac68L }, - { 0x2dddaa3a358610L,0x2da264bc560e47L,0x545615d538bf13L, - 0x1c95ac244b8cc7L,0x77de1f741852cbL,0x75d324f00996abL, - 0x3a79b13b46aa3bL } }, - /* 80 */ - { { 0x7db63998683186L,0x6849bb989d530cL,0x7b53c39ef7ed73L, - 0x53bcfbf664d3ffL,0x25ef27c57f71c7L,0x50120ee80f3ad6L, - 0x243aba40ed0205L }, - { 0x2aae5e0ee1fcebL,0x3449d0d8343fbeL,0x5b2864fb7cffc7L, - 0x64dceb5407ac3eL,0x20303a5695523dL,0x3def70812010b2L, - 0x07be937f2e9b6fL } }, - /* 81 */ - { { 0x5838f9e0540015L,0x728d8720efb9f7L,0x1ab5864490b0c8L, - 0x6531754458fdcfL,0x600ff9612440c0L,0x48735b36a585b7L, - 0x3d4aaea86b865dL }, - { 0x6898942cac32adL,0x3c84c5531f23a1L,0x3c9dbd572f7edeL, - 0x5691f0932a2976L,0x186f0db1ac0d27L,0x4fbed18bed5bc9L, - 0x0e26b0dee0b38cL } }, - /* 82 */ - { { 0x1188b4f8e60f5bL,0x602a915455b4a2L,0x60e06af289ff99L, - 0x579fe4bed999e5L,0x2bc03b15e6d9ddL,0x1689649edd66d5L, - 0x3165e277dca9d2L }, - { 0x7cb8a529cf5279L,0x57f8035b34d84dL,0x352e2eb26de8f1L, - 0x6406820c3367c4L,0x5d148f4c899899L,0x483e1408482e15L, - 0x1680bd1e517606L } }, - /* 83 */ - { { 0x5c877cc1c90202L,0x2881f158eae1f4L,0x6f45e207df4267L, - 0x59280eba1452d8L,0x4465b61e267db5L,0x171f1137e09e5cL, - 0x1368eb821daa93L }, - { 0x70fe26e3e66861L,0x52a6663170da7dL,0x71d1ce5b7d79dcL, - 0x1cffe9be1e1afdL,0x703745115a29c4L,0x73b7f897b2f65aL, - 0x02218c3a95891aL } }, - /* 84 */ - { { 0x16866db8a9e8c9L,0x4770b770123d9bL,0x4c116cf34a8465L, - 0x079b28263fc86aL,0x3751c755a72b58L,0x7bc8df1673243aL, - 0x12fff72454f064L }, - { 0x15c049b89554e7L,0x4ea9ef44d7cd9aL,0x42f50765c0d4f1L, - 0x158bb603cb011bL,0x0809dde16470b1L,0x63cad7422ea819L, - 0x38b6cd70f90d7eL } }, - /* 85 */ - { { 0x1e4aab6328e33fL,0x70575f026da3aeL,0x7e1b55c8c55219L, - 0x328d4b403d24caL,0x03b6df1f0a5bd1L,0x26b4bb8b648ed0L, - 0x17161f2f10b76aL }, - { 0x6cdb32bae8b4c0L,0x33176266227056L,0x4975fa58519b45L, - 0x254602ea511d96L,0x4e82e93e402a67L,0x0ca8b5929cdb4fL, - 0x3ae7e0a07918f5L } }, - /* 86 */ - { { 0x60f9d1fecf5b9bL,0x6257e40d2cd469L,0x6c7aa814d28456L, - 0x58aac7caac8e79L,0x703a55f0293cbfL,0x702390a0f48378L, - 0x24b9ae07218b07L }, - { 0x1ebc66cdaf24e3L,0x7d9ae5f9f8e199L,0x42055ee921a245L, - 0x035595936e4d49L,0x129c45d425c08bL,0x6486c5f19ce6ddL, - 0x027dbd5f18ba24L } }, - /* 87 */ - { { 0x7d6b78d29375fbL,0x0a3dc6ba22ae38L,0x35090fa91feaf6L, - 0x7f18587fb7b16eL,0x6e7091dd924608L,0x54e102cdbf5ff8L, - 0x31b131a4c22079L }, - { 0x368f87d6a53fb0L,0x1d3f3d69a3f240L,0x36bf5f9e40e1c6L, - 0x17f150e01f8456L,0x76e5d0835eb447L,0x662fc0a1207100L, - 0x14e3dd97a98e39L } }, - /* 88 */ - { { 0x0249d9c2663b4bL,0x56b68f9a71ba1cL,0x74b119567f9c02L, - 0x5e6f336d8c92acL,0x2ced58f9f74a84L,0x4b75a2c2a467c5L, - 0x30557011cf740eL }, - { 0x6a87993be454ebL,0x29b7076fb99a68L,0x62ae74aaf99bbaL, - 0x399f9aa8fb6c1bL,0x553c24a396dd27L,0x2868337a815ea6L, - 0x343ab6635cc776L } }, - /* 89 */ - { { 0x0e0b0eec142408L,0x79728229662121L,0x605d0ac75e6250L, - 0x49a097a01edfbeL,0x1e20cd270df6b6L,0x7438a0ca9291edL, - 0x29daa430da5f90L }, - { 0x7a33844624825aL,0x181715986985c1L,0x53a6853cae0b92L, - 0x6d98401bd925e8L,0x5a0a34f5dd5e24L,0x7b818ef53cf265L, - 0x0836e43c9d3194L } }, - /* 90 */ - { { 0x1179b70e6c5fd9L,0x0246d9305dd44cL,0x635255edfbe2fbL, - 0x5397b3523b4199L,0x59350cc47e6640L,0x2b57aa97ed4375L, - 0x37efd31abd153aL }, - { 0x7a7afa6907f4faL,0x75c10cb94e6a7eL,0x60a925ab69cc47L, - 0x2ff5bcd9239bd5L,0x13c2113e425f11L,0x56bd3d2f8a1437L, - 0x2c9adbab13774fL } }, - /* 91 */ - { { 0x4ab9f52a2e5f2bL,0x5e537e70b58903L,0x0f242658ebe4f2L, - 0x2648a1e7a5f9aeL,0x1b4c5081e73007L,0x6827d4aff51850L, - 0x3925e41726cd01L }, - { 0x56dd8a55ab3cfbL,0x72d6a31b6d5beaL,0x697bd2e5575112L, - 0x66935519a7aa12L,0x55e97dda7a3aceL,0x0e16afb4237b4cL, - 0x00b68fbff08093L } }, - /* 92 */ - { { 0x4b00366481d0d9L,0x37cb031fbfc5c4L,0x14643f6800dd03L, - 0x6793fef60fe0faL,0x4f43e329c92803L,0x1fce86b96a6d26L, - 0x0ad416975e213aL }, - { 0x7cc6a6711adcc9L,0x64b8a63c43c2d9L,0x1e6caa2a67c0d0L, - 0x610deffd17a54bL,0x57d669d5f38423L,0x77364b8f022636L, - 0x36d4d13602e024L } }, - /* 93 */ - { { 0x72e667ae50a2f5L,0x1b15c950c3a21aL,0x3ccc37c72e6dfeL, - 0x027f7e1d094fb8L,0x43ae1e90aa5d7eL,0x3f5feac3d97ce5L, - 0x0363ed0a336e55L }, - { 0x235f73d7663784L,0x5d8cfc588ad5a4L,0x10ab6ff333016eL, - 0x7d8886af2e1497L,0x549f34fd17988eL,0x3fc4fcaee69a33L, - 0x0622b133a13d9eL } }, - /* 94 */ - { { 0x6344cfa796c53eL,0x0e9a10d00136fdL,0x5d1d284a56efd8L, - 0x608b1968f8aca7L,0x2fa5a66776edcaL,0x13430c44f1609cL, - 0x1499973cb2152aL }, - { 0x3764648104ab58L,0x3226e409fadafcL,0x1513a8466459ddL, - 0x649206ec365035L,0x46149aa3f765b1L,0x3aebf0a035248eL, - 0x1ee60b8c373494L } }, - /* 95 */ - { { 0x4e9efcc15f3060L,0x5e5d50fd77cdc8L,0x071e5403516b58L, - 0x1b7d4e89b24ceaL,0x53b1fa66d6dc03L,0x457f15f892ab5fL, - 0x076332c9397260L }, - { 0x31422b79d7584bL,0x0b01d47e41ba80L,0x3e5611a3171528L, - 0x5f53b9a9fc1be4L,0x7e2fc3d82f110fL,0x006cf350ef0fbfL, - 0x123ae98ec81c12L } }, - /* 96 */ - { { 0x310d41df46e2f6L,0x2ff032a286cf13L,0x64751a721c4eadL, - 0x7b62bcc0339b95L,0x49acf0c195afa4L,0x359d48742544e5L, - 0x276b7632d9e2afL }, - { 0x656c6be182579aL,0x75b65a4d85b199L,0x04a911d1721bfaL, - 0x46e023d0e33477L,0x1ec2d580acd869L,0x540b456f398a37L, - 0x001f698210153dL } }, - /* 97 */ - { { 0x3ca35217b00dd0L,0x73961d034f4d3cL,0x4f520b61c4119dL, - 0x4919fde5cccff7L,0x4d0e0e6f38134dL,0x55c22586003e91L, - 0x24d39d5d8f1b19L }, - { 0x4d4fc3d73234dcL,0x40c50c9d5f8368L,0x149afbc86bf2b8L, - 0x1dbafefc21d7f1L,0x42e6b61355107fL,0x6e506cf4b54f29L, - 0x0f498a6c615228L } }, - /* 98 */ - { { 0x30618f437cfaf8L,0x059640658532c4L,0x1c8a4d90e96e1dL, - 0x4a327bcca4fb92L,0x54143b8040f1a0L,0x4ec0928c5a49e4L, - 0x2af5ad488d9b1fL }, - { 0x1b392bd5338f55L,0x539c0292b41823L,0x1fe35d4df86a02L, - 0x5fa5bb17988c65L,0x02b6cb715adc26L,0x09a48a0c2cb509L, - 0x365635f1a5a9f2L } }, - /* 99 */ - { { 0x58aa87bdc21f31L,0x156900c7cb1935L,0x0ec1f75ee2b6cfL, - 0x5f3e35a77ec314L,0x582dec7b9b7621L,0x3e65deb0e8202aL, - 0x325c314b8a66b7L }, - { 0x702e2a22f24d66L,0x3a20e9982014f1L,0x6424c5b86bbfb0L, - 0x424eea4d795351L,0x7fc4cce7c22055L,0x581383fceb92d7L, - 0x32b663f49ee81bL } }, - /* 100 */ - { { 0x76e2d0b648b73eL,0x59ca39fa50bddaL,0x18bb44f786a7e4L, - 0x28c8d49d464360L,0x1b8bf1d3a574eaL,0x7c670b9bf1635aL, - 0x2efb30a291f4b3L }, - { 0x5326c069cec548L,0x03bbe481416531L,0x08a415c8d93d6fL, - 0x3414a52120d383L,0x1f17a0fc6e9c5cL,0x0de9a090717463L, - 0x22d84b3c67ff07L } }, - /* 101 */ - { { 0x30b5014c3830ebL,0x70791dc1a18b37L,0x09e6ea4e24f423L, - 0x65e148a5253132L,0x446f05d5d40449L,0x7ad5d3d707c0e9L, - 0x18eedd63dd3ab5L }, - { 0x40d2eac6bb29e0L,0x5b0e9605e83c38L,0x554f2c666a56a8L, - 0x0ac27b6c94c48bL,0x1aaecdd91bafe5L,0x73c6e2bdf72634L, - 0x306dab96d19e03L } }, - /* 102 */ - { { 0x6d3e4b42772f41L,0x1aba7796f3a39bL,0x3a03fbb980e9c0L, - 0x2f2ea5da2186a8L,0x358ff444ef1fcfL,0x0798cc0329fcdcL, - 0x39a28bcc9aa46dL }, - { 0x42775c977fe4d2L,0x5eb8fc5483d6b0L,0x0bfe37c039e3f7L, - 0x429292eaf9df60L,0x188bdf4b840cd5L,0x06e10e090749cdL, - 0x0e52678e73192eL } }, - /* 103 */ - { { 0x05de80b08df5feL,0x2af8c77406c5f8L,0x53573c50a0304aL, - 0x277b10b751bca0L,0x65cf8c559132a5L,0x4c667abe25f73cL, - 0x0271809e05a575L }, - { 0x41ced461f7a2fbL,0x0889a9ebdd7075L,0x320c63f2b7760eL, - 0x4f8d4324151c63L,0x5af47315be2e5eL,0x73c62f6aee2885L, - 0x206d6412a56a97L } }, - /* 104 */ - { { 0x6b1c508b21d232L,0x3781185974ead6L,0x1aba7c3ebe1fcfL, - 0x5bdc03cd3f3a5aL,0x74a25036a0985bL,0x5929e30b7211b2L, - 0x16a9f3bc366bd7L }, - { 0x566a7057dcfffcL,0x23b5708a644bc0L,0x348cda2aa5ba8cL, - 0x466aa96b9750d4L,0x6a435ed9b20834L,0x2e7730f2cf9901L, - 0x2b5cd71d5b0410L } }, - /* 105 */ - { { 0x285ab3cee76ef4L,0x68895e3a57275dL,0x6fab2e48fd1265L, - 0x0f1de060428c94L,0x668a2b080b5905L,0x1b589dc3b0cb37L, - 0x3c037886592c9bL }, - { 0x7fb5c0f2e90d4dL,0x334eefb3d8c91aL,0x75747124700388L, - 0x547a2c2e2737f5L,0x2af9c080e37541L,0x0a295370d9091aL, - 0x0bb5c36dad99e6L } }, - /* 106 */ - { { 0x644116586f25cbL,0x0c3f41f9ee1f5dL,0x00628d43a3dedaL, - 0x16e1437aae9669L,0x6aba7861bf3e59L,0x60735631ff4c44L, - 0x345609efaa615eL }, - { 0x41f54792e6acefL,0x4791583f75864dL,0x37f2ff5c7508b1L, - 0x1288912516c3b0L,0x51a2135f6a539bL,0x3b775511f42091L, - 0x127c6afa7afe66L } }, - /* 107 */ - { { 0x79f4f4f7492b73L,0x583d967256342dL,0x51a729bff33ca3L, - 0x3977d2c22d8986L,0x066f528ba8d40bL,0x5d759d30f8eb94L, - 0x0f8e649192b408L }, - { 0x22d84e752555bbL,0x76953855c728c7L,0x3b2254e72aaaa4L, - 0x508cd4ce6c0212L,0x726296d6b5a6daL,0x7a77aa066986f3L, - 0x2267a497bbcf31L } }, - /* 108 */ - { { 0x7f3651bf825dc4L,0x3988817388c56fL,0x257313ed6c3dd0L, - 0x3feab7f3b8ffadL,0x6c0d3cb9e9c9b4L,0x1317be0a7b6ac4L, - 0x2a5f399d7df850L }, - { 0x2fe5a36c934f5eL,0x429199df88ded1L,0x435ea21619b357L, - 0x6aac6a063bac2bL,0x600c149978f5edL,0x76543aa1114c95L, - 0x163ca9c83c7596L } }, - /* 109 */ - { { 0x7dda4a3e4daedbL,0x1824cba360a4cdL,0x09312efd70e0c6L, - 0x454e68a146c885L,0x40aee762fe5c47L,0x29811cbd755a59L, - 0x34b37c95f28319L }, - { 0x77c58b08b717d2L,0x309470d9a0f491L,0x1ab9f40448e01cL, - 0x21c8bd819207b1L,0x6a01803e9361bcL,0x6e5e4c350ec415L, - 0x14fd55a91f8798L } }, - /* 110 */ - { { 0x4cee562f512a90L,0x0008361d53e390L,0x3789b307a892cfL, - 0x064f7be8770ae9L,0x41435d848762cfL,0x662204dd38baa6L, - 0x23d6dcf73f6c5aL }, - { 0x69bef2d2c75d95L,0x2b037c0c9bb43eL,0x495fb4d79a34cfL, - 0x184e140c601260L,0x60193f8d435f9cL,0x283fa52a0c3ad2L, - 0x1998635e3a7925L } }, - /* 111 */ - { { 0x1cfd458ce382deL,0x0dddbd201bbcaeL,0x14d2ae8ed45d60L, - 0x73d764ab0c24cbL,0x2a97fe899778adL,0x0dbd1e01eddfe9L, - 0x2ba5c72d4042c3L }, - { 0x27eebc3af788f1L,0x53ffc827fc5a30L,0x6d1d0726d35188L, - 0x4721275c50aa2aL,0x077125f02e690fL,0x6da8142405db5dL, - 0x126cef68992513L } }, - /* 112 */ - { { 0x3c6067035b2d69L,0x2a1ad7db2361acL,0x3debece6cad41cL, - 0x30095b30f9afc1L,0x25f50b9bd9c011L,0x79201b2f2c1da1L, - 0x3b5c151449c5bdL }, - { 0x76eff4127abdb4L,0x2d31e03ce0382aL,0x24ff21f8bda143L, - 0x0671f244fd3ebaL,0x0c1c00b6bcc6fbL,0x18de9f7c3ebefbL, - 0x33dd48c3809c67L } }, - /* 113 */ - { { 0x61d6c2722d94edL,0x7e426e31041cceL,0x4097439f1b47b0L, - 0x579e798b2d205bL,0x6a430d67f830ebL,0x0d2c676700f727L, - 0x05fea83a82f25bL }, - { 0x3f3482df866b98L,0x3dd353b6a5a9cdL,0x77fe6ae1a48170L, - 0x2f75cc2a8f7cddL,0x7442a3863dad17L,0x643de42d877a79L, - 0x0fec8a38fe7238L } }, - /* 114 */ - { { 0x79b70c0760ac07L,0x195d3af37e9b29L,0x1317ff20f7cf27L, - 0x624e1c739e7504L,0x67330ef50f943dL,0x775e8cf455d793L, - 0x17b94d2d913a9fL }, - { 0x4b627203609e7fL,0x06aac5fb93e041L,0x603c515fdc2611L, - 0x2592ca0d7ae472L,0x02395d1f50a6cbL,0x466ef9648f85d9L, - 0x297cf879768f72L } }, - /* 115 */ - { { 0x3489d67d85fa94L,0x0a6e5b739c8e04L,0x7ebb5eab442e90L, - 0x52665a007efbd0L,0x0967ca57b0d739L,0x24891f9d932b63L, - 0x3cc2d6dbadc9d3L }, - { 0x4b4773c81c5338L,0x73cd47dad7a0f9L,0x7c755bab6ae158L, - 0x50b03d6becefcaL,0x574d6e256d57f0L,0x188db4fffb92aeL, - 0x197e10118071eaL } }, - /* 116 */ - { { 0x45d0cbcba1e7f1L,0x1180056abec91aL,0x6c5f86624bbc28L, - 0x442c83f3b8e518L,0x4e16ae1843ecb4L,0x670cef2fd786c9L, - 0x205b4acb637d2cL }, - { 0x70b0e539aa8671L,0x67c982056bebd0L,0x645c831a5e7c36L, - 0x09e06951a14b32L,0x5dd610ad4c89e6L,0x41c35f20164831L, - 0x3821f29cb4cdb8L } }, - /* 117 */ - { { 0x2831ffaba10079L,0x70f6dac9ffe444L,0x1cfa32ccc03717L, - 0x01519fda22a3c8L,0x23215e815aaa27L,0x390671ad65cbf7L, - 0x03dd4d72de7d52L }, - { 0x1ecd972ee95923L,0x166f8da3813e8eL,0x33199bbd387a1aL, - 0x04525fe15e3dc7L,0x44d2ef54165898L,0x4b7e47d3dc47f7L, - 0x10d5c8db0b5d44L } }, - /* 118 */ - { { 0x176d95ba9cdb1bL,0x14025f04f23dfcL,0x49379332891687L, - 0x6625e5ccbb2a57L,0x7ac0abdbf9d0e5L,0x7aded4fbea15b2L, - 0x314844ac184d67L }, - { 0x6d9ce34f05eae3L,0x3805d2875856d2L,0x1c2122f85e40ebL, - 0x51cb9f2d483a9aL,0x367e91e20f1702L,0x573c3559838dfdL, - 0x0b282b0cb85af1L } }, - /* 119 */ - { { 0x6a12e4ef871eb5L,0x64bb517e14f5ffL,0x29e04d3aaa530bL, - 0x1b07d88268f261L,0x411be11ed16fb0L,0x1f480536db70bfL, - 0x17a7deadfd34e4L }, - { 0x76d72f30646612L,0x5a3bbb43a1b0a0L,0x5e1687440e82bfL, - 0x713b5e69481112L,0x46c3dcb499e174L,0x0862da3b4e2a24L, - 0x31cb55b4d62681L } }, - /* 120 */ - { { 0x5ffc74dae5bb45L,0x18944c37adb9beL,0x6aaa63b1ee641aL, - 0x090f4b6ee057d3L,0x4045cedd2ee00fL,0x21c2c798f7c282L, - 0x2c2c6ef38cd6bdL }, - { 0x40d78501a06293L,0x56f8caa5cc89a8L,0x7231d5f91b37aeL, - 0x655f1e5a465c6dL,0x3f59a81f9cf783L,0x09bbba04c23624L, - 0x0f71ee23bbacdeL } }, - /* 121 */ - { { 0x38d398c4741456L,0x5204c0654243c3L,0x34498c916ea77eL, - 0x12238c60e5fe43L,0x0fc54f411c7625L,0x30b2ca43aa80b6L, - 0x06bead1bb6ea92L }, - { 0x5902ba8674b4adL,0x075ab5b0fa254eL,0x58db83426521adL, - 0x5b66b6b3958e39L,0x2ce4e39890e07bL,0x46702513338b37L, - 0x363690c2ded4d7L } }, - /* 122 */ - { { 0x765642c6b75791L,0x0f4c4300d7f673L,0x404d8bbe101425L, - 0x61e91c88651f1bL,0x61ddc9bc60aed8L,0x0ef36910ce2e65L, - 0x04b44367aa63b8L }, - { 0x72822d3651b7dcL,0x4b750157a2716dL,0x091cb4f2118d16L, - 0x662ba93b101993L,0x447cbd54a1d40aL,0x12cdd48d674848L, - 0x16f10415cbec69L } }, - /* 123 */ - { { 0x0c57a3a751cd0eL,0x0833d7478fadceL,0x1e751f55686436L, - 0x489636c58e1df7L,0x26ad6da941266fL,0x22225d3559880fL, - 0x35b397c45ba0e2L }, - { 0x3ca97b70e1f2ceL,0x78e50427a8680cL,0x06137e042a8f91L, - 0x7ec40d2500b712L,0x3f0ad688ad7b0dL,0x24746fb33f9513L, - 0x3638fcce688f0bL } }, - /* 124 */ - { { 0x753163750bed6fL,0x786507cd16157bL,0x1d6ec228ce022aL, - 0x587255f42d1b31L,0x0c6adf72a3a0f6L,0x4bfeee2da33f5eL, - 0x08b7300814de6cL }, - { 0x00bf8df9a56e11L,0x75aead48fe42e8L,0x3de9bad911b2e2L, - 0x0fadb233e4b8bbL,0x5b054e8fd84f7dL,0x5eb3064152889bL, - 0x01c1c6e8c777a1L } }, - /* 125 */ - { { 0x5fa0e598f8fcb9L,0x11c129a1ae18dfL,0x5c41b482a2273bL, - 0x545664e5044c9cL,0x7e01c915bfb9abL,0x7f626e19296aa0L, - 0x20c91a9822a087L }, - { 0x273a9fbe3c378fL,0x0f126b44b7d350L,0x493764a75df951L, - 0x32dec3c367d24bL,0x1a7ae987fed9d3L,0x58a93055928b85L, - 0x11626975d7775fL } }, - /* 126 */ - { { 0x2bb174a95540a9L,0x10de02c58b613fL,0x2fa8f7b861f3eeL, - 0x44731260bdf3b3L,0x19c38ff7da41feL,0x3535a16e3d7172L, - 0x21a948b83cc7feL }, - { 0x0e6f72868bc259L,0x0c70799df3c979L,0x526919955584c3L, - 0x4d95fda04f8fa2L,0x7bb228e6c0f091L,0x4f728b88d92194L, - 0x2b361c5a136bedL } }, - /* 127 */ - { { 0x0c72ca10c53841L,0x4036ab49f9da12L,0x578408d2b7082bL, - 0x2c4903201fbf5eL,0x14722b3f42a6a8L,0x1997b786181694L, - 0x25c6f10de32849L }, - { 0x79f46d517ff2ffL,0x2dc5d97528f6deL,0x518a494489aa72L, - 0x52748f8af3cf97L,0x472da30a96bb16L,0x1be228f92465a9L, - 0x196f0c47d60479L } }, - /* 128 */ - { { 0x47dd7d139b3239L,0x049c9b06775d0fL,0x627ffc00562d5eL, - 0x04f578d5e5e243L,0x43a788ffcef8b9L,0x7db320be9dde28L, - 0x00837528b8572fL }, - { 0x2969eca306d695L,0x195b72795ec194L,0x5e1fa9b8e77e50L, - 0x4c627f2b3fbfd5L,0x4b91e0d0ee10ffL,0x5698c8d0f35833L, - 0x12d3a9431f475eL } }, - /* 129 */ - { { 0x6409457a0db57eL,0x795b35192e0433L,0x146f973fe79805L, - 0x3d49c516dfb9cfL,0x50dfc3646b3cdaL,0x16a08a2210ad06L, - 0x2b4ef5bcd5b826L }, - { 0x5ebabfee2e3e3eL,0x2e048e724d9726L,0x0a7a7ed6abef40L, - 0x71ff7f83e39ad8L,0x3405ac52a1b852L,0x2e3233357a608dL, - 0x38c1bf3b0e40e6L } }, - /* 130 */ - { { 0x59aec823e4712cL,0x6ed9878331ddadL,0x1cc6faf629f2a0L, - 0x445ff79f36c18cL,0x4edc7ed57aff3dL,0x22ee54c8bdd9e8L, - 0x35398f42d72ec5L }, - { 0x4e7a1cceee0ecfL,0x4c66a707dd1d31L,0x629ad157a23c04L, - 0x3b2c6031dc3c83L,0x3336acbcd3d96cL,0x26ce43adfce0f0L, - 0x3c869c98d699dcL } }, - /* 131 */ - { { 0x58b3cd9586ba11L,0x5d6514b8090033L,0x7c88c3bd736782L, - 0x1735f84f2130edL,0x47784095a9dee0L,0x76312c6e47901bL, - 0x1725f6ebc51455L }, - { 0x6744344bc4503eL,0x16630b4d66e12fL,0x7b3481752c3ec7L, - 0x47bb2ed1f46f95L,0x08a1a497dd1bcfL,0x1f525df2b8ed93L, - 0x0fe492ea993713L } }, - /* 132 */ - { { 0x71b8dd7268b448L,0x1743dfaf3728d7L,0x23938d547f530aL, - 0x648c3d497d0fc6L,0x26c0d769e3ad45L,0x4d25108769a806L, - 0x3fbf2025143575L }, - { 0x485bfd90339366L,0x2de2b99ed87461L,0x24a33347713badL, - 0x1674bc7073958aL,0x5bb2373ee85b5fL,0x57f9bd657e662cL, - 0x2041b248d39042L } }, - /* 133 */ - { { 0x5f01617d02f4eeL,0x2a8e31c4244b91L,0x2dab3e790229e0L, - 0x72d319ea7544afL,0x01ffb8b000cb56L,0x065e63b0daafd3L, - 0x3d7200a7111d6fL }, - { 0x4561ce1b568973L,0x37034c532dd8ecL,0x1368215020be02L, - 0x30e7184cf289ebL,0x199e0c27d815deL,0x7ee1b4dff324e5L, - 0x2f4a11de7fab5cL } }, - /* 134 */ - { { 0x33c2f99b1cdf2bL,0x1e0d78bf42a2c0L,0x64485dececaa67L, - 0x2242a41be93e92L,0x62297b1f15273cL,0x16ebfaafb02205L, - 0x0f50f805f1fdabL }, - { 0x28bb0b3a70eb28L,0x5b1c7d0160d683L,0x05c30a37959f78L, - 0x3d9301184922d2L,0x46c1ead7dbcb1aL,0x03ee161146a597L, - 0x2d413ed9a6ccc1L } }, - /* 135 */ - { { 0x685ab5f97a27c2L,0x59178214023751L,0x4ffef3c585ab17L, - 0x2bc85302aba2a9L,0x675b001780e856L,0x103c8a37f0b33dL, - 0x2241e98ece70a6L }, - { 0x546738260189edL,0x086c8f7a6b96edL,0x00832ad878a129L, - 0x0b679056ba7462L,0x020ce6264bf8c4L,0x3f9f4b4d92abfbL, - 0x3e9c55343c92edL } }, - /* 136 */ - { { 0x482cec9b3f5034L,0x08b59b3cd1fa30L,0x5a55d1bc8e58b5L, - 0x464a5259337d8eL,0x0a5b6c66ade5a5L,0x55db77b504ddadL, - 0x015992935eac35L }, - { 0x54fe51025e32fcL,0x5d7f52dbe4a579L,0x08c564a8c58696L, - 0x4482a8bec4503fL,0x440e75d9d94de9L,0x6992d768020bfaL, - 0x06c311e8ba01f6L } }, - /* 137 */ - { { 0x2a6ac808223878L,0x04d3ccb4aab0b8L,0x6e6ef09ff6e823L, - 0x15cb03ee9158dcL,0x0dc58919171bf7L,0x3273568abf3cb1L, - 0x1b55245b88d98bL }, - { 0x28e9383b1de0c1L,0x30d5009e4f1f1bL,0x334d185a56a134L, - 0x0875865dfa4c46L,0x266edf5eae3beeL,0x2e03ff16d1f7e5L, - 0x29a36bd9f0c16dL } }, - /* 138 */ - { { 0x004cff44b2e045L,0x426c96380ba982L,0x422292281e46d7L, - 0x508dd8d29d7204L,0x3a4ea73fb2995eL,0x4be64090ae07b2L, - 0x3339177a0eff22L }, - { 0x74a97ec2b3106eL,0x0c616d09169f5fL,0x1bb5d8907241a7L, - 0x661fb67f6d41bdL,0x018a88a0daf136L,0x746333a093a7b4L, - 0x3e19f1ac76424eL } }, - /* 139 */ - { { 0x542a5656527296L,0x0e7b9ce22f1bc9L,0x31b0945992b89bL, - 0x6e0570eb85056dL,0x32daf813483ae5L,0x69eeae9d59bb55L, - 0x315ad4b730b557L }, - { 0x2bc16795f32923L,0x6b02b7ba55130eL,0x1e9da67c012f85L, - 0x5616f014dabf8fL,0x777395fcd9c723L,0x2ff075e7743246L, - 0x2993538aff142eL } }, - /* 140 */ - { { 0x72dae20e552b40L,0x2e4ba69aa5d042L,0x001e563e618bd2L, - 0x28feeba3c98772L,0x648c356da2a907L,0x687e2325069ea7L, - 0x0d34ab09a394f0L }, - { 0x73c21813111286L,0x5829b53b304e20L,0x6fba574de08076L, - 0x79f7058f61614eL,0x4e71c9316f1191L,0x24ef12193e0a89L, - 0x35dc4e2bc9d848L } }, - /* 141 */ - { { 0x045e6d3b4ad1cdL,0x729c95493782f0L,0x77f59de85b361aL, - 0x5309b4babf28f8L,0x4d893d9290935fL,0x736f47f2b2669eL, - 0x23270922d757f3L }, - { 0x23a4826f70d4e9L,0x68a8c63215d33eL,0x4d6c2069205c9cL, - 0x46b2938a5eebe0L,0x41d1f1e2de3892L,0x5ca1775544bcb0L, - 0x3130629e5d19dcL } }, - /* 142 */ - { { 0x6e2681593375acL,0x117cfbabc22621L,0x6c903cd4e13ccaL, - 0x6f358f14d4bd97L,0x1bc58fa11089f1L,0x36aa2db4ac426aL, - 0x15ced8464b7ea1L }, - { 0x6966836cba7df5L,0x7c2b1851568113L,0x22b50ff2ffca66L, - 0x50e77d9f48e49aL,0x32775e9bbc7cc9L,0x403915bb0ece71L, - 0x1b8ec7cb9dd7aaL } }, - /* 143 */ - { { 0x65a888b677788bL,0x51887fac2e7806L,0x06792636f98d2bL, - 0x47bbcd59824c3bL,0x1aca908c43e6dcL,0x2e00d15c708981L, - 0x08e031c2c80634L }, - { 0x77fbc3a297c5ecL,0x10a7948af2919eL,0x10cdafb1fb6b2fL, - 0x27762309b486f0L,0x13abf26bbac641L,0x53da38478fc3eeL, - 0x3c22eff379bf55L } }, - /* 144 */ - { { 0x0163f484770ee3L,0x7f28e8942e0cbfL,0x5f86cb51b43831L, - 0x00feccd4e4782fL,0x40e5b417eafe7dL,0x79e5742bbea228L, - 0x3717154aa469beL }, - { 0x271d74a270f721L,0x40eb400890b70cL,0x0e37be81d4cb02L, - 0x786907f4e8d43fL,0x5a1f5b590a7acbL,0x048861883851fdL, - 0x11534a1e563dbbL } }, - /* 145 */ - { { 0x37a6357c525435L,0x6afe6f897b78a5L,0x7b7ff311d4f67bL, - 0x38879df15dc9f4L,0x727def7b8ba987L,0x20285dd0db4436L, - 0x156b0fc64b9243L }, - { 0x7e3a6ec0c1c390L,0x668a88d9bcf690L,0x5925aba5440dbeL, - 0x0f6891a044f593L,0x70b46edfed4d97L,0x1a6cc361bab201L, - 0x046f5bc6e160bcL } }, - /* 146 */ - { { 0x79350f076bc9d1L,0x077d9e79a586b9L,0x0896bc0c705764L, - 0x58e632b90e7e46L,0x14e87e0ad32488L,0x4b1bb3f72c6e00L, - 0x3c3ce9684a5fc5L }, - { 0x108fbaf1f703aaL,0x08405ecec17577L,0x199a8e2d44be73L, - 0x2eb22ed0067763L,0x633944deda3300L,0x20d739eb8e5efbL, - 0x2bbbd94086b532L } }, - /* 147 */ - { { 0x03c8b17a19045dL,0x6205a0a504980bL,0x67fdb3e962b9f0L, - 0x16399e01511a4bL,0x44b09fe9dffc96L,0x00a74ff44a1381L, - 0x14590deed3f886L }, - { 0x54e3d5c2a23ddbL,0x310e5138209d28L,0x613f45490c1c9bL, - 0x6bbc85d44bbec8L,0x2f85fc559e73f6L,0x0d71fa7d0fa8cbL, - 0x2898571d17fbb9L } }, - /* 148 */ - { { 0x5607a84335167dL,0x3009c1eb910f91L,0x7ce63447e62d0bL, - 0x03a0633afcf89eL,0x1234b5aaa50872L,0x5a307b534d547bL, - 0x2f4e97138a952eL }, - { 0x13914c2db0f658L,0x6cdcb47e6e75baL,0x5549169caca772L, - 0x0f20423dfeb16fL,0x6b1ae19d180239L,0x0b7b3bee9b7626L, - 0x1ca81adacfe4efL } }, - /* 149 */ - { { 0x219ec3ad19d96fL,0x3549f6548132dbL,0x699889c7aacd0bL, - 0x74602a58730b19L,0x62dc63bcece81cL,0x316f991c0c317aL, - 0x2b8627867b95e3L }, - { 0x67a25ddced1eedL,0x7e14f0eba756e7L,0x0873fbc09b0495L, - 0x0fefb0e16596adL,0x03e6cd98ef39bbL,0x1179b1cded249dL, - 0x35c79c1db1edc2L } }, - /* 150 */ - { { 0x1368309d4245bfL,0x442e55852a7667L,0x095b0f0f348b65L, - 0x6834cf459dfad4L,0x6645950c9be910L,0x06bd81288c71e6L, - 0x1b015b6e944edfL }, - { 0x7a6a83045ab0e3L,0x6afe88b9252ad0L,0x2285bd65523502L, - 0x6c78543879a282L,0x1c5e264b5c6393L,0x3a820c6a7453eeL, - 0x37562d1d61d3c3L } }, - /* 151 */ - { { 0x6c084f62230c72L,0x599490270bc6cfL,0x1d3369ddd3c53dL, - 0x516ddb5fac5da0L,0x35ab1e15011b1aL,0x5fba9106d3a180L, - 0x3be0f092a0917cL }, - { 0x57328f9fdc2538L,0x0526323fc8d5f6L,0x10cbb79521e602L, - 0x50d01167147ae2L,0x2ec7f1b3cda99eL,0x43073cc736e7beL, - 0x1ded89cadd83a6L } }, - /* 152 */ - { { 0x1d51bda65d56d5L,0x63f2fd4d2dc056L,0x326413d310ea6dL, - 0x3abba5bca92876L,0x6b9aa8bc4d6ebeL,0x1961c687f15d5dL, - 0x311cf07464c381L }, - { 0x2321b1064cd8aeL,0x6e3caac4443850L,0x3346fc4887d2d0L, - 0x1640417e0e640fL,0x4a958a52a07a9eL,0x1346a1b1cb374cL, - 0x0a793cf79beccbL } }, - /* 153 */ - { { 0x29d56cba89aaa5L,0x1581898c0b3c15L,0x1af5b77293c082L, - 0x1617ba53a006ceL,0x62dd3b384e475fL,0x71a9820c3f962aL, - 0x0e4938920b854eL }, - { 0x0b8d98849808abL,0x64c14923546de7L,0x6a20883b78a6fcL, - 0x72de211428acd6L,0x009678b47915bbL,0x21b5269ae5dae6L, - 0x313cc0e60b9457L } }, - /* 154 */ - { { 0x69ee421b1de38bL,0x44b484c6cec1c7L,0x0240596c6a8493L, - 0x2321a62c85fb9eL,0x7a10921802a341L,0x3d2a95507e45c3L, - 0x0752f40f3b6714L }, - { 0x596a38798751e6L,0x46bf186a0feb85L,0x0b23093e23b49cL, - 0x1bfa7bc5afdc07L,0x4ba96f873eefadL,0x292e453fae9e44L, - 0x2773646667b75cL } }, - /* 155 */ - { { 0x1f81a64e94f22aL,0x3125ee3d8683ddL,0x76a660a13b9582L, - 0x5aa584c3640c6eL,0x27cc99fd472953L,0x7048f4d58061d1L, - 0x379a1397ac81e8L }, - { 0x5d1ecd2b6b956bL,0x0829e0366b0697L,0x49548cec502421L, - 0x7af5e2f717c059L,0x329a25a0fec54eL,0x028e99e4bcd7f1L, - 0x071d5fe81fca78L } }, - /* 156 */ - { { 0x4b5c4aeb0fdfe4L,0x1367e11326ce37L,0x7c16f020ef5f19L, - 0x3c55303d77b471L,0x23a4457a06e46aL,0x2174426dd98424L, - 0x226f592114bd69L }, - { 0x4411b94455f15aL,0x52e0115381fae4L,0x45b6d8efbc8f7eL, - 0x58b1221bd86d26L,0x284fb6f8a7ec1fL,0x045835939ddd30L, - 0x0216960accd598L } }, - /* 157 */ - { { 0x4b61f9ec1f138aL,0x4460cd1e18502bL,0x277e4fce3c4726L, - 0x0244246d6414b9L,0x28fbfcef256984L,0x3347ed0db40577L, - 0x3b57fa9e044718L }, - { 0x4f73bcd6d1c833L,0x2c0d0dcf7f0136L,0x2010ac75454254L, - 0x7dc4f6151539a8L,0x0b8929ef6ea495L,0x517e20119d2bdfL, - 0x1e29f9a126ba15L } }, - /* 158 */ - { { 0x683a7c10470cd8L,0x0d05f0dbe0007fL,0x2f6a5026d649cdL, - 0x249ce2fdaed603L,0x116dc1e7a96609L,0x199bd8d82a0b98L, - 0x0694ad0219aeb2L }, - { 0x03a3656e864045L,0x4e552273df82a6L,0x19bcc7553d17abL, - 0x74ac536c1df632L,0x440302fb4a86f6L,0x1becec0e31c9feL, - 0x002045f8fa46b8L } }, - /* 159 */ - { { 0x5833ba384310a2L,0x1db83fad93f8baL,0x0a12713ee2f7edL, - 0x40e0f0fdcd2788L,0x1746de5fb239a5L,0x573748965cfa15L, - 0x1e3dedda0ef650L }, - { 0x6c8ca1c87607aeL,0x785dab9554fc0eL,0x649d8f91860ac8L, - 0x4436f88b52c0f9L,0x67f22ca8a5e4a3L,0x1f990fd219e4c9L, - 0x013dd21c08573fL } }, - /* 160 */ - { { 0x05d116141d161cL,0x5c1d2789da2ea5L,0x11f0d861f99f34L, - 0x692c2650963153L,0x3bd69f5329539eL,0x215898eef8885fL, - 0x041f79dd86f7f1L }, - { 0x76dcc5e96beebdL,0x7f2b50cb42a332L,0x067621cabef8abL, - 0x31e0be607054edL,0x4c67c5e357a3daL,0x5b1a63fbfb1c2bL, - 0x3112efbf5e5c31L } }, - /* 161 */ - { { 0x3f83e24c0c62f1L,0x51dc9c32aae4e0L,0x2ff89b33b66c78L, - 0x21b1c7d354142cL,0x243d8d381c84bcL,0x68729ee50cf4b7L, - 0x0ed29e0f442e09L }, - { 0x1ad7b57576451eL,0x6b2e296d6b91dcL,0x53f2b306e30f42L, - 0x3964ebd9ee184aL,0x0a32855df110e4L,0x31f2f90ddae05fL, - 0x3410cd04e23702L } }, - /* 162 */ - { { 0x60d1522ca8f2feL,0x12909237a83e34L,0x15637f80d58590L, - 0x3c72431b6d714dL,0x7c8e59a615bea2L,0x5f977b688ef35aL, - 0x071c198c0b3ab0L }, - { 0x2b54c699699b4bL,0x14da473c2fd0bcL,0x7ba818ea0ad427L, - 0x35117013940b2fL,0x6e1df6b5e609dbL,0x3f42502720b64dL, - 0x01ee7dc890e524L } }, - /* 163 */ - { { 0x12ec1448ff4e49L,0x3e2edac882522bL,0x20455ab300f93aL, - 0x5849585bd67c14L,0x0393d5aa34ba8bL,0x30f9a1f2044fa7L, - 0x1059c9377a93e0L }, - { 0x4e641cc0139e73L,0x0d9f23c9b0fa78L,0x4b2ad87e2b83f9L, - 0x1c343a9f6d9e3cL,0x1098a4cb46de4dL,0x4ddc893843a41eL, - 0x1797f4167d6e3aL } }, - /* 164 */ - { { 0x4add4675856031L,0x499bd5e5f7a0ffL,0x39ea1f1202271eL, - 0x0ecd7480d7a91eL,0x395f5e5fc10956L,0x0fa7f6b0c9f79bL, - 0x2fad4623aed6cbL }, - { 0x1563c33ae65825L,0x29881cafac827aL,0x50650baf4c45a1L, - 0x034aad988fb9e9L,0x20a6224dc5904cL,0x6fb141a990732bL, - 0x3ec9ae1b5755deL } }, - /* 165 */ - { { 0x3108e7c686ae17L,0x2e73a383b4ad8aL,0x4e6bb142ba4243L, - 0x24d355922c1d80L,0x2f850dd9a088baL,0x21c50325dd5e70L, - 0x33237dd5bd7fa4L }, - { 0x7823a39cab7630L,0x1535f71cff830eL,0x70d92ff0599261L, - 0x227154d2a2477cL,0x495e9bbb4f871cL,0x40d2034835686bL, - 0x31b08f97eaa942L } }, - /* 166 */ - { { 0x0016c19034d8ddL,0x68961627cf376fL,0x6acc90681615aeL, - 0x6bc7690c2e3204L,0x6ddf28d2fe19a2L,0x609b98f84dae4dL, - 0x0f32bfd7c94413L }, - { 0x7d7edc6b21f843L,0x49bbd2ebbc9872L,0x593d6ada7b6a23L, - 0x55736602939e9cL,0x79461537680e39L,0x7a7ee9399ca7cdL, - 0x008776f6655effL } }, - /* 167 */ - { { 0x64585f777233cfL,0x63ec12854de0f6L,0x6b7f9bbbc3f99dL, - 0x301c014b1b55d3L,0x7cf3663bbeb568L,0x24959dcb085bd1L, - 0x12366aa6752881L }, - { 0x77a74c0da5e57aL,0x3279ca93ad939fL,0x33c3c8a1ef08c9L, - 0x641b05ab42825eL,0x02f416d7d098dbL,0x7e3d58be292b68L, - 0x1864dbc46e1f46L } }, - /* 168 */ - { { 0x1da167b8153a9dL,0x47593d07d9e155L,0x386d984e12927fL, - 0x421a6f08a60c7cL,0x5ae9661c24dab3L,0x7927b2e7874507L, - 0x3266ea80609d53L }, - { 0x7d198f4c26b1e3L,0x430d4ea2c4048eL,0x58d8ab77e84ba3L, - 0x1cb14299c37297L,0x6db6031e8f695cL,0x159bd855e26d55L, - 0x3f3f6d318a73ddL } }, - /* 169 */ - { { 0x3ee958cca40298L,0x02a7e5eba32ad6L,0x43b4bab96f0e1eL, - 0x534be79062b2b1L,0x029ead089b37e3L,0x4d585da558f5aaL, - 0x1f9737eb43c376L }, - { 0x0426dfd9b86202L,0x4162866bc0a9f3L,0x18fc518e7bb465L, - 0x6db63380fed812L,0x421e117f709c30L,0x1597f8d0f5cee6L, - 0x04ffbf1289b06aL } }, - /* 170 */ - { { 0x61a1987ffa0a5fL,0x42058c7fc213c6L,0x15b1d38447d2c9L, - 0x3d5f5d7932565eL,0x5db754af445fa7L,0x5d489189fba499L, - 0x02c4c55f51141bL }, - { 0x26b15972e9993dL,0x2fc90bcbd97c45L,0x2ff60f8684b0f1L, - 0x1dc641dd339ab0L,0x3e38e6be23f82cL,0x3368162752c817L, - 0x19bba80ceb45ceL } }, - /* 171 */ - { { 0x7c6e95b4c6c693L,0x6bbc6d5efa7093L,0x74d7f90bf3bf1cL, - 0x54d5be1f0299a1L,0x7cb24f0aa427c6L,0x0a18f3e086c941L, - 0x058a1c90e4faefL }, - { 0x3d6bd016927e1eL,0x1da4ce773098b8L,0x2133522e690056L, - 0x0751416d3fc37eL,0x1beed1643eda66L,0x5288b6727d5c54L, - 0x199320e78655c6L } }, - /* 172 */ - { { 0x74575027eeaf94L,0x124bd533c3ceaeL,0x69421ab7a8a1d7L, - 0x37f2127e093f3dL,0x40281765252a08L,0x25a228798d856dL, - 0x326eca62759c4cL }, - { 0x0c337c51acb0a5L,0x122ba78c1ef110L,0x02498adbb68dc4L, - 0x67240c124b089eL,0x135865d25d9f89L,0x338a76d5ae5670L, - 0x03a8efaf130385L } }, - /* 173 */ - { { 0x3a450ac5e49beaL,0x282af80bb4b395L,0x6779eb0db1a139L, - 0x737cabdd174e55L,0x017b14ca79b5f2L,0x61fdef6048e137L, - 0x3acc12641f6277L }, - { 0x0f730746fe5096L,0x21d05c09d55ea1L,0x64d44bddb1a560L, - 0x75e5035c4778deL,0x158b7776613513L,0x7b5efa90c7599eL, - 0x2caa0791253b95L } }, - /* 174 */ - { { 0x288e5b6d53e6baL,0x435228909d45feL,0x33b4cf23b2a437L, - 0x45b352017d6db0L,0x4372d579d6ef32L,0x0fa9e5badbbd84L, - 0x3a78cff24759bbL }, - { 0x0899d2039eab6eL,0x4cf47d2f76bc22L,0x373f739a3a8c69L, - 0x09beaa5b1000b3L,0x0acdfbe83ebae5L,0x10c10befb0e900L, - 0x33d2ac4cc31be3L } }, - /* 175 */ - { { 0x765845931e08fbL,0x2a3c2a0dc58007L,0x7270da587d90e1L, - 0x1ee648b2bc8f86L,0x5d2ca68107b29eL,0x2b7064846e9e92L, - 0x3633ed98dbb962L }, - { 0x5e0f16a0349b1bL,0x58d8941f570ca4L,0x20abe376a4cf34L, - 0x0f4bd69a360977L,0x21eb07cc424ba7L,0x720d2ecdbbe6ecL, - 0x255597d5a97c34L } }, - /* 176 */ - { { 0x67bbf21a0f5e94L,0x422a3b05a64fc1L,0x773ac447ebddc7L, - 0x1a1331c08019f1L,0x01ef6d269744ddL,0x55f7be5b3b401aL, - 0x072e031c681273L }, - { 0x7183289e21c677L,0x5e0a3391f3162fL,0x5e02d9e65d914aL, - 0x07c79ea1adce2fL,0x667ca5c2e1cbe4L,0x4f287f22caccdaL, - 0x27eaa81673e75bL } }, - /* 177 */ - { { 0x5246180a078fe6L,0x67cc8c9fa3bb15L,0x370f8dd123db31L, - 0x1938dafa69671aL,0x5af72624950c5eL,0x78cc5221ebddf8L, - 0x22d616fe2a84caL }, - { 0x723985a839327fL,0x24fa95584a5e22L,0x3d8a5b3138d38bL, - 0x3829ef4a017acfL,0x4f09b00ae055c4L,0x01df84552e4516L, - 0x2a7a18993e8306L } }, - /* 178 */ - { { 0x7b6224bc310eccL,0x69e2cff429da16L,0x01c850e5722869L, - 0x2e4889443ee84bL,0x264a8df1b3d09fL,0x18a73fe478d0d6L, - 0x370b52740f9635L }, - { 0x52b7d3a9d6f501L,0x5c49808129ee42L,0x5b64e2643fd30cL, - 0x27d903fe31b32cL,0x594cb084d078f9L,0x567fb33e3ae650L, - 0x0db7be9932cb65L } }, - /* 179 */ - { { 0x19b78113ed7cbeL,0x002b2f097a1c8cL,0x70b1dc17fa5794L, - 0x786e8419519128L,0x1a45ba376af995L,0x4f6aa84b8d806cL, - 0x204b4b3bc7ca47L }, - { 0x7581a05fd94972L,0x1c73cadb870799L,0x758f6fefc09b88L, - 0x35c62ba8049b42L,0x6f5e71fc164cc3L,0x0cd738b5702721L, - 0x10021afac9a423L } }, - /* 180 */ - { { 0x654f7937e3c115L,0x5d198288b515cbL,0x4add965c25a6e3L, - 0x5a37df33cd76ffL,0x57bb7e288e1631L,0x049b69089e1a31L, - 0x383a88f4122a99L }, - { 0x4c0e4ef3d80a73L,0x553c77ac9f30e2L,0x20bb18c2021e82L, - 0x2aec0d1c4225c5L,0x397fce0ac9c302L,0x2ab0c2a246e8aaL, - 0x02e5e5190be080L } }, - /* 181 */ - { { 0x7a255a4ae03080L,0x0d68b01513f624L,0x29905bd4e48c8cL, - 0x1d81507027466bL,0x1684aaeb70dee1L,0x7dd460719f0981L, - 0x29c43b0f0a390cL }, - { 0x272567681b1f7dL,0x1d2a5f8502e0efL,0x0fd5cd6b221befL, - 0x5eb4749e9a0434L,0x7d1553a324e2a6L,0x2eefd8e86a7804L, - 0x2ad80d5335109cL } }, - /* 182 */ - { { 0x25342aef4c209dL,0x24e811ac4e0865L,0x3f209757f8ae9dL, - 0x1473ff8a5da57bL,0x340f61c3919cedL,0x7523bf85fb9bc0L, - 0x319602ebca7cceL }, - { 0x121e7541d442cbL,0x4ffa748e49c95cL,0x11493cd1d131dcL, - 0x42b215172ab6b5L,0x045fd87e13cc77L,0x0ae305df76342fL, - 0x373b033c538512L } }, - /* 183 */ - { { 0x389541e9539819L,0x769f3b29b7e239L,0x0d05f695e3232cL, - 0x029d04f0e9a9fbL,0x58b78b7a697fb8L,0x7531b082e6386bL, - 0x215d235bed95a9L }, - { 0x503947c1859c5dL,0x4b82a6ba45443fL,0x78328eab71b3a5L, - 0x7d8a77f8cb3509L,0x53fcd9802e41d4L,0x77552091976edbL, - 0x226c60ad7a5156L } }, - /* 184 */ - { { 0x77ad6a43360710L,0x0fdeabd326d7aeL,0x4012886c92104aL, - 0x2d6c378dd7ae33L,0x7e72ef2c0725f3L,0x4a4671f4ca18e0L, - 0x0afe3b4bb6220fL }, - { 0x212cf4b56e0d6aL,0x7c24d086521960L,0x0662cf71bd414dL, - 0x1085b916c58c25L,0x781eed2be9a350L,0x26880e80db6ab2L, - 0x169e356442f061L } }, - /* 185 */ - { { 0x57aa2ad748b02cL,0x68a34256772a9aL,0x1591c44962f96cL, - 0x110a9edd6e53d2L,0x31eab597e091a3L,0x603e64e200c65dL, - 0x2f66b72e8a1cfcL }, - { 0x5c79d138543f7fL,0x412524363fdfa3L,0x547977e3b40008L, - 0x735ca25436d9f7L,0x232b4888cae049L,0x27ce37a53d8f23L, - 0x34d45881a9b470L } }, - /* 186 */ - { { 0x76b95255924f43L,0x035c9f3bd1aa5dL,0x5eb71a010b4bd0L, - 0x6ce8dda7e39f46L,0x35679627ea70c0L,0x5c987767c7d77eL, - 0x1fa28952b620b7L }, - { 0x106f50b5924407L,0x1cc3435a889411L,0x0597cdce3bc528L, - 0x738f8b0d5077d1L,0x5894dd60c7dd6aL,0x0013d0721f5e2eL, - 0x344573480527d3L } }, - /* 187 */ - { { 0x2e2c1da52abf77L,0x394aa8464ad05eL,0x095259b7330a83L, - 0x686e81cf6a11f5L,0x405c7e48c93c7cL,0x65c3ca9444a2ecL, - 0x07bed6c59c3563L }, - { 0x51f9d994fb1471L,0x3c3ecfa5283b4eL,0x494dccda63f6ccL, - 0x4d07b255363a75L,0x0d2b6d3155d118L,0x3c688299fc9497L, - 0x235692fa3dea3aL } }, - /* 188 */ - { { 0x16b4d452669e98L,0x72451fa85406b9L,0x674a145d39151fL, - 0x325ffd067ae098L,0x527e7805cd1ae0L,0x422a1d1789e48dL, - 0x3e27be63f55e07L }, - { 0x7f95f6dee0b63fL,0x008e444cc74969L,0x01348f3a72b614L, - 0x000cfac81348c3L,0x508ae3e5309ce5L,0x2584fcdee44d34L, - 0x3a4dd994899ee9L } }, - /* 189 */ - { { 0x4d289cc0368708L,0x0e5ebc60dc3b40L,0x78cc44bfab1162L, - 0x77ef2173b7d11eL,0x06091718e39746L,0x30fe19319b83a4L, - 0x17e8f2988529c6L }, - { 0x68188bdcaa9f2aL,0x0e64b1350c1bddL,0x5b18ebac7cc4b3L, - 0x75315a9fcc046eL,0x36e9770fd43db4L,0x54c5857fc69121L, - 0x0417e18f3e909aL } }, - /* 190 */ - { { 0x29795db38059adL,0x6efd20c8fd4016L,0x3b6d1ce8f95a1aL, - 0x4db68f177f8238L,0x14ec7278d2340fL,0x47bd77ff2b77abL, - 0x3d2dc8cd34e9fcL }, - { 0x285980a5a83f0bL,0x08352e2d516654L,0x74894460481e1bL, - 0x17f6f3709c480dL,0x6b590d1b55221eL,0x45c100dc4c9be9L, - 0x1b13225f9d8b91L } }, - /* 191 */ - { { 0x0b905fb4b41d9dL,0x48cc8a474cb7a2L,0x4eda67e8de09b2L, - 0x1de47c829adde8L,0x118ad5b9933d77L,0x7a12665ac3f9a4L, - 0x05631a4fb52997L }, - { 0x5fb2a8e6806e63L,0x27d96bbcca369bL,0x46066f1a6b8c7bL, - 0x63b58fc7ca3072L,0x170a36229c0d62L,0x57176f1e463203L, - 0x0c7ce083e73b9cL } }, - /* 192 */ - { { 0x31caf2c09e1c72L,0x6530253219e9d2L,0x7650c98b601c57L, - 0x182469f99d56c0L,0x415f65d292b7a7L,0x30f62a55549b8eL, - 0x30f443f643f465L }, - { 0x6b35c575ddadd0L,0x14a23cf6d299eeL,0x2f0198c0967d7dL, - 0x1013058178d5bfL,0x39da601c9cc879L,0x09d8963ec340baL, - 0x1b735db13ad2a7L } }, - /* 193 */ - { { 0x20916ffdc83f01L,0x16892aa7c9f217L,0x6bff179888d532L, - 0x4adf3c3d366288L,0x41a62b954726aeL,0x3139609022aeb6L, - 0x3e8ab9b37aff7aL }, - { 0x76bbc70f24659aL,0x33fa98513886c6L,0x13b26af62c4ea6L, - 0x3c4d5826389a0cL,0x526ec28c02bf6aL,0x751ff083d79a7cL, - 0x110ac647990224L } }, - /* 194 */ - { { 0x2c6c62fa2b6e20L,0x3d37edad30c299L,0x6ef25b44b65fcaL, - 0x7470846914558eL,0x712456eb913275L,0x075a967a9a280eL, - 0x186c8188f2a2a0L }, - { 0x2f3b41a6a560b1L,0x3a8070b3f9e858L,0x140936ff0e1e78L, - 0x5fd298abe6da8aL,0x3823a55d08f153L,0x3445eafaee7552L, - 0x2a5fc96731a8b2L } }, - /* 195 */ - { { 0x06317be58edbbbL,0x4a38f3bfbe2786L,0x445b60f75896b7L, - 0x6ec7c92b5adf57L,0x07b6be8038a441L,0x1bcfe002879655L, - 0x2a2174037d6d0eL }, - { 0x776790cf9e48bdL,0x73e14a2c4ed1d3L,0x7eb5ed5f2fc2f7L, - 0x3e0aedb821b384L,0x0ee3b7e151c12fL,0x51a6a29e044bb2L, - 0x0ba13a00cb0d86L } }, - /* 196 */ - { { 0x77607d563ec8d8L,0x023fc726996e44L,0x6bd63f577a9986L, - 0x114a6351e53973L,0x3efe97989da046L,0x1051166e117ed7L, - 0x0354933dd4fb5fL }, - { 0x7699ca2f30c073L,0x4c973b83b9e6d3L,0x2017c2abdbc3e8L, - 0x0cdcdd7a26522bL,0x511070f5b23c7dL,0x70672327e83d57L, - 0x278f842b4a9f26L } }, - /* 197 */ - { { 0x0824f0d4ae972fL,0x60578dd08dcf52L,0x48a74858290fbbL, - 0x7302748bf23030L,0x184b229a178acfL,0x3e8460ade089d6L, - 0x13f2b557fad533L }, - { 0x7f96f3ae728d15L,0x018d8d40066341L,0x01fb94955a289aL, - 0x2d32ed6afc2657L,0x23f4f5e462c3acL,0x60eba5703bfc5aL, - 0x1b91cc06f16c7aL } }, - /* 198 */ - { { 0x411d68af8219b9L,0x79cca36320f4eeL,0x5c404e0ed72e20L, - 0x417cb8692e43f2L,0x305d29c7d98599L,0x3b754d5794a230L, - 0x1c97fb4be404e9L }, - { 0x7cdbafababd109L,0x1ead0eb0ca5090L,0x1a2b56095303e3L, - 0x75dea935012c8fL,0x67e31c071b1d1dL,0x7c324fbfd172c3L, - 0x157e257e6498f7L } }, - /* 199 */ - { { 0x19b00db175645bL,0x4c4f6cb69725f1L,0x36d9ce67bd47ceL, - 0x2005e105179d64L,0x7b952e717867feL,0x3c28599204032cL, - 0x0f5659d44fb347L }, - { 0x1ebcdedb979775L,0x4378d45cfd11a8L,0x14c85413ca66e9L, - 0x3dd17d681c8a4dL,0x58368e7dc23142L,0x14f3eaac6116afL, - 0x0adb45b255f6a0L } }, - /* 200 */ - { { 0x2f5e76279ad982L,0x125b3917034d09L,0x3839a6399e6ed3L, - 0x32fe0b3ebcd6a2L,0x24ccce8be90482L,0x467e26befcc187L, - 0x2828434e2e218eL }, - { 0x17247cd386efd9L,0x27f36a468d85c3L,0x65e181ef203bbfL, - 0x0433a6761120afL,0x1d607a2a8f8625L,0x49f4e55a13d919L, - 0x3367c3b7943e9dL } }, - /* 201 */ - { { 0x3391c7d1a46d4dL,0x38233d602d260cL,0x02127a0f78b7d4L, - 0x56841c162c24c0L,0x4273648fd09aa8L,0x019480bb0e754eL, - 0x3b927987b87e58L }, - { 0x6676be48c76f73L,0x01ec024e9655aeL,0x720fe1c6376704L, - 0x17e06b98885db3L,0x656adec85a4200L,0x73780893c3ce88L, - 0x0a339cdd8df664L } }, - /* 202 */ - { { 0x69af7244544ac7L,0x31ab7402084d2fL,0x67eceb7ef7cb19L, - 0x16f8583b996f61L,0x1e208d12faf91aL,0x4a91584ce4a42eL, - 0x3e08337216c93eL }, - { 0x7a6eea94f4cf77L,0x07a52894678c60L,0x302dd06b14631eL, - 0x7fddb7225c9ceaL,0x55e441d7acd153L,0x2a00d4490b0f44L, - 0x053ef125338cdbL } }, - /* 203 */ - { { 0x120c0c51584e3cL,0x78b3efca804f37L,0x662108aefb1dccL, - 0x11deb55f126709L,0x66def11ada8125L,0x05bbc0d1001711L, - 0x1ee1c99c7fa316L }, - { 0x746f287de53510L,0x1733ef2e32d09cL,0x1df64a2b0924beL, - 0x19758da8f6405eL,0x28f6eb3913e484L,0x7175a1090cc640L, - 0x048aee0d63f0bcL } }, - /* 204 */ - { { 0x1f3b1e3b0b29c3L,0x48649f4882a215L,0x485eca3a9e0dedL, - 0x4228ba85cc82e4L,0x36da1f39bc9379L,0x1659a7078499d1L, - 0x0a67d5f6c04188L }, - { 0x6ac39658afdce3L,0x0d667a0bde8ef6L,0x0ae6ec0bfe8548L, - 0x6d9cb2650571bfL,0x54bea107760ab9L,0x705c53bd340cf2L, - 0x111a86b610c70fL } }, - /* 205 */ - { { 0x7ecea05c6b8195L,0x4f8be93ce3738dL,0x305de9eb9f5d12L, - 0x2c3b9d3d474b56L,0x673691a05746c3L,0x2e3482c428c6eaL, - 0x2a8085fde1f472L }, - { 0x69d15877fd3226L,0x4609c9ec017cc3L,0x71e9b7fc1c3dbcL, - 0x4f8951254e2675L,0x63ee9d15afa010L,0x0f05775b645190L, - 0x28a0a439397ae3L } }, - /* 206 */ - { { 0x387fa03e9de330L,0x40cc32b828b6abL,0x02a482fbc04ac9L, - 0x68cad6e70429b7L,0x741877bff6f2c4L,0x48efe633d3b28bL, - 0x3e612218fe24b3L }, - { 0x6fc1d34fe37657L,0x3d04b9e1c8b5a1L,0x6a2c332ef8f163L, - 0x7ca97e2b135690L,0x37357d2a31208aL,0x29f02f2332bd68L, - 0x17c674c3e63a57L } }, - /* 207 */ - { { 0x683d9a0e6865bbL,0x5e77ec68ad4ce5L,0x4d18f236788bd6L, - 0x7f34b87204f4e3L,0x391ca40e9e578dL,0x3470ed6ddf4e23L, - 0x225544b3e50989L }, - { 0x48eda8cb4e462bL,0x2a948825cf9109L,0x473adedc7e1300L, - 0x37b843b82192edL,0x2b9ac1537dde36L,0x4efe7412732332L, - 0x29cc5981b5262bL } }, - /* 208 */ - { { 0x190d2fcad260f5L,0x7c53dd81d18027L,0x003def5f55db0eL, - 0x7f5ed25bee2df7L,0x2b87e9be167d2eL,0x2b999c7bbcd224L, - 0x1d68a2c260ad50L }, - { 0x010bcde84607a6L,0x0250de9b7e1bedL,0x746d36bfaf1b56L, - 0x3359475ff56abbL,0x7e84b9bc440b20L,0x2eaa7e3b52f162L, - 0x01165412f36a69L } }, - /* 209 */ - { { 0x639a02329e5836L,0x7aa3ee2e4d3a27L,0x5bc9b258ecb279L, - 0x4cb3dfae2d62c6L,0x08d9d3b0c6c437L,0x5a2c177d47eab2L, - 0x36120479fc1f26L }, - { 0x7609a75bd20e4aL,0x3ba414e17551fcL,0x42cd800e1b90c9L, - 0x04921811b88f9bL,0x4443697f9562fdL,0x3a8081b8186959L, - 0x3f5b5c97379e73L } }, - /* 210 */ - { { 0x6fd0e3cf13eafbL,0x3976b5415cbf67L,0x4de40889e48402L, - 0x17e4d36f24062aL,0x16ae7755cf334bL,0x2730ac94b7e0e1L, - 0x377592742f48e0L }, - { 0x5e10b18a045041L,0x682792afaae5a1L,0x19383ec971b816L, - 0x208b17dae2ffc0L,0x439f9d933179b6L,0x55485a9090bcaeL, - 0x1c316f42a2a35cL } }, - /* 211 */ - { { 0x67173897bdf646L,0x0b6956653ef94eL,0x5be3c97f7ea852L, - 0x3110c12671f08eL,0x2474076a3fc7ecL,0x53408be503fe72L, - 0x09155f53a5b44eL }, - { 0x5c804bdd4c27cdL,0x61e81eb8ffd50eL,0x2f7157fdf84717L, - 0x081f880d646440L,0x7aa892acddec51L,0x6ae70683443f33L, - 0x31ed9e8b33a75aL } }, - /* 212 */ - { { 0x0d724f8e357586L,0x1febbec91b4134L,0x6ff7b98a9475fdL, - 0x1c4d9b94e1f364L,0x2b8790499cef00L,0x42fd2080a1b31dL, - 0x3a3bbc6d9b0145L }, - { 0x75bfebc37e3ca9L,0x28db49c1723bd7L,0x50b12fa8a1f17aL, - 0x733d95bbc84b98L,0x45ede81f6c109eL,0x18f5e46fb37b5fL, - 0x34b980804aaec1L } }, - /* 213 */ - { { 0x56060c8a4f57bfL,0x0d2dfe223054c2L,0x718a5bbc03e5d6L, - 0x7b3344cc19b3b9L,0x4d11c9c054bcefL,0x1f5ad422c22e33L, - 0x2609299076f86bL }, - { 0x7b7a5fba89fd01L,0x7013113ef3b016L,0x23d5e0a173e34eL, - 0x736c14462f0f50L,0x1ef5f7ac74536aL,0x4baba6f4400ea4L, - 0x17b310612c9828L } }, - /* 214 */ - { { 0x4ebb19a708c8d3L,0x209f8c7f03d9bbL,0x00461cfe5798fbL, - 0x4f93b6ae822fadL,0x2e5b33b5ad5447L,0x40b024e547a84bL, - 0x22ffad40443385L }, - { 0x33809c888228bfL,0x559f655fefbe84L,0x0032f529fd2f60L, - 0x5a2191ece3478cL,0x5b957fcd771246L,0x6fec181f9ed123L, - 0x33eed3624136a3L } }, - /* 215 */ - { { 0x6a5df93b26139aL,0x55076598fd7134L,0x356a592f34f81dL, - 0x493c6b5a3d4741L,0x435498a4e2a39bL,0x2cd26a0d931c88L, - 0x01925ea3fc7835L }, - { 0x6e8d992b1efa05L,0x79508a727c667bL,0x5f3c15e6b4b698L, - 0x11b6c755257b93L,0x617f5af4b46393L,0x248d995b2b6656L, - 0x339db62e2e22ecL } }, - /* 216 */ - { { 0x52537a083843dcL,0x6a283c82a768c7L,0x13aa6bf25227acL, - 0x768d76ba8baf5eL,0x682977a6525808L,0x67ace52ac23b0bL, - 0x2374b5a2ed612dL }, - { 0x7139e60133c3a4L,0x715697a4f1d446L,0x4b018bf36677a0L, - 0x1dd43837414d83L,0x505ec70730d4f6L,0x09ac100907fa79L, - 0x21caad6e03217eL } }, - /* 217 */ - { { 0x0776d3999d4d49L,0x33bdd87e8bcff8L,0x1036b87f068fadL, - 0x0a9b8ffde4c872L,0x7ab2533596b1eaL,0x305a88fb965378L, - 0x3356d8fa4d65e5L }, - { 0x3366fa77d1ff11L,0x1e0bdbdcd2075cL,0x46910cefc967caL, - 0x7ce700737a1ff6L,0x1c5dc15409c9bdL,0x368436b9bdb595L, - 0x3e7ccd6560b5efL } }, - /* 218 */ - { { 0x1443789422c792L,0x524792b1717f2bL,0x1f7c1d95048e7aL, - 0x5cfe2a225b0d12L,0x245594d29ce85bL,0x20134d254ce168L, - 0x1b83296803921aL }, - { 0x79a78285b3beceL,0x3c738c3f3124d6L,0x6ab9d1fe0907cdL, - 0x0652ceb7fc104cL,0x06b5f58c8ae3fdL,0x486959261c5328L, - 0x0b3813ae677c90L } }, - /* 219 */ - { { 0x66b9941ac37b82L,0x651a4b609b0686L,0x046711edf3fc31L, - 0x77f89f38faa89bL,0x2683ddbf2d5edbL,0x389ef1dfaa3c25L, - 0x20b3616e66273eL }, - { 0x3c6db6e0cb5d37L,0x5d7ae5dc342bc4L,0x74a1dc6c52062bL, - 0x6f7c0bec109557L,0x5c51f7bc221d91L,0x0d7b5880745288L, - 0x1c46c145c4b0ddL } }, - /* 220 */ - { { 0x59ed485ea99eccL,0x201b71956bc21dL,0x72d5c32f73de65L, - 0x1aefd76547643eL,0x580a452cfb2c2dL,0x7cb1a63f5c4dc9L, - 0x39a8df727737aaL }, - { 0x365a341deca452L,0x714a1ad1689cbaL,0x16981d12c42697L, - 0x5a124f4ac91c75L,0x1b2e3f2fedc0dbL,0x4a1c72b8e9d521L, - 0x3855b4694e4e20L } }, - /* 221 */ - { { 0x16b3d047181ae9L,0x17508832f011afL,0x50d33cfeb2ebd1L, - 0x1deae237349984L,0x147c641aa6adecL,0x24a9fb4ebb1ddbL, - 0x2b367504a7a969L }, - { 0x4c55a3d430301bL,0x379ef6a5d492cbL,0x3c56541fc0f269L, - 0x73a546e91698ceL,0x2c2b62ee0b9b5dL,0x6284184d43d0efL, - 0x0e1f5cf6a4b9f0L } }, - /* 222 */ - { { 0x44833e8cd3fdacL,0x28e6665cb71c27L,0x2f8bf87f4ddbf3L, - 0x6cc6c767fb38daL,0x3bc114d734e8b5L,0x12963d5a78ca29L, - 0x34532a161ece41L }, - { 0x2443af5d2d37e9L,0x54e6008c8c452bL,0x2c55d54111cf1bL, - 0x55ac7f7522575aL,0x00a6fba3f8575fL,0x3f92ef3b793b8dL, - 0x387b97d69ecdf7L } }, - /* 223 */ - { { 0x0b464812d29f46L,0x36161daa626f9aL,0x5202fbdb264ca5L, - 0x21245805ff1304L,0x7f9c4a65657885L,0x542d3887f9501cL, - 0x086420deef8507L }, - { 0x5e159aa1b26cfbL,0x3f0ef5ffd0a50eL,0x364b29663a432aL, - 0x49c56888af32a8L,0x6f937e3e0945d1L,0x3cbdeec6d766cdL, - 0x2d80d342ece61aL } }, - /* 224 */ - { { 0x255e3026d8356eL,0x4ddba628c4de9aL,0x074323b593e0d9L, - 0x333bdb0a10eefbL,0x318b396e473c52L,0x6ebb5a95efd3d3L, - 0x3f3bff52aa4e4fL }, - { 0x3138a111c731d5L,0x674365e283b308L,0x5585edd9c416f2L, - 0x466763d9070fd4L,0x1b568befce8128L,0x16eb040e7b921eL, - 0x3d5c898687c157L } }, - /* 225 */ - { { 0x14827736973088L,0x4e110d53f301e6L,0x1f811b09870023L, - 0x53b5e500dbcacaL,0x4ddf0df1e6a7dcL,0x1e9575fb10ce35L, - 0x3fdc153644d936L }, - { 0x763547e2260594L,0x26e5ae764efc59L,0x13be6f4d791a29L, - 0x2021e61e3a0cf1L,0x339cd2b4a1c202L,0x5c7451e08f5121L, - 0x3728b3a851be68L } }, - /* 226 */ - { { 0x78873653277538L,0x444b9ed2ee7156L,0x79ac8b8b069cd3L, - 0x5f0e90933770e8L,0x307662c615389eL,0x40fe6d95a80057L, - 0x04822170cf993cL }, - { 0x677d5690fbfec2L,0x0355af4ae95cb3L,0x417411794fe79eL, - 0x48daf87400a085L,0x33521d3b5f0aaaL,0x53567a3be00ff7L, - 0x04712ccfb1cafbL } }, - /* 227 */ - { { 0x2b983283c3a7f3L,0x579f11b146a9a6L,0x1143d3b16a020eL, - 0x20f1483ef58b20L,0x3f03e18d747f06L,0x3129d12f15de37L, - 0x24c911f7222833L }, - { 0x1e0febcf3d5897L,0x505e26c01cdaacL,0x4f45a9adcff0e9L, - 0x14dfac063c5cebL,0x69e5ce713fededL,0x3481444a44611aL, - 0x0ea49295c7fdffL } }, - /* 228 */ - { { 0x64554cb4093beeL,0x344b4b18dd81f6L,0x350f43b4de9b59L, - 0x28a96a220934caL,0x4aa8da5689a515L,0x27171cbd518509L, - 0x0cfc1753f47c95L }, - { 0x7dfe091b615d6eL,0x7d1ee0aa0fb5c1L,0x145eef3200b7b5L, - 0x33fe88feeab18fL,0x1d62d4f87453e2L,0x43b8db4e47fff1L, - 0x1572f2b8b8f368L } }, - /* 229 */ - { { 0x6bc94e6b4e84f3L,0x60629dee586a66L,0x3bbad5fe65ca18L, - 0x217670db6c2fefL,0x0320a7f4e3272aL,0x3ccff0d976a6deL, - 0x3c26da8ae48cccL }, - { 0x53ecf156778435L,0x7533064765a443L,0x6c5c12f03ca5deL, - 0x44f8245350dabfL,0x342cdd777cf8b3L,0x2b539c42e9f58dL, - 0x10138affc279b1L } }, - /* 230 */ - { { 0x1b135e204c5ddbL,0x40887dfeaa1d37L,0x7fb0ef83da76ffL, - 0x521f2b79af55a5L,0x3f9b38b4c3f0d0L,0x20a9838cce61ceL, - 0x24bb4e2f4b1e32L }, - { 0x003f6aa386e27cL,0x68df59db0a0f8eL,0x21677d5192e713L, - 0x14ab9757501276L,0x411944af961524L,0x3184f39abc5c3fL, - 0x2a8dda80ca078dL } }, - /* 231 */ - { { 0x0592233cdbc95cL,0x54d5de5c66f40fL,0x351caa1512ab86L, - 0x681bdbee020084L,0x6ee2480c853e68L,0x6a5a44262b918fL, - 0x06574e15a3b91dL }, - { 0x31ba03dacd7fbeL,0x0c3da7c18a57a9L,0x49aaaded492d6bL, - 0x3071ff53469e02L,0x5efb4f0d7248c6L,0x6db5fb67f12628L, - 0x29cff668e3d024L } }, - /* 232 */ - { { 0x1b9ef3bb1b17ceL,0x6ccf8c24fe6312L,0x34c15487f45008L, - 0x1a84044095972cL,0x515073a47e449eL,0x2ddc93f9097feeL, - 0x1008fdc894c434L }, - { 0x08e5edb73399faL,0x65b1aa65547d4cL,0x3a117a1057c498L, - 0x7e16c3089d13acL,0x502f2ae4b6f851L,0x57a70f3eb62673L, - 0x111b48a9a03667L } }, - /* 233 */ - { { 0x5023024be164f1L,0x25ad117032401eL,0x46612b3bfe3427L, - 0x2f4f406a8a02b7L,0x16a93a5c4ddf07L,0x7ee71968fcdbe9L, - 0x2267875ace37daL }, - { 0x687e88b59eb2a6L,0x3ac7368fe716d3L,0x28d953a554a036L, - 0x34d52c0acca08fL,0x742a7cf8dd4fd9L,0x10bfeb8575ea60L, - 0x290e454d868dccL } }, - /* 234 */ - { { 0x4e72a3a8a4bdd2L,0x1ba36d1dee04d5L,0x7a43136b63195bL, - 0x6ca8e286a519f3L,0x568e64aece08a9L,0x571d5000b5c10bL, - 0x3f75e9f5dbdd40L }, - { 0x6fb0a698d6fa45L,0x0ce42209d7199cL,0x1f68275f708a3eL, - 0x5749832e91ec3cL,0x6c3665521428b2L,0x14b2bf5747bd4aL, - 0x3b6f940e42a22bL } }, - /* 235 */ - { { 0x4da0adbfb26c82L,0x16792a585f39acL,0x17df9dfda3975cL, - 0x4796b4afaf479bL,0x67be67234e0020L,0x69df5f201dda25L, - 0x09f71a4d12b3dcL }, - { 0x64ff5ec260a46aL,0x579c5b86385101L,0x4f29a7d549f697L, - 0x4e64261242e2ebL,0x54ecacdfb6b296L,0x46e0638b5fddadL, - 0x31eefd3208891dL } }, - /* 236 */ - { { 0x5b72c749fe01b2L,0x230cf27523713aL,0x533d1810e0d1e1L, - 0x5590db7d1dd1e2L,0x7b8ab73e8e43d3L,0x4c8a19bd1c17caL, - 0x19222ce9f74810L }, - { 0x6398b3dddc4582L,0x0352b7d88dfd53L,0x3c55b4e10c5a63L, - 0x38194d13f8a237L,0x106683fd25dd87L,0x59e0b62443458eL, - 0x196cb70aa9cbb9L } }, - /* 237 */ - { { 0x2885f7cd021d63L,0x162bfd4c3e1043L,0x77173dcf98fcd1L, - 0x13d4591d6add36L,0x59311154d0d8f2L,0x74336e86e79b8aL, - 0x13faadc5661883L }, - { 0x18938e7d9ec924L,0x14bcda8fcaa0a1L,0x706d85d41a1355L, - 0x0ac34520d168deL,0x5a92499fe17826L,0x36c2e3b4f00600L, - 0x29c2fd7b5f63deL } }, - /* 238 */ - { { 0x41250dfe2216c5L,0x44a0ec0366a217L,0x575bc1adf8b0dfL, - 0x5ff5cdbdb1800bL,0x7843d4dde8ca18L,0x5fa9e420865705L, - 0x235c38be6c6b02L }, - { 0x473b78aae91abbL,0x39470c6051e44bL,0x3f973cc2dc08c3L, - 0x2837932c5c91f6L,0x25e39ed754ec25L,0x1371c837118e53L, - 0x3b99f3b0aeafe2L } }, - /* 239 */ - { { 0x03acf51be46c65L,0x271fceacbaf5c3L,0x476589ed3a5e25L, - 0x78ec8c3c3c399cL,0x1f5c8bf4ac4c19L,0x730bb733ec68d2L, - 0x29a37e00dd287eL }, - { 0x448ed1bf92b5faL,0x10827c17b86478L,0x55e6fc05b28263L, - 0x0af1226c73a66aL,0x0b66e5df0d09c1L,0x26128315a02682L, - 0x22d84932c5e808L } }, - /* 240 */ - { { 0x5ec3afc26e3392L,0x08e142e45c0084L,0x4388d5ad0f01feL, - 0x0f7acd36e6140cL,0x028c14ed97dffbL,0x311845675a38c6L, - 0x01c1c8f09a3062L }, - { 0x5a302f4cf49e7dL,0x79267e254a44e1L,0x746165052317a1L, - 0x53a09263a566e8L,0x7d478ad5f73abcL,0x187ce5c947dad3L, - 0x18564e1a1ec45fL } }, - /* 241 */ - { { 0x7b9577a9aa0486L,0x766b40c7aaaef6L,0x1f6a411f5db907L, - 0x4543dd4d80beaeL,0x0ad938c7482806L,0x451568bf4b9be1L, - 0x3367ec85d30a22L }, - { 0x5446425747843dL,0x18d94ac223c6b2L,0x052ff3a354d359L, - 0x0b4933f89723f5L,0x03fb517740e056L,0x226b892871dddaL, - 0x2768c2b753f0fdL } }, - /* 242 */ - { { 0x685282ccfa5200L,0x411ed433627b89L,0x77d5c9b8bc9c1dL, - 0x4a13ef2ee5cd29L,0x5582a612407c9eL,0x2307cb42fc3aa9L, - 0x2e661df79956b8L }, - { 0x0e972b015254deL,0x5b63e14def8adeL,0x06995be2ca4a95L, - 0x6cc0cc1e94bf27L,0x7ed8499fe0052aL,0x671a6ca5a5e0f9L, - 0x31e10d4ba10f05L } }, - /* 243 */ - { { 0x690af07e9b2d8aL,0x6030af9e32c8ddL,0x45c7ca3bf2b235L, - 0x40959077b76c81L,0x61eee7f70d5a96L,0x6b04f6aafe9e38L, - 0x3c726f55f1898dL }, - { 0x77d0142a1a6194L,0x1c1631215708b9L,0x403a4f0a9b7585L, - 0x066c8e29f7cef0L,0x6fc32f98cf575eL,0x518a09d818c297L, - 0x34144e99989e75L } }, - /* 244 */ - { { 0x6adbada859fb6aL,0x0dcfb6506ccd51L,0x68f88b8d573e0dL, - 0x4b1ce35bd9af30L,0x241c8293ece2c9L,0x3b5f402c5c4adeL, - 0x34b9b1ee6fde87L }, - { 0x5e625340075e63L,0x54c3f3d9050da1L,0x2a3f9152509016L, - 0x3274e46111bc18L,0x3a7504fd01ac73L,0x4169b387a43209L, - 0x35626f852bc6d4L } }, - /* 245 */ - { { 0x576a4f4662e53bL,0x5ea3f20eecec26L,0x4e5f02be5cd7b0L, - 0x72cc5ac3314be8L,0x0f604ed3201fe9L,0x2a29378ea54bceL, - 0x2d52bd4d6ec4b6L }, - { 0x6a4c2b212c1c76L,0x778fd64a1bfa6dL,0x326828691863d6L, - 0x5616c8bd06a336L,0x5fab552564da4dL,0x46640cab3e91d2L, - 0x1d21f06427299eL } }, - /* 246 */ - { { 0x2bfe37dde98e9cL,0x164c54822332ebL,0x5b736c7df266e4L, - 0x59dab3a8da084cL,0x0ae1eab346f118L,0x182090a4327e3fL, - 0x07b13489dae2e6L }, - { 0x3bc92645452baaL,0x30b159894ae574L,0x5b947c5c78e1f4L, - 0x18f0e004a3c77fL,0x48ca8f357077d9L,0x349ffdcef9bca9L, - 0x3ed224bfd54772L } }, - /* 247 */ - { { 0x1bdad02db8dff8L,0x69fab4450b44b6L,0x3b6802d187518bL, - 0x098368d8eb556cL,0x3fe1943fbefcf4L,0x008851d0de6d42L, - 0x322cbc4605fe25L }, - { 0x2528aaf0d51afbL,0x7d48a9363a0cecL,0x4ba8f77d9a8f8bL, - 0x7dee903437d6c7L,0x1ff5a0d9ccc4b4L,0x34d9bd2fa99831L, - 0x30d9e4f58667c6L } }, - /* 248 */ - { { 0x38909b51b85197L,0x7ba16992512bd4L,0x2c776cfcfffec5L, - 0x2be7879075843cL,0x557e2b05d28ffcL,0x641b17bc5ce357L, - 0x1fcaf8a3710306L }, - { 0x54dca2299a2d48L,0x745d06ef305acaL,0x7c41c65c6944c2L, - 0x679412ec431902L,0x48f2b15ee62827L,0x341a96d8afe06eL, - 0x2a78fd3690c0e1L } }, - /* 249 */ - { { 0x6b7cec83fbc9c6L,0x238e8a82eefc67L,0x5d3c1d9ff0928cL, - 0x55b816d6409bbfL,0x7969612adae364L,0x55b6ff96db654eL, - 0x129beca10073a9L }, - { 0x0b1d2acdfc73deL,0x5d1a3605fa64bdL,0x436076146743beL, - 0x64044b89fcce0cL,0x7ae7b3c18f7fafL,0x7f083ee27cea36L, - 0x0292cd0d7c1ff0L } }, - /* 250 */ - { { 0x5a3c4c019b7d2eL,0x1a35a9b89712fbL,0x38736cc4f18c72L, - 0x603dd832a44e6bL,0x000d1d44aed104L,0x69b1f2fc274ebeL, - 0x03a7b993f76977L }, - { 0x299f3b3e346910L,0x5243f45295afd5L,0x34342cbfa588bdL, - 0x72c40dd1155510L,0x718024fed2f991L,0x2f935e765ad82aL, - 0x246799ea371fb8L } }, - /* 251 */ - { { 0x24fe4c76250533L,0x01cafb02fdf18eL,0x505cb25d462882L, - 0x3e038175157d87L,0x7e3e99b10cdeb1L,0x38b7e72ebc7936L, - 0x081845f7c73433L }, - { 0x049e61be05ebd5L,0x6ab82d8f0581f6L,0x62adffb427ac2eL, - 0x19431f809d198dL,0x36195f6c58b1d6L,0x22cc4c9dedc9a7L, - 0x24b146d8e694fcL } }, - /* 252 */ - { { 0x7c7bc8288b364dL,0x5c10f683cb894aL,0x19a62a68452958L, - 0x1fc24dcb4ce90eL,0x726baa4ed9581fL,0x1f34447dde73d6L, - 0x04c56708f30a21L }, - { 0x131e583a3f4963L,0x071215b4d502e7L,0x196aca542e5940L, - 0x3afd5a91f7450eL,0x671b6eedf49497L,0x6aac7aca5c29e4L, - 0x3fb512470f138bL } }, - /* 253 */ - { { 0x5eadc3f4eb453eL,0x16c795ba34b666L,0x5d7612a4697fddL, - 0x24dd19bb499e86L,0x415b89ca3eeb9bL,0x7c83edf599d809L, - 0x13bc64c9b70269L }, - { 0x52d3243dca3233L,0x0b21444b3a96a7L,0x6d551bc0083b90L, - 0x4f535b88c61176L,0x11e61924298010L,0x0a155b415bb61dL, - 0x17f94fbd26658fL } }, - /* 254 */ - { { 0x2dd06b90c28c65L,0x48582339c8fa6eL,0x01ac8bf2085d94L, - 0x053e660e020fdcL,0x1bece667edf07bL,0x4558f2b33ce24cL, - 0x2f1a766e8673fcL }, - { 0x1d77cd13c06819L,0x4d5dc5056f3a01L,0x18896c6fa18d69L, - 0x120047ca76d625L,0x6af8457d4f4e45L,0x70ddc53358b60aL, - 0x330e11130e82f0L } }, - /* 255 */ - { { 0x0643b1cd4c2356L,0x10a2ea0a8f7c92L,0x2752513011d029L, - 0x4cd4c50321f579L,0x5fdf9ba5724792L,0x2f691653e2ddc0L, - 0x0cfed3d84226cbL }, - { 0x704902a950f955L,0x069bfdb87bbf0cL,0x5817eeda8a5f84L, - 0x1914cdd9089905L,0x0e4a323d7b93f4L,0x1cc3fc340af0b2L, - 0x23874161bd6303L } }, -}; - -/* 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. - * 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_7(sp_point_384* r, const sp_digit* k, - int map, int ct, void* heap) -{ - return sp_384_ecc_mulmod_stripe_7(r, &p384_base, p384_table, - k, map, ct, heap); -} - -#endif - -/* Multiply the base point of P384 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_384(const mp_int* km, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_384, point, 1); - SP_DECL_VAR(sp_digit, k, 7); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 7, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_384_from_mp(k, 7, km); - - err = sp_384_ecc_mulmod_base_7(point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_7(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_384, point, 2); - SP_DECL_VAR(sp_digit, k, 7 + 7 * 2 * 6); - sp_point_384* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 7 + 7 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ -#ifndef WC_NO_RNG -/* Add 1 to a. (a = a + 1) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_add_one_7(sp_digit* a) -{ - a[0]++; - sp_384_norm_7(a); -} - -#endif -/* 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_384_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 >= 47U) { - r[j] &= 0x7fffffffffffffL; - s = 55U - 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; - } -} - -/* Generates a scalar that is in the range 1..order-1. - * - * rng Random number generator. - * k Scalar value. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. - */ -static int sp_384_ecc_gen_k_7(WC_RNG* rng, sp_digit* k) -{ -#ifndef WC_NO_RNG - int err; - byte buf[48]; - - do { - err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); - if (err == 0) { - sp_384_from_bin(k, 7, buf, (int)sizeof(buf)); - if (sp_384_cmp_7(k, p384_order2) <= 0) { - sp_384_add_one_7(k); - break; - } - } - } - while (err == 0); - - return err; -#else - (void)rng; - (void)k; - return NOT_COMPILED_IN; -#endif -} - -/* Makes a random EC key pair. - * - * rng Random number generator. - * priv Generated private value. - * pub Generated public point. - * heap Heap to use for allocation. - * returns ECC_INF_E when the point does not have the correct order, RNG - * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) -{ -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_DECL_VAR(sp_point_384, point, 2); -#else - SP_DECL_VAR(sp_point_384, point, 1); -#endif - SP_DECL_VAR(sp_digit, k, 7); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384* infinity = NULL; -#endif - int err = MP_OKAY; - - - (void)heap; - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_ALLOC_VAR(sp_point_384, point, 2, heap, DYNAMIC_TYPE_ECC); -#else - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); -#endif - SP_ALLOC_VAR(sp_digit, k, 7, heap, DYNAMIC_TYPE_ECC); - 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) { - err = sp_384_ecc_mulmod_base_7(point, k, 1, 1, NULL); - } - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_7(infinity, point, p384_order, 1, 1, NULL); - } - if (err == MP_OKAY) { - if (sp_384_iszero_7(point->x) || sp_384_iszero_7(point->y)) { - err = ECC_INF_E; - } - } -#endif - - if (err == MP_OKAY) { - err = sp_384_to_mp(k, priv); - } - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_7(point, pub); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - /* point is not sensitive, so no need to zeroize */ - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_key_gen_384_ctx { - int state; - sp_384_ecc_mulmod_7_ctx mulmod_ctx; - sp_digit k[7]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 point[2]; -#else - sp_point_384 point[1]; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ -} sp_ecc_key_gen_384_ctx; - -int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, - ecc_point* pub, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384* infinity = ctx->point + 1; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - - typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) - >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - err = sp_384_ecc_gen_k_7(rng, ctx->k); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - ctx->state = 1; - } - break; - case 1: - err = sp_384_ecc_mulmod_base_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - #else - ctx->state = 3; - #endif - } - break; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - case 2: - err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p384_order, 1, 1); - if (err == MP_OKAY) { - if (sp_384_iszero_7(ctx->point->x) || - sp_384_iszero_7(ctx->point->y)) { - err = ECC_INF_E; - } - else { - err = FP_WOULDBLOCK; - ctx->state = 3; - } - } - break; - #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - case 3: - err = sp_384_to_mp(ctx->k, priv); - if (err == MP_OKAY) { - err = sp_384_point_to_ecc_point_7(ctx->point, pub); - } - break; - } - - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#ifdef HAVE_ECC_DHE -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 48 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_384_to_bin_7(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<6; i++) { - r[i+1] += r[i] >> 55; - r[i] &= 0x7fffffffffffffL; - } - j = 391 / 8 - 1; - a[j] = 0; - for (i=0; i<7 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 55) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 55); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Multiply the point by the scalar and serialize the X ordinate. - * The number is 0 padded to maximum size on output. - * - * priv Scalar to multiply the point by. - * pub Point to multiply. - * out Buffer to hold X ordinate. - * outLen On entry, size of the buffer in bytes. - * On exit, length of data in buffer in bytes. - * heap Heap to use for allocation. - * 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(const mp_int* priv, const ecc_point* pub, byte* out, - word32* outLen, void* heap) -{ - SP_DECL_VAR(sp_point_384, point, 1); - SP_DECL_VAR(sp_digit, k, 7); - int err = MP_OKAY; - - if (*outLen < 48U) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 7, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_384_from_mp(k, 7, priv); - sp_384_point_from_ecc_point_7(point, pub); - err = sp_384_ecc_mulmod_7(point, point, k, 1, 1, heap); - } - if (err == MP_OKAY) { - sp_384_to_bin_7(point->x, out); - *outLen = 48; - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sec_gen_384_ctx { - int state; - union { - sp_384_ecc_mulmod_7_ctx mulmod_ctx; - }; - sp_digit k[7]; - sp_point_384 point; -} sp_ecc_sec_gen_384_ctx; - -int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, - const ecc_point* pub, byte* out, word32* outLen, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - if (*outLen < 32U) { - err = BUFFER_E; - } - - switch (ctx->state) { - case 0: - sp_384_from_mp(ctx->k, 7, priv); - sp_384_point_from_ecc_point_7(&ctx->point, pub); - ctx->state = 1; - break; - case 1: - err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - sp_384_to_bin_7(ctx->point.x, out); - *outLen = 48; - } - break; - } - - if (err == MP_OKAY && ctx->state != 1) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_DHE */ - -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -SP_NOINLINE static void sp_384_rshift_7(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<6; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (55 - n))) & 0x7fffffffffffffL); - } -#else - for (i=0; i<0; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (55 - n)) & 0x7fffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (55 - n)) & 0x7fffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (55 - n)) & 0x7fffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (55 - n)) & 0x7fffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (55 - n)) & 0x7fffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (55 - n)) & 0x7fffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (55 - n)) & 0x7fffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (55 - n)) & 0x7fffffffffffffL); - } - r[0] = (a[0] >> n) | (sp_digit)((a[1] << (55 - n)) & 0x7fffffffffffffL); - r[1] = (a[1] >> n) | (sp_digit)((a[2] << (55 - n)) & 0x7fffffffffffffL); - r[2] = (a[2] >> n) | (sp_digit)((a[3] << (55 - n)) & 0x7fffffffffffffL); - r[3] = (a[3] >> n) | (sp_digit)((a[4] << (55 - n)) & 0x7fffffffffffffL); - r[4] = (a[4] >> n) | (sp_digit)((a[5] << (55 - n)) & 0x7fffffffffffffL); - r[5] = (a[5] >> n) | (sp_digit)((a[6] << (55 - n)) & 0x7fffffffffffffL); -#endif /* WOLFSSL_SP_SMALL */ - r[6] = a[6] >> n; -} - -/* 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_384_mul_d_7(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 7; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x7fffffffffffffL); - t >>= 55; - } - r[7] = (sp_digit)t; -#else - sp_int128 tb = b; - sp_int128 t[7]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - r[ 0] = (sp_digit) (t[ 0] & 0x7fffffffffffffL); - r[ 1] = (sp_digit)((t[ 0] >> 55) + (t[ 1] & 0x7fffffffffffffL)); - r[ 2] = (sp_digit)((t[ 1] >> 55) + (t[ 2] & 0x7fffffffffffffL)); - r[ 3] = (sp_digit)((t[ 2] >> 55) + (t[ 3] & 0x7fffffffffffffL)); - r[ 4] = (sp_digit)((t[ 3] >> 55) + (t[ 4] & 0x7fffffffffffffL)); - r[ 5] = (sp_digit)((t[ 4] >> 55) + (t[ 5] & 0x7fffffffffffffL)); - r[ 6] = (sp_digit)((t[ 5] >> 55) + (t[ 6] & 0x7fffffffffffffL)); - r[ 7] = (sp_digit) (t[ 6] >> 55); -#endif /* WOLFSSL_SP_SMALL */ -} - -SP_NOINLINE static void sp_384_lshift_14(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[14] = a[13] >> (55 - n); - for (i=13; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (55 - n))) & 0x7fffffffffffffL); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[13]; - r[14] = s >> (55U - n); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (55U - n))) & 0x7fffffffffffffUL); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0x7fffffffffffffL); -} - -/* 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. - * - * Simplified based on top word of divisor being (1 << 55) - 1 - * - * 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, - const sp_digit* m, sp_digit* r) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 7 + 3); - int i; - sp_digit r1; - sp_digit mask; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 7 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 14 + 1; - sd = t2 + 7 + 1; - - sp_384_mul_d_7(sd, d, (sp_digit)1 << 1); - sp_384_lshift_14(t1, a, 1); - t1[7 + 7] += t1[7 + 7 - 1] >> 55; - t1[7 + 7 - 1] &= 0x7fffffffffffffL; - for (i=6; i>=0; i--) { - r1 = t1[7 + i]; - sp_384_mul_d_7(t2, sd, r1); - (void)sp_384_sub_7(&t1[i], &t1[i], t2); - t1[7 + i] -= t2[7]; - sp_384_norm_7(&t1[i + 1]); - - mask = ~((t1[7 + i] - 1) >> 63); - sp_384_cond_sub_7(t1 + i, t1 + i, sd, mask); - sp_384_norm_7(&t1[i + 1]); - } - sp_384_norm_7(t1); - sp_384_rshift_7(r, t1, 1); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_384_mod_7(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_384_div_7(a, m, NULL, r); -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply two number mod the order of P384 curve. (r = a * b mod order) - * - * r Result of the multiplication. - * a First operand of the multiplication. - * b Second operand of the multiplication. - */ -static void sp_384_mont_mul_order_7(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_384_mul_7(r, a, b); - sp_384_mont_reduce_order_7(r, p384_order, p384_mp_order); -} - -#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL)) -#ifdef WOLFSSL_SP_SMALL -/* Order-2 for the P384 curve. */ -static const word64 p384_order_minus_2[6] = { - 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU, - 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU -}; -#else -/* The low half of the order-2 of the P384 curve. */ -static const word64 p384_order_low[3] = { - 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU -}; -#endif /* WOLFSSL_SP_SMALL */ - -/* Square number mod the order of P384 curve. (r = a * a mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_384_mont_sqr_order_7(sp_digit* r, const sp_digit* a) -{ - sp_384_sqr_7(r, a); - sp_384_mont_reduce_order_7(r, p384_order, p384_mp_order); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square number mod the order of P384 curve a number of times. - * (r = a ^ n mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_384_mont_sqr_n_order_7(sp_digit* r, const sp_digit* a, int n) -{ - int i; - - sp_384_mont_sqr_order_7(r, a); - for (i=1; i= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - XMEMCPY(t, a, sizeof(sp_digit) * 7); - ctx->i = 382; - ctx->state = 1; - break; - case 1: - sp_384_mont_sqr_order_7(t, t); - ctx->state = 2; - break; - case 2: - if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { - sp_384_mont_mul_order_7(t, t, a); - } - ctx->i--; - ctx->state = (ctx->i >= 0) ? 1 : 3; - break; - case 3: - XMEMCPY(r, t, sizeof(sp_digit) * 7U); - err = MP_OKAY; - break; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, - sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 7); - for (i=382; i>=0; i--) { - sp_384_mont_sqr_order_7(t, t); - if ((p384_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_384_mont_mul_order_7(t, t, a); - } - } - XMEMCPY(r, t, sizeof(sp_digit) * 7U); -#else - sp_digit* t = td; - sp_digit* t2 = td + 2 * 7; - sp_digit* t3 = td + 4 * 7; - int i; - - /* t = a^2 */ - sp_384_mont_sqr_order_7(t, a); - /* t = a^3 = t * a */ - sp_384_mont_mul_order_7(t, t, a); - /* t2= a^c = t ^ 2 ^ 2 */ - sp_384_mont_sqr_n_order_7(t2, t, 2); - /* t = a^f = t2 * t */ - sp_384_mont_mul_order_7(t, t2, t); - /* t2= a^f0 = t ^ 2 ^ 4 */ - sp_384_mont_sqr_n_order_7(t2, t, 4); - /* t = a^ff = t2 * t */ - sp_384_mont_mul_order_7(t, t2, t); - /* t2= a^ff00 = t ^ 2 ^ 8 */ - sp_384_mont_sqr_n_order_7(t2, t, 8); - /* t3= a^ffff = t2 * t */ - sp_384_mont_mul_order_7(t3, t2, t); - /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ - sp_384_mont_sqr_n_order_7(t2, t3, 16); - /* t = a^ffffffff = t2 * t3 */ - sp_384_mont_mul_order_7(t, t2, t3); - /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ - sp_384_mont_sqr_n_order_7(t2, t, 16); - /* t = a^ffffffffffff = t2 * t3 */ - sp_384_mont_mul_order_7(t, t2, t3); - /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ - sp_384_mont_sqr_n_order_7(t2, t, 48); - /* t= a^fffffffffffffffffffffffff = t2 * t */ - sp_384_mont_mul_order_7(t, t2, t); - /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ - sp_384_mont_sqr_n_order_7(t2, t, 96); - /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ - sp_384_mont_mul_order_7(t2, t2, t); - for (i=191; i>=1; i--) { - sp_384_mont_sqr_order_7(t2, t2); - if ((p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_384_mont_mul_order_7(t2, t2, a); - } - } - sp_384_mont_sqr_order_7(t2, t2); - sp_384_mont_mul_order_7(r, t2, a); -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */ -#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; - sp_int64 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, - (sp_digit)0 - (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 - * s = (r * x + e) / k mod order - * The hash is truncated to the first 384 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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. - */ -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) -{ - SP_DECL_VAR(sp_digit, e, 7 * 2 * 7); - SP_DECL_VAR(sp_point_384, point, 1); - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, e, 7 * 2 * 7, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - x = e + 2 * 7; - k = e + 4 * 7; - r = e + 6 * 7; - tmp = e + 8 * 7; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_7(rng, k); - } - else { - sp_384_from_mp(k, 7, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_7(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 7U); - sp_384_norm_7(r); - c = sp_384_cmp_7(r, p384_order); - sp_384_cond_sub_7(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_7(r); - - if (!sp_384_iszero_7(r)) { - /* x is modified in calculation of s. */ - sp_384_from_mp(x, 7, priv); - /* s ptr == e ptr, e is modified in calculation of s. */ - sp_384_from_bin(e, 7, hash, (int)hashLen); - - err = sp_384_calc_s_7(s, r, k, x, e, tmp); - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (!sp_384_iszero_7(s))) { - break; - } - } - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - - SP_ZEROFREE_VAR(sp_point_384, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_digit, e, 7 * 2 * 7, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sign_384_ctx { - int state; - union { - sp_384_ecc_mulmod_7_ctx mulmod_ctx; - sp_384_mont_inv_order_7_ctx mont_inv_order_ctx; - }; - sp_digit e[2*7]; - sp_digit x[2*7]; - sp_digit k[2*7]; - sp_digit r[2*7]; - sp_digit tmp[3 * 2*7]; - sp_point_384 point; - sp_digit* s; - sp_digit* kInv; - 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 err = FP_WOULDBLOCK; - sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - ctx->s = ctx->e; - ctx->kInv = ctx->k; - - ctx->i = SP_ECC_MAX_SIG_GEN; - ctx->state = 1; - break; - case 1: /* GEN */ - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_7(rng, ctx->k); - } - else { - sp_384_from_mp(ctx->k, 7, km); - mp_zero(km); - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - break; - case 2: /* MULMOD */ - err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &p384_base, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - ctx->state = 3; - } - break; - case 3: /* MODORDER */ - { - sp_int64 c; - /* r = point->x mod order */ - XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 7U); - sp_384_norm_7(ctx->r); - c = sp_384_cmp_7(ctx->r, p384_order); - sp_384_cond_sub_7(ctx->r, ctx->r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_7(ctx->r); - - if (hashLen > 48U) { - hashLen = 48U; - } - sp_384_from_mp(ctx->x, 7, priv); - sp_384_from_bin(ctx->e, 7, hash, (int)hashLen); - ctx->state = 4; - break; - } - case 4: /* KMODORDER */ - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_7(ctx->k, ctx->k, p384_norm_order); - err = sp_384_mod_7(ctx->k, ctx->k, p384_order); - if (err == MP_OKAY) { - sp_384_norm_7(ctx->k); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 5; - } - break; - case 5: /* KINV */ - /* kInv = 1/k mod order */ - err = sp_384_mont_inv_order_7_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); - if (err == MP_OKAY) { - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 6; - } - break; - case 6: /* KINVNORM */ - sp_384_norm_7(ctx->kInv); - ctx->state = 7; - break; - case 7: /* R */ - /* s = r * x + e */ - sp_384_mul_7(ctx->x, ctx->x, ctx->r); - ctx->state = 8; - break; - case 8: /* S1 */ - err = sp_384_mod_7(ctx->x, ctx->x, p384_order); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* S2 */ - { - sp_digit carry; - sp_int64 c; - sp_384_norm_7(ctx->x); - carry = sp_384_add_7(ctx->s, ctx->e, ctx->x); - sp_384_cond_sub_7(ctx->s, ctx->s, - p384_order, 0 - carry); - sp_384_norm_7(ctx->s); - c = sp_384_cmp_7(ctx->s, p384_order); - sp_384_cond_sub_7(ctx->s, ctx->s, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_7(ctx->s); - - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_7(ctx->s, ctx->s, ctx->kInv); - sp_384_norm_7(ctx->s); - - /* Check that signature is usable. */ - if (sp_384_iszero_7(ctx->s) == 0) { - ctx->state = 10; - break; - } - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - ctx->i = 1; - #endif - - /* not usable gen, try again */ - ctx->i--; - if (ctx->i == 0) { - err = RNG_FAILURE_E; - } - ctx->state = 1; - break; - } - case 10: /* RES */ - err = sp_384_to_mp(ctx->r, rm); - if (err == MP_OKAY) { - err = sp_384_to_mp(ctx->s, sm); - } - break; - } - - if (err == MP_OKAY && ctx->state != 10) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 7U); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_SIGN */ - -#ifndef WOLFSSL_SP_SMALL -static const char sp_384_tab64_7[64] = { - 64, 1, 59, 2, 60, 48, 54, 3, - 61, 40, 49, 28, 55, 34, 43, 4, - 62, 52, 38, 41, 50, 19, 29, 21, - 56, 31, 35, 12, 44, 15, 23, 5, - 63, 58, 47, 53, 39, 27, 33, 42, - 51, 37, 18, 20, 30, 11, 14, 22, - 57, 46, 26, 32, 36, 17, 10, 13, - 45, 25, 16, 9, 24, 8, 7, 6}; - -static int sp_384_num_bits_55_7(sp_digit v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - return sp_384_tab64_7[((word64)((v - (v >> 1))*0x07EDD5E59A4E28C2)) >> 58]; -} - -static int sp_384_num_bits_7(const sp_digit* a) -{ - int i; - int r = 0; - - for (i = 6; i >= 0; i--) { - if (a[i] != 0) { - r = sp_384_num_bits_55_7(a[i]); - r += i * 55; - break; - } - } - - return r; -} - -/* 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. - * @return MEMEORY_E when dynamic memory allocation fails. - */ -static int sp_384_mod_inv_7(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int err = MP_OKAY; - SP_DECL_VAR(sp_digit, u, 7 * 4); - sp_digit* v = NULL; - sp_digit* b = NULL; - sp_digit* d = NULL; - int ut; - int vt; - - SP_ALLOC_VAR(sp_digit, u, 7 * 4, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - v = u + 7; - b = u + 2 * 7; - d = u + 3 * 7; - - XMEMCPY(u, m, sizeof(sp_digit) * 7); - XMEMCPY(v, a, sizeof(sp_digit) * 7); - - ut = sp_384_num_bits_7(u); - vt = sp_384_num_bits_7(v); - - XMEMSET(b, 0, sizeof(sp_digit) * 7); - if ((v[0] & 1) == 0) { - sp_384_rshift1_7(v, v); - XMEMCPY(d, m, sizeof(sp_digit) * 7); - d[0]++; - sp_384_rshift1_7(d, d); - vt--; - - while ((v[0] & 1) == 0) { - sp_384_rshift1_7(v, v); - if (d[0] & 1) - sp_384_add_7(d, d, m); - sp_384_rshift1_7(d, d); - vt--; - } - } - else { - XMEMSET(d+1, 0, sizeof(sp_digit) * (7 - 1)); - d[0] = 1; - } - - while (ut > 1 && vt > 1) { - if ((ut > vt) || ((ut == vt) && - (sp_384_cmp_7(u, v) >= 0))) { - sp_384_sub_7(u, u, v); - sp_384_norm_7(u); - - sp_384_sub_7(b, b, d); - sp_384_norm_7(b); - if (b[6] < 0) - sp_384_add_7(b, b, m); - sp_384_norm_7(b); - ut = sp_384_num_bits_7(u); - - do { - sp_384_rshift1_7(u, u); - if (b[0] & 1) - sp_384_add_7(b, b, m); - sp_384_rshift1_7(b, b); - ut--; - } - while (ut > 0 && (u[0] & 1) == 0); - } - else { - sp_384_sub_7(v, v, u); - sp_384_norm_7(v); - - sp_384_sub_7(d, d, b); - sp_384_norm_7(d); - if (d[6] < 0) - sp_384_add_7(d, d, m); - sp_384_norm_7(d); - vt = sp_384_num_bits_7(v); - - do { - sp_384_rshift1_7(v, v); - if (d[0] & 1) - sp_384_add_7(d, d, m); - sp_384_rshift1_7(d, d); - vt--; - } - while (vt > 0 && (v[0] & 1) == 0); - } - } - - if (ut == 1) - XMEMCPY(r, b, sizeof(sp_digit) * 7); - else - XMEMCPY(r, d, sizeof(sp_digit) * 7); - } - SP_FREE_VAR(u, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#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 Temporary 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 - err = sp_384_mod_inv_7(s, s, p384_order); - if (err == MP_OKAY) -#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) - * u1 = e/s mod order - * u2 = r/s mod order - * r == (u1.G + u2.Q)->x mod order - * Optimization: Leave point in projective form. - * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') - * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' - * The hash is truncated to the first 384 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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 MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -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) -{ - SP_DECL_VAR(sp_digit, u1, 18 * 7); - SP_DECL_VAR(sp_point_384, p1, 2); - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, u1, 18 * 7, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p1, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - 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, 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); - - err = sp_384_calc_vfy_point_7(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (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, rm); - err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_7(p1->z, p1->z, p384_mod, p384_mp_mod); - 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) { - /* Reload r and add order. */ - 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) { - sp_384_norm_7(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_7(u2, p384_mod); - } - } - 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); - } - } - } - - SP_FREE_VAR(p1, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(u1, heap, DYNAMIC_TYPE_ECC); - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_verify_384_ctx { - int state; - union { - sp_384_ecc_mulmod_7_ctx mulmod_ctx; - sp_384_mont_inv_order_7_ctx mont_inv_order_ctx; - sp_384_proj_point_dbl_7_ctx dbl_ctx; - sp_384_proj_point_add_7_ctx add_ctx; - }; - sp_digit u1[2*7]; - sp_digit u2[2*7]; - sp_digit s[2*7]; - sp_digit tmp[2*7 * 6]; - sp_point_384 p1; - 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, 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; - - typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(ctx->u1, 7, hash, (int)hashLen); - 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); - sp_384_from_mp(ctx->p2.z, 7, pZ); - ctx->state = 1; - break; - case 1: /* NORMS0 */ - sp_384_mul_7(ctx->s, ctx->s, p384_norm_order); - err = sp_384_mod_7(ctx->s, ctx->s, p384_order); - if (err == MP_OKAY) - ctx->state = 2; - break; - case 2: /* NORMS1 */ - sp_384_norm_7(ctx->s); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 3; - break; - case 3: /* NORMS2 */ - err = sp_384_mont_inv_order_7_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 4; - } - break; - case 4: /* NORMS3 */ - sp_384_mont_mul_order_7(ctx->u1, ctx->u1, ctx->s); - ctx->state = 5; - break; - case 5: /* NORMS4 */ - sp_384_mont_mul_order_7(ctx->u2, ctx->u2, ctx->s); - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 6; - break; - case 6: /* MULBASE */ - err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_384_iszero_7(ctx->p1.z)) { - ctx->p1.infinity = 1; - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 7; - } - break; - case 7: /* MULMOD */ - err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_384_iszero_7(ctx->p2.z)) { - ctx->p2.infinity = 1; - } - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 8; - } - break; - case 8: /* ADD */ - err = sp_384_proj_point_add_7_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); - if (err == MP_OKAY) - ctx->state = 9; - break; - 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, rm); - err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) - ctx->state = 10; - break; - 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 = 11; - break; - case 11: /* MUL */ - sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 12; - break; - case 12: /* RES */ - { - sp_int64 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; - - /* Reload r and add order. */ - 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) { - sp_384_norm_7(ctx->u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_7(ctx->u2, p384_mod); - } - } - 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 != 12) { - err = FP_WOULDBLOCK; - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_VERIFY */ - -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* Check that the x and y ordinates 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_384_ecc_is_point_7(const sp_point_384* point, - void* heap) -{ - SP_DECL_VAR(sp_digit, t1, 7 * 4); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 7 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 7; - - /* y^2 - x^3 - a.x = b */ - sp_384_sqr_7(t1, point->y); - (void)sp_384_mod_7(t1, t1, p384_mod); - sp_384_sqr_7(t2, point->x); - (void)sp_384_mod_7(t2, t2, p384_mod); - sp_384_mul_7(t2, t2, point->x); - (void)sp_384_mod_7(t2, t2, p384_mod); - sp_384_mont_sub_7(t1, t1, t2, p384_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - sp_384_mont_add_7(t1, t1, point->x, p384_mod); - sp_384_mont_add_7(t1, t1, point->x, p384_mod); - sp_384_mont_add_7(t1, t1, point->x, p384_mod); - - - if (sp_384_cmp_7(t1, p384_b) != 0) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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_384(const mp_int* pX, const mp_int* pY) -{ - SP_DECL_VAR(sp_point_384, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_384, pub, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - 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)); - - err = sp_384_ecc_is_point_7(pub, NULL); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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_384(const mp_int* pX, const mp_int* pY, - const mp_int* privm, void* heap) -{ - SP_DECL_VAR(sp_digit, priv, 7); - SP_DECL_VAR(sp_point_384, pub, 2); - 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 (((mp_count_bits(pX) > 384) || - (mp_count_bits(pY) > 384) || - ((privm != NULL) && (mp_count_bits(privm) > 384)))) { - err = ECC_OUT_OF_RANGE_E; - } - - SP_ALLOC_VAR(sp_digit, priv, 7, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, pub, 2, heap, DYNAMIC_TYPE_ECC); - 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)); - if (privm) - sp_384_from_mp(priv, 7, privm); - - /* Check point at infinitiy. */ - if ((sp_384_iszero_7(pub->x) != 0) && - (sp_384_iszero_7(pub->y) != 0)) { - err = ECC_INF_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) { - /* Check point is on curve */ - err = sp_384_ecc_is_point_7(pub, heap); - } - - if (err == MP_OKAY) { - /* Point * order = infinity */ - err = sp_384_ecc_mulmod_7(p, pub, p384_order, 1, 1, heap); - } - /* 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) { - if (err == MP_OKAY) { - /* Base * private = point */ - err = sp_384_ecc_mulmod_base_7(p, priv, 1, 1, heap); - } - /* 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; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL -/* Add two projective EC points together. - * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) - * - * pX First EC point's X ordinate. - * pY First EC point's Y ordinate. - * pZ First EC point's Z ordinate. - * qX Second EC point's X ordinate. - * qY Second EC point's Y ordinate. - * qZ Second EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 7 * 6); - SP_DECL_VAR(sp_point_384, p, 2); - sp_point_384* q = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 7 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p, 2, NULL, DYNAMIC_TYPE_ECC); - 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); - sp_384_from_mp(q->x, 7, qX); - sp_384_from_mp(q->y, 7, qY); - sp_384_from_mp(q->z, 7, qZ); - p->infinity = sp_384_iszero_7(p->x) & - sp_384_iszero_7(p->y); - q->infinity = sp_384_iszero_7(q->x) & - sp_384_iszero_7(q->y); - - sp_384_proj_point_add_7(p, p, q, tmp); - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Double a projective EC point. - * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 7 * 2); - SP_DECL_VAR(sp_point_384, p, 1); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 7 * 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - p->infinity = sp_384_iszero_7(p->x) & - sp_384_iszero_7(p->y); - - sp_384_proj_point_dbl_7(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Map a projective EC point to affine in place. - * pZ will be one. - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 7 * 6); - SP_DECL_VAR(sp_point_384, p, 1); - int err = MP_OKAY; - - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 7 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_384, p, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - p->infinity = sp_384_iszero_7(p->x) & - sp_384_iszero_7(p->y); - - sp_384_map_7(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(p->x, pX); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pY); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifdef HAVE_COMP_KEY -/* Find the square root of a number mod the prime of the curve. - * - * y The number to operate on and the result. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mont_sqrt_7(sp_digit* y) -{ - SP_DECL_VAR(sp_digit, t1, 5 * 2 * 7); - sp_digit* t2 = NULL; - sp_digit* t3 = NULL; - sp_digit* t4 = NULL; - sp_digit* t5 = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, t1, 5 * 2 * 7, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 7; - t3 = t1 + 4 * 7; - t4 = t1 + 6 * 7; - t5 = t1 + 8 * 7; - - { - /* t2 = y ^ 0x2 */ - sp_384_mont_sqr_7(t2, y, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3 */ - sp_384_mont_mul_7(t1, t2, y, p384_mod, p384_mp_mod); - /* t5 = y ^ 0xc */ - sp_384_mont_sqr_n_7(t5, t1, 2, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xf */ - sp_384_mont_mul_7(t1, t1, t5, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x1e */ - sp_384_mont_sqr_7(t2, t1, p384_mod, p384_mp_mod); - /* t3 = y ^ 0x1f */ - sp_384_mont_mul_7(t3, t2, y, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3e0 */ - sp_384_mont_sqr_n_7(t2, t3, 5, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3ff */ - sp_384_mont_mul_7(t1, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x7fe0 */ - sp_384_mont_sqr_n_7(t2, t1, 5, p384_mod, p384_mp_mod); - /* t3 = y ^ 0x7fff */ - sp_384_mont_mul_7(t3, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fff800 */ - sp_384_mont_sqr_n_7(t2, t3, 15, p384_mod, p384_mp_mod); - /* t4 = y ^ 0x3ffffff */ - sp_384_mont_mul_7(t4, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xffffffc000000 */ - sp_384_mont_sqr_n_7(t2, t4, 30, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xfffffffffffff */ - sp_384_mont_mul_7(t1, t4, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xfffffffffffffff000000000000000 */ - sp_384_mont_sqr_n_7(t2, t1, 60, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ - sp_384_mont_mul_7(t1, t1, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ - sp_384_mont_sqr_n_7(t2, t1, 120, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_7(t1, t1, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ - sp_384_mont_sqr_n_7(t2, t1, 15, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_384_mont_mul_7(t1, t3, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ - sp_384_mont_sqr_n_7(t2, t1, 31, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ - sp_384_mont_mul_7(t1, t4, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ - sp_384_mont_sqr_n_7(t2, t1, 4, p384_mod, p384_mp_mod); - /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ - sp_384_mont_mul_7(t1, t5, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ - sp_384_mont_sqr_n_7(t2, t1, 62, p384_mod, p384_mp_mod); - /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ - sp_384_mont_mul_7(t1, y, t2, p384_mod, p384_mp_mod); - /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ - sp_384_mont_sqr_n_7(y, t1, 30, p384_mod, p384_mp_mod); - } - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - - -/* Uncompress the point given the X ordinate. - * - * xm X ordinate. - * odd Whether the Y ordinate is odd. - * ym Calculated Y ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) -{ - SP_DECL_VAR(sp_digit, x, 4 * 7); - sp_digit* y = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, x, 4 * 7, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - y = x + 2 * 7; - - sp_384_from_mp(x, 7, xm); - err = sp_384_mod_mul_norm_7(x, x, p384_mod); - } - if (err == MP_OKAY) { - /* y = x^3 */ - { - sp_384_mont_sqr_7(y, x, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(y, y, x, p384_mod, p384_mp_mod); - } - /* y = x^3 - 3x */ - sp_384_mont_sub_7(y, y, x, p384_mod); - sp_384_mont_sub_7(y, y, x, p384_mod); - sp_384_mont_sub_7(y, y, x, p384_mod); - /* y = x^3 - 3x + b */ - err = sp_384_mod_mul_norm_7(x, p384_b, p384_mod); - } - if (err == MP_OKAY) { - sp_384_mont_add_7(y, y, x, p384_mod); - /* y = sqrt(x^3 - 3x + b) */ - err = sp_384_mont_sqrt_7(y); - } - if (err == MP_OKAY) { - XMEMSET(y + 7, 0, 7U * sizeof(sp_digit)); - sp_384_mont_reduce_7(y, p384_mod, p384_mp_mod); - if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { - sp_384_mont_sub_7(y, p384_mod, y, p384_mod); - } - - err = sp_384_to_mp(y, ym); - } - - SP_FREE_VAR(x, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* WOLFSSL_SP_384 */ -#ifdef WOLFSSL_SP_521 - -/* Point structure to use. */ -typedef struct sp_point_521 { - /* X ordinate of point. */ - sp_digit x[2 * 9]; - /* Y ordinate of point. */ - sp_digit y[2 * 9]; - /* Z ordinate of point. */ - sp_digit z[2 * 9]; - /* Indicates point is at infinity. */ - int infinity; -} sp_point_521; - -/* The modulus (prime) of the curve P521. */ -static const sp_digit p521_mod[9] = { - 0x3ffffffffffffffL,0x3ffffffffffffffL,0x3ffffffffffffffL,0x3ffffffffffffffL, - 0x3ffffffffffffffL,0x3ffffffffffffffL,0x3ffffffffffffffL,0x3ffffffffffffffL, - 0x1ffffffffffffffL -}; -/* The Montgomery normalizer for modulus of the curve P521. */ -static const sp_digit p521_norm_mod[9] = { - 0x000000000000001L,0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L -}; -/* The Montgomery multiplier for modulus of the curve P521. */ -static const sp_digit p521_mp_mod = 0x00000000000001; -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -/* The order of the curve P521. */ -static const sp_digit p521_order[9] = { - 0x36fb71e91386409L,0x1726e226711ebaeL,0x0148f709a5d03bbL,0x20efcbe59adff30L, - 0x3fffffffa518687L,0x3ffffffffffffffL,0x3ffffffffffffffL,0x3ffffffffffffffL, - 0x1ffffffffffffffL -}; -#endif -#ifndef WC_NO_RNG -/* The order of the curve P521 minus 2. */ -static const sp_digit p521_order2[9] = { - 0x36fb71e91386407L,0x1726e226711ebaeL,0x0148f709a5d03bbL,0x20efcbe59adff30L, - 0x3fffffffa518687L,0x3ffffffffffffffL,0x3ffffffffffffffL,0x3ffffffffffffffL, - 0x1ffffffffffffffL -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery normalizer for order of the curve P521. */ -static const sp_digit p521_norm_order[9] = { - 0x09048e16ec79bf7L,0x28d91dd98ee1451L,0x3eb708f65a2fc44L,0x1f10341a65200cfL, - 0x000000005ae7978L,0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L -}; -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* The Montgomery multiplier for order of the curve P521. */ -static const sp_digit p521_mp_order = 0x12f5ccd79a995c7L; -#endif -/* The base point of curve P521. */ -static const sp_point_521 p521_base = { - /* X ordinate */ - { - 0x17e7e31c2e5bd66L,0x22cf0615a90a6feL,0x0127a2ffa8de334L, - 0x1dfbf9d64a3f877L,0x06b4d3dbaa14b5eL,0x14fed487e0a2bd8L, - 0x15b4429c6481390L,0x3a73678fb2d988eL,0x0c6858e06b70404L, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Y ordinate */ - { - 0x0be94769fd16650L,0x31c21a89cb09022L,0x39013fad0761353L, - 0x2657bd099031542L,0x3273e662c97ee72L,0x1e6d11a05ebef45L, - 0x3d1bd998f544495L,0x3001172297ed0b1L,0x11839296a789a3bL, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Z ordinate */ - { - 0x000000000000001L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) || \ - defined(HAVE_COMP_KEY) -static const sp_digit p521_b[9] = { - 0x3451fd46b503f00L,0x0f7e20f4b0d3c7bL,0x00bd3bb1bf07357L,0x147b1fa4dec594bL, - 0x18ef109e1561939L,0x26cc57cee2d2264L,0x0540eea2da725b9L,0x2687e4a688682daL, - 0x051953eb9618e1cL -}; -#endif - -#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. - */ -SP_NOINLINE static void sp_521_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[8]) * b[8]; - r[17] = (sp_digit)(c >> 58); - c &= 0x3ffffffffffffffL; - for (k = 15; k >= 0; k--) { - if (k >= 9) { - i = k - 8; - imax = 8; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 58; - r[k + 2] += (sp_digit)(c >> 58); - r[k + 1] = (sp_digit)(c & 0x3ffffffffffffffL); - c = lo & 0x3ffffffffffffffL; - } - r[0] = (sp_digit)c; -} - -#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_521_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_int128 t0; - sp_int128 t1; - sp_digit t[9]; - - t0 = ((sp_int128)a[ 0]) * b[ 0]; - t1 = ((sp_int128)a[ 0]) * b[ 1] - + ((sp_int128)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 0]) * b[ 2] - + ((sp_int128)a[ 1]) * b[ 1] - + ((sp_int128)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 0]) * b[ 3] - + ((sp_int128)a[ 1]) * b[ 2] - + ((sp_int128)a[ 2]) * b[ 1] - + ((sp_int128)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 0]) * b[ 4] - + ((sp_int128)a[ 1]) * b[ 3] - + ((sp_int128)a[ 2]) * b[ 2] - + ((sp_int128)a[ 3]) * b[ 1] - + ((sp_int128)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 0]) * b[ 5] - + ((sp_int128)a[ 1]) * b[ 4] - + ((sp_int128)a[ 2]) * b[ 3] - + ((sp_int128)a[ 3]) * b[ 2] - + ((sp_int128)a[ 4]) * b[ 1] - + ((sp_int128)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 0]) * b[ 6] - + ((sp_int128)a[ 1]) * b[ 5] - + ((sp_int128)a[ 2]) * b[ 4] - + ((sp_int128)a[ 3]) * b[ 3] - + ((sp_int128)a[ 4]) * b[ 2] - + ((sp_int128)a[ 5]) * b[ 1] - + ((sp_int128)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 0]) * b[ 7] - + ((sp_int128)a[ 1]) * b[ 6] - + ((sp_int128)a[ 2]) * b[ 5] - + ((sp_int128)a[ 3]) * b[ 4] - + ((sp_int128)a[ 4]) * b[ 3] - + ((sp_int128)a[ 5]) * b[ 2] - + ((sp_int128)a[ 6]) * b[ 1] - + ((sp_int128)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 0]) * b[ 8] - + ((sp_int128)a[ 1]) * b[ 7] - + ((sp_int128)a[ 2]) * b[ 6] - + ((sp_int128)a[ 3]) * b[ 5] - + ((sp_int128)a[ 4]) * b[ 4] - + ((sp_int128)a[ 5]) * b[ 3] - + ((sp_int128)a[ 6]) * b[ 2] - + ((sp_int128)a[ 7]) * b[ 1] - + ((sp_int128)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 1]) * b[ 8] - + ((sp_int128)a[ 2]) * b[ 7] - + ((sp_int128)a[ 3]) * b[ 6] - + ((sp_int128)a[ 4]) * b[ 5] - + ((sp_int128)a[ 5]) * b[ 4] - + ((sp_int128)a[ 6]) * b[ 3] - + ((sp_int128)a[ 7]) * b[ 2] - + ((sp_int128)a[ 8]) * b[ 1]; - t[ 8] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 2]) * b[ 8] - + ((sp_int128)a[ 3]) * b[ 7] - + ((sp_int128)a[ 4]) * b[ 6] - + ((sp_int128)a[ 5]) * b[ 5] - + ((sp_int128)a[ 6]) * b[ 4] - + ((sp_int128)a[ 7]) * b[ 3] - + ((sp_int128)a[ 8]) * b[ 2]; - r[ 9] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 3]) * b[ 8] - + ((sp_int128)a[ 4]) * b[ 7] - + ((sp_int128)a[ 5]) * b[ 6] - + ((sp_int128)a[ 6]) * b[ 5] - + ((sp_int128)a[ 7]) * b[ 4] - + ((sp_int128)a[ 8]) * b[ 3]; - r[10] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 4]) * b[ 8] - + ((sp_int128)a[ 5]) * b[ 7] - + ((sp_int128)a[ 6]) * b[ 6] - + ((sp_int128)a[ 7]) * b[ 5] - + ((sp_int128)a[ 8]) * b[ 4]; - r[11] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 5]) * b[ 8] - + ((sp_int128)a[ 6]) * b[ 7] - + ((sp_int128)a[ 7]) * b[ 6] - + ((sp_int128)a[ 8]) * b[ 5]; - r[12] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 6]) * b[ 8] - + ((sp_int128)a[ 7]) * b[ 7] - + ((sp_int128)a[ 8]) * b[ 6]; - r[13] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = ((sp_int128)a[ 7]) * b[ 8] - + ((sp_int128)a[ 8]) * b[ 7]; - r[14] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 8]) * b[ 8]; - r[15] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - r[16] = (sp_digit)(t0 & 0x3ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 58); - XMEMCPY(r, t, sizeof(t)); -} - -#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_521_sqr_9(sp_digit* r, const sp_digit* a) -{ - int i; - int imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[8]) * a[8]; - r[17] = (sp_digit)(c >> 58); - c = (c & 0x3ffffffffffffffL) << 58; - for (k = 15; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 8) { - imax = k; - } - else { - imax = 8; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - r[k + 2] += (sp_digit) (c >> 116); - r[k + 1] = (sp_digit)((c >> 58) & 0x3ffffffffffffffL); - c = (c & 0x3ffffffffffffffL) << 58; - } - r[0] = (sp_digit)(c >> 58); -} - -#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_521_sqr_9(sp_digit* r, const sp_digit* a) -{ - sp_int128 t0; - sp_int128 t1; - sp_digit t[9]; - - t0 = ((sp_int128)a[ 0]) * a[ 0]; - t1 = (((sp_int128)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 0]) * a[ 2]) * 2 - + ((sp_int128)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 0]) * a[ 3] - + ((sp_int128)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 0]) * a[ 4] - + ((sp_int128)a[ 1]) * a[ 3]) * 2 - + ((sp_int128)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 0]) * a[ 5] - + ((sp_int128)a[ 1]) * a[ 4] - + ((sp_int128)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 0]) * a[ 6] - + ((sp_int128)a[ 1]) * a[ 5] - + ((sp_int128)a[ 2]) * a[ 4]) * 2 - + ((sp_int128)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 0]) * a[ 7] - + ((sp_int128)a[ 1]) * a[ 6] - + ((sp_int128)a[ 2]) * a[ 5] - + ((sp_int128)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 0]) * a[ 8] - + ((sp_int128)a[ 1]) * a[ 7] - + ((sp_int128)a[ 2]) * a[ 6] - + ((sp_int128)a[ 3]) * a[ 5]) * 2 - + ((sp_int128)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 1]) * a[ 8] - + ((sp_int128)a[ 2]) * a[ 7] - + ((sp_int128)a[ 3]) * a[ 6] - + ((sp_int128)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 2]) * a[ 8] - + ((sp_int128)a[ 3]) * a[ 7] - + ((sp_int128)a[ 4]) * a[ 6]) * 2 - + ((sp_int128)a[ 5]) * a[ 5]; - r[ 9] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 3]) * a[ 8] - + ((sp_int128)a[ 4]) * a[ 7] - + ((sp_int128)a[ 5]) * a[ 6]) * 2; - r[10] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 4]) * a[ 8] - + ((sp_int128)a[ 5]) * a[ 7]) * 2 - + ((sp_int128)a[ 6]) * a[ 6]; - r[11] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 5]) * a[ 8] - + ((sp_int128)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = (((sp_int128)a[ 6]) * a[ 8]) * 2 - + ((sp_int128)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - t1 = (((sp_int128)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x3ffffffffffffffL); t1 += t0 >> 58; - t0 = ((sp_int128)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x3ffffffffffffffL); t0 += t1 >> 58; - r[16] = (sp_digit)(t0 & 0x3ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 58); - XMEMCPY(r, t, sizeof(t)); -} - -#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_521_add_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 9; 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_521_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; -} - -#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_521_sub_9(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 9; 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_521_sub_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; -} - -#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_521_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 58 - int i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 57); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 57); - } -#elif DIGIT_BIT > 58 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x3ffffffffffffffL; - s = 58U - 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 + 58U) <= (word32)DIGIT_BIT) { - s += 58U; - r[j] &= 0x3ffffffffffffffL; - 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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 58) { - r[j] &= 0x3ffffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 58 - 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_521. - * - * p Point of type sp_point_521 (result). - * pm Point of type ecc_point. - */ -static void sp_521_point_from_ecc_point_9(sp_point_521* 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_521_from_mp(p->x, 9, pm->x); - sp_521_from_mp(p->y, 9, pm->y); - sp_521_from_mp(p->z, 9, 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_521_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (521 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 58 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 9); - r->used = 9; - mp_clamp(r); -#elif DIGIT_BIT < 58 - int i; - int j = 0; - int s = 0; - - r->dp[0] = 0; - for (i = 0; i < 9; 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 <= 58) { - 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 = 58 - s; - } - r->used = (521 + 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 < 9; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 58 >= 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 = 58 - s; - } - else { - s += 58; - } - } - r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_521 to type ecc_point. - * - * p Point of type sp_point_521. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_521_point_to_ecc_point_9(const sp_point_521* p, ecc_point* pm) -{ - int err; - - err = sp_521_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, pm->z); - } - - return err; -} - -/* Normalize the values in each word to 58 bits. - * - * a Array of sp_digit to normalize. - */ -static void sp_521_norm_9(sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - for (i = 0; i < 8; i++) { - a[i+1] += a[i] >> 58; - a[i] &= 0x3ffffffffffffffL; - } -#else - a[1] += a[0] >> 58; a[0] &= 0x3ffffffffffffffL; - a[2] += a[1] >> 58; a[1] &= 0x3ffffffffffffffL; - a[3] += a[2] >> 58; a[2] &= 0x3ffffffffffffffL; - a[4] += a[3] >> 58; a[3] &= 0x3ffffffffffffffL; - a[5] += a[4] >> 58; a[4] &= 0x3ffffffffffffffL; - a[6] += a[5] >> 58; a[5] &= 0x3ffffffffffffffL; - a[7] += a[6] >> 58; a[6] &= 0x3ffffffffffffffL; - a[8] += a[7] >> 58; a[7] &= 0x3ffffffffffffffL; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Reduce the number back to 521 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_521_mont_reduce_9(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - - (void)m; - (void)mp; - - for (i = 0; i < 8; i++) { - a[i] += (sp_digit)(((a[8 + i] >> 57) + (a[8 + i + 1] << 1)) & 0x3ffffffffffffffL); - } - a[8] &= 0x1ffffffffffffff; - a[8] += (sp_digit)(((a[16] >> 57) + (a[17] << 1)) & 0x3ffffffffffffffL); - - sp_521_norm_9(a); - - a[0] += a[8] >> 57; - a[8] &= 0x1ffffffffffffff; -} - -/* 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_521_cmp_9(const sp_digit* a, const sp_digit* b) -{ - sp_digit r = 0; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=8; i>=0; i--) { - r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 57); - } -#else - r |= (a[ 8] - b[ 8]) & (0 - (sp_digit)1); - r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 57); - r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 57); -#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_521_cond_sub_9(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 < 9; i++) { - r[i] = a[i] - (b[i] & m); - } -#else - r[ 0] = a[ 0] - (b[ 0] & m); - r[ 1] = a[ 1] - (b[ 1] & m); - r[ 2] = a[ 2] - (b[ 2] & m); - r[ 3] = a[ 3] - (b[ 3] & m); - r[ 4] = a[ 4] - (b[ 4] & m); - r[ 5] = a[ 5] - (b[ 5] & m); - r[ 6] = a[ 6] - (b[ 6] & m); - r[ 7] = a[ 7] - (b[ 7] & m); - r[ 8] = a[ 8] - (b[ 8] & 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_521_mul_add_9(sp_digit* r, const sp_digit* a, - const sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 8; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x3ffffffffffffffL); - t[1] += t[0] >> 58; - r[i+1] = (sp_digit)(t[1] & 0x3ffffffffffffffL); - t[2] += t[1] >> 58; - r[i+2] = (sp_digit)(t[2] & 0x3ffffffffffffffL); - t[3] += t[2] >> 58; - r[i+3] = (sp_digit)(t[3] & 0x3ffffffffffffffL); - t[0] = t[3] >> 58; - } - t[0] += (tb * a[8]) + r[8]; - r[8] = (sp_digit)(t[0] & 0x3ffffffffffffffL); - r[9] += (sp_digit)(t[0] >> 58); -#else - sp_int128 tb = b; - sp_int128 t[9]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - t[ 7] = tb * a[ 7]; - t[ 8] = tb * a[ 8]; - r[ 0] += (sp_digit) (t[ 0] & 0x3ffffffffffffffL); - r[ 1] += (sp_digit)((t[ 0] >> 58) + (t[ 1] & 0x3ffffffffffffffL)); - r[ 2] += (sp_digit)((t[ 1] >> 58) + (t[ 2] & 0x3ffffffffffffffL)); - r[ 3] += (sp_digit)((t[ 2] >> 58) + (t[ 3] & 0x3ffffffffffffffL)); - r[ 4] += (sp_digit)((t[ 3] >> 58) + (t[ 4] & 0x3ffffffffffffffL)); - r[ 5] += (sp_digit)((t[ 4] >> 58) + (t[ 5] & 0x3ffffffffffffffL)); - r[ 6] += (sp_digit)((t[ 5] >> 58) + (t[ 6] & 0x3ffffffffffffffL)); - r[ 7] += (sp_digit)((t[ 6] >> 58) + (t[ 7] & 0x3ffffffffffffffL)); - r[ 8] += (sp_digit)((t[ 7] >> 58) + (t[ 8] & 0x3ffffffffffffffL)); - r[ 9] += (sp_digit) (t[ 8] >> 58); -#endif /* WOLFSSL_SP_SMALL */ -} - -/* Shift the result in the high 521 bits down to the bottom. - * - * r A single precision number. - * a A single precision number. - */ -static void sp_521_mont_shift_9(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - sp_uint64 n; - - n = a[8] >> 57; - for (i = 0; i < 8; i++) { - n += (sp_uint64)a[9 + i] << 1; - r[i] = (sp_digit)(n & 0x3ffffffffffffffL); - n >>= 58; - } - n += (sp_uint64)a[17] << 1; - r[8] = n; -#else - sp_uint64 n; - - n = a[8] >> 57; - n += (sp_uint64)a[ 9] << 1U; r[ 0] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[10] << 1U; r[ 1] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[11] << 1U; r[ 2] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[12] << 1U; r[ 3] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[13] << 1U; r[ 4] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[14] << 1U; r[ 5] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[15] << 1U; r[ 6] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[16] << 1U; r[ 7] = (sp_digit)(n & 0x3ffffffffffffffUL); n >>= 58U; - n += (sp_uint64)a[17] << 1U; r[ 8] = n; -#endif /* WOLFSSL_SP_SMALL */ - XMEMSET(&r[9], 0, sizeof(*r) * 9U); -} - -/* Reduce the number back to 521 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_521_mont_reduce_order_9(sp_digit* a, const sp_digit* m, sp_digit mp) -{ - int i; - sp_digit mu; - sp_digit over; - - sp_521_norm_9(a + 9); - - for (i=0; i<8; i++) { - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x3ffffffffffffffL); - sp_521_mul_add_9(a+i, m, mu); - a[i+1] += a[i] >> 58; - } - mu = (sp_digit)(((sp_uint64)a[i] * (sp_uint64)mp) & 0x1ffffffffffffffL); - sp_521_mul_add_9(a+i, m, mu); - a[i+1] += a[i] >> 58; - a[i] &= 0x3ffffffffffffffL; - sp_521_mont_shift_9(a, a); - over = a[8] >> 57; - sp_521_cond_sub_9(a, a, m, ~((over - 1) >> 63)); - sp_521_norm_9(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_521_mont_mul_9(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit* m, sp_digit mp) -{ - sp_521_mul_9(r, a, b); - sp_521_mont_reduce_9(r, m, mp); -} - -/* Square the Montgomery form number. (r = a * a mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_521_mont_sqr_9(sp_digit* r, const sp_digit* a, - const sp_digit* m, sp_digit mp) -{ - sp_521_sqr_9(r, a); - sp_521_mont_reduce_9(r, m, mp); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square the Montgomery form number a number of times. (r = a ^ n mod m) - * - * r Result of squaring. - * a Number to square in Montgomery form. - * n Number of times to square. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE static void sp_521_mont_sqr_n_9(sp_digit* r, - const sp_digit* a, int n, const sp_digit* m, sp_digit mp) -{ - sp_521_mont_sqr_9(r, a, m, mp); - for (; n > 1; n--) { - sp_521_mont_sqr_9(r, r, m, mp); - } -} - -#endif /* !WOLFSSL_SP_SMALL */ -#ifdef WOLFSSL_SP_SMALL -/* Mod-2 for the P521 curve. */ -static const word64 p521_mod_minus_2[9] = { - 0xfffffffffffffffdU,0xffffffffffffffffU,0xffffffffffffffffU, - 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU, - 0xffffffffffffffffU,0xffffffffffffffffU,0x00000000000001ffU -}; -#endif /* !WOLFSSL_SP_SMALL */ - -/* Invert the number, in Montgomery form, modulo the modulus (prime) of the - * P521 curve. (r = 1 / a mod m) - * - * r Inverse result. - * a Number to invert. - * td Temporary data. - */ -static void sp_521_mont_inv_9(sp_digit* r, const sp_digit* a, sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 9); - for (i=519; i>=0; i--) { - sp_521_mont_sqr_9(t, t, p521_mod, p521_mp_mod); - if (p521_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) - sp_521_mont_mul_9(t, t, a, p521_mod, p521_mp_mod); - } - XMEMCPY(r, t, sizeof(sp_digit) * 9); -#else - sp_digit* t1 = td; - sp_digit* t2 = td + 2 * 9; - sp_digit* t3 = td + 4 * 9; - - /* 0x2 */ - sp_521_mont_sqr_9(t1, a, p521_mod, p521_mp_mod); - /* 0x3 */ - sp_521_mont_mul_9(t2, t1, a, p521_mod, p521_mp_mod); - /* 0x6 */ - sp_521_mont_sqr_9(t1, t2, p521_mod, p521_mp_mod); - /* 0x7 */ - sp_521_mont_mul_9(t3, t1, a, p521_mod, p521_mp_mod); - /* 0xc */ - sp_521_mont_sqr_n_9(t1, t2, 2, p521_mod, p521_mp_mod); - /* 0xf */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0x78 */ - sp_521_mont_sqr_n_9(t1, t2, 3, p521_mod, p521_mp_mod); - /* 0x7f */ - sp_521_mont_mul_9(t3, t3, t1, p521_mod, p521_mp_mod); - /* 0xf0 */ - sp_521_mont_sqr_n_9(t1, t2, 4, p521_mod, p521_mp_mod); - /* 0xff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xff00 */ - sp_521_mont_sqr_n_9(t1, t2, 8, p521_mod, p521_mp_mod); - /* 0xffff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffff0000 */ - sp_521_mont_sqr_n_9(t1, t2, 16, p521_mod, p521_mp_mod); - /* 0xffffffff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffff00000000 */ - sp_521_mont_sqr_n_9(t1, t2, 32, p521_mod, p521_mp_mod); - /* 0xffffffffffffffff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffffffffffff0000000000000000 */ - sp_521_mont_sqr_n_9(t1, t2, 64, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 */ - sp_521_mont_sqr_n_9(t1, t2, 128, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000 */ - sp_521_mont_sqr_n_9(t1, t2, 256, p521_mod, p521_mp_mod); - /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_9(t2, t2, t1, p521_mod, p521_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 */ - sp_521_mont_sqr_n_9(t1, t2, 7, p521_mod, p521_mp_mod); - /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ - sp_521_mont_mul_9(t2, t3, t1, p521_mod, p521_mp_mod); - /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc */ - sp_521_mont_sqr_n_9(t1, t2, 2, p521_mod, p521_mp_mod); - /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd */ - sp_521_mont_mul_9(r, t1, a, p521_mod, p521_mp_mod); - -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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_521_map_9(sp_point_521* r, const sp_point_521* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*9; - sp_int64 n; - - sp_521_mont_inv_9(t1, p->z, t + 2*9); - - sp_521_mont_sqr_9(t2, t1, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t1, t2, t1, p521_mod, p521_mp_mod); - - /* x /= z^2 */ - sp_521_mont_mul_9(r->x, p->x, t2, p521_mod, p521_mp_mod); - XMEMSET(r->x + 9, 0, sizeof(sp_digit) * 9U); - sp_521_mont_reduce_9(r->x, p521_mod, p521_mp_mod); - /* Reduce x to less than modulus */ - n = sp_521_cmp_9(r->x, p521_mod); - sp_521_cond_sub_9(r->x, r->x, p521_mod, (sp_digit)~(n >> 57)); - sp_521_norm_9(r->x); - - /* y /= z^3 */ - sp_521_mont_mul_9(r->y, p->y, t1, p521_mod, p521_mp_mod); - XMEMSET(r->y + 9, 0, sizeof(sp_digit) * 9U); - sp_521_mont_reduce_9(r->y, p521_mod, p521_mp_mod); - /* Reduce y to less than modulus */ - n = sp_521_cmp_9(r->y, p521_mod); - sp_521_cond_sub_9(r->y, r->y, p521_mod, (sp_digit)~(n >> 57)); - sp_521_norm_9(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_add_9(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - sp_digit over; - (void)sp_521_add_9(r, a, b); - sp_521_norm_9(r); - over = r[8] >> 57; - sp_521_cond_sub_9(r, r, m, ~((over - 1) >> 63)); - sp_521_norm_9(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_dbl_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_521_add_9(r, a, a); - sp_521_norm_9(r); - over = r[8] >> 57; - sp_521_cond_sub_9(r, r, m, ~((over - 1) >> 63)); - sp_521_norm_9(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_tpl_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_521_add_9(r, a, a); - sp_521_norm_9(r); - over = r[8] >> 57; - sp_521_cond_sub_9(r, r, m, ~((over - 1) >> 63)); - sp_521_norm_9(r); - (void)sp_521_add_9(r, r, a); - sp_521_norm_9(r); - over = r[8] >> 57; - sp_521_cond_sub_9(r, r, m, ~((over - 1) >> 63)); - sp_521_norm_9(r); -} - -#ifdef 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_521_cond_add_9(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - int i; - - for (i = 0; i < 9; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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_521_cond_add_9(sp_digit* r, const sp_digit* a, - const sp_digit* b, const sp_digit m) -{ - r[ 0] = a[ 0] + (b[ 0] & m); - r[ 1] = a[ 1] + (b[ 1] & m); - r[ 2] = a[ 2] + (b[ 2] & m); - r[ 3] = a[ 3] + (b[ 3] & m); - r[ 4] = a[ 4] + (b[ 4] & m); - r[ 5] = a[ 5] + (b[ 5] & m); - r[ 6] = a[ 6] + (b[ 6] & m); - r[ 7] = a[ 7] + (b[ 7] & m); - r[ 8] = a[ 8] + (b[ 8] & m); -} -#endif /* !WOLFSSL_SP_SMALL */ - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_521_mont_sub_9(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_521_sub_9(r, a, b); - sp_521_norm_9(r); - sp_521_cond_add_9(r, r, m, r[8] >> 57); - sp_521_norm_9(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -SP_NOINLINE static void sp_521_rshift1_9(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=0; i<8; i++) { - r[i] = (a[i] >> 1) + (sp_digit)((a[i + 1] << 57) & 0x3ffffffffffffffL); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 57) & 0x3ffffffffffffffL); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 57) & 0x3ffffffffffffffL); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 57) & 0x3ffffffffffffffL); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 57) & 0x3ffffffffffffffL); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 57) & 0x3ffffffffffffffL); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 57) & 0x3ffffffffffffffL); - r[6] = (a[6] >> 1) + (sp_digit)((a[7] << 57) & 0x3ffffffffffffffL); - r[7] = (a[7] >> 1) + (sp_digit)((a[8] << 57) & 0x3ffffffffffffffL); -#endif - r[8] = a[8] >> 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_521_mont_div2_9(sp_digit* r, const sp_digit* a, - const sp_digit* m) -{ - sp_521_cond_add_9(r, a, m, 0 - (a[0] & 1)); - sp_521_norm_9(r); - sp_521_rshift1_9(r, r); -} - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static void sp_521_proj_point_dbl_9(sp_point_521* r, const sp_point_521* p, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*9; - 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_521_mont_sqr_9(t1, p->z, p521_mod, p521_mp_mod); - /* Z = Y * Z */ - sp_521_mont_mul_9(z, p->y, p->z, p521_mod, p521_mp_mod); - /* Z = 2Z */ - sp_521_mont_dbl_9(z, z, p521_mod); - /* T2 = X - T1 */ - sp_521_mont_sub_9(t2, p->x, t1, p521_mod); - /* T1 = X + T1 */ - sp_521_mont_add_9(t1, p->x, t1, p521_mod); - /* T2 = T1 * T2 */ - sp_521_mont_mul_9(t2, t1, t2, p521_mod, p521_mp_mod); - /* T1 = 3T2 */ - sp_521_mont_tpl_9(t1, t2, p521_mod); - /* Y = 2Y */ - sp_521_mont_dbl_9(y, p->y, p521_mod); - /* Y = Y * Y */ - sp_521_mont_sqr_9(y, y, p521_mod, p521_mp_mod); - /* T2 = Y * Y */ - sp_521_mont_sqr_9(t2, y, p521_mod, p521_mp_mod); - /* T2 = T2/2 */ - sp_521_mont_div2_9(t2, t2, p521_mod); - /* Y = Y * X */ - sp_521_mont_mul_9(y, y, p->x, p521_mod, p521_mp_mod); - /* X = T1 * T1 */ - sp_521_mont_sqr_9(x, t1, p521_mod, p521_mp_mod); - /* X = X - Y */ - sp_521_mont_sub_9(x, x, y, p521_mod); - /* X = X - Y */ - sp_521_mont_sub_9(x, x, y, p521_mod); - /* Y = Y - X */ - sp_521_mont_sub_9(y, y, x, p521_mod); - /* Y = Y * T1 */ - sp_521_mont_mul_9(y, y, t1, p521_mod, p521_mp_mod); - /* Y = Y - T2 */ - sp_521_mont_sub_9(y, y, t2, p521_mod); -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_521_proj_point_dbl_9_ctx { - int state; - sp_digit* t1; - sp_digit* t2; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_521_proj_point_dbl_9_ctx; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -static int sp_521_proj_point_dbl_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_point_521* p, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_521_proj_point_dbl_9_ctx* ctx = (sp_521_proj_point_dbl_9_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_521_proj_point_dbl_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - ctx->t1 = t; - ctx->t2 = t + 2*9; - 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_521_mont_sqr_9(ctx->t1, p->z, p521_mod, p521_mp_mod); - ctx->state = 2; - break; - case 2: - /* Z = Y * Z */ - sp_521_mont_mul_9(ctx->z, p->y, p->z, p521_mod, p521_mp_mod); - ctx->state = 3; - break; - case 3: - /* Z = 2Z */ - sp_521_mont_dbl_9(ctx->z, ctx->z, p521_mod); - ctx->state = 4; - break; - case 4: - /* T2 = X - T1 */ - sp_521_mont_sub_9(ctx->t2, p->x, ctx->t1, p521_mod); - ctx->state = 5; - break; - case 5: - /* T1 = X + T1 */ - sp_521_mont_add_9(ctx->t1, p->x, ctx->t1, p521_mod); - ctx->state = 6; - break; - case 6: - /* T2 = T1 * T2 */ - sp_521_mont_mul_9(ctx->t2, ctx->t1, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 7; - break; - case 7: - /* T1 = 3T2 */ - sp_521_mont_tpl_9(ctx->t1, ctx->t2, p521_mod); - ctx->state = 8; - break; - case 8: - /* Y = 2Y */ - sp_521_mont_dbl_9(ctx->y, p->y, p521_mod); - ctx->state = 9; - break; - case 9: - /* Y = Y * Y */ - sp_521_mont_sqr_9(ctx->y, ctx->y, p521_mod, p521_mp_mod); - ctx->state = 10; - break; - case 10: - /* T2 = Y * Y */ - sp_521_mont_sqr_9(ctx->t2, ctx->y, p521_mod, p521_mp_mod); - ctx->state = 11; - break; - case 11: - /* T2 = T2/2 */ - sp_521_mont_div2_9(ctx->t2, ctx->t2, p521_mod); - ctx->state = 12; - break; - case 12: - /* Y = Y * X */ - sp_521_mont_mul_9(ctx->y, ctx->y, p->x, p521_mod, p521_mp_mod); - ctx->state = 13; - break; - case 13: - /* X = T1 * T1 */ - sp_521_mont_sqr_9(ctx->x, ctx->t1, p521_mod, p521_mp_mod); - ctx->state = 14; - break; - case 14: - /* X = X - Y */ - sp_521_mont_sub_9(ctx->x, ctx->x, ctx->y, p521_mod); - ctx->state = 15; - break; - case 15: - /* X = X - Y */ - sp_521_mont_sub_9(ctx->x, ctx->x, ctx->y, p521_mod); - ctx->state = 16; - break; - case 16: - /* Y = Y - X */ - sp_521_mont_sub_9(ctx->y, ctx->y, ctx->x, p521_mod); - ctx->state = 17; - break; - case 17: - /* Y = Y * T1 */ - sp_521_mont_mul_9(ctx->y, ctx->y, ctx->t1, p521_mod, p521_mp_mod); - ctx->state = 18; - break; - case 18: - /* Y = Y - T2 */ - sp_521_mont_sub_9(ctx->y, ctx->y, ctx->t2, p521_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 */ -/* 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_521_cmp_equal_9(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])) == 0; -} - -/* 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_521_iszero_9(const sp_digit* a) -{ - return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | - a[8]) == 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. - */ -static void sp_521_proj_point_add_9(sp_point_521* r, - const sp_point_521* p, const sp_point_521* q, sp_digit* t) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*9; - sp_digit* t2 = t + 4*9; - sp_digit* t3 = t + 6*9; - sp_digit* t4 = t + 8*9; - sp_digit* t5 = t + 10*9; - - /* U1 = X1*Z2^2 */ - sp_521_mont_sqr_9(t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t3, t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t1, t1, p->x, p521_mod, p521_mp_mod); - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_9(t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t4, t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t2, t2, q->x, p521_mod, p521_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_521_mont_mul_9(t3, t3, p->y, p521_mod, p521_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_9(t4, t4, q->y, p521_mod, p521_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_521_cmp_equal_9(t2, t1) & - sp_521_cmp_equal_9(t4, t3)) { - sp_521_proj_point_dbl_9(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* H = U2 - U1 */ - sp_521_mont_sub_9(t2, t2, t1, p521_mod); - /* R = S2 - S1 */ - sp_521_mont_sub_9(t4, t4, t3, p521_mod); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_521_mont_sqr_9(t5, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(y, t1, t5, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t5, t5, t2, p521_mod, p521_mp_mod); - /* Z3 = H*Z1*Z2 */ - sp_521_mont_mul_9(z, p->z, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(z, z, q->z, p521_mod, p521_mp_mod); - sp_521_mont_sqr_9(x, t4, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(x, x, t5, p521_mod); - sp_521_mont_mul_9(t5, t5, t3, p521_mod, p521_mp_mod); - sp_521_mont_dbl_9(t3, y, p521_mod); - sp_521_mont_sub_9(x, x, t3, p521_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_521_mont_sub_9(y, y, x, p521_mod); - sp_521_mont_mul_9(y, y, t4, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(y, y, t5, p521_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 9; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_521_proj_point_add_9_ctx { - int state; - sp_521_proj_point_dbl_9_ctx dbl_ctx; - const sp_point_521* ap[2]; - sp_point_521* rp[2]; - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; - sp_digit* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_521_proj_point_add_9_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -static int sp_521_proj_point_add_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_point_521* p, const sp_point_521* q, sp_digit* t) -{ - int err = FP_WOULDBLOCK; - sp_521_proj_point_add_9_ctx* ctx = (sp_521_proj_point_add_9_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_521_proj_point_add_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_521* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*9; - ctx->t2 = t + 4*9; - ctx->t3 = t + 6*9; - ctx->t4 = t + 8*9; - ctx->t5 = t + 10*9; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_521_mont_sqr_9(ctx->t1, q->z, p521_mod, p521_mp_mod); - ctx->state = 2; - break; - case 2: - sp_521_mont_mul_9(ctx->t3, ctx->t1, q->z, p521_mod, p521_mp_mod); - ctx->state = 3; - break; - case 3: - sp_521_mont_mul_9(ctx->t1, ctx->t1, p->x, p521_mod, p521_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_9(ctx->t2, p->z, p521_mod, p521_mp_mod); - ctx->state = 5; - break; - case 5: - sp_521_mont_mul_9(ctx->t4, ctx->t2, p->z, p521_mod, p521_mp_mod); - ctx->state = 6; - break; - case 6: - sp_521_mont_mul_9(ctx->t2, ctx->t2, q->x, p521_mod, p521_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_521_mont_mul_9(ctx->t3, ctx->t3, p->y, p521_mod, p521_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_9(ctx->t4, ctx->t4, q->y, p521_mod, p521_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_521_cmp_equal_9(ctx->t2, ctx->t1) & - sp_521_cmp_equal_9(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_521_proj_point_dbl_9(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_521_mont_sub_9(ctx->t2, ctx->t2, ctx->t1, p521_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_521_mont_sub_9(ctx->t4, ctx->t4, ctx->t3, p521_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_521_mont_sqr_9(ctx->t5, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 13; - break; - case 13: - sp_521_mont_mul_9(ctx->y, ctx->t1, ctx->t5, p521_mod, p521_mp_mod); - ctx->state = 14; - break; - case 14: - sp_521_mont_mul_9(ctx->t5, ctx->t5, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_521_mont_mul_9(ctx->z, p->z, ctx->t2, p521_mod, p521_mp_mod); - ctx->state = 16; - break; - case 16: - sp_521_mont_mul_9(ctx->z, ctx->z, q->z, p521_mod, p521_mp_mod); - ctx->state = 17; - break; - case 17: - sp_521_mont_sqr_9(ctx->x, ctx->t4, p521_mod, p521_mp_mod); - ctx->state = 18; - break; - case 18: - sp_521_mont_sub_9(ctx->x, ctx->x, ctx->t5, p521_mod); - ctx->state = 19; - break; - case 19: - sp_521_mont_mul_9(ctx->t5, ctx->t5, ctx->t3, p521_mod, p521_mp_mod); - ctx->state = 20; - break; - case 20: - sp_521_mont_dbl_9(ctx->t3, ctx->y, p521_mod); - sp_521_mont_sub_9(ctx->x, ctx->x, ctx->t3, p521_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_521_mont_sub_9(ctx->y, ctx->y, ctx->x, p521_mod); - ctx->state = 22; - break; - case 22: - sp_521_mont_mul_9(ctx->y, ctx->y, ctx->t4, p521_mod, p521_mp_mod); - ctx->state = 23; - break; - case 23: - sp_521_mont_sub_9(ctx->y, ctx->y, ctx->t5, p521_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 9; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -/* Multiply a number by Montgomery 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_521_mod_mul_norm_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - (void)m; - - if (r != a) { - XMEMCPY(r, a, 9 * sizeof(sp_digit)); - } - - return MP_OKAY; -} - -#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. - * 521 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. - */ -static int sp_521_ecc_mulmod_9(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_521, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_521, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_521) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_521_mod_mul_norm_9(t[1].x, g->x, p521_mod); - } - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_9(t[1].y, g->y, p521_mod); - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_9(t[1].z, g->z, p521_mod); - - if (err == MP_OKAY) { - i = 8; - c = 57; - n = k[i--] << (58 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 58; - } - - y = (n >> 57) & 1; - n <<= 1; - - sp_521_proj_point_add_9(&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_521)); - sp_521_proj_point_dbl_9(&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_521)); - } - - if (map != 0) { - sp_521_map_9(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_521)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_521, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_521_ecc_mulmod_9_ctx { - int state; - union { - sp_521_proj_point_dbl_9_ctx dbl_ctx; - sp_521_proj_point_add_9_ctx add_ctx; - }; - sp_point_521 t[3]; - sp_digit tmp[2 * 9 * 6]; - sp_digit n; - int i; - int c; - int y; -} sp_521_ecc_mulmod_9_ctx; - -static int sp_521_ecc_mulmod_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_point_521* g, const sp_digit* k, int map, int ct, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_521_ecc_mulmod_9_ctx* ctx = (sp_521_ecc_mulmod_9_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_521_ecc_mulmod_9_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_521) * 3); - ctx->i = 8; - ctx->c = 57; - ctx->n = k[ctx->i--] << (58 - 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_521_mod_mul_norm_9(ctx->t[1].x, g->x, p521_mod); - ctx->state = 2; - break; - case 2: /* T1Y */ - err = sp_521_mod_mul_norm_9(ctx->t[1].y, g->y, p521_mod); - ctx->state = 3; - break; - case 3: /* T1Z */ - err = sp_521_mod_mul_norm_9(ctx->t[1].z, g->z, p521_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 = 58; - } - ctx->y = (ctx->n >> 57) & 1; - ctx->n <<= 1; - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 5; - break; - case 5: /* ADD */ - err = sp_521_proj_point_add_9_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_521)); - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 6; - } - break; - case 6: /* DBL */ - err = sp_521_proj_point_dbl_9_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_521)); - ctx->state = 4; - ctx->c--; - } - break; - case 7: /* MAP */ - if (map != 0) { - sp_521_map_9(r, &ctx->t[0], ctx->tmp); - } - else { - XMEMCPY(r, &ctx->t[0], sizeof(sp_point_521)); - } - 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 */ - -#else -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_521 { - sp_digit x[9]; - sp_digit y[9]; -} sp_table_entry_521; - -/* 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_521_cond_copy_9(sp_digit* r, const sp_digit* a, const sp_digit m) -{ - sp_digit t[9]; -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i = 0; i < 9; i++) { - t[i] = r[i] ^ a[i]; - } - for (i = 0; i < 9; 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]; - 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; -#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_521_proj_point_dbl_n_9(sp_point_521* p, int i, - sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*9; - sp_digit* b = t + 4*9; - sp_digit* t1 = t + 6*9; - sp_digit* t2 = t + 8*9; - sp_digit* x; - sp_digit* y; - sp_digit* z; - volatile int n = i - 1; - - x = p->x; - y = p->y; - z = p->z; - - /* Y = 2*Y */ - sp_521_mont_dbl_9(y, y, p521_mod); - /* W = Z^4 */ - sp_521_mont_sqr_9(w, z, p521_mod, p521_mp_mod); - sp_521_mont_sqr_9(w, w, p521_mod, p521_mp_mod); -#ifndef WOLFSSL_SP_SMALL - while (n > 0) -#else - while (n >= 0) -#endif - { - /* A = 3*(X^2 - W) */ - sp_521_mont_sqr_9(t1, x, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(t1, t1, w, p521_mod); - sp_521_mont_tpl_9(a, t1, p521_mod); - /* B = X*Y^2 */ - sp_521_mont_sqr_9(t1, y, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(b, t1, x, p521_mod, p521_mp_mod); - /* X = A^2 - 2B */ - sp_521_mont_sqr_9(x, a, p521_mod, p521_mp_mod); - sp_521_mont_dbl_9(t2, b, p521_mod); - sp_521_mont_sub_9(x, x, t2, p521_mod); - /* B = 2.(B - X) */ - sp_521_mont_sub_9(t2, b, x, p521_mod); - sp_521_mont_dbl_9(b, t2, p521_mod); - /* Z = Z*Y */ - sp_521_mont_mul_9(z, z, y, p521_mod, p521_mp_mod); - /* t1 = Y^4 */ - sp_521_mont_sqr_9(t1, t1, p521_mod, p521_mp_mod); -#ifdef WOLFSSL_SP_SMALL - if (n != 0) -#endif - { - /* W = W*Y^4 */ - sp_521_mont_mul_9(w, w, t1, p521_mod, p521_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_521_mont_mul_9(y, b, a, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(y, y, t1, p521_mod); - n = n - 1; - } -#ifndef WOLFSSL_SP_SMALL - /* A = 3*(X^2 - W) */ - sp_521_mont_sqr_9(t1, x, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(t1, t1, w, p521_mod); - sp_521_mont_tpl_9(a, t1, p521_mod); - /* B = X*Y^2 */ - sp_521_mont_sqr_9(t1, y, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(b, t1, x, p521_mod, p521_mp_mod); - /* X = A^2 - 2B */ - sp_521_mont_sqr_9(x, a, p521_mod, p521_mp_mod); - sp_521_mont_dbl_9(t2, b, p521_mod); - sp_521_mont_sub_9(x, x, t2, p521_mod); - /* B = 2.(B - X) */ - sp_521_mont_sub_9(t2, b, x, p521_mod); - sp_521_mont_dbl_9(b, t2, p521_mod); - /* Z = Z*Y */ - sp_521_mont_mul_9(z, z, y, p521_mod, p521_mp_mod); - /* t1 = Y^4 */ - sp_521_mont_sqr_9(t1, t1, p521_mod, p521_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_521_mont_mul_9(y, b, a, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(y, y, t1, p521_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_521_mont_div2_9(y, y, p521_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_521_proj_point_dbl_n_store_9(sp_point_521* r, - const sp_point_521* p, int n, int m, sp_digit* t) -{ - sp_digit* w = t; - sp_digit* a = t + 2*9; - sp_digit* b = t + 4*9; - sp_digit* t1 = t + 6*9; - sp_digit* t2 = t + 8*9; - sp_digit* x = r[2*m].x; - sp_digit* y = r[(1<x[i]; - } - for (i=0; i<9; i++) { - y[i] = p->y[i]; - } - for (i=0; i<9; i++) { - z[i] = p->z[i]; - } - - /* Y = 2*Y */ - sp_521_mont_dbl_9(y, y, p521_mod); - /* W = Z^4 */ - sp_521_mont_sqr_9(w, z, p521_mod, p521_mp_mod); - sp_521_mont_sqr_9(w, w, p521_mod, p521_mp_mod); - j = m; - for (i=1; i<=n; i++) { - j *= 2; - - /* A = 3*(X^2 - W) */ - sp_521_mont_sqr_9(t1, x, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(t1, t1, w, p521_mod); - sp_521_mont_tpl_9(a, t1, p521_mod); - /* B = X*Y^2 */ - sp_521_mont_sqr_9(t1, y, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(b, t1, x, p521_mod, p521_mp_mod); - x = r[j].x; - /* X = A^2 - 2B */ - sp_521_mont_sqr_9(x, a, p521_mod, p521_mp_mod); - sp_521_mont_dbl_9(t2, b, p521_mod); - sp_521_mont_sub_9(x, x, t2, p521_mod); - /* B = 2.(B - X) */ - sp_521_mont_sub_9(t2, b, x, p521_mod); - sp_521_mont_dbl_9(b, t2, p521_mod); - /* Z = Z*Y */ - sp_521_mont_mul_9(r[j].z, z, y, p521_mod, p521_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_521_mont_sqr_9(t1, t1, p521_mod, p521_mp_mod); - if (i != n) { - /* W = W*Y^4 */ - sp_521_mont_mul_9(w, w, t1, p521_mod, p521_mp_mod); - } - /* y = 2*A*(B - X) - Y^4 */ - sp_521_mont_mul_9(y, b, a, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(y, y, t1, p521_mod); - /* Y = Y/2 */ - sp_521_mont_div2_9(r[j].y, y, p521_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_521_proj_point_add_sub_9(sp_point_521* ra, - sp_point_521* rs, const sp_point_521* p, const sp_point_521* q, - sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2*9; - sp_digit* t3 = t + 4*9; - sp_digit* t4 = t + 6*9; - sp_digit* t5 = t + 8*9; - sp_digit* t6 = t + 10*9; - sp_digit* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, p->z, sizeof(p->z) / 2); - ra->infinity = 0; - rs->infinity = 0; - - /* U1 = X1*Z2^2 */ - sp_521_mont_sqr_9(t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t3, t1, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t1, t1, xa, p521_mod, p521_mp_mod); - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_9(t2, za, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t4, t2, za, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t2, t2, q->x, p521_mod, p521_mp_mod); - /* S1 = Y1*Z2^3 */ - sp_521_mont_mul_9(t3, t3, ya, p521_mod, p521_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_9(t4, t4, q->y, p521_mod, p521_mp_mod); - /* H = U2 - U1 */ - sp_521_mont_sub_9(t2, t2, t1, p521_mod); - /* RS = S2 + S1 */ - sp_521_mont_add_9(t6, t4, t3, p521_mod); - /* R = S2 - S1 */ - sp_521_mont_sub_9(t4, t4, t3, p521_mod); - /* Z3 = H*Z1*Z2 */ - /* ZS = H*Z1*Z2 */ - sp_521_mont_mul_9(za, za, q->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(za, za, t2, p521_mod, p521_mp_mod); - XMEMCPY(zs, za, sizeof(p->z)/2); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - /* XS = RS^2 - H^3 - 2*U1*H^2 */ - sp_521_mont_sqr_9(xa, t4, p521_mod, p521_mp_mod); - sp_521_mont_sqr_9(xs, t6, p521_mod, p521_mp_mod); - sp_521_mont_sqr_9(t5, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(ya, t1, t5, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t5, t5, t2, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(xa, xa, t5, p521_mod); - sp_521_mont_sub_9(xs, xs, t5, p521_mod); - sp_521_mont_dbl_9(t1, ya, p521_mod); - sp_521_mont_sub_9(xa, xa, t1, p521_mod); - sp_521_mont_sub_9(xs, xs, t1, p521_mod); - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ - sp_521_mont_sub_9(ys, ya, xs, p521_mod); - sp_521_mont_sub_9(ya, ya, xa, p521_mod); - sp_521_mont_mul_9(ya, ya, t4, p521_mod, p521_mp_mod); - sp_521_sub_9(t6, p521_mod, t6); - sp_521_mont_mul_9(ys, ys, t6, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t5, t5, t3, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(ya, ya, t5, p521_mod); - sp_521_mont_sub_9(ys, ys, t5, p521_mod); -} - -/* Structure used to describe recoding of scalar multiplication. */ -typedef struct ecc_recode_521 { - /* Index into pre-computation table. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_521; - -/* The index into pre-computation table to use. */ -static const word8 recode_index_9_6[66] = { - 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, 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 word8 recode_neg_9_6[66] = { - 0, 0, 0, 0, 0, 0, 0, 0, 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, - 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_521_ecc_recode_6_9(const sp_digit* k, ecc_recode_521* v) -{ - int i; - int j; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<87; i++) { - y = (word8)(int8_t)n; - if (o + 6 < 58) { - y &= 0x3f; - n >>= 6; - o += 6; - } - else if (o + 6 == 58) { - n >>= 6; - if (++j < 9) - n = k[j]; - o = 0; - } - else if (++j < 9) { - n = k[j]; - y |= (word8)((n << (58 - o)) & 0x3f); - o -= 52; - n >>= o; - } - - y = (word8)(y + carry); - v[i].i = recode_index_9_6[y]; - v[i].neg = recode_neg_9_6[y]; - carry = (y >> 6) + v[i].neg; - } -} - -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible point that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_521_get_point_33_9(sp_point_521* r, const sp_point_521* 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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - r->z[0] = 0; - r->z[1] = 0; - r->z[2] = 0; - r->z[3] = 0; - r->z[4] = 0; - r->z[5] = 0; - r->z[6] = 0; - r->z[7] = 0; - r->z[8] = 0; - for (i = 1; i < 33; i++) { - mask = (sp_digit)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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - r->z[0] |= mask & table[i].z[0]; - r->z[1] |= mask & table[i].z[1]; - r->z[2] |= mask & table[i].z[2]; - r->z[3] |= mask & table[i].z[3]; - r->z[4] |= mask & table[i].z[4]; - r->z[5] |= mask & table[i].z[5]; - r->z[6] |= mask & table[i].z[6]; - r->z[7] |= mask & table[i].z[7]; - r->z[8] |= mask & table[i].z[8]; - } -} -#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. - * - * Window technique of 6 bits. (Add-Sub variation.) - * Calculate 0..32 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_521_ecc_mulmod_win_add_sub_9(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ - SP_DECL_VAR(sp_point_521, t, 33+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - sp_point_521* rt = NULL; - sp_point_521* p = NULL; - sp_digit* negy; - int i; - ecc_recode_521 v[87]; - int err = MP_OKAY; - - /* Constant time used for cache attack resistance implementation. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_521, t, 33+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - 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_521_mod_mul_norm_9(t[1].x, g->x, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_9(t[1].y, g->y, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_9(t[1].z, g->z, p521_mod); - } - - if (err == MP_OKAY) { - t[1].infinity = 0; - /* t[2] ... t[32] */ - sp_521_proj_point_dbl_n_store_9(t, &t[ 1], 5, 1, tmp); - sp_521_proj_point_add_9(&t[ 3], &t[ 2], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[ 6], &t[ 3], tmp); - sp_521_proj_point_add_sub_9(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[10], &t[ 5], tmp); - sp_521_proj_point_add_sub_9(&t[11], &t[ 9], &t[10], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[12], &t[ 6], tmp); - sp_521_proj_point_dbl_9(&t[14], &t[ 7], tmp); - sp_521_proj_point_add_sub_9(&t[15], &t[13], &t[14], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[18], &t[ 9], tmp); - sp_521_proj_point_add_sub_9(&t[19], &t[17], &t[18], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[20], &t[10], tmp); - sp_521_proj_point_dbl_9(&t[22], &t[11], tmp); - sp_521_proj_point_add_sub_9(&t[23], &t[21], &t[22], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[24], &t[12], tmp); - sp_521_proj_point_dbl_9(&t[26], &t[13], tmp); - sp_521_proj_point_add_sub_9(&t[27], &t[25], &t[26], &t[ 1], tmp); - sp_521_proj_point_dbl_9(&t[28], &t[14], tmp); - sp_521_proj_point_dbl_9(&t[30], &t[15], tmp); - sp_521_proj_point_add_sub_9(&t[31], &t[29], &t[30], &t[ 1], tmp); - - negy = t[0].y; - - sp_521_ecc_recode_6_9(k, v); - - i = 86; - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_point_33_9(rt, t, v[i].i); - rt->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_521)); - } - for (--i; i>=0; i--) { - sp_521_proj_point_dbl_n_9(rt, 6, tmp); - - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_point_33_9(p, t, v[i].i); - p->infinity = !v[i].i; - } - else - #endif - { - XMEMCPY(p, &t[v[i].i], sizeof(sp_point_521)); - } - sp_521_sub_9(negy, p521_mod, p->y); - sp_521_norm_9(negy); - sp_521_cond_copy_9(p->y, negy, (sp_digit)0 - v[i].neg); - sp_521_proj_point_add_9(rt, rt, p, tmp); - } - - if (map != 0) { - sp_521_map_9(r, rt, tmp); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_521)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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_521_proj_point_add_qz1_9(sp_point_521* r, - const sp_point_521* p, const sp_point_521* q, sp_digit* t) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*9; - sp_digit* t6 = t + 4*9; - sp_digit* t1 = t + 6*9; - sp_digit* t4 = t + 8*9; - sp_digit* t5 = t + 10*9; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_521_mont_sqr_9(t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t4, t2, p->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t2, t2, q->x, p521_mod, p521_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_521_mont_mul_9(t4, t4, q->y, p521_mod, p521_mp_mod); - - if ((~p->infinity) & (~q->infinity) & - sp_521_cmp_equal_9(p->x, t2) & - sp_521_cmp_equal_9(p->y, t4)) { - sp_521_proj_point_dbl_9(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_521_mont_sub_9(t2, t2, p->x, p521_mod); - /* R = S2 - Y1 */ - sp_521_mont_sub_9(t4, t4, p->y, p521_mod); - /* Z3 = H*Z1 */ - sp_521_mont_mul_9(z, p->z, t2, p521_mod, p521_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_521_mont_sqr_9(t1, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t3, p->x, t1, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t1, t1, t2, p521_mod, p521_mp_mod); - sp_521_mont_sqr_9(t2, t4, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(t2, t2, t1, p521_mod); - sp_521_mont_dbl_9(t5, t3, p521_mod); - sp_521_mont_sub_9(x, t2, t5, p521_mod); - /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_521_mont_sub_9(t3, t3, x, p521_mod); - sp_521_mont_mul_9(t3, t3, t4, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t1, t1, p->y, p521_mod, p521_mp_mod); - sp_521_mont_sub_9(y, t3, t1, p521_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 9; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 9; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#ifdef FP_ECC -/* Convert the projective point to affine. - * Ordinates are in Montgomery form. - * - * a Point to convert. - * t Temporary data. - */ -static void sp_521_proj_to_affine_9(sp_point_521* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 9; - sp_digit* tmp = t + 4 * 9; - - sp_521_mont_inv_9(t1, a->z, tmp); - - sp_521_mont_sqr_9(t2, t1, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(t1, t2, t1, p521_mod, p521_mp_mod); - - sp_521_mont_mul_9(a->x, a->x, t2, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(a->y, a->y, t1, p521_mod, p521_mp_mod); - XMEMCPY(a->z, p521_norm_mod, sizeof(p521_norm_mod)); -} - -/* Generate the pre-computed table of points for the base point. - * - * width = 8 - * 256 entries - * 65 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_521_gen_stripe_table_9(const sp_point_521* a, - sp_table_entry_521* table, sp_digit* tmp, void* heap) -{ - SP_DECL_VAR(sp_point_521, t, 3); - sp_point_521* s1 = NULL; - sp_point_521* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_521, t, 3, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - s1 = t + 1; - s2 = t + 2; - - err = sp_521_mod_mul_norm_9(t->x, a->x, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_9(t->y, a->y, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_mod_mul_norm_9(t->z, a->z, p521_mod); - } - if (err == MP_OKAY) { - t->infinity = 0; - sp_521_proj_to_affine_9(t, tmp); - - XMEMCPY(s1->z, p521_norm_mod, sizeof(p521_norm_mod)); - s1->infinity = 0; - XMEMCPY(s2->z, p521_norm_mod, sizeof(p521_norm_mod)); - s2->infinity = 0; - - /* table[0] = {0, 0, infinity} */ - XMEMSET(&table[0], 0, sizeof(sp_table_entry_521)); - /* 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_521_proj_point_dbl_n_9(t, 66, tmp); - sp_521_proj_to_affine_9(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_521_proj_point_add_qz1_9(t, s1, s2, tmp); - sp_521_proj_to_affine_9(t, tmp); - XMEMCPY(table[j].x, t->x, sizeof(table->x)); - XMEMCPY(table[j].y, t->y, sizeof(table->y)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -/* Touch each possible entry that could be being copied. - * - * r Point to copy into. - * table Table - start of the entries to access - * idx Index of entry to retrieve. - */ -static void sp_521_get_entry_256_9(sp_point_521* r, - const sp_table_entry_521* 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->x[6] = 0; - r->x[7] = 0; - r->x[8] = 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; - r->y[6] = 0; - r->y[7] = 0; - r->y[8] = 0; - for (i = 1; i < 256; i++) { - sp_digit gte = (sp_digit)((((sp_uint64)i - (sp_uint64)idx) >> 63) - 1); - sp_digit lte = (sp_digit)((((sp_uint64)idx - (sp_uint64)i) >> 63) - 1); - mask = gte & lte; - 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->x[6] |= mask & table[i].x[6]; - r->x[7] |= mask & table[i].x[7]; - r->x[8] |= mask & table[i].x[8]; - 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]; - r->y[6] |= mask & table[i].y[6]; - r->y[7] |= mask & table[i].y[7]; - r->y[8] |= mask & table[i].y[8]; - } -} -#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^65, ... - * 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_521_ecc_mulmod_stripe_9(sp_point_521* r, const sp_point_521* g, - const sp_table_entry_521* table, const sp_digit* k, int map, - int ct, void* heap) -{ - SP_DECL_VAR(sp_point_521, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 9 * 6); - sp_point_521* 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; - - - SP_ALLOC_VAR(sp_point_521, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - p = rt + 1; - - XMEMCPY(p->z, p521_norm_mod, sizeof(p521_norm_mod)); - XMEMCPY(rt->z, p521_norm_mod, sizeof(p521_norm_mod)); - - y = 0; - x = 65; - for (j=0; j<8 && x<521; j++) { - y |= (int)(((k[x / 58] >> (x % 58)) & 1) << j); - x += 66; - } - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_entry_256_9(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=64; i>=0; i--) { - y = 0; - x = i; - for (j=0; j<8 && x<521; j++) { - y |= (int)(((k[x / 58] >> (x % 58)) & 1) << j); - x += 66; - } - - sp_521_proj_point_dbl_9(rt, rt, t); - #ifndef WC_NO_CACHE_RESISTANT - if (ct) { - sp_521_get_entry_256_9(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_521_proj_point_add_qz1_9(rt, rt, p, t); - } - - if (map != 0) { - sp_521_map_9(r, rt, t); - } - else { - XMEMCPY(r, rt, sizeof(sp_point_521)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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_521_t { - /* X ordinate of point that table was generated from. */ - sp_digit x[9]; - /* Y ordinate of point that table was generated from. */ - sp_digit y[9]; - /* Precomputation table for point. */ - sp_table_entry_521 table[256]; - /* Count of entries in table. */ - word32 cnt; - /* Point and table set in entry. */ - int set; -} sp_cache_521_t; - -/* Cache of tables. */ -static THREAD_LS_T sp_cache_521_t sp_cache_521[FP_ENTRIES]; -/* Index of last entry in cache. */ -static THREAD_LS_T int sp_cache_521_last = -1; -/* Cache has been initialized. */ -static THREAD_LS_T int sp_cache_521_inited = 0; - -#ifndef HAVE_THREAD_LS - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_521 = 0; - #endif - static wolfSSL_Mutex sp_cache_521_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_521_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * cache [out] Cache table to use. - */ -static void sp_ecc_get_cache_521(const sp_point_521* g, sp_cache_521_t** cache) -{ - int i; - int j; - word32 least; - - if (sp_cache_521_inited == 0) { - for (i=0; ix, sp_cache_521[i].x) & - sp_521_cmp_equal_9(g->y, sp_cache_521[i].y)) { - sp_cache_521[i].cnt++; - break; - } - } - - /* No match. */ - if (i == FP_ENTRIES) { - /* Find empty entry. */ - i = (sp_cache_521_last + 1) % FP_ENTRIES; - for (; i != sp_cache_521_last; i=(i+1)%FP_ENTRIES) { - if (!sp_cache_521[i].set) { - break; - } - } - - /* Evict least used. */ - if (i == sp_cache_521_last) { - least = sp_cache_521[0].cnt; - for (j=1; jx, sizeof(sp_cache_521[i].x)); - XMEMCPY(sp_cache_521[i].y, g->y, sizeof(sp_cache_521[i].y)); - sp_cache_521[i].set = 1; - sp_cache_521[i].cnt = 1; - } - - *cache = &sp_cache_521[i]; - sp_cache_521_last = i; -} -#endif /* FP_ECC */ - -/* Multiply the base point of P521 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_521_ecc_mulmod_9(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#ifndef FP_ECC - return sp_521_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap); -#else - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - sp_cache_521_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_521 == 0) { - wc_InitMutex(&sp_cache_521_lock); - initCacheMutex_521 = 1; - } - #endif - if (wc_LockMutex(&sp_cache_521_lock) != 0) { - err = BAD_MUTEX_E; - } - } -#endif /* HAVE_THREAD_LS */ - - if (err == MP_OKAY) { - sp_ecc_get_cache_521(g, &cache); - if (cache->cnt == 2) - sp_521_gen_stripe_table_9(g, cache->table, tmp, heap); - -#ifndef HAVE_THREAD_LS - wc_UnLockMutex(&sp_cache_521_lock); -#endif /* HAVE_THREAD_LS */ - - if (cache->cnt < 2) { - err = sp_521_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap); - } - else { - err = sp_521_ecc_mulmod_stripe_9(r, g, cache->table, k, - map, ct, heap); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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_521(const mp_int* km, const ecc_point* gm, ecc_point* r, - int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 1); - SP_DECL_VAR(sp_digit, k, 9); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(k, 9, km); - sp_521_point_from_ecc_point_9(point, gm); - - err = sp_521_ecc_mulmod_9(point, point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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_521(const mp_int* km, const ecc_point* gm, - const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 2); - SP_DECL_VAR(sp_digit, k, 9 + 9 * 2 * 6); - sp_point_521* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9 + 9 * 2 * 6, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - addP = point + 1; - tmp = k + 9; - - sp_521_from_mp(k, 9, km); - sp_521_point_from_ecc_point_9(point, gm); - sp_521_point_from_ecc_point_9(addP, am); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_9(addP->x, addP->x, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_9(addP->y, addP->y, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_9(addP->z, addP->z, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_9(point, point, k, 0, 0, heap); - } - if (err == MP_OKAY) { - sp_521_proj_point_add_9(point, point, addP, tmp); - - if (map) { - sp_521_map_9(point, point, tmp); - } - - err = sp_521_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_SMALL -/* Multiply the base point of P521 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_521_ecc_mulmod_base_9(sp_point_521* r, const sp_digit* k, - int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_521_ecc_mulmod_9(r, &p521_base, k, map, ct, heap); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_521_ecc_mulmod_base_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_521_ecc_mulmod_9_nb(sp_ctx, r, &p521_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#else -/* Striping precomputation table. - * 8 points combined into a table of 256 points. - * Distance of 66 between points. - */ -static const sp_table_entry_521 p521_table[256] = { - /* 0 */ - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - /* 1 */ - { { 0x17e7e31c2e5bd66L,0x22cf0615a90a6feL,0x0127a2ffa8de334L, - 0x1dfbf9d64a3f877L,0x06b4d3dbaa14b5eL,0x14fed487e0a2bd8L, - 0x15b4429c6481390L,0x3a73678fb2d988eL,0x0c6858e06b70404L }, - { 0x0be94769fd16650L,0x31c21a89cb09022L,0x39013fad0761353L, - 0x2657bd099031542L,0x3273e662c97ee72L,0x1e6d11a05ebef45L, - 0x3d1bd998f544495L,0x3001172297ed0b1L,0x11839296a789a3bL } }, - /* 2 */ - { { 0x03986670f0ccb51L,0x387404d9525d2a0L,0x0f21b2b29ed9b87L, - 0x2aa8eb74cddfd63L,0x0e9d08ffb06c0e9L,0x19d8589fc4ecd74L, - 0x0a3ef4dd8bf44c9L,0x0eb6e92863051d6L,0x13e96a576dda004L }, - { 0x3de24f8632d95a3L,0x057bc5314920a4aL,0x063e9bdaba1979fL, - 0x3d2a58adc1eab76L,0x214258d98dde053L,0x18708d7316628b7L, - 0x3fd32c9fa5a19d0L,0x33ab03b519443a3L,0x1852aea9dd1ef78L } }, - /* 3 */ - { { 0x0a91dd8eaaf1fe3L,0x0e19891002d4af4L,0x06a921abf0d20dbL, - 0x26a9da32503fda8L,0x09a1eec37941287L,0x1ce0d0f3cde46afL, - 0x22abc1c913fbe62L,0x3cc4dca2d0aaf88L,0x157874c0a862b9eL }, - { 0x2c8f184e6f03d49L,0x0d5f907922f80c2L,0x1ef3815cbdefa9cL, - 0x2ad7f6370f00b39L,0x1faeb109d7a41c7L,0x213d34e12fbd9f2L, - 0x2f0aae2f98cca1aL,0x25a2df80f51f59cL,0x00724b1ab581d58L } }, - /* 4 */ - { { 0x04f2d4bdf9314e0L,0x3a14379e802ab24L,0x1083582efb03daaL, - 0x20fb1ff9b49e48cL,0x2199d74a880f1c2L,0x25401f9cb56ce65L, - 0x33f03e5f120b9b3L,0x2da18c348ddcd1dL,0x121f4c192733b78L }, - { 0x103ff6dfa8b51f0L,0x2bed45038af7c3cL,0x380e83254171ae7L, - 0x2e33684365444c0L,0x24f3a8c01e83501L,0x3201c1a4415ddc7L, - 0x2238218f52196aaL,0x29fc4d826c2aa95L,0x1db8c25790694a0L } }, - /* 5 */ - { { 0x00370ccb2c0958dL,0x3bc599a69ece1ccL,0x33cf480c9b3889aL, - 0x3cbeacf85249e4bL,0x2507489670b2984L,0x34cf6caa5d4790dL, - 0x0a4daa9cab99d5aL,0x1cc95365174cad1L,0x00aa26cca5216c7L }, - { 0x1be1d41f9e66d18L,0x3bbe5aa845f9eb3L,0x14a2ddb0d24b80aL, - 0x09d7262defc14c8L,0x2dfd3c8486dcfb2L,0x329354b184f9d0dL, - 0x151e646e703fa13L,0x149f43238a5dc61L,0x1c6f5e90eacbfa8L } }, - /* 6 */ - { { 0x2c2f1e74ab2d58fL,0x2fe0b0a825e00a8L,0x2b24770bb76ac1bL, - 0x3b5599fdef5960fL,0x2fd96897e8e4ed9L,0x3ef83c576300761L, - 0x1cdcb166395a133L,0x3ac954793ce7766L,0x082de08424a720dL }, - { 0x3aa53b260ea91afL,0x212bdde8c77f765L,0x32395cd09bbea43L, - 0x36bcc016387360bL,0x2e5c78e97997c19L,0x1d6c611510ed831L, - 0x02ce16faae9b5f5L,0x3ea1973a1bccc23L,0x073983ce58f4f63L } }, - /* 7 */ - { { 0x2e931318217609dL,0x2a7750904bf002bL,0x264c286c63297f8L, - 0x359efc7197b845fL,0x38d03eee5cc3782L,0x2ae4de67a305136L, - 0x3784c701acacb29L,0x3361c857ac6d6c1L,0x0f82c409fa81affL }, - { 0x07d3766378139a4L,0x25a7aed56faa4c0L,0x0d6f68c8bc9dc6dL, - 0x1857e4fc90b1f18L,0x2741717d9844e84L,0x02fc483a118728aL, - 0x1699d78e930e79fL,0x2db7b85552809adL,0x07de69c77026a4fL } }, - /* 8 */ - { { 0x1b51bb04bee80d7L,0x3da87dda4b79a58L,0x246ca0ebc3bd0e1L, - 0x29e4c1913c20de7L,0x3390db0771c0bffL,0x2b6873a65f19ee1L, - 0x14b512095c33e1fL,0x21958f1402b76b1L,0x0b0c231d360d311L }, - { 0x228929839bcab2fL,0x019e01937488281L,0x2084763dc2a0c0cL, - 0x1cc64e30f8c18bdL,0x152e46eb988e9daL,0x297783f5a6fa3cbL, - 0x2c0e26e55c8d2d6L,0x3fd5fce8ff58f6cL,0x14a899c6d9f1e4bL } }, - /* 9 */ - { { 0x3f6e3a1ec05ce88L,0x30925adabf480a7L,0x20776fbeb007f8fL, - 0x2f7baf7b5002e74L,0x2693700f7b50ec0L,0x3dec0c3abbe5dd0L, - 0x101f77806e37a13L,0x2b83d73c5f45c6eL,0x1599036e5dfca95L }, - { 0x0af64b5000e8e0cL,0x0ab8101bed37e40L,0x1a67449f23bad3fL, - 0x108956c96a57d87L,0x28e33c6500ca918L,0x0b009f07e9abcf9L, - 0x2840a514373c00cL,0x1090267cf36865cL,0x0e798c62b79d0e8L } }, - /* 10 */ - { { 0x0c7c4a8ae4d0f28L,0x2957bd59b401bbaL,0x1f65066e40233a8L, - 0x2d574c86dd8de61L,0x2b8351b078deccaL,0x1f5522ace2e59b5L, - 0x31ab0b2e889e535L,0x14dedea7a38bf98L,0x05945c60f95e75cL }, - { 0x0a27d347867d79cL,0x182c5607206602fL,0x19ab976b8c517f4L, - 0x21986e47b65fb0bL,0x1d9c1d15ffcd044L,0x253276e5cc29e89L, - 0x2c5a3b8a2cf259fL,0x0c7ba39e12e1d77L,0x004062526073e51L } }, - /* 11 */ - { { 0x2e04e5cf1631bbaL,0x1b077c55bd14937L,0x3f30e4c3099040eL, - 0x10dadaafb1c1980L,0x0f6b94f6edb649aL,0x1adf82d4d53d427L, - 0x1e6dd27fecf4693L,0x1432a9e9c41fae8L,0x022889edac56894L }, - { 0x012916ed05596f2L,0x0076b2c08f2e2e4L,0x13ece7d4abe1e39L, - 0x102a7240c4c9407L,0x1c6d146d0b28150L,0x13b8625a76f34fcL, - 0x1226fb6fa1d5b17L,0x0261126ba8586a4L,0x154754ceedfb8a8L } }, - /* 12 */ - { { 0x24e27b04270b2f0L,0x0d3922fd35d35edL,0x3e8b0c2722ba84bL, - 0x2767fe6dc72c61aL,0x334fd6bc4f54a58L,0x104bd276621f937L, - 0x389d16b7c669fd7L,0x381d1002366eddfL,0x1cfafb9426bc902L }, - { 0x0a4f2d1662935caL,0x1f1c0e65f7311b3L,0x29e5353c79f8284L, - 0x2254857c3d30227L,0x080911b9d9ed8d9L,0x3789ea8d673c22fL, - 0x1e320d4b03540e6L,0x064ed4bd358fbdaL,0x0e6a0217fd694efL } }, - /* 13 */ - { { 0x37de62774214780L,0x19a05c81d167aadL,0x39b7e9c7fb01ca0L, - 0x3075b52df1fde15L,0x0a66caa39e55548L,0x2141693d15d5864L, - 0x0864ebf8141b039L,0x274fe972835f132L,0x053bf8af9509e12L }, - { 0x09b29d885285092L,0x0c76aa3bb5797efL,0x290ef618aab982fL, - 0x3d34989bb4670cdL,0x307ed8e090eee14L,0x1cdb410108a55c2L, - 0x27d01d1977920e8L,0x2dced1fb897ffb7L,0x1b93c921c3abc7aL } }, - /* 14 */ - { { 0x36a07cca08b2b14L,0x1e37aefc5d31fc2L,0x3828c40cb2a4aa9L, - 0x1ca42b720e0a472L,0x28c1edde695c782L,0x03ef4880236a2caL, - 0x2db94e741ceb2f9L,0x152397e272794c8L,0x07d18266085b73cL }, - { 0x1ebf82a2defd012L,0x32c2516854dfbdaL,0x35353ef0811d01eL, - 0x29ecaf537a8f155L,0x27bf969c859c882L,0x2c96b46c0287e5cL, - 0x136005063adf5e0L,0x3f861307fcc1bc9L,0x1178e515bec4112L } }, - /* 15 */ - { { 0x314787fefe3d3d5L,0x1dbd967625c89e4L,0x3ed1e0b6acf529eL, - 0x080717a3764571dL,0x15f5667af9c2b7bL,0x0d5dbbd1e200e3cL, - 0x00154af38c766ffL,0x0ed4e7c188f2001L,0x09647d3c44bde88L }, - { 0x2075638de1b21a4L,0x0e67055c420704cL,0x206775c03599bb6L, - 0x1feb79833d4c8b9L,0x0efc190595c7fdeL,0x35ece5806c65510L, - 0x2fa73e7e70ac8cdL,0x01d912a96a0f5a9L,0x04234f8cfac6308L } }, - /* 16 */ - { { 0x231e71a286492adL,0x0f791197e1ab13bL,0x00d4da713cb408fL, - 0x3a6a1adc413a25cL,0x32572c1617ad0f5L,0x173072676698b93L, - 0x162e0c77d223ef2L,0x2c817b7fda584eeL,0x08e818d28f381d8L }, - { 0x21231cf8cdf1f60L,0x103cad9c5dd83dcL,0x2f8ce045a4038b6L, - 0x3700dc1a27ef9c9L,0x372ea0dcb422285L,0x2021988dc65afe3L, - 0x26fe48a16f7855cL,0x2fd1353867f1f0cL,0x13efdbc856e8f68L } }, - /* 17 */ - { { 0x234d04fe6a3ace5L,0x2d80fa258647077L,0x0007f75ed0f40dbL, - 0x2f256c966d6d370L,0x22615f02015e0e6L,0x0c7a8fe37ef2e99L, - 0x3ff824b2ec5433dL,0x0ccb90ac2c39040L,0x11119315060c480L }, - { 0x197ea28045452f1L,0x19e33dc7cfdcee6L,0x3ddc41e9328e80bL, - 0x1bb9abc708d294aL,0x1b44215e7b7f265L,0x02900a2f10e016eL, - 0x2476e23aa734f2fL,0x033df8f1c91e508L,0x1f16dc2e8b068c6L } }, - /* 18 */ - { { 0x0dfae6ffffc0de5L,0x06053ead297c92fL,0x3658ea2aa8dda80L, - 0x3d7693c11046404L,0x334100611f3b1caL,0x1b833e23c92e736L, - 0x055c8248c324ed9L,0x0b8a52dfa8cd08cL,0x1d36e835b648909L }, - { 0x2b77ae707372f27L,0x26d3ea0eeb8669fL,0x1ae165429ebb477L, - 0x19bf00fbcfe85d7L,0x16991c7c4942ec2L,0x1894f4f0397f1aaL, - 0x34e738a0f61e4f5L,0x3a465e847fd6379L,0x00260524cd4624dL } }, - /* 19 */ - { { 0x1b5d0ca01342e08L,0x3b53c2dd27c2bd1L,0x02d96529d804509L, - 0x36db600d673ad54L,0x34c3848005eb087L,0x1d6a1e13aa99aa1L, - 0x34317ee972c7a0cL,0x3efd2305a7885a1L,0x14f81c556e0e5c9L }, - { 0x2b0b12be120674dL,0x3c26e4867c02b09L,0x332dd658caa6c6bL, - 0x2be0a4b66787879L,0x125fdbf80c771c5L,0x199b0df57604d4aL, - 0x0df680e61bd7983L,0x0260e36b251a874L,0x09f58dcf684c39fL } }, - /* 20 */ - { { 0x01691027b7dc837L,0x065d52d43ac7105L,0x092ad7e6741b2d7L, - 0x076f20928e013d0L,0x2c8e20bcf1d0a7fL,0x286076c15c2c815L, - 0x3b508a6732e3b9dL,0x01249e2018db829L,0x04511af502cc9f7L }, - { 0x3820d94c56f4ffaL,0x08168b13c303e82L,0x3d4ea1a0606a1c6L, - 0x199e6cc5bee67ccL,0x2e4f240fc1bab64L,0x0b5f710c16a8214L, - 0x23c07322539b789L,0x198cc0d95fc481bL,0x05928405280cedbL } }, - /* 21 */ - { { 0x0d087114397760cL,0x082dd8727f341a4L,0x07fa987e24f7b90L, - 0x281488cd6831ffbL,0x1ae21ca100e33b8L,0x2c0c8881cf6fabfL, - 0x145da6458c060a3L,0x18bbe6e71cee3b8L,0x0aa31c661e527ffL }, - { 0x3518eb081430b5eL,0x3e73a943b835a6bL,0x30b5aa6ebe8bb32L, - 0x3ca7f875a243b36L,0x31a59cc9a1f15f7L,0x22aca98f3975a3cL, - 0x07ce54f4d679940L,0x01ddba16c73bd0dL,0x1768ff423c0286dL } }, - /* 22 */ - { { 0x164104c33dcec23L,0x03586f3741d4661L,0x2f514c4f309abafL, - 0x3d779221c5521b6L,0x1d3539ba3f01bc8L,0x28efa3b3775aebcL, - 0x1d865fbb7e665d3L,0x12683e4676b0f2dL,0x173fe203da3f121L }, - { 0x03ae9a178d4a3d1L,0x173d62194c5b601L,0x26c041176463a4dL, - 0x23fe12be913abc0L,0x3ffea422d316c63L,0x188ad84d44bc8e5L, - 0x27068d691eaa046L,0x2ccf12215ba8e5fL,0x1b542d1b2e3f4a1L } }, - /* 23 */ - { { 0x11b2d5e1f487402L,0x005b99eabc7757dL,0x31f56da9c20ae36L, - 0x187b3916ff47acfL,0x3027a9e1825b7d3L,0x210459250b6c18cL, - 0x0773d0bf228777eL,0x297c3d7f3831116L,0x01fb2b3151d2dd7L }, - { 0x02773e8fbaa096aL,0x1c9baf824ea1e04L,0x0d072c7f1781152L, - 0x342ad7729d9714fL,0x187ef2d4a38d3dfL,0x1fac470aed29f61L, - 0x2da22f5c9c2013bL,0x3b2b578d4f0d02dL,0x039846d50a5a325L } }, - /* 24 */ - { { 0x2da77361677df58L,0x2f559c72d435b1dL,0x07d70a080ff2364L, - 0x0a6194c90c0110fL,0x2c35101e7a0a854L,0x231735da0800b74L, - 0x2cf13fbebc61434L,0x23703fc5646bb29L,0x0fb91c7c2e698bfL }, - { 0x27c5cad12de14d5L,0x12317d95872089aL,0x24307cdbb3dabc4L, - 0x0471da0475e7e37L,0x2754620499c58f0L,0x269d39247a2601bL, - 0x3e37c3e52ad0a2cL,0x31cb480d1a172caL,0x0ec7a8632450a0bL } }, - /* 25 */ - { { 0x3818c218a86786eL,0x0dfdd084df8b20cL,0x10d1a7e6eb20ed5L, - 0x1c17371200d765aL,0x024f7bd759790ecL,0x387c3c511a458b2L, - 0x1915ca09e7ef9d4L,0x089bf4c304a2f3aL,0x02d810145f66c71L }, - { 0x12749f5b71d87e5L,0x0ec505ec0b3b68cL,0x2d2ee0baff1625fL, - 0x2a7f2b9989c0915L,0x337bd985f97f7b3L,0x3e9b430435bafe3L, - 0x32f13720aa81b97L,0x376c6ca7c680487L,0x03de326a2f85cc0L } }, - /* 26 */ - { { 0x2f3398b38c2ee78L,0x0f44069d682fb89L,0x1706565a7f8e40cL, - 0x38c10067974d68cL,0x2b8174b6ed12985L,0x3e0294a8878a990L, - 0x18d80e25a15ee8aL,0x3aa6974783f9a14L,0x0848cbbc13804f6L }, - { 0x2828690dfd45169L,0x1f8261674fa341dL,0x0811cdb8bfc238dL, - 0x1e858b3d9208dd6L,0x3b4d15b8c849954L,0x18126699252eaceL, - 0x21cfed822cbc57cL,0x1662eb10c893aa2L,0x0d94356346957c6L } }, - /* 27 */ - { { 0x306925368271323L,0x2782a12734135caL,0x1fbf2b31cc7d24dL, - 0x13d5e8f8d86ab8dL,0x20294e85644f64bL,0x0f3b52b852411a1L, - 0x2cda47ddc82ee74L,0x3e5a32e4a9a95f8L,0x13f989c42efbfc1L }, - { 0x2d98bdfb8651600L,0x18d0d1e8f3ebbafL,0x254335b1a2268c3L, - 0x3775609541e4e84L,0x3852eb1e9558da7L,0x0a57d516945cec8L, - 0x06d101df5ae5852L,0x3e18b951b8bbd99L,0x1faf7e16a2c5d89L } }, - /* 28 */ - { { 0x1746c8ec7ec136dL,0x07609f3444d46c3L,0x3ad3f187a116f8eL, - 0x23c4dba1195d928L,0x0850983c22f1b96L,0x39c5c967506a8a5L, - 0x3c149c2123ecc4bL,0x2e0b77372ad49d8L,0x16da7f50b181022L }, - { 0x19e532d0ca5e258L,0x22b45e5ed8a9efeL,0x242ec77fddefa14L, - 0x335d3e6db123428L,0x07fd122d458518bL,0x2d42cb5f14ecc2eL, - 0x01aae9bb8cd193fL,0x1b824685a6bbaf0L,0x1c57e49b10a1de2L } }, - /* 29 */ - { { 0x0abe67521210716L,0x0a5a8c1f809000bL,0x011d8c83795b81aL, - 0x0d3767be9aa52bfL,0x3677d686f68f203L,0x3d7389d56f8be7aL, - 0x357c5c6a13f277bL,0x12e33df648906e5L,0x13270c3d2f4c74fL }, - { 0x1c8609c8d209aa4L,0x104e8b6cad50dbeL,0x2d1a2992345d46fL, - 0x3ae521f0d3e5adcL,0x2b440a375186f2aL,0x3694d6393e9c85dL, - 0x25b3103a4209367L,0x182e3c47ab78ffcL,0x1a99a570153505dL } }, - /* 30 */ - { { 0x21513936e7495bbL,0x0bf4a12421e746bL,0x2b0b29fd76fcebdL, - 0x26f1839c872708cL,0x3517a09e2a1a0d4L,0x362eb7e27d60ae0L, - 0x148bb4ac37809e9L,0x3121d2a937a782bL,0x027fd041312cb6cL }, - { 0x05502eeead4fb6dL,0x3097b42980b2fb0L,0x2841bd7f4a07760L, - 0x0c953b7385162e9L,0x10397614cc28b60L,0x207bb64ee75078eL, - 0x2d4b0b4221b71d1L,0x3906740438f08ccL,0x096dfe58a27dab0L } }, - /* 31 */ - { { 0x0d6fcd67debd24eL,0x3f29826b8ac1d53L,0x022ef217c26cbe3L, - 0x382e58838fe9f63L,0x2c7f9f87dd42d03L,0x25cbffb98d2fc85L, - 0x0d3e7722b1ec538L,0x14dfa0ea55f0758L,0x162edfe5f860f6aL }, - { 0x0a05400f0ea20b8L,0x0ab1f875e5a4010L,0x25c90edb0cac287L, - 0x0c2d8a4e69ddd96L,0x2af2cb7089df5b9L,0x0bfaf04bde299dbL, - 0x190ad3030732bf5L,0x38d04e999037ae8L,0x0d536eae15f93e7L } }, - /* 32 */ - { { 0x06119f6a1c88f3cL,0x397fb0bb1a5129bL,0x2c605742ff2a924L, - 0x07b76c8b1f1322aL,0x0fa5d25bb60addeL,0x3045f7825ca24e3L, - 0x2929c1fa5ac4f7eL,0x257d507cd6add20L,0x180d1c4e8f90afdL }, - { 0x3c4e73da7cd8358L,0x18695fca872480bL,0x3130ad94d288393L, - 0x198ada9e38bdbcbL,0x379c262cde37e24L,0x06d65ee42eaffe2L, - 0x0d4e646cae01ef6L,0x3e1167078cfc298L,0x00e52a42280dd01L } }, - /* 33 */ - { { 0x2d640a40f013755L,0x3739dfee0e03a5cL,0x0e797eb64b310b6L, - 0x02e4f2968d89e27L,0x358bdffc98e704bL,0x08c30dc8630d83fL, - 0x3385d153b1f323bL,0x0efdf5ace422169L,0x04a071130f556b9L }, - { 0x1a2096bfeef3f88L,0x2ea1a6e0ace514aL,0x184a872664a722eL, - 0x286163fe509ff88L,0x17490c9daa0dc0bL,0x056233a0cde67adL, - 0x32cee21d356f628L,0x2bba5f766f1fe9eL,0x0d21e61a4e8a3cfL } }, - /* 34 */ - { { 0x05db629e9068656L,0x2f5c327fb7937fbL,0x15bdfcd45546623L, - 0x3498a469d071e2bL,0x2761e688ef7981dL,0x16e49cbceb14f64L, - 0x146fec6a96892a5L,0x0bd59085f9ee019L,0x15e793c03cbab9eL }, - { 0x0fd95436eff39beL,0x2bc1fb6ffd3da02L,0x3abdb02416165a1L, - 0x3f751e600a60f51L,0x060b2e6fb37c5d2L,0x3a36e662761b65eL, - 0x28b9bbe3e3284ecL,0x062ce7c127ad761L,0x18e3b3e8a789dadL } }, - /* 35 */ - { { 0x3026c56e51e61f0L,0x2f2a8cc1fc9d5d5L,0x26ebb1aeaf41dddL, - 0x1f38b5fd6ea4a80L,0x2bc5ead91a33e93L,0x391a01f47df3007L, - 0x01951990ab665d2L,0x101270a913d554dL,0x0aa099c1ca67966L }, - { 0x161a9098f97e387L,0x145de1178775a6dL,0x112b7ff1d6abf60L, - 0x293426a72247fe9L,0x1d2282e2b42da55L,0x1d0616b57969f1cL, - 0x0baeffdfa5a203eL,0x0285866c4da77a8L,0x1a3a5eef9141eccL } }, - /* 36 */ - { { 0x2f20d0a7a573b81L,0x3072a1986533bcaL,0x2d8d0b711c347eaL, - 0x1b2e826750bbc34L,0x05067a8ca6aea01L,0x284d47be998274aL, - 0x1c26346a52c6007L,0x00cf36ae16062c4L,0x121f17fa45dbb1cL }, - { 0x3b8b87afc3279d6L,0x39daaf0807c7867L,0x2a83806c21dde30L, - 0x0af18fe093c0abdL,0x246bd1a53eafd7eL,0x084e4591ec1d389L, - 0x32d9bfcd6f4931aL,0x273c6acb3f4e705L,0x10a62f3eb4b4db5L } }, - /* 37 */ - { { 0x002de36e0689a1bL,0x3327f5f72bf9cb9L,0x2d7e255d0bfb9dcL, - 0x3b92b681367937aL,0x2bfd2e774d7ee87L,0x1c2cae6d6a140e7L, - 0x103bba282c66577L,0x141c69eb2a09ae8L,0x11aac7028bac7cdL }, - { 0x261d39c680c8f04L,0x271332d22ced78bL,0x09bd95744f3c2f0L, - 0x2d2ab32d64c4c58L,0x25adfb2096d72e4L,0x3f4fb33f6dc1832L, - 0x352a73c67d9e431L,0x215f0521e89bf85L,0x1e33d95366364d0L } }, - /* 38 */ - { { 0x264506b4cec9e7fL,0x1592d0c2aae63f9L,0x101f173fa284a44L, - 0x1f85725d1c9786dL,0x082dec033e7b7bdL,0x298edd8b5b319eaL, - 0x0e2fcd1fe2e9340L,0x39d48e821386cfeL,0x0fdccce4da89ae6L }, - { 0x397f8eec12fd820L,0x3e24aa5b691ccc1L,0x241d55997bf4325L, - 0x2b00add4f3d65f4L,0x1f677ceba3aef35L,0x06eeb1b229cfe57L, - 0x1278b05b2892b7dL,0x117da41d4560f31L,0x01c2f5ed53fa47fL } }, - /* 39 */ - { { 0x114165eab40b79cL,0x1bbb6096d226a0eL,0x2b7d8a6c107fbfbL, - 0x22e3807ca2f684dL,0x1a4d79907d431dbL,0x11c79a161397437L, - 0x376ff869a91472aL,0x047f56341a5a660L,0x006ce369b74c463L }, - { 0x00773d11add1452L,0x3a7257b63a68a9bL,0x0e32ca15a40c2e4L, - 0x0dabd8bc63fa3feL,0x2eec9484b3fcb7dL,0x2c81016cb28cdbbL, - 0x2d8352a4d6e7a93L,0x00f9db64340c655L,0x0e5dd375603d9caL } }, - /* 40 */ - { { 0x05f297d8b481bf7L,0x0a8f90a84ce0f33L,0x128cdc40b96c06aL, - 0x17c462768f27851L,0x16cd57fa79a2bf3L,0x0d5f4caee2b6e62L, - 0x176fadc1a4935c9L,0x0f78547ec96030bL,0x1ba98721eb424f2L }, - { 0x002daaf52a4b397L,0x17d330342d39523L,0x0db37b7e79cdc3cL, - 0x3b2cce5c2d8a6f9L,0x092808c7ff34336L,0x08a236c7b4f72dfL, - 0x2ed59aec290eff0L,0x3e97ca91e7547a5L,0x0929d7ed87076d8L } }, - /* 41 */ - { { 0x0edaf0be660043cL,0x28b32c05b81d376L,0x28e7e2cc3b3d84aL, - 0x0c1709a7f12748dL,0x13de33e3647b501L,0x2272941340653b8L, - 0x0db11ddb3361b97L,0x24bc2335460ce61L,0x0c6d5b801ecc8ecL }, - { 0x3f91c1547ab9887L,0x2178a9ad6ac044cL,0x0e5a133fc8182f2L, - 0x1d0e361a4b26dcdL,0x043282e815c435aL,0x31ef36a8f24ad1fL, - 0x158c86191231f59L,0x0f328eb90970d34L,0x0117f568febc5a2L } }, - /* 42 */ - { { 0x0cbd9d5bf5caa87L,0x3f183da37632763L,0x0dbbc7d4dede17bL, - 0x11609c2d6fd8fadL,0x1cc098fe7bf6e59L,0x175ee3d621c4de9L, - 0x25a533ca5eb6870L,0x029b12df7bbb92cL,0x0ef8e045c324a70L }, - { 0x20c1c9270cf52bcL,0x0fd8ea43318a605L,0x021cbf3028fb4bfL, - 0x35d48efbfc57ffdL,0x38b9ce1050a8102L,0x19886c7bfccc268L, - 0x0a78078e9da4d00L,0x2184a5dd7e27f30L,0x0eb590448650017L } }, - /* 43 */ - { { 0x26664fdebbd33ecL,0x269983396b55e62L,0x2c0550fb56ed0cfL, - 0x2b4756aa9bbb341L,0x3948a7f07b4ca5fL,0x3f870468db6bb96L, - 0x12544bd2e37887eL,0x363a907d86b1247L,0x0be49df70712bffL }, - { 0x0e2f1f565acdb56L,0x04f21179796f798L,0x1354e17a0412f2fL, - 0x33f6724efbee5ffL,0x325a957e48a2867L,0x28618d7e72a745aL, - 0x26ae711f55c19b4L,0x150766ce1a3d634L,0x000ac4480414c94L } }, - /* 44 */ - { { 0x01bcf89d4ad38dbL,0x03ce04f5c51445bL,0x2759cb70243a118L, - 0x18c58e9c5b16d30L,0x213648bdb5dd64dL,0x137a65a6ef4bbfaL, - 0x1e8c45a47187f9eL,0x3429d9779a44b8bL,0x048e075f29c4bdaL }, - { 0x03354745e4dd88dL,0x20d8e2015debf00L,0x1c01227288f7182L, - 0x2479a26277b92cdL,0x1cd3f71bad008fdL,0x3936878908508c5L, - 0x262bb15cb023ff3L,0x13f95f9ae70d6d5L,0x072143f41657fb0L } }, - /* 45 */ - { { 0x06b046c26f40f2cL,0x3491b1b35f0c76cL,0x22701953a9b7bd5L, - 0x2e23c010dbeaa95L,0x021d0660d5ac929L,0x2f5b6f9864dce4bL, - 0x3c43f9d279ed159L,0x34094ddf1356b45L,0x179800eda50b8fcL }, - { 0x08ddc0b36132f31L,0x3d3c04ab79ce8eeL,0x1ec3203de2b96f8L, - 0x0508c6d94cce216L,0x0a14093caedb038L,0x30af8be6b423348L, - 0x2bc09fb9f86d445L,0x11e37f4f654cbdbL,0x13d757b58991aefL } }, - /* 46 */ - { { 0x19ad100580f894bL,0x09222b649791bdfL,0x3e142e5a6865b61L, - 0x14c5fe6a04d1525L,0x2f8a33541c86e10L,0x299b55e362aa082L, - 0x358e23a67906607L,0x2ad711f7d82b97dL,0x107cadd4c90a7f8L }, - { 0x16b044f6764ad0eL,0x3f8384940626ccdL,0x0a625f14db6af69L, - 0x27c6f5df550b7abL,0x25cfa895ce9f277L,0x1bc66b0e5e6447cL, - 0x2f44b1d4e94cedbL,0x09fd70d4cd05c06L,0x03bcac43fff50c7L } }, - /* 47 */ - { { 0x342951c83c1d4cfL,0x1e4742c9170d3c5L,0x0ef69c2dcc71e03L, - 0x0a4a8c41d9faa3eL,0x3b12948bd2ea57aL,0x3fabae0c956d1aeL, - 0x1abf592adc1e090L,0x29a26834b463112L,0x0199e8c9ff5c4a8L }, - { 0x1f7b9cdeb28171aL,0x1e100f55da61ef2L,0x33bf22ff824cefdL, - 0x24efcccf31562d3L,0x2b01ceb72ee09b3L,0x080a6737affe0e8L, - 0x2bf7515bb34c452L,0x173ce8f0fa2819bL,0x1a65dee07bb49d0L } }, - /* 48 */ - { { 0x1a958d6b114257bL,0x2bf507525d78c02L,0x39b53aae7b11729L, - 0x24fb746b20c1ca1L,0x11eb679750791b0L,0x099d6d2b3fbf1f4L, - 0x29517f0e54bd37eL,0x0268e2698b5fa35L,0x06b96f805d82021L }, - { 0x015d51757b5f9f4L,0x2790d9016d13452L,0x1de0e4870160e5cL, - 0x2547bdacfe0d10bL,0x1f7497faf953fefL,0x05bbc2de467933dL, - 0x12eeed24e3cc4d0L,0x05c0ff172aa1c94L,0x1b6f1ba4029a3bdL } }, - /* 49 */ - { { 0x2668435529252acL,0x189b01d39ec360aL,0x0cc1e0be86ab3daL, - 0x3dd3b57714d5420L,0x00cd41fd0534a53L,0x19d22472a7bfc50L, - 0x13b5ad0e7c945c5L,0x026237a92e257b1L,0x1ffefc67bef1515L }, - { 0x08dc109306033fdL,0x21e5e7cda1d7666L,0x2f26e3c335c51b2L, - 0x3f44938a75934e6L,0x0c41dbdfca47259L,0x33036255758315cL, - 0x28ff8606224b610L,0x21c1e81075397baL,0x1fd2920e15cae4dL } }, - /* 50 */ - { { 0x2d15f0ccd67da85L,0x22dbd16b1528559L,0x2021f1ac71c3ae9L, - 0x0991d564890bc17L,0x166e856dc1feb22L,0x3ed2e91ca8bc558L, - 0x1d920b65eb14566L,0x32e6cd1a22f4a8aL,0x061943ce86ef9d4L }, - { 0x0696218aac91174L,0x1467b1077648d2dL,0x2df29f0763a485bL, - 0x09dc4b22ccedfbeL,0x3b053863098517fL,0x3fcf8f9280b9fb0L, - 0x09648646bc45bb1L,0x2e4fd1aba25bca5L,0x1462aeb1649ebd2L } }, - /* 51 */ - { { 0x334f41fe8e4d3c3L,0x361ffd6edfa76c7L,0x2c0ad910b579c80L, - 0x186e1cd26bbc085L,0x02b0a6cc02a24b7L,0x3cb4655c152f14aL, - 0x3e6cdd3b4c7029aL,0x028d0392e438ab6L,0x0cf8e774f812606L }, - { 0x07f9dbc2e229950L,0x07e11b67e0adc0fL,0x19a3f10c05f3ab1L, - 0x13c3c608328adebL,0x0ccbfb332203eadL,0x199c1bc5476f2f2L, - 0x059d5e3bd9caf00L,0x3993968e6f89418L,0x14c984387c8dcafL } }, - /* 52 */ - { { 0x08a757f8e011531L,0x16c5cb0f7355f1cL,0x09fdc2d99e297f4L, - 0x07ee4ed9056a3abL,0x0a5488e869d4ee8L,0x2edeadc2960ced5L, - 0x3df3a9ddd561c30L,0x0ccaed6f68e12ceL,0x124f909f8e01ddfL }, - { 0x1b8aa84ab41e782L,0x08049a14776e1f1L,0x2a7d99482bd21deL, - 0x3afd2d904efd26eL,0x37cd1e22405963dL,0x2eb583bbb4da7eeL, - 0x2e30eddcf495dd1L,0x084b7ad1d5a4e24L,0x10baaf11bd8af0aL } }, - /* 53 */ - { { 0x146017416ec64e2L,0x052b3df5f1baf9cL,0x04a3668b7176bfdL, - 0x3cdd06c107078d4L,0x22d3b67b072e3f3L,0x15f64a35947e952L, - 0x08f419623edca3eL,0x2ebbca6dd3a2dcbL,0x0383d99cb47327aL }, - { 0x08dd0b3da342a3fL,0x00918b7bd2a5520L,0x242eeab5a860120L, - 0x0141b952db46c71L,0x310c6cf1a5e1e2aL,0x3e40f3426e85c43L, - 0x0166f5334fc3660L,0x10d4e5a7800044dL,0x0fafaa26074155cL } }, - /* 54 */ - { { 0x05cd0e6712de285L,0x3fe2c21a7d77172L,0x2b92df4ed389cd2L, - 0x0c156e67210dca8L,0x2e07a003363524dL,0x1b82524d1bfbd68L, - 0x28952b0a2c82dadL,0x1fadacd899885caL,0x02c9afcb188af21L }, - { 0x3b9d4769a64c5b5L,0x23577913133f874L,0x18ef11c6dbffa0dL, - 0x23d07052bb55821L,0x235efe854ce1d97L,0x11d15d74947e79cL, - 0x289c03f9d0c14c0L,0x2770034b20e3af6L,0x16fa25f040b36ccL } }, - /* 55 */ - { { 0x23d9dea9cad682dL,0x32c6cd18da4e46cL,0x19885c0f24d787aL, - 0x31f50620f3a7d70L,0x353555e46dff62fL,0x2473681746aca77L, - 0x0633ed569b1cb28L,0x150a36c536f114bL,0x1941acbb86c2a34L }, - { 0x06a70c824db8127L,0x1958fd06df3d6f6L,0x1abeb908d9b484aL, - 0x18e2670982a3613L,0x344436957aaeaaeL,0x02a4b2344fb5acaL, - 0x0bcb973bc94f99dL,0x1597e5e3cb8af41L,0x07456a388ef716aL } }, - /* 56 */ - { { 0x082dfe496fc1f77L,0x310d7c4d1eb5a98L,0x14dc25ebe457b04L, - 0x1a6dbdd92abd09aL,0x104d83da164a170L,0x03208cc380e1cf5L, - 0x239b3eb0b9db52eL,0x0536a621acd3b50L,0x16a76587f2a5988L }, - { 0x118f8e8ebc71a5dL,0x10690a150148cdaL,0x09ccc182cbcc491L, - 0x34f82415e9f58fcL,0x1e239d8eb4afe59L,0x365252cb98cf6c3L, - 0x04fd61bac8582dfL,0x3bf662e4569051cL,0x10ee0866a9dfceaL } }, - /* 57 */ - { { 0x350c47052e07a4dL,0x34e2e3975d1740aL,0x047ce1af12267f6L, - 0x12ce71417ded053L,0x186f739be03e4b4L,0x1f0bc6f167cf5e5L, - 0x23fad4ca19bca7eL,0x22bec7147007b01L,0x080da3937a57f42L }, - { 0x1d8ca9d102369faL,0x26ffedc1b038d7aL,0x19a796b55d80e00L, - 0x37ab0342530b828L,0x1787c187ada0e42L,0x33e812d9b06f8b1L, - 0x1773406d4ae2cc9L,0x18a156c33a981d9L,0x0d82d525245c7c9L } }, - /* 58 */ - { { 0x1cb238cae93de69L,0x0f20cceff6ba6dbL,0x1f4de8b79836496L, - 0x112ba2fe2b8cf20L,0x24c3ebacce13a22L,0x15696b582f1b9e1L, - 0x3e9459a837a53c5L,0x1bf361d7634d6f1L,0x01fb3705534f9f4L }, - { 0x0e9270c7fb974a1L,0x123e83a7b49205eL,0x2c3d64bffbd4234L, - 0x10f5e7d2cf05059L,0x13b9f32a0a05aa4L,0x32408d7b615693cL, - 0x352b484bebcf8daL,0x027459612661e36L,0x183aa4d59f1e48dL } }, - /* 59 */ - { { 0x2585d75dbffad9fL,0x3d85d3d06763f3bL,0x3f59e6c6934564dL, - 0x3460f566c31bdceL,0x3929c8950b80793L,0x2658aeadaebd3f0L, - 0x291273bd445a952L,0x1e16d4ad86517aaL,0x1be4fccdfff3d1cL }, - { 0x1c384d97cb2857fL,0x20c1601adeafd01L,0x1d1743ace6b24cfL, - 0x28af10f5adbd4a3L,0x314e564b92c7b8fL,0x0ae7c06a3c38a2fL, - 0x1383e61b69bc73dL,0x251aeae2fad00f7L,0x0aeaccea0c59791L } }, - /* 60 */ - { { 0x268baee0163c2deL,0x342cafac9da2926L,0x3124ffdae767c42L, - 0x3542ab2a50d5a1bL,0x2e01091cf926da5L,0x0c92fb35a670d33L, - 0x13a0a93d2545405L,0x332746dad63c506L,0x14ff144925ed611L }, - { 0x361a60cc1ed9259L,0x0dea8cbc7569fdfL,0x313d07aef4311beL, - 0x12539be9ee80e11L,0x28bd3730c99f33dL,0x2e555f710e4a305L, - 0x22bee573cf8ccf5L,0x158402f1b518346L,0x14527cd194383b1L } }, - /* 61 */ - { { 0x3e651353427af4eL,0x302ec4c4364df52L,0x276acaa671c32e6L, - 0x3534ea70ddaf63aL,0x3471709aa9d7b3fL,0x060147004933a18L, - 0x28ee1c225ce41d0L,0x13b215224a13fe7L,0x13d22d829c9535cL }, - { 0x301ed9da1b15e02L,0x24aeb0c07961a1aL,0x21835764135b1d0L, - 0x2ddbdc56692fe9eL,0x118090d0dc0ee59L,0x2014865a45c6814L, - 0x1279045c1531bbbL,0x1da15d024c3f082L,0x008963b48cc7633L } }, - /* 62 */ - { { 0x3e8b620f4aaaed5L,0x2379f7fa1c7ba03L,0x030ffebfcb4b106L, - 0x39f0e88556cac88L,0x02769b805d4dfbeL,0x34e7abc29e89aa3L, - 0x15f032377de7706L,0x2dcc7c6a4911fd8L,0x12aa1b81a8442d9L }, - { 0x19e67d0b1152e8fL,0x1cf65e4ad78530aL,0x1073f1cb57a22e7L, - 0x272fc76928b8360L,0x2c22b449a03af0aL,0x34b5f4745a6c583L, - 0x098ee4b82c1ac8dL,0x3a855d422b29affL,0x15054992440e3cbL } }, - /* 63 */ - { { 0x0004a0aa13a4602L,0x31c68f434b1839cL,0x2463a6d79bc5505L, - 0x0eb553677d293f8L,0x373d3c7b8e878ebL,0x113b3e95fb32a41L, - 0x24d1795b3bb2782L,0x0abc228c3d87ec4L,0x1155b7e50014f63L }, - { 0x2c42ecc9ef0021aL,0x05ff5fe15b27518L,0x03b82e6478bc580L, - 0x1a45416936c4389L,0x04cd7eea5af0746L,0x14abb42b66ec287L, - 0x09f09de8ba39a2dL,0x3e9901d1d126ad5L,0x13fd5c8f7bd9e57L } }, - /* 64 */ - { { 0x3d8ce7b5a53c22bL,0x0cff35f2ad11a86L,0x24e248acb394787L, - 0x07a8e31e43f1132L,0x315c34237a9888bL,0x2dc0818cdabedbaL, - 0x3508fab913b8a8fL,0x1ccacd2ddf31645L,0x050a931d7a7f9e4L }, - { 0x10a429056d21d18L,0x198c1d56d04286aL,0x0a8b894a6b05826L, - 0x18e0a33dd72d1a1L,0x2127702a38a1adeL,0x37dedc253ecbe16L, - 0x0d1db683ff7d05aL,0x3357074fd6a4a9aL,0x0f5243ce1dbc093L } }, - /* 65 */ - { { 0x3c183c3d37d7891L,0x140527f6197b2a3L,0x03d68f21844117bL, - 0x095681fd9603db9L,0x3ad303202af51ecL,0x019dbbd63f969b2L, - 0x0e000c95de68f31L,0x14951d4238c7f29L,0x159783e5a957773L }, - { 0x01db5712e537ad9L,0x1c44b4d6fa73defL,0x2b48d57f9bcb5e8L, - 0x242a2cf2f1eed48L,0x1e5ecdb5c1eff78L,0x0e1f9fb53cc1b84L, - 0x321e3d30da83923L,0x299f13647f3d1c8L,0x09f8487bb62e412L } }, - /* 66 */ - { { 0x2f5f80f8cb8e08eL,0x34b104925bfb5a1L,0x374360b7dcdf7cfL, - 0x37d5fd3417c0186L,0x2458061f24dbaffL,0x37a65312c664f0aL, - 0x07e0626c6ca8d09L,0x172f3bdc349349dL,0x0ffd4e5d4e3b999L }, - { 0x171e245c6f40077L,0x0b81141c8f9418cL,0x2f7e6a6bfd88159L, - 0x345b6767380d721L,0x03eb5770cba0959L,0x10358f74b9fe3faL, - 0x1e441958eb0881cL,0x07d3558ccef6baeL,0x034fb0397df3afdL } }, - /* 67 */ - { { 0x384e05eb358815cL,0x32cb5390421f65eL,0x188907f05d7a3abL, - 0x355ea7520721e9dL,0x042d64cbd350778L,0x33ca27fa74d33feL, - 0x2b2c6e0859cd5acL,0x02d8a0dcb564774L,0x06bc06d482e18b4L }, - { 0x10695a0da4ed375L,0x2bd620a636abab4L,0x21b4f4b7092c51bL, - 0x2b9e8cd6cd6c0a2L,0x20567efd88ab87dL,0x0c830dd29cd64d8L, - 0x158b307a49fc103L,0x33a6dcdeb2b128dL,0x01ed30696a34c0fL } }, - /* 68 */ - { { 0x1550ab0bd3902feL,0x292d2e1aa74ecf6L,0x20a9975cac379bbL, - 0x0c4ccd81770e967L,0x21afc2c58045e87L,0x3be72fc7cb16630L, - 0x383c4281ff8d6feL,0x0c7560afb57426fL,0x1579d1d9d5b5281L }, - { 0x07da3055519258eL,0x14e7e409f78aa1aL,0x1747d6a230d673fL, - 0x08d7d745a11a7eaL,0x35f7e41f5ab1aebL,0x1a9ffacd6effa51L, - 0x2d5187bd546abb1L,0x14f74abef53a385L,0x1607437be13bcc9L } }, - /* 69 */ - { { 0x1f165a9ee9755a3L,0x35686ae0b26ac55L,0x245aab6b97e60c8L, - 0x2c2ac1789c59687L,0x26db0830f3004cdL,0x16b2f7ae7830ed4L, - 0x1e8498aae1ec1a7L,0x318b904f51211d8L,0x1e9589e09bbb1b9L }, - { 0x35120819c72258dL,0x335cd170564f519L,0x3a7b91c11fdb61dL, - 0x2fe215e4239b189L,0x2530bc68ed1d3e9L,0x2d6d13fe6ab01bfL, - 0x10edd5125c16bb6L,0x36d70e2182edb6eL,0x1aa96fe8b08fbbeL } }, - /* 70 */ - { { 0x23a5dd8f257c0f8L,0x13724b74e84364cL,0x39cebbb8ce03488L, - 0x14e91c98aa40fcdL,0x352e06c6d6217adL,0x0c90a336877c805L, - 0x30c62cf5b723e0cL,0x20b307974e224b0L,0x1fdd9a90f1f477fL }, - { 0x30d27ba1763ab59L,0x1f64f9c8de0fa60L,0x0264945968aacf2L, - 0x0c85c0357560556L,0x303146d9f63251aL,0x196fc3cb3daef9cL, - 0x2323fb6cdcf455eL,0x11d1202a803398cL,0x1496e49e62cd96aL } }, - /* 71 */ - { { 0x2ff0b7e40574c09L,0x3c990cffa03a5afL,0x1352eb237d91b76L, - 0x2ddfb70c4082cefL,0x3424a36dc3c0c62L,0x31b10d7be624e52L, - 0x08d076e9ea64c27L,0x2792cb7f087138eL,0x139cc3852f6a4e6L }, - { 0x238a3ffbb096b91L,0x0b2795cf6350f94L,0x1b118c577558ee7L, - 0x34b711f52d3045bL,0x142e1955f54ec89L,0x10dd1d70801b74dL, - 0x2e9041004aed6a7L,0x0cb2707770ca8afL,0x1fb597417a2ed93L } }, - /* 72 */ - { { 0x00f1981859bae66L,0x23a6c61175f06cfL,0x1c03452a3c1eab4L, - 0x033fe040ce71b3aL,0x15f98d6fe2384a0L,0x2283756f35fb784L, - 0x3e1c06f7a00e3d3L,0x2987d5b765228f1L,0x0d09d21a7d18e53L }, - { 0x1cfdbaf880eb3fbL,0x3f4a5d7a0fdf27eL,0x3d6fa28a74b464cL, - 0x17f7ec4f80d86e9L,0x3232a6128b8200dL,0x06a361b80ef23d2L, - 0x2d6ea7d1fb92c28L,0x06309a19d7eb9c1L,0x11d9b08608aefabL } }, - /* 73 */ - { { 0x3cf6146bbd2f539L,0x14bf01db89ae885L,0x1d18d4be4a67960L, - 0x08a7cfce6a0da08L,0x1433f873a8f8234L,0x05bd15a1a2e11aeL, - 0x1477507a1d3f367L,0x3889b7d80f8a0bfL,0x00377cb02c56975L }, - { 0x275add38c01dd59L,0x04ea7ae7068debcL,0x11044dfc54039c2L, - 0x0181fb83619a42bL,0x1661fc40e202ee2L,0x02c0bd5a25bb7a5L, - 0x2f1a246b4d7398dL,0x1c49732e5a64796L,0x09fd5c281afc13fL } }, - /* 74 */ - { { 0x058c54bd7073a5aL,0x206972187ab1f72L,0x0a39e720201a87cL, - 0x23903800f3947e1L,0x358f199de952a9fL,0x15b300addaf712aL, - 0x3162f31cf12322dL,0x27846d98d398e0fL,0x16984c017ee8f96L }, - { 0x1f433625c89f1faL,0x0a98c2da5ec1e3cL,0x1e5c4b05b7f44a0L, - 0x1453fb79330ccc4L,0x04b025aa4a7ccaeL,0x2136deb4349ba1dL, - 0x31c1fe7d5b77bbfL,0x33480e7bc6aa3d5L,0x18d65eba928418cL } }, - /* 75 */ - { { 0x37866ab8abb2537L,0x3132ed96cc25be8L,0x27ed2a428ad314aL, - 0x18843a7865a09feL,0x089801b4e95d19fL,0x2ba2e08cc7ae5e8L, - 0x1c9642aae77a62aL,0x22e125a4f58a97dL,0x0adff5bfe973e36L }, - { 0x3efae21492b0deeL,0x0fa7ba580b0b3a8L,0x3c996f3b99e5214L, - 0x2c3a4ee3d6484d9L,0x01064c13edd78b2L,0x15ce39ea355070eL, - 0x33b1a4e6b970dafL,0x0823ebdbb305a0dL,0x180dbfa3f4f74aeL } }, - /* 76 */ - { { 0x024621a907a6aa0L,0x1b2da101e1e7dacL,0x0b688168a934ef5L, - 0x34e6e6a4121130eL,0x082541f2070d638L,0x3f222d41a5a32a8L, - 0x2357840c5970531L,0x2533d55937b56bdL,0x097e7e898c7c4d4L }, - { 0x1dc98d96b6ebb2fL,0x285ff1eaa7849b8L,0x0fdbfa2a2c68292L, - 0x032cb86146ed83cL,0x181ca4cfe9c6327L,0x046567562636c99L, - 0x0b8d1994082638bL,0x0c253913cc23a95L,0x0d696399eb844e6L } }, - /* 77 */ - { { 0x200f362b83769eeL,0x0102b0fbf132cfeL,0x388957abd68772dL, - 0x0965029c4a30e4cL,0x3ec242a31622644L,0x168695464271323L, - 0x1c2172d1e48f1e6L,0x1ff51a2f5c3c412L,0x041c8692d2b709bL }, - { 0x2388aa1df816784L,0x23229406f9d7393L,0x1ffb02a678124a5L, - 0x383b69c87826d27L,0x1e67a65eca73299L,0x15b1c6da282f47dL, - 0x05aa30d81e91e88L,0x2efc8debb8bd300L,0x073d94007500595L } }, - /* 78 */ - { { 0x112ac4a010c0ef3L,0x152f613a06c682aL,0x23dc4f3535090e6L, - 0x3ced1f4626a3c15L,0x2f238c09c10dc41L,0x106b3d9c48bb741L, - 0x358520224c16afcL,0x2b9bc732e4cd20dL,0x1271a4b5f292275L }, - { 0x12fd4733ce688b5L,0x19b4df72a71a2deL,0x326e541711d0145L, - 0x3b8f30d06a3f3a4L,0x02122c11fe3ba14L,0x174de6d5ae2ad33L, - 0x122f91c0fa763bfL,0x25696578b4abbc5L,0x0acd4e21b3d31cfL } }, - /* 79 */ - { { 0x013a7791d8e061aL,0x01f9c2b32128c10L,0x0266eb2f636a627L, - 0x085dec97275ab02L,0x170ff35cfe917eaL,0x106262fb76de2efL, - 0x0ae4455008db2b0L,0x3439c3d6293f338L,0x043ed0923972257L }, - { 0x0ad77b3e2e129e6L,0x312a1c3c6f935cbL,0x0dff20056333fb8L, - 0x304a9a4550ebb94L,0x2b8fe2640bc2658L,0x259682be5770332L, - 0x11d99e694eb5841L,0x3721df4eea94fb7L,0x0832df13b208a1eL } }, - /* 80 */ - { { 0x2ad2247d181c3f2L,0x34d6fbccdec8fffL,0x3cba74890672915L, - 0x23ff69e8e876d33L,0x179275686e4f70dL,0x3fc7de7889ad906L, - 0x1fa4e8e80408636L,0x27d8263a12ce73dL,0x0da57aa0be9d8a0L }, - { 0x00cecf54efcea66L,0x3cabb2bf1dbebb5L,0x1a48c91585a898dL, - 0x29c4fc02a958fc6L,0x344b5cb9fb111bdL,0x149883459a1ebeaL, - 0x0b35abc6d5fb126L,0x3134abe54fc6eebL,0x0ed99709370ff94L } }, - /* 81 */ - { { 0x09f56e068b54c89L,0x3305f739cdf08abL,0x283fab089b5308eL, - 0x0a550fef46c823bL,0x0844dd706b0f3a1L,0x3b0b90346c8133eL, - 0x19914a80975c89dL,0x137dc22c046ba4eL,0x0176b4ba1707467L }, - { 0x1216ea98fdfc175L,0x1ff18df83d6c31cL,0x285fceb33a3477bL, - 0x13c088faade2340L,0x351c6d922b67981L,0x304fd47641e1c82L, - 0x2d60b55859d5a49L,0x32acb9a7e142febL,0x05c2499a8446d0cL } }, - /* 82 */ - { { 0x1d581fb73e7bcf1L,0x37987374f05ef90L,0x17ecfa199fd916dL, - 0x1cf05676e5f18a6L,0x2641328301a7588L,0x250aa4613b5de25L, - 0x2ba4bb9672ce892L,0x375ffcfb9161e05L,0x1234fb7a148ce54L }, - { 0x05d80aff009be8cL,0x24e35de37c6e87cL,0x2e84312de62062eL, - 0x1fd81c312e69f88L,0x3a1b5da3748d29eL,0x11c5d14d73670faL, - 0x2b9e671e51bd2faL,0x31a8650262ac15aL,0x049bb584abc49f7L } }, - /* 83 */ - { { 0x1f255301ea470f7L,0x2fe023a49538c2aL,0x29ea71a0038da01L, - 0x385644f2a1c2615L,0x3b8281fdb0d2b2eL,0x063970aab85c012L, - 0x2943abdb5c6eb01L,0x3540695ab19307eL,0x0531aaf64771a92L }, - { 0x279ef4906345730L,0x2aa93a11bcdf0a5L,0x26b01a7c3aab946L, - 0x28a059b7d3be05cL,0x24e04dc3ecb808dL,0x1bb066d3a7ecff0L, - 0x16d13e9e0b61db7L,0x14e11b9fd997bbbL,0x0e570ed8c0786a7L } }, - /* 84 */ - { { 0x2456e58108ce13fL,0x3f163438e5e04d9L,0x284bea3949e9b5bL, - 0x2f1d6bd99f412daL,0x0a891566bea9b66L,0x3d856569f2d35b7L, - 0x2e25201b3cecf0bL,0x297e90c4b1cf400L,0x14b81d768986135L }, - { 0x047bc25841078ecL,0x2a72585e7115350L,0x06094851f8fc75aL, - 0x0fb38d0247da858L,0x088e54102998d4eL,0x36a2b17a6a7d9c1L, - 0x2c230cbf280f885L,0x2ddd71932b2823fL,0x02b0ac864b05094L } }, - /* 85 */ - { { 0x3606e398f5daf7fL,0x2152244249d419aL,0x1c5c08c58a72483L, - 0x343243cfb8e8895L,0x008795f022f362fL,0x1097d6ab258cebdL, - 0x06dbfb71710bd10L,0x2ef370805f817b0L,0x1c8d9c7dc82c1b8L }, - { 0x1b41fdf18b8bed9L,0x20cc238e88c495fL,0x1de77291c4bbe94L, - 0x0ad05122abef3e4L,0x3c44da4629b0b97L,0x06fd428a577f18cL, - 0x1e313190b9c4630L,0x2ab6462d9bdde1aL,0x0f5a8a4e2fa121bL } }, - /* 86 */ - { { 0x0a55109ca0251eaL,0x3bb62c9e9b26c23L,0x0beb5620f528f2aL, - 0x3a2b84ff15a406aL,0x085993c079a8421L,0x346ac35c4d27c71L, - 0x35d90929e083590L,0x299be5b8a4a6ebaL,0x0ce96c2f1f8f599L }, - { 0x0bc4b5112be8bd7L,0x11a83cf19fa66f9L,0x07d34d3a3864f48L, - 0x049cfd0e6076273L,0x026dce5671f6471L,0x00ac25af0caf0c9L, - 0x0682b7f7134ebffL,0x22d655813c02c34L,0x11cfd23d7eae3ceL } }, - /* 87 */ - { { 0x09646cca27689a6L,0x1f710d55905cafeL,0x248eb57cbfccd6aL, - 0x3ed6c6b7f94c2f6L,0x3711d8bf49b11ffL,0x1c39696e7cb6036L, - 0x118a1de879fdf0bL,0x354125d4d060dafL,0x114c8c526bd8cbfL }, - { 0x1fe725bef7388bdL,0x0f6f7f9ffeba9f5L,0x1b897e6de2acf1cL, - 0x26a7afc6fede0e5L,0x36978514681a72cL,0x1499c2bd94995c1L, - 0x157d483925ecd9fL,0x32c090def374a0fL,0x1ceb5d732a7c80eL } }, - /* 88 */ - { { 0x3f9fccecfd376d7L,0x3aacfa99ac21369L,0x0d08d5b91bd86b4L, - 0x1fa2a8c1361ab24L,0x37f866a4faa3d5bL,0x2e04eb849fcf50aL, - 0x0a920695d19fa8bL,0x073774e1e635f8dL,0x073df7c0a69a32cL }, - { 0x22c01bb38315b16L,0x29f226786323e6fL,0x3fb408b6b8531daL, - 0x231a024aa068f50L,0x2836faad4b159e4L,0x11a65cc1dfa4f67L, - 0x17e476d4ed6361aL,0x07e995a72cfd98aL,0x185b69d8183e781L } }, - /* 89 */ - { { 0x0f27eb3ab9cb764L,0x3bf0863af075b46L,0x0ddb0479aa79bbbL, - 0x09027950bd51dd8L,0x1bc699b96b4d16dL,0x3236322b8d70e34L, - 0x23a45d13b2ae258L,0x1301215e705499eL,0x0d9773b73576c55L }, - { 0x220a4730218c299L,0x38a6ce67de28ce5L,0x2009484f414f69bL, - 0x0de68b293511a12L,0x268db7ab3b2c749L,0x0d70d5fc2701dcfL, - 0x3de3f26181f0599L,0x1b82024c4c0f62dL,0x060f3effcd0e0fbL } }, - /* 90 */ - { { 0x23c14beb25d6530L,0x056ce66a5f503dcL,0x3c4bfbf7f6225e0L, - 0x27052d3c3c48270L,0x23f7e8ecf83d8c5L,0x3ac7bc3f3c00bf7L, - 0x1f0c6035d353c91L,0x3b8d0e5310a9480L,0x1b5787128ab7be8L }, - { 0x0937d3ab70110cdL,0x293bf11de446d68L,0x2f5bc53a4c19e0fL, - 0x3cce35427cb1ab2L,0x3e54ac1c6bd3010L,0x13ca8efcfb8aa0aL, - 0x09c7b931ea67c3eL,0x0d8bde93299bbc2L,0x0b05bda2c4f34a2L } }, - /* 91 */ - { { 0x024a071d1f575cdL,0x24ec06948dc60adL,0x36029a2c9d40156L, - 0x22e72452980504cL,0x1095b31c150c434L,0x0bf5258a40915cfL, - 0x10b2776f975fd22L,0x24dee85c1221b88L,0x1f6ac29b8136dbaL }, - { 0x1edef55775da491L,0x14fe78adaab6082L,0x21061bb40d5b259L, - 0x04535449f619a5aL,0x181ead062cfc453L,0x3cedc48cbc8772aL, - 0x06f20d3f3e4f07aL,0x3d6ec4b341ae259L,0x15e241363696910L } }, - /* 92 */ - { { 0x0844fd03ecfc44eL,0x17cb21410ecf543L,0x27dbc9bd059a409L, - 0x3ebd96fb37e697fL,0x1a67961cd239328L,0x2ed77f778c4091cL, - 0x3dc5baea9e39bfbL,0x30de6008adb404cL,0x141bed7aa9b5f12L }, - { 0x16f0059fd94d941L,0x3a7c01f53fc0602L,0x3598779f05e3fc6L, - 0x2cc0120f26798ebL,0x372a198704c40f0L,0x192929c4134bfbbL, - 0x367f1edb773b5b4L,0x2f4a802d9dc3d24L,0x1694f7e03012a9fL } }, - /* 93 */ - { { 0x1f5dd738a9095fdL,0x1e80874f3a15e83L,0x396be5edc767c4bL, - 0x3fc6028202242a9L,0x366f10aab56497eL,0x261e5d9ae615b87L, - 0x280601312988243L,0x2a4a585d233dceeL,0x01207d9076c555dL }, - { 0x3049a011c44394dL,0x097bdc339279142L,0x09f0b1694265f5fL, - 0x3f8426ccfe078e8L,0x3a30932e42c5bd9L,0x1b3e2bc81fca90fL, - 0x366722736abfcacL,0x09ac2b7dfe813ccL,0x0e02f1e92fbfa9dL } }, - /* 94 */ - { { 0x124e4a663be4d4aL,0x15efb59bcf32465L,0x13fa7e7a7ccd1faL, - 0x1aa2317474f75f2L,0x23f251f1e70e8cfL,0x0d5533d6c95e65eL, - 0x1a71090a5ec58eeL,0x227a9a349a35c19L,0x04c7c23d4d20850L }, - { 0x3ae575bbd52d132L,0x236a9ce32073158L,0x2e51e4e63b990fbL, - 0x19ac8e74e1c25a9L,0x0a5d49fed51d6b3L,0x0ea301ebb57e21dL, - 0x286ae2025091d94L,0x3bd68403e116b91L,0x1c21af59d747eb4L } }, - /* 95 */ - { { 0x37bc01edd441308L,0x0d251218c222417L,0x0a74759611cd0dcL, - 0x185308f3998abceL,0x1f8bafed211a712L,0x324f81e4dfcc5edL, - 0x0c52cf4efbb9ff4L,0x360aa203c3b763bL,0x028480cdd2cddc9L }, - { 0x0f1ca0dc3f807acL,0x393f0af41c1527aL,0x0a1491f8bb6c6a3L, - 0x3f4f5b7eb36b4f4L,0x15fb46ffbe3ee1cL,0x37573ef3b91ac6eL, - 0x38e8b75207b3ac7L,0x3446b56030366c6L,0x08452c669f4c7bdL } }, - /* 96 */ - { { 0x02b4747c0ace6d5L,0x32d92ef9ca1eb69L,0x089989bc2614d5aL, - 0x0dbfc171c7bccc1L,0x2d35ac450817fe8L,0x1d6a70f1dcbac91L, - 0x00d6fd7f5fc2163L,0x25ccfedbe786b2fL,0x09a7643c315720eL }, - { 0x32216b4f3845ccfL,0x1d3a0242f016f52L,0x0c74d60490379c1L, - 0x2858d632019e954L,0x1aa677b6dbd7220L,0x1b8b823a0e3e710L, - 0x2f6da537332c196L,0x18c36c0ca1d7925L,0x00c52b274cf9c30L } }, - /* 97 */ - { { 0x2c2e7828ea58bebL,0x013074d997e921bL,0x1fad20b40ff02b4L, - 0x2d8a74f9a9551b5L,0x166c81991fb5df7L,0x38b3f8fbc61a11bL, - 0x10d16bbe690bde6L,0x23a4a5ebae68050L,0x0cb59d81548baccL }, - { 0x105d3adbaf66a23L,0x0dce1d037ec2076L,0x35de4b00f432c33L, - 0x3a01f4e80f9b554L,0x3066bca80e17fe8L,0x2b7fe954a5513fdL, - 0x226ea460c2b96cbL,0x13ff27c06365116L,0x11ed543816724a3L } }, - /* 98 */ - { { 0x2a873fbbd7f8a61L,0x2335c6ef9602ed8L,0x1eb3667f69805e1L, - 0x1855c74f703f572L,0x1783f9bc8ab8d4fL,0x10e62c538b91485L, - 0x1811b536c3774b2L,0x38f0cb6d28d8dd3L,0x1389f7f12972debL }, - { 0x397f21c798fefb2L,0x1bf2d441eea9caeL,0x3760fadbb5689c7L, - 0x39f4cfa9b144befL,0x3236134a51a648bL,0x261624ed04a8a64L, - 0x26ada44a3d81698L,0x2d15d8512563cf9L,0x140b4dfc79b7687L } }, - /* 99 */ - { { 0x3b145707abe5bb9L,0x32ff63947606fa0L,0x1f49c9827affae0L, - 0x1229a1ed550836bL,0x3eeb41733c3a725L,0x0e09f18c20098feL, - 0x23b70e7014fdc3dL,0x1c5a1f4063e12d7L,0x0151d483e00fbcfL }, - { 0x14e3c7c6b578aa3L,0x33a6d74c10f6b85L,0x1e9bb6008101511L, - 0x04bd016b1bd57e2L,0x02008ac7b4ec311L,0x1714be99f99a936L, - 0x0ac2eb73c00d392L,0x1d14fb86e66622bL,0x08fdfa31d9560b5L } }, - /* 100 */ - { { 0x074a0e0251cf8d8L,0x225274107caf4b3L,0x0a4933ebce52d4dL, - 0x145716f36b82dcdL,0x016200b93e1ac5fL,0x1e4dcdbb4fb37f3L, - 0x2e69402506a266aL,0x3e4d56168722fa9L,0x00e081cdd539190L }, - { 0x15f995653e28412L,0x149bcb6c9c592c1L,0x25eb1df3adc70d1L, - 0x32b74d77b773558L,0x1a838ffe2d2c453L,0x30339627b510a12L, - 0x19b609ad20c1375L,0x3ec1cb57eea06f6L,0x1ad5be41dcc622eL } }, - /* 101 */ - { { 0x23af6678f850756L,0x0deab94bced65d5L,0x0a53796842f586dL, - 0x27fdd0fe65c434eL,0x193f1a8bacdaaf9L,0x027df364be9d579L, - 0x10650b1af04e154L,0x3f6698efe682b5bL,0x00e67b1cead55abL }, - { 0x260a8e0b5f43178L,0x3504b6730d6cccdL,0x3a63880f680856bL, - 0x198b988b1c4f5efL,0x36ff824457f372dL,0x36c13946b5edef9L, - 0x115c8d0f2bde808L,0x00bcb879e07f92fL,0x1941f475bfbb8e5L } }, - /* 102 */ - { { 0x1482bf9d63543ecL,0x32d9f2845fbcf9eL,0x0638160ccc63985L, - 0x355ca6f707a2b14L,0x1a22686df556cbeL,0x207addf358bb65fL, - 0x3a2ed9b124cb5fcL,0x16e5935ed3d99cbL,0x17260b29aa77833L }, - { 0x1bfc7b6a43df7c6L,0x32b08ef081c1b08L,0x37bc345d958085aL, - 0x34a8ca822f3adbcL,0x2d1953c5e9d8f20L,0x13da0343c22493dL, - 0x29912c7d25d7c6cL,0x19131939a88dcb7L,0x0ebda1c06c452ceL } }, - /* 103 */ - { { 0x2677c5c411dd110L,0x1e1ea8b26471289L,0x2a41a45666d60d6L, - 0x2ab057e7c554ef9L,0x30e0cc7b273e716L,0x29892ac2a4ee18fL, - 0x39c260a40571172L,0x3c4c3979d95b868L,0x046af8d78b52ef6L }, - { 0x16214b170f38dffL,0x1760a048e84415eL,0x04d4957ed8123e3L, - 0x2e83698058411a9L,0x154f84413618fa9L,0x27aa56af9f374a9L, - 0x2a30b4f1c2563e1L,0x26aa7111678532cL,0x183c748add661ffL } }, - /* 104 */ - { { 0x2981f399de58cafL,0x2e03f61d4fa990cL,0x1f242d11948605bL, - 0x0180fbac02b20feL,0x17c73d79cf490cfL,0x0935186d00dfc94L, - 0x2420cf844209fd7L,0x23e89ac0fdb489cL,0x1526f4bd29eb343L }, - { 0x24d034ac389e51cL,0x2957a5b6df663a5L,0x17dee913c583acdL, - 0x1effac0d102cabaL,0x09d461e29079307L,0x10efe2faa85b8deL, - 0x3d8c3fb0a675330L,0x0977275d2690ae9L,0x0ec7c41e6d66bb9L } }, - /* 105 */ - { { 0x29b345dc5da8398L,0x1a107eece310c0bL,0x05627c3bb47abc6L, - 0x0adce34b37738ebL,0x3687311858fbeb1L,0x2f53d3d352f0ab5L, - 0x0e1b0e9521db1cbL,0x2f8f8a9a432bbf9L,0x194375215eb7bfeL }, - { 0x0b234f12edfd661L,0x26613bb54b07d13L,0x3260d8f8f98c014L, - 0x391ef8e1640cb49L,0x195e8b672fe76e4L,0x0ac03a0950d61cfL, - 0x161eb8916c397ffL,0x06ef8ee6fdc16ebL,0x0007ee90182ae13L } }, - /* 106 */ - { { 0x36fea9e93fbcb5cL,0x2f960e7ea14a6f4L,0x3125fd611ba0382L, - 0x1ff362898dc2c90L,0x23d8d4704a59ae3L,0x13106de6ade3183L, - 0x249cc51bac243d4L,0x1fa7f10007fabb6L,0x0f6988ea44a83dcL }, - { 0x190caa4f077f79eL,0x05d807678964353L,0x3bb3d21b4b77f4dL, - 0x18240df86d8477aL,0x2135becf0031b3fL,0x0a40f76bc44fb60L, - 0x319296f6c01379fL,0x2b614daf79f2a9bL,0x06c57d3b6849dbbL } }, - /* 107 */ - { { 0x23fee389abfccb0L,0x38a892e59db98e5L,0x0f0284ba6d276c6L, - 0x2e919614f47e1daL,0x11b8ab9b6c38ba3L,0x1e81ccc5b8eacdbL, - 0x233f3201fc97424L,0x379ebf7505c6094L,0x0214dacfa81ac61L }, - { 0x25a9f37eaa3198cL,0x228d17f22e6754dL,0x312ad4f5ecbccbeL, - 0x180308dd452909fL,0x228a27b05e841ffL,0x0a167fcd767a316L, - 0x0bde372d3774446L,0x16fe0701183ffaaL,0x1810a0e49a129cfL } }, - /* 108 */ - { { 0x08203af45843c3eL,0x078c0eaafaeb9daL,0x08f3624df62b460L, - 0x22b48796aa0e5ecL,0x39a242b0e568734L,0x0a9db1b4b3c4b1cL, - 0x2751a2c848ed013L,0x0b416dcaa870bd4L,0x0f3b63296c392c0L }, - { 0x24b42adc6f3d1f0L,0x37314cbd4cae533L,0x333583443d9c2f0L, - 0x3bb7237672d5e04L,0x1ee87192fb50118L,0x15d06708c0e7869L, - 0x396b0c9977267d5L,0x30d6918bbe930c3L,0x1f7454fb7963cd3L } }, - /* 109 */ - { { 0x0f281949d153926L,0x0a32460ad5d5204L,0x3b30509e94c942eL, - 0x0ab7a75ad5d2d08L,0x18b3ca314c5acc5L,0x18f56f16a9d1b0eL, - 0x0cc9890f4ea307cL,0x2465109554e8b87L,0x08e271198bff76dL }, - { 0x3900e463c8e672bL,0x19d734fcb7f09f1L,0x11f7af2163c9703L, - 0x021eb3aaac1c125L,0x17e8d236974d699L,0x04f7045520bc86aL, - 0x36cd13dcfbc1dc8L,0x2bfc8338af20013L,0x03f2a54662c82bfL } }, - /* 110 */ - { { 0x1cf41e61588a8bcL,0x23343884314b2c3L,0x22bd758e7a456f4L, - 0x12d22e6e55cce15L,0x3a6b89b9e1600d5L,0x263320bd1877e02L, - 0x177147f7fd4f170L,0x317e459fc073452L,0x048b13385116116L }, - { 0x2b763335d2617f0L,0x295dc9bb2e181b7L,0x032d1b91fce93f9L, - 0x22db212e65ea4f0L,0x1823ca5bef7a438L,0x168cbdaeffa0089L, - 0x0b5c586f19c0283L,0x07767c9b356b78fL,0x1e77f5ddc776d0cL } }, - /* 111 */ - { { 0x09feec86ee764c9L,0x3b20dac1f20b30fL,0x32e6a005b142d1bL, - 0x28ca7a297a9afc6L,0x23ffe241c70ef51L,0x0a59b0a145f4a63L, - 0x3acc76bb389e287L,0x086d4e8b6a2a4b1L,0x04a902c9126732aL }, - { 0x2c51b9c8f7ce110L,0x0cea1ebac0dbc65L,0x10980a6a59e2dccL, - 0x29f9e36d40209a5L,0x0c95bb030ceaf26L,0x1310bd0a0bcf0e1L, - 0x2c4a0a6dd6e9f72L,0x0bbf1da3778a5c2L,0x16f4aedce4b03d2L } }, - /* 112 */ - { { 0x37f032aeded03c0L,0x128149623775341L,0x3c4f9a85be0f268L, - 0x1ff82e6daedb426L,0x2f2fb5887bdda0cL,0x30f339f865a271fL, - 0x0d2ae5f8a96960eL,0x0866ac10f6755daL,0x06829c8081bdb21L }, - { 0x3f872fade59f006L,0x27ff1b2e5fbd69aL,0x15db58ae7ef8c2bL, - 0x287d332a87cdc64L,0x289c27cc4c2e23cL,0x21af73186be3183L, - 0x18de43eee5d7e7cL,0x3c22e4896d1fe6fL,0x0b453e7f4634b24L } }, - /* 113 */ - { { 0x0c496d0e3048bdaL,0x19d2650f0f79395L,0x09f74c2d509ee2bL, - 0x07950f14226b081L,0x3105a365bb01f69L,0x22c5c1273665828L, - 0x2c946734d93ffe7L,0x29d540a7e66cfe0L,0x091785c5ea20161L }, - { 0x055f978953dbdb6L,0x3a13665fb2867edL,0x102936d4d75aea9L, - 0x2a30549dbe91cefL,0x347c76356a9c17cL,0x0e5ce34a73d984cL, - 0x3336094a68360b0L,0x1fc874f90c2a1a5L,0x1b40ae532dee2b2L } }, - /* 114 */ - { { 0x0110e825164cb8bL,0x26bd3c954a99f5aL,0x2d0e8d185527697L, - 0x21fed93ab138435L,0x3ac424592cf6c57L,0x33836042102058eL, - 0x04c15c5d8fff37fL,0x0fb262ca139276aL,0x010ed8055673266L }, - { 0x06f403051f3ee9eL,0x38fba6ce2b7c784L,0x3a6ea13d64492e8L, - 0x1160386aec74f21L,0x10bfd729827b49fL,0x3f1e8d7f0a0f45eL, - 0x23ad4f8fe50fa5aL,0x077c9dcf69516b7L,0x1f878bfaae4d9a2L } }, - /* 115 */ - { { 0x260d8e8abad5678L,0x29cb3b9803096ebL,0x20b44c288e210afL, - 0x1db49533e7ee753L,0x0959e2ba564447fL,0x25844cb07ecdaf1L, - 0x140f19393c44d72L,0x199235ea2207ff0L,0x09127a861288d09L }, - { 0x136c0218a9e690cL,0x331487aad3e856dL,0x0423b00ee54c85dL, - 0x096bcea392026bdL,0x0b7731d85b37935L,0x1073ed5787cd8c2L, - 0x3c4529b5361d781L,0x098d3a907ca7bbfL,0x0e8cf5755b19f7dL } }, - /* 116 */ - { { 0x1edb80dd212b398L,0x25860754f74dcc0L,0x20478a52fa95d03L, - 0x0ca9e0979b43821L,0x1330ece4fad1e64L,0x01e24dbf80616f1L, - 0x3f6ea3508f7313bL,0x1ad8077260bf679L,0x0e8dbf3a602d555L }, - { 0x3763234279e05bcL,0x3d03b3d1114f4f0L,0x1f4d7fa307937f5L, - 0x0d84235f888c431L,0x3c2a98bbc5cffadL,0x1f51fe03cbc07bcL, - 0x322e1c30ab1719dL,0x37e51ef27e462a6L,0x1f9f53dc52ae834L } }, - /* 117 */ - { { 0x266b49ec183f89bL,0x2d7c097d601b53cL,0x02b594ec3080d3fL, - 0x100dc73645f4c29L,0x3b7f7e26d4b6b19L,0x356ded93dd506aaL, - 0x0036c5e55269eb2L,0x099d4386a1705feL,0x1cea0ff0f22da5fL }, - { 0x02bd56a3a8e11f8L,0x190087d7e6ad518L,0x2c5a0ccc92d7298L, - 0x39948fd942f19d0L,0x3f7fabfb4d64569L,0x0f279b2f2391a06L, - 0x35ff20b4275947cL,0x2ba88ace54b54e3L,0x1b0818f8e381f04L } }, - /* 118 */ - { { 0x3e5bffae50d90f0L,0x0ec46fd4047370eL,0x2711a691dfac4cbL, - 0x0753a869dcf8432L,0x3e586eeb662ec21L,0x030bc7f56a5e7aeL, - 0x3bbfea4df16ab1aL,0x09bdbfa78fdfb15L,0x15e1b05960e5ae5L }, - { 0x08e04a58630e62eL,0x00c439911f86dc7L,0x2b6143b4447a3d0L, - 0x145d18b9e8f3c79L,0x00002724d92abb8L,0x114a5b7e0c27a82L, - 0x0ed8121d805d70eL,0x351383ce126ccf5L,0x0962d6bffbc6834L } }, - /* 119 */ - { { 0x13fe58d48e07711L,0x20d92349c28ecb4L,0x092d8cdff04c70fL, - 0x1e145047c50545eL,0x03e4f8a5515bb65L,0x104cd8bdb0c7364L, - 0x206d4d73f871520L,0x0c5fcbf8097bbb2L,0x0ad32a6e417954eL }, - { 0x238c63f69d147dfL,0x2ec1b9c42fcdedfL,0x2bef28d514deb69L, - 0x3ee34470f66e537L,0x10385c6044b2307L,0x1e003a0cecda77eL, - 0x101c1c68ea2f49eL,0x1e063c0a2c961f5L,0x055970782215cefL } }, - /* 120 */ - { { 0x0c351db54c1d751L,0x114c06e83e54484L,0x334fbfdc8bed814L, - 0x0e33c8da02a9dfaL,0x0e04f2860498d81L,0x1a96db6a4a30529L, - 0x1a910396192dba1L,0x10409277aa56d7eL,0x08580dd45780172L }, - { 0x10725000e09221cL,0x016c87c877815baL,0x2fa1e0e6095062eL, - 0x1edbddd44a51232L,0x1f1f34aca657fb9L,0x27fc575974a646fL, - 0x09ec79a66cd5ac4L,0x2baa37075a25f41L,0x067388fca84e72bL } }, - /* 121 */ - { { 0x120b49da6ef1dd3L,0x281178ee9b35d99L,0x180af33d5f48391L, - 0x2cbbc1d1d2a7212L,0x278bfb1eae53cf5L,0x36a41bea8d6cba6L, - 0x1f2cf4eca97fd6eL,0x21627c6a4de246eL,0x10d667533693ab2L }, - { 0x351049673691fafL,0x0f4ea755fb18616L,0x21bb930a8525dc7L, - 0x07902c16da5f8a4L,0x3413bedca094f57L,0x3469ae617a5a805L, - 0x2de8b79e7d4f728L,0x115355450ff68faL,0x0fb859b8444d16eL } }, - /* 122 */ - { { 0x022083e7c667aafL,0x1172e52a4732e9fL,0x19318ca0e94a335L, - 0x08f93aa831f287aL,0x242f56844c3afffL,0x0354b42e886b10dL, - 0x1301d4fcc68a8b6L,0x2f3850069616daaL,0x0a3547f762c907aL }, - { 0x3dd3ed3fbe260ceL,0x1dd4b6037007e98L,0x375d6f1da3e4271L, - 0x1294987c43b57eaL,0x3d20cd6bb5f1686L,0x086b195af9ec7d8L, - 0x3b918e9d638c102L,0x0bee0c4dee3d99cL,0x17423eb44384adaL } }, - /* 123 */ - { { 0x14e27c42a1fbcf4L,0x34a16d7eb357b86L,0x2bdd915e66074c0L, - 0x043bc29aa69d70bL,0x1067cf4581e6965L,0x2fb87ee84f16be8L, - 0x1279e72be013c17L,0x33d6616901b5b6bL,0x0310042951d5142L }, - { 0x2735ec1a22bbc45L,0x14e469fd5bd361aL,0x39d0236001de4eeL, - 0x146a8be3494c16bL,0x0187db78aa8b218L,0x06a2230c38b0db6L, - 0x3e7d5bcfcc083faL,0x3408ee476adfef4L,0x0f462d85460f4fdL } }, - /* 124 */ - { { 0x168ba024972d703L,0x132874e426280fdL,0x2542ae28c855fc4L, - 0x1816c6d14dba6e3L,0x34c7f7e484fd4f3L,0x08c208f4b822c1eL, - 0x09fd13042f3b982L,0x20d6727ff4c4c62L,0x1bb56af0652c6c6L }, - { 0x1bf05e206e0f16aL,0x2b0beb5d191297bL,0x0a980f92c71afc1L, - 0x35cdb2002879668L,0x2236178dc13ae37L,0x2d1bbc417c83bf1L, - 0x2509e4443a58b82L,0x366c32545f73d10L,0x1667d0bb415640eL } }, - /* 125 */ - { { 0x2a30a613d22842dL,0x3803d6cf13b380eL,0x0f876df82b798c6L, - 0x1b5e34823161d93L,0x1e788854ada92d8L,0x166c2650294b4e4L, - 0x05fc9a499b26fbaL,0x3c4d17704ceb413L,0x1dda5c0926934e3L }, - { 0x30dcac2fad6d673L,0x3f7c1403cecff9bL,0x1941631756e96d8L, - 0x24c2936038fb39cL,0x231d130013990f4L,0x156058e3cab2a4dL, - 0x1d5679ee91966c7L,0x07369b7c3d5d39bL,0x111be124868ccd7L } }, - /* 126 */ - { { 0x244c726475cc1b4L,0x3f0be4adce5e33dL,0x26d10e3d7eb7915L, - 0x06bd030e381969fL,0x1e1ad24fcbb44e2L,0x0d581b9662198aeL, - 0x0f93f7270ba4ddcL,0x2935f0e0d28b069L,0x02193d0c9a23362L }, - { 0x2cb7b8cf769fd7fL,0x176a5e26884ee78L,0x0c566b910fef181L, - 0x0249a4c50e1ed3eL,0x1925b37c02088b3L,0x1a9903951dedc6fL, - 0x21c6efa049a9212L,0x15acb4f77c6f7f4L,0x0649b5f9d7d232aL } }, - /* 127 */ - { { 0x240adf8679a9c35L,0x36638f2dd35e5b5L,0x0ebb5f8e9dafcdaL, - 0x13ab5281cf1192eL,0x22edde557473861L,0x1db382e6f61b03bL, - 0x15fb96773317385L,0x2bab66d74cc9d02L,0x13672f0aeb3ee09L }, - { 0x388c76d64e54ba5L,0x39ebc7711d34868L,0x29d1b2a7708163fL, - 0x27b784902b5fe8fL,0x2c720303a0447b4L,0x1af4084f67d92d9L, - 0x203ea5b1c78029eL,0x174ac72bc71c02aL,0x103179180eb3bb8L } }, - /* 128 */ - { { 0x1bf4f9faf2ed12fL,0x346793ce03f62abL,0x3db5a39e81aece1L, - 0x08589bbdaf0255eL,0x20cf5b28df98333L,0x00e4b350442b97aL, - 0x067855ab1594502L,0x187199f12621dafL,0x04ace7e5938a3fdL }, - { 0x1c5b9ef28c7dea9L,0x3e56e829a9c6116L,0x02578202769cd02L, - 0x0225375a2580d37L,0x3b5dea95a213b0bL,0x05f2a2240dcc2dfL, - 0x1ba052fe243ed06L,0x25b685b3d345fecL,0x1c0d8691d6b226fL } }, - /* 129 */ - { { 0x22edf3fbf8015c2L,0x208db712540b62aL,0x36e0a6a43157e7fL, - 0x0968b412c33a243L,0x1a809dbab318ef3L,0x299f288673019a3L, - 0x3ebc49dd26937adL,0x261123c9f04b20fL,0x02987b3db2f3c9bL }, - { 0x3e7aed0fd2e3dc7L,0x3a2f6dd057f554dL,0x2c9a58a45f25498L, - 0x2e882721743f035L,0x2d579e1ee83d5baL,0x140affb4c7b2371L, - 0x01bef11f4cad0baL,0x3299710cb9b387dL,0x1913b10afaabbffL } }, - /* 130 */ - { { 0x19f7df053053af7L,0x011d96ca2873d2fL,0x38fc7ce90438603L, - 0x1bab2317775105dL,0x3fb59ec618fbed3L,0x06c6fb3c9ec4c4eL, - 0x1973a99d2656ffaL,0x2d654cd384d1651L,0x18c3261888cc362L }, - { 0x013a414aa7f6ff8L,0x2bae20feadf1ebdL,0x086b7cc307ba092L, - 0x0948d18403be876L,0x302140c93dc81c1L,0x184120d64f5349cL, - 0x1795f3a1ed7e3ceL,0x3505b8ae47b3f7cL,0x191160dc11a369eL } }, - /* 131 */ - { { 0x272f46e8b57d7ccL,0x02c3952fc08e1a6L,0x396e05b3a91d314L, - 0x2a693b09b8221b0L,0x3c50f58e91b9ab3L,0x1789abc1d0bfabaL, - 0x1cd9f71592c6085L,0x0b22650f351daecL,0x17c3ed97fd4c7f0L }, - { 0x3b02503e6d54964L,0x34458b1a8c63014L,0x2cf49cc28c22d9bL, - 0x1000d4d190063fdL,0x2b4cc0668a45c78L,0x10b6f80e3a8ccd7L, - 0x36c3cd7ad727f8fL,0x0b5dac55fa447f7L,0x1b3a7f894c9ec99L } }, - /* 132 */ - { { 0x1e6e397af09ea77L,0x1d82e5d77097164L,0x0c08b94a197b26aL, - 0x2a2da3398663010L,0x15bd23564041bacL,0x25deccfe8668345L, - 0x3bd02986ca5b94dL,0x07e67cc7e1fe397L,0x0b8f76c55a6b190L }, - { 0x35bf8c33846ec9fL,0x08817277ab29185L,0x1ec0a3108df0f46L, - 0x20f3ebb64a24b2dL,0x065049fb2879db2L,0x1bb940c51df7001L, - 0x2dce4548d24bac9L,0x1a13e9f6dac595aL,0x0fc0110cdabab1cL } }, - /* 133 */ - { { 0x11b66d84d308bf2L,0x04f27f598e00105L,0x1f92fd383bf9990L, - 0x210fff23bf1a24bL,0x0313ea287a10efdL,0x2837dd0149f8c5bL, - 0x2bd2a18ef6e3cd3L,0x3933b2e5b90c3dbL,0x18cc1ebecf2a70eL }, - { 0x0d14ad71a70404cL,0x087743e738a8c20L,0x3cde3aa3e0726adL, - 0x0458d8e9a42e532L,0x1c6b1e2b40ab596L,0x1b3bb16f9c2ffd1L, - 0x3757c01296dd0b6L,0x247a3532ca9d1d1L,0x0aa08988ca63d7dL } }, - /* 134 */ - { { 0x22dcfcaf8db0396L,0x3a3cded08b69daaL,0x034996485724e8aL, - 0x311efc524fd94beL,0x2b0247a4ef647c3L,0x2baf6a3a2d802d1L, - 0x158df0abf3e4397L,0x2eac8b8748c7e9eL,0x0ef38e692b1f881L }, - { 0x33c168926cf3047L,0x053e51654e61607L,0x1d1c293f20b6dadL, - 0x1bbd5eaec5ff7a1L,0x01794de382ea543L,0x2ffb34bc346a3ffL, - 0x3860429ba508e22L,0x0c7e0443c29ff6dL,0x1962ade6f647cdeL } }, - /* 135 */ - { { 0x196a537fec78898L,0x2779cb783e9dff2L,0x36acd34cb08f0b3L, - 0x20b69e34d4fdb41L,0x3a0392cc1acd8bbL,0x160552757fa0134L, - 0x27c6d9ab7adedeeL,0x0fcde20e4068301L,0x1915855ffa24ed9L }, - { 0x1570e36bf9ebef3L,0x011a977d2cc5dcaL,0x1a95a6816b5ce21L, - 0x204a2343847e6e2L,0x13979159aadf392L,0x323eaecb5aeaaf9L, - 0x07af10411afee05L,0x38defc64b0ebf97L,0x0f7aa72e81cd7dcL } }, - /* 136 */ - { { 0x0fa3c0f16c386eeL,0x2c11a7530260e48L,0x1722876a3136b33L, - 0x248f101b019e783L,0x24debe27d343c0aL,0x25bc03abbc8838fL, - 0x29dcff09d7b1e11L,0x34215283d776092L,0x1e253582ec599c1L }, - { 0x08ef2625138c7edL,0x10c651951fe2373L,0x13addd0a9488decL, - 0x3ea095faf70adb9L,0x31f08c989eb9f1eL,0x0058dda3160f1baL, - 0x020e3df17369114L,0x145398a0bfe2f6fL,0x0d526b810059cbdL } }, - /* 137 */ - { { 0x049522fa0025949L,0x36223c2ef625149L,0x2f5fe637216fb26L, - 0x1911ca09fd8cd10L,0x399fc2681d8ec3bL,0x231dc4364762868L, - 0x1b27626d232ead6L,0x27e9e396ff8bf94L,0x0040f9f4fedfd10L }, - { 0x152ea516b4a05e0L,0x3523bbc871e3ac6L,0x26191997dfdbcb0L, - 0x0122d3087f5934dL,0x2be92303a0d11b2L,0x2317a0269bd5a6dL, - 0x005d8e2b8f60967L,0x27289c89ad6acdaL,0x1bdd6cff180db34L } }, - /* 138 */ - { { 0x09f8576943cc612L,0x10c67a0cacc71e9L,0x2297cccadebdc91L, - 0x10ac18660864897L,0x025b1cc7c4918fbL,0x191b97c2b32cc21L, - 0x0e3e22751d3347aL,0x00023abed2ab964L,0x151821460382c4aL }, - { 0x02481dbbf96a461L,0x048ba6d4a8ee90fL,0x058e464db08b51cL, - 0x1e1b5a82074870aL,0x0f533cef7b1014bL,0x05517df059f4fb5L, - 0x1b7b9f6cfb32948L,0x30a67a91b4c7112L,0x081cfad76139621L } }, - /* 139 */ - { { 0x3796327478a7f0eL,0x060f8b785dc177bL,0x26df572117e8914L, - 0x026df354b3f4928L,0x3ad83c1603cdb1bL,0x027be326790ae7eL, - 0x254ccd6971d2ea7L,0x083f06253f16e3bL,0x0fcf757b4e534a5L }, - { 0x25518cc86b62347L,0x072749ef0aa4a16L,0x2b052966727fec5L, - 0x0e82b90f9bcbba8L,0x205ca066bbc8a8eL,0x20ce61b6014d6d7L, - 0x374cdd91ffcdb18L,0x0890cbd296ee8c8L,0x12408763a490d20L } }, - /* 140 */ - { { 0x098b9724efac14dL,0x12fe369e6a74f39L,0x0dbdd6e07c29b6fL, - 0x3f5c5dc54e03c7aL,0x271b03263fac30cL,0x26d157d53247b48L, - 0x3092bfbf9383351L,0x0ef65da979e2449L,0x128a97674e1b481L }, - { 0x1b63c41583e5924L,0x26bfc63c5c7418aL,0x33cdab227a2861fL, - 0x36a2846adc0ad16L,0x0e8db6971939d5dL,0x3b042014afed1ecL, - 0x0e1801562379df0L,0x12aeabd69920493L,0x1508d98c43434f9L } }, - /* 141 */ - { { 0x2a9fe73cfffc80fL,0x38ba6f50d1cfdb7L,0x3ed3c9d37ba7e23L, - 0x349e8ff0d5c9fecL,0x38e04a03d733766L,0x2ef83d0f436d33cL, - 0x186f4f8ce017522L,0x2c0df61fadc676aL,0x1536d1b50ae2fe6L }, - { 0x31f5defda40bab1L,0x1aa2be6caf698cdL,0x1c890d4aca8707dL, - 0x3fd90ffe2ad7a29L,0x14bf8ec2f4d72f0L,0x3ae4f88a7130436L, - 0x2dfd0136b0eaba0L,0x2820af12c3a3c74L,0x1429f252e5a9d34L } }, - /* 142 */ - { { 0x2ffd4c17d0e7020L,0x1a6aaad52085a12L,0x1708588f348f9b1L, - 0x3fe21661aef6f80L,0x115f9c381daebf6L,0x12a529eecce61fdL, - 0x2d68497e455f2c0L,0x1e630e690510a83L,0x1541c1ad4a61ef7L }, - { 0x247b628072709c4L,0x035a2e204397f9dL,0x0874e92e0f63b33L, - 0x2e7e2faa6eb46f6L,0x08318981a144e4fL,0x1a31a81f056bf06L, - 0x200b66e19c5c82bL,0x1ebb216315e88dbL,0x0119b25511007cbL } }, - /* 143 */ - { { 0x21ced27c887027dL,0x03ccd4afeaca184L,0x3c1c19d511e2605L, - 0x2a5fd31a7d5b8dcL,0x325226bb402d4c3L,0x0f9eb0c39bcd5abL, - 0x18fdfb3b9011c38L,0x28d8d0ec308f4cfL,0x00ba8c390f7af2eL }, - { 0x030c3d67e851bacL,0x070e2697d513f31L,0x3c6467fba061899L, - 0x13a5f2f6fd001aeL,0x17734adadd49d02L,0x232db4a914e6df7L, - 0x24b3ad90ba8f9f2L,0x1a4a1ea4860c137L,0x06ab28732efa7b9L } }, - /* 144 */ - { { 0x1dab52d22ed5986L,0x3989e9614cf819cL,0x237acf155fe3deeL, - 0x035eba2c4cba3fbL,0x134a08b94cd6149L,0x270570c09c1b861L, - 0x25ad46a85ffd52fL,0x002ef568893cd46L,0x1e644d1b6d554d7L }, - { 0x2830686862e4e9cL,0x335db121d8ff925L,0x1679c0839caafe5L, - 0x3ae360f58b580c2L,0x211bc4ae2c0e4cbL,0x13f2818a4478953L, - 0x22704596a0d7c86L,0x104b3d5e17757a6L,0x1be2f4677d0f3e0L } }, - /* 145 */ - { { 0x00012ddab01a6dcL,0x2f5b06b86b6da53L,0x1aecb9b05079391L, - 0x2798a84187ceb9fL,0x3a96536b7c2714fL,0x385d952dc65e3b9L, - 0x2b3dd4eec11bd05L,0x2fd871c459b83beL,0x1d70f7aa57287edL }, - { 0x2ea6f7d51eb5932L,0x3a82a97e20b2909L,0x20977739f7dc354L, - 0x0aa6f95e4d05d6dL,0x378545eccd33519L,0x2d90f2766007d08L, - 0x23abec32b8e2567L,0x19426e504775c8fL,0x0ee656dea68cf1cL } }, - /* 146 */ - { { 0x138e140a0890debL,0x2f61f6f3ae12f53L,0x3f72ba041decbf7L, - 0x02a9a082fa547c3L,0x38c486298afeec7L,0x1c043b11d546428L, - 0x3879b1ecdba558eL,0x085733b6476e231L,0x14c08de3e4cef5eL }, - { 0x01534ed16266da2L,0x0c8baded3240267L,0x0aef699276889ceL, - 0x1fc170a1134df7bL,0x31ac519ab652509L,0x168f321b48edf84L, - 0x0c4575682ebb726L,0x14dcc314c76e58aL,0x0be2e00e8b87380L } }, - /* 147 */ - { { 0x007c80057ed32e9L,0x39033df009265ceL,0x2abbabb54830427L, - 0x1bf3a082fd16141L,0x3b2c43e81564977L,0x3fbd9922d4d4ca4L, - 0x3bdca5671e8353cL,0x3f5e49c85f4fe40L,0x1dc40a9c109a813L }, - { 0x3eaa6c33db21a38L,0x088b875cfbdf91aL,0x04e7bd1d507fcaeL, - 0x19161e9deac7fdaL,0x20c64a4d6f5bac6L,0x29f0de29631d3d8L, - 0x02e4094ca837d96L,0x3853fd0f7d4c4f9L,0x13f8a9a4347fb49L } }, - /* 148 */ - { { 0x1ab4edf992f8923L,0x2a9781bf4827ce1L,0x1b871b1340eee24L, - 0x07e4782ed009efaL,0x2f3d4c62c2957d1L,0x1ffdeabd096beb4L, - 0x14cbe92d231286cL,0x0d4a65904acac04L,0x19f6706a231c3e2L }, - { 0x2b3bbd2225c02afL,0x2f0598fe8fa6341L,0x2b75b84f482e53eL, - 0x084aff1577e9b7cL,0x0512a73da912b45L,0x354faa90c2f6f50L, - 0x27fd53ac0f43d93L,0x092d3f0d63f9030L,0x0a32cb183be9194L } }, - /* 149 */ - { { 0x39b0c2d3fa6a746L,0x29e488756892a38L,0x091478cdf2b5e84L, - 0x1f4c199b2cdc296L,0x2f6d71d068a8806L,0x01974612c269c27L, - 0x1c944850007a3e0L,0x24eb1c11abd2ee3L,0x1fd2b6a3129c654L }, - { 0x3d5d5bde45f2771L,0x0ac22bd0cbb6574L,0x00fbf232a6bb854L, - 0x10fa2fb32c8bb35L,0x2bf8e247f0fcb61L,0x368c0e6f3b3144eL, - 0x02a0df955d56f78L,0x3f8aa455f18655bL,0x18ca6d35cbf3031L } }, - /* 150 */ - { { 0x1800b1bbe0c4923L,0x2b9d01a40a41ef7L,0x337f957bd0c7046L, - 0x2765957e2e08e62L,0x2500f4150aa8e1aL,0x00b9ebbb34a49feL, - 0x29692e826a9c6d2L,0x15df2d33d62ce7cL,0x11f3093868cbf41L }, - { 0x1cb5e7a333ed442L,0x3238be41bfbdeebL,0x01233d98f228ae5L, - 0x369fff84970b66cL,0x1ba2318354632f2L,0x0b4b14496521dccL, - 0x17d9c4a0caae5b1L,0x003dafc03996261L,0x172c5d1008654f2L } }, - /* 151 */ - { { 0x09540462fc283e0L,0x0ce611fb8220396L,0x340eb7fd1622f76L, - 0x07bd66317b7ebc6L,0x37e00d9bbecf515L,0x2310ff51ad364bdL, - 0x11d1d27543e3b3aL,0x2db4ce65384b194L,0x0c6dd841a1daf05L }, - { 0x3da17e023b991adL,0x0ac84dc7ee94508L,0x2c5a0ddc1879aabL, - 0x2b57d8eb372d05fL,0x01e2a7d50173bc8L,0x041b4020bf3d484L, - 0x3012cf63373fd06L,0x117bc7a084779f6L,0x18ca07766d95765L } }, - /* 152 */ - { { 0x24347b9af80dfafL,0x2d8c7e71199fce3L,0x1b266ddbc238a80L, - 0x196aa1c6281bfc7L,0x0af31c35f6161e3L,0x31a11ba39fdeb24L, - 0x0175b4c03831d1fL,0x1cc68799a7441a1L,0x0c76da9d620934bL }, - { 0x01f597ba3e4e78bL,0x137b7154267e6a6L,0x399593088c612c1L, - 0x01e6c81d162fcdcL,0x3a22769007c5683L,0x1f9b6bcf1110311L, - 0x129103b6df23c8fL,0x1e58d3d98b0950aL,0x0f9f4ea6db18b3bL } }, - /* 153 */ - { { 0x269eb88ced36049L,0x13ff87d06e67e31L,0x35636a72e10887aL, - 0x2319682ee29a42dL,0x096e4295567dd6aL,0x2aaffeb50b3e316L, - 0x2f26a45286b5f31L,0x3940c7df7ebca3dL,0x120c5d9e0ac0e1aL }, - { 0x3bee3ffacc10da7L,0x0b57e651251b96bL,0x3e863c4220ff67eL, - 0x052f5bd8cba3b05L,0x3c3fc9ef4fe6f74L,0x0efee1c12a78f03L, - 0x03342d25ff3cba0L,0x334b863f4d802ecL,0x1ac1e63e7530050L } }, - /* 154 */ - { { 0x183d07c8f3d6a02L,0x3050f1fbd343477L,0x0bf0d4c7af6171fL, - 0x26209f173c32a65L,0x32b697882c8a93eL,0x2957a2e92840b1eL, - 0x2d64f0633c87d58L,0x007f06ba208bf30L,0x1c12ce9b53f986dL }, - { 0x19639fd95dc1b79L,0x23dd50fd3985aa1L,0x3c4cede2fb9f272L, - 0x203543eba79b9c0L,0x3c2d530ed042f76L,0x375662b0151af0eL, - 0x29491000a4006bcL,0x258a4fcca1b2784L,0x14677782255b6bfL } }, - /* 155 */ - { { 0x381421ee30c98feL,0x03fac3f0b35c16bL,0x0ca614df6ad2debL, - 0x37a6e8c53a26cb1L,0x04f04b16dd38134L,0x01fe32a2910f7aeL, - 0x0f3917fc556ee0fL,0x33504f0720eece9L,0x1998397dd24b1adL }, - { 0x201e17edf4781e6L,0x1f0c651bc7e4072L,0x2613b53090da32dL, - 0x3729f23181e889eL,0x2ddc697092495b1L,0x1582026073cbefbL, - 0x1134d71d3d82bb4L,0x231073f37768c21L,0x0d23dd171b59679L } }, - /* 156 */ - { { 0x3a40f84d4dd7e96L,0x1323aa1027f0325L,0x29e6a9d11393711L, - 0x0863f631b5b15bcL,0x200269e7c3b6066L,0x164a757eb4eeaa1L, - 0x2e365b1413c6b00L,0x2abb306b5f90088L,0x1d36a82621a4798L }, - { 0x2ac45c4c1003c81L,0x27bd6bd0f6180abL,0x1f5e60f774699efL, - 0x2aefd74a160da99L,0x1c84acef1f312e7L,0x34922d48bd4fb20L, - 0x265c6063e32ca29L,0x065cffa6a9f1607L,0x017e3686c9a5284L } }, - /* 157 */ - { { 0x32efe659e90de99L,0x1216f2b416ad8c2L,0x2a52e14e4892be4L, - 0x0c0898a1a1f1229L,0x15eb3db542ad854L,0x11796104987c3a5L, - 0x17573948e81863dL,0x2b7933f87383e3bL,0x03fbd6f1ff57d84L }, - { 0x03711ddd1bf968cL,0x235f35237e91cb5L,0x1223e425a566d55L, - 0x0e1709b410527c2L,0x17c2c17430cf833L,0x050f6766f9ee07cL, - 0x3d3faee3bdc33e5L,0x2046bce16b0d653L,0x1137551cf429fd1L } }, - /* 158 */ - { { 0x128f55b20193bb2L,0x15e741cc42e1c92L,0x2309d345d27696eL, - 0x0caa1c61a297b81L,0x1110386839a43e4L,0x0ccbc420a3044f8L, - 0x05cbb48286ecf3aL,0x236bccd22a8dc0eL,0x0c6698ffcaaef15L }, - { 0x044c54af6908745L,0x0cdb91a8cd4fee8L,0x2852d561e821a6bL, - 0x1c0d8d245fda530L,0x181f613151b2979L,0x3d1a97bdb8408eeL, - 0x114f7f6817dc2beL,0x316fe4f7a82be38L,0x136c3cf3cd5ed72L } }, - /* 159 */ - { { 0x38799ab7b080de4L,0x3de0775a760e5aeL,0x2aaa986f8f633b8L, - 0x0e2952f1729dad0L,0x1a9c2fbb95d74c0L,0x005e24c1dbf2d81L, - 0x286f0d8451b4408L,0x0c98d03c030e274L,0x14c3038e9520c54L }, - { 0x14bc3816977aad9L,0x3f420b5c21ef8f2L,0x020c875fed08adbL, - 0x350d1595bf01b42L,0x00fd6dd4ee1ce84L,0x297ead01c713638L, - 0x2eeb6f23338b226L,0x309b351dfab042eL,0x078e4db08bb5f80L } }, - /* 160 */ - { { 0x111d12a1078342aL,0x11c979566841900L,0x1d590fd3ffdd053L, - 0x27c1bc2b07fa916L,0x33e19bc69cf694aL,0x27773403db492b6L, - 0x32dd4e3ce38f5ebL,0x07154e1003d9ad8L,0x085cab8fdfbe15eL }, - { 0x2943f6b8d09422fL,0x0a5d583e6230ec2L,0x01fa2ef2e4d917dL, - 0x0ecd7df04fd5691L,0x3edaad3ff674352L,0x0d1c90b49d34d01L, - 0x38615d594114359L,0x2533472c9cc04eeL,0x07da0437004bd77L } }, - /* 161 */ - { { 0x24b99a62d712c44L,0x0da3e29a5895de0L,0x0432d65e2287148L, - 0x019bd6f17e23b5aL,0x14ec3479d140283L,0x0c9b6dc39b3cc48L, - 0x32936b96db6f449L,0x086bf296b026328L,0x04d69e248c72feaL }, - { 0x2a89092a71269fbL,0x2f6ea061942d802L,0x02a39fb55db22f6L, - 0x37d8c47a7407673L,0x090ac2c1d0fceb0L,0x2c7cdca9bebade7L, - 0x0c41932393b222cL,0x399d18a9bcf7ef2L,0x0019dea30b22fe8L } }, - /* 162 */ - { { 0x1f689ac12b3118bL,0x3b8e75b2dba959fL,0x22c2187cd978d06L, - 0x206354df61f3f30L,0x2e9f56db2b985b6L,0x38263055d611454L, - 0x212cd20f8398715L,0x0711efa5a9720ecL,0x1fb3dda0338d9acL }, - { 0x06b7fe0cfa0a9b8L,0x22eb1f88b73dd7cL,0x1e04136887c8947L, - 0x37a453152f3ce05L,0x00f51ea64ed811dL,0x321c15df2309058L, - 0x2bbcb463914d834L,0x3d4bbb493954aa2L,0x0019e5eb9e82644L } }, - /* 163 */ - { { 0x365a04e66d52313L,0x25151534fdcaf47L,0x1dafa6b7ae11fd6L, - 0x3615c6ac91caf03L,0x2ae5a8d68921f79L,0x3b17384f5317e59L, - 0x24bd39fde17716aL,0x19e0dc39bb692ddL,0x1efffe94085990dL }, - { 0x3fa0e27d88f92e8L,0x3bc3f671dc48f3cL,0x174c89274dbaa21L, - 0x296e6e89d898966L,0x246ebcaf6d4cfa4L,0x3e38a1c04324274L, - 0x3aeea20317a10d8L,0x2c28ec1dc778514L,0x0eadf0c479168c6L } }, - /* 164 */ - { { 0x1bc1e484c854477L,0x3096d218e391f04L,0x202b869c54d92beL, - 0x0caf879fb490f53L,0x06b460c4ae318deL,0x2909abfbd51c7acL, - 0x052dc138ae7bf3aL,0x37a748eb89b7761L,0x1649d3fc1d55782L }, - { 0x07cae310ade1979L,0x1c1074ed2f1ca36L,0x3c4056c3c9bea84L, - 0x0ab5d2b919ce248L,0x0ecbe49ae36fe18L,0x3107e7d64affdbdL, - 0x2307156680db80dL,0x1cc1cd6eb01bf91L,0x0c06d68b4c7d6d0L } }, - /* 165 */ - { { 0x3e22be7854dfcf2L,0x069f7e9ab8ef436L,0x3ad1a521ec46ee2L, - 0x1e906a52133d18cL,0x32aa123f3ee9452L,0x2b8f2a484517ae6L, - 0x05d9255634a82acL,0x0b63385dab283f2L,0x078504cf7fc1908L }, - { 0x34ce7c43799793cL,0x375862d5467ed75L,0x1f9395ff980874dL, - 0x346e2fd8798b3dbL,0x3dcfcf54f00ea45L,0x0c00d6c09a18d84L, - 0x28a9cb67423b760L,0x01dfa7ef1d4d100L,0x0f47b52ce37051aL } }, - /* 166 */ - { { 0x3f7d8ad96bec962L,0x3207d85f8041ebaL,0x0509214e1058d1cL, - 0x10d08e5327d9311L,0x11a6605136c298cL,0x037e090f644014bL, - 0x1cdea4c36437549L,0x2dec48c4ef87bf9L,0x076249a60f7d27fL }, - { 0x09758381cf593a0L,0x33bbee0d931679dL,0x1333e05c99910c9L, - 0x07d0860238cbd68L,0x34f5e8f4f30ea5eL,0x1b032d1d5bece93L, - 0x3dcc6a2cae6e2ebL,0x3045d82cc1ff422L,0x01aee17901c0ff8L } }, - /* 167 */ - { { 0x048336b89aa9e14L,0x0d09c7d9d9c03f0L,0x0433906b6980666L, - 0x387aedeac8d36a8L,0x3eb59a05330247eL,0x0003d3565a6d2a9L, - 0x026b5bd78ef8258L,0x15b13976ce3ad18L,0x03b06a43e5d7d68L }, - { 0x20ae838ed2a0ee7L,0x2f94a3c5ba204eaL,0x1f5c4ea6413704bL, - 0x2d81b8a619e2adbL,0x2f459ed2b5be80cL,0x1d85486bc66c6dcL, - 0x116f3b7a9cce4d1L,0x1a494e6bfe652a9L,0x00797d92e86b341L } }, - /* 168 */ - { { 0x1aeede15af3a8caL,0x091e0a970d47b09L,0x23fbf93ec080339L, - 0x3139bd096d1079eL,0x081e76009b04f93L,0x0603ff1b93b04bbL, - 0x0aef3a797366d45L,0x076474a4f2ed438L,0x061a149694468d7L }, - { 0x12c541c675a67a1L,0x0e34c23d7fa41bdL,0x3cccf6be988e67dL, - 0x2f861626218a9c2L,0x27067045bae03ecL,0x032a365bb340985L, - 0x00735d1facdd991L,0x3c871ea842a08c3L,0x0152a27e5543328L } }, - /* 169 */ - { { 0x1d609e0e6057e27L,0x22da9f1e915368fL,0x11451f32dd5b87eL, - 0x22343bd478bfd66L,0x125567546ea397aL,0x08a2d20312619a8L, - 0x01997aea45c8b13L,0x19f48f6f839df74L,0x1f80e2ea28fc518L }, - { 0x295412d69d0820bL,0x1cc49c7a9968618L,0x0221eb06380d031L, - 0x3f1d7fa5c1b09f2L,0x35a71d2507ffd4eL,0x1f2dd50dece5a95L, - 0x0dbee361c80051cL,0x0b51781f6d35eb5L,0x1431c7481f49b19L } }, - /* 170 */ - { { 0x2ab2d0408e1cc4dL,0x1d634eb4b707b97L,0x3dfe5c9c7393e93L, - 0x2a74cde5a0c33adL,0x2e24f86d7530d86L,0x02c6ec2fbd4a0f2L, - 0x1b4e3cab5d1a64fL,0x031665aaaf07d53L,0x1443e3d87cc3bc0L }, - { 0x10a82131d60e7b0L,0x2d8a6d74cf40639L,0x2e42fd05338dfc9L, - 0x303a0871bab152bL,0x306ac09cb0678f2L,0x0c0637db97275d7L, - 0x38c667833575135L,0x38b760729beb02fL,0x0e17fc8020e9d0aL } }, - /* 171 */ - { { 0x2dd47411baaa5ebL,0x2edd65e6f600da2L,0x0c40cdffed2202cL, - 0x3c13824450761a0L,0x120748b871c23a8L,0x167a4a25974507bL, - 0x06dbfe586a15756L,0x269d1f1a35f3540L,0x148da0ad0df2256L }, - { 0x0fcc5db7f9069d7L,0x1f49157014c6932L,0x0899e9a2db3a248L, - 0x0e2d3fa5c8316adL,0x0d27f35e452bfd5L,0x38b6b24dce81329L, - 0x3ee7e27cbbc549eL,0x24d800a1c8a77fcL,0x0d03179878d28daL } }, - /* 172 */ - { { 0x1b7e9bb3b66c047L,0x1961a580a8f8762L,0x2297c8db9c0022eL, - 0x28f4229d28d13e0L,0x1fcd398de0e76acL,0x0c8399abefc69c7L, - 0x1c9fc52fbb6eaa8L,0x2cad2a0b43af05eL,0x00f4e00cf6f4e7aL }, - { 0x24c0e9a4890c439L,0x1928aef0d69ac90L,0x079dd9b7497d375L, - 0x03584b7a50a5691L,0x0e60d0033a1ff3fL,0x08905f68d6189ffL, - 0x2b8385815da8c05L,0x25aa941841353bdL,0x120800728d2f16eL } }, - /* 173 */ - { { 0x36f2372ab039042L,0x1a5e327e8213b65L,0x1d2f58bec14310eL, - 0x007f881170f40ffL,0x2b0a5a9283200c1L,0x187ebfe39a1a3deL, - 0x31226526c95d1deL,0x3b45e8788049edeL,0x0898e63dd78c2a5L }, - { 0x36533da22bba4eeL,0x3d8e5fd25a95d2eL,0x29f714f2a6b93efL, - 0x2f477f75cfd024cL,0x269bca1b1a08248L,0x28b80c9d8bccfcbL, - 0x1df7419a177e64bL,0x2f472f143a64dd7L,0x095b87a979f4a56L } }, - /* 174 */ - { { 0x03736a967c1f177L,0x34d4218004cf27aL,0x3b926eac9a5b1b6L, - 0x29b09fbcc725092L,0x1122b48707a9c01L,0x346b2616b64eee9L, - 0x3f175b9eb94e2a9L,0x364514470081b54L,0x0b1d13eb2525102L }, - { 0x3e7dbeb675a1171L,0x20a5705b034ac73L,0x1b5a057c88cab22L, - 0x25b4c03a73e36c9L,0x3269552eb73ea9eL,0x383e637ec3800dfL, - 0x10480fea9d035c9L,0x2cc66183926e34aL,0x037a35e9512c036L } }, - /* 175 */ - { { 0x16729ee8f00df48L,0x329ed846b20c131L,0x17f98b3a8123b89L, - 0x06708728fa925e9L,0x3e2bb3ce7e0431bL,0x371de065169cf7aL, - 0x2b3df12f86cc2baL,0x373c17fc0179397L,0x05ef955dd7add27L }, - { 0x0c22ffa00ee402fL,0x0d78a8ecc2ed338L,0x11d0643cb1015b3L, - 0x114f3465a215095L,0x2f0be54b4c6183fL,0x3083379319993c8L, - 0x24c475a5f4cfee4L,0x07b6772aa5cbe02L,0x19cde4af2005911L } }, - /* 176 */ - { { 0x29d0bc8d771f428L,0x07b36790f28e0a7L,0x2480eb93acf03acL, - 0x2041968a8fe357bL,0x22f0b8a7316232fL,0x0951d2887f013eaL, - 0x315f6f4a8df7e70L,0x0394946b13fc8eeL,0x06b66e21b73e095L }, - { 0x1c9848067a41deeL,0x2a56b9ecf8acfd6L,0x0386891454e12cfL, - 0x37fbbf29a915366L,0x011e9cb75f0dddbL,0x3bc8230d7da46c9L, - 0x333cf6a9b9e766fL,0x1d2a7a37c400062L,0x1c4b8a55ac9d1c1L } }, - /* 177 */ - { { 0x19f58625c4cccb8L,0x3d4824bbd34fbeaL,0x257689efc87870bL, - 0x25b685081b8a3d3L,0x07c52107da2366fL,0x1283c3c240cc680L, - 0x2a47b0478d4ceadL,0x1d526ca267b891cL,0x110ae96534e6420L }, - { 0x0c1d655cced05b0L,0x30fc2405d6550cbL,0x30a48e577cd7abaL, - 0x24d03a635b6ebadL,0x3603d24f184b008L,0x15c85cf49a60d94L, - 0x1141de6e1458832L,0x1fcd074d22c9984L,0x06be52257dcefa2L } }, - /* 178 */ - { { 0x2678f33c947e655L,0x3edda82248de564L,0x2745790239d1ff0L, - 0x248f36edf3acb7fL,0x105f6d41cea0874L,0x2771562084c9b6eL, - 0x0317025b1ae9ae7L,0x22a738514d033a7L,0x0c307502c29a2c3L }, - { 0x0124f11c156ace2L,0x1c3f9de7fc94a43L,0x1a816e1171b22c1L, - 0x20d57789e5d837eL,0x27c6cc79da19bcaL,0x3587ddc06b649faL, - 0x1c06bb285901121L,0x10aeffa03209898L,0x15e4050d338aa26L } }, - /* 179 */ - { { 0x1397829eaad87bcL,0x324d9e07a132f72L,0x024d6ade4fdee0aL, - 0x295a435fd5ad5e7L,0x3d14fb0b950b9abL,0x16839edbc26ca74L, - 0x2f4ff3d0684f232L,0x1ccec1453a74d81L,0x077e63bdd26e8adL }, - { 0x2fd06ece0d25c6dL,0x00086802e8b73c2L,0x17708c5bb398dd9L, - 0x360663fe3f06c09L,0x1b7e2cd68077f06L,0x18e8d5ca1f543fcL, - 0x125a9aef75e0572L,0x03a56fc95e24beaL,0x111847d3df0739dL } }, - /* 180 */ - { { 0x2ab9cc7fec82924L,0x1b75a69c8835a54L,0x27dea06ef0e21c7L, - 0x3089c60e41298d4L,0x2716807c8ab3e51L,0x123c491bd36cd7aL, - 0x1560958f3ede0a7L,0x0e37bc524d91104L,0x0f75f6583d1874bL }, - { 0x39189e10b927eb7L,0x318d670b8bc49e8L,0x02337fe966f4a87L, - 0x208417956142dcbL,0x2e58c39f9102b83L,0x246d4ca58ffb801L, - 0x2ff97b3f052ee39L,0x14181fd6e15332eL,0x16a935e5f6c5f80L } }, - /* 181 */ - { { 0x19a0355dfd88d38L,0x33638f15277d03cL,0x29e304d006e1555L, - 0x1b3f42c3398c89cL,0x135f2ad31f16b70L,0x1e8f7e7fc55b702L, - 0x1e5fb5b30c5213fL,0x2368a7ca7324a95L,0x144a0ecfdd42b85L }, - { 0x1c115df52658a92L,0x0fb45f10a0585adL,0x1f707fd92a91bceL, - 0x3f67357625a9565L,0x35a9472b1663c8bL,0x00cf86f41dd8d0fL, - 0x1c02fb14e44ca8bL,0x3ecc89e87261879L,0x1b5ece0f2c4cc4fL } }, - /* 182 */ - { { 0x3127bab31211943L,0x232b195a10c9705L,0x0b88d855fc3e44aL, - 0x0333a47ba974bf8L,0x078ec7d1247ababL,0x3367fbe9748f771L, - 0x255766a3986de70L,0x31fe8cb1ee19e09L,0x0873e54018beeaeL }, - { 0x16e86f2b38d17c1L,0x3ef431c7e810372L,0x2b79f88499cb9cbL, - 0x33bdc7b202f8446L,0x146c896921d47c5L,0x34c58cc6b2a8ef0L, - 0x28765b5f921c0e3L,0x3c9c0c7e8207b9dL,0x0fed5dafd5f41efL } }, - /* 183 */ - { { 0x2f10b9d4cda1348L,0x1a7f48970c04ea2L,0x25b18957c22bb07L, - 0x31fd6b3c711142aL,0x09fef80295cafd6L,0x38227d773dc6850L, - 0x3d2ba8e12029f5eL,0x32d625d4aa3ec3eL,0x09061e2275f6f70L }, - { 0x30a4ac51fbda16aL,0x0439e7c77e8a8adL,0x2132d9945f6f799L, - 0x2bbad2e93bee8b3L,0x34bf2d53d450d59L,0x18831ea1aa3826cL, - 0x13c6f476010204eL,0x3d5a98fe250f429L,0x13214c91d1987eaL } }, - /* 184 */ - { { 0x14fb120490d66c3L,0x35cca2837208139L,0x0c3804b4294deaeL, - 0x2acc777119ee805L,0x28342ed113f2fa2L,0x0c0d3839c3fd57aL, - 0x0ae3c1b18da72f2L,0x1680ab70c36faf6L,0x09c179bdf6f3e94L }, - { 0x2c928ef7484c26fL,0x2df6c7bcab6ec51L,0x35483f58dda7206L, - 0x0312f1fb6d8221fL,0x1975cafdcfde4e2L,0x1afbb0812134487L, - 0x16db67c5b596708L,0x1d222d5e6aa229bL,0x01522c6d87e4118L } }, - /* 185 */ - { { 0x2890757c471d4aeL,0x12c6950e8769d82L,0x31826aa701a1fefL, - 0x14967197e4ee24aL,0x1d789df35bf4d4eL,0x2de70fca48ebe4aL, - 0x0cf1303ccb46c60L,0x03b125560b39f3dL,0x11c7da081b4257fL }, - { 0x12c6ae59aeef274L,0x16fd3c50df020feL,0x3023e13c86afe6cL, - 0x398a8894d82a9d2L,0x022589fa5d21dacL,0x3e9d2c3ecf55caeL, - 0x2891a93d4a3916dL,0x33ef79db36372c4L,0x19aa0391a3f59f4L } }, - /* 186 */ - { { 0x14ba69e203fc3f1L,0x1a332d8841a8a41L,0x0540aad5fa9f091L, - 0x03affdfb5bec206L,0x0bef94afdecb8f2L,0x02af476cb202986L, - 0x0e0a7ce25d8ca0bL,0x16e69d799e9040aL,0x1b2dd7662ddd6e9L }, - { 0x3dff279f289d7eeL,0x157567ba8881721L,0x3d54c18adac64d7L, - 0x33dfb004066bac3L,0x2b48d70a43a8c46L,0x02ce7be1bf2439fL, - 0x145a20965c53c11L,0x008f9155ddf30e1L,0x16ea33430f757ddL } }, - /* 187 */ - { { 0x29f39490ff53d2cL,0x24565ac00d26e7eL,0x1014d59979678dcL, - 0x2aea29ade2bc429L,0x08b517b104dd72dL,0x1b4e6f83bd77950L, - 0x217f70142b90bcaL,0x044632baa8fa7b6L,0x16da01689d606b3L }, - { 0x26ca563f46afff7L,0x171ee8d29797cfaL,0x24c8aa998fd8394L, - 0x11ad8fd4d7b07ffL,0x0d1f509e542a601L,0x3e33436d4205a22L, - 0x236772d1918daa9L,0x3719994179aede2L,0x1ef4ab03a819cc6L } }, - /* 188 */ - { { 0x2089d14d376d986L,0x1381de8b70d6c01L,0x309a53ff2c86d0fL, - 0x11448f0ff207045L,0x31b656fc2fef4baL,0x3fbea2ee14b3569L, - 0x110b77b57c74891L,0x284a63c14e0f920L,0x04c4b55d3ad52c5L }, - { 0x110cff3f3827633L,0x1e1357802bfa594L,0x38823ead32fa086L, - 0x058ae47361b2ce1L,0x0e6f3638a3dcf4dL,0x22dff5081e2da96L, - 0x1683e733792112eL,0x210cda5901137b9L,0x1223b84210f28e2L } }, - /* 189 */ - { { 0x028a9a9c3ebeb27L,0x3372d4fbd643e1bL,0x2e114dae7f37d7bL, - 0x391c9ba9f27a228L,0x28c141388033522L,0x058855d667540e1L, - 0x0564d859b1aeca6L,0x238d9c67f3faff3L,0x0433a577af11aebL }, - { 0x3f26ce06feba922L,0x320fb91d695a4f0L,0x274028bf378e5f6L, - 0x1a2f70fdbc5fde5L,0x2a6ed90aed2a5e3L,0x291f2f54f40d282L, - 0x0e2bc83b1c3a4c4L,0x003ae93c2a9b937L,0x1c097c7af4374caL } }, - /* 190 */ - { { 0x037717879c28de7L,0x2a8aaaae70cc300L,0x182666bc61eb617L, - 0x33d35e2d4110c20L,0x19870fc72e0b5b5L,0x102def175da9d4bL, - 0x32d03a3b4689f5dL,0x182a6a5ff619e1fL,0x1c06ab7b5eefd60L }, - { 0x19eadb1ffb71704L,0x3962ece43f8ec7aL,0x382cab4f19aa436L, - 0x3eb83cf6773bb2aL,0x16e20ad12da492dL,0x36ef4988a83d52fL, - 0x12eb54af89fa0f7L,0x01d637314286ba3L,0x0b79799f816ef7dL } }, - /* 191 */ - { { 0x2c46462104f98ccL,0x056489cabb7aba7L,0x3dd07e62186f451L, - 0x09a35b5a6d9eba4L,0x0fd43a8f3d17ce0L,0x302ade5ed4d1d82L, - 0x1f991de87f1c137L,0x38358efd65ea04eL,0x08de293a85be547L }, - { 0x182add38ef668b1L,0x39acb584725d902L,0x2b121c1d4263c54L, - 0x23bbfd939ccf39dL,0x02871612a3134b2L,0x2824d652bdc6a6bL, - 0x1108e831c88af2bL,0x0df682d92444aeaL,0x1138febc5c55cf4L } }, - /* 192 */ - { { 0x29ca589c4a2daa2L,0x29c0f1003d8231fL,0x1058d517510318eL, - 0x1c92aedbca5be33L,0x194296ab4264934L,0x314595f42f954f8L, - 0x080ea89af9398faL,0x386c788cb7bb13eL,0x1372f81761e67b1L }, - { 0x1014bc73a20f662L,0x1f9df127b654094L,0x096fb62b96521fbL, - 0x19e8ba34dfa27d4L,0x25804170e3a659cL,0x3b5428d03caca89L, - 0x03c00f1674fce69L,0x2764eaa914dfbf7L,0x198f3c3bfda4ce9L } }, - /* 193 */ - { { 0x2b1f5cd81614189L,0x15b11492c967deeL,0x24b245fb415ec7dL, - 0x371ebdafbe71eeaL,0x074b48e82302bc8L,0x2db46c7e46ddc38L, - 0x280c974a1336e09L,0x2d894a1704d5f99L,0x12d59bcb813c7ccL }, - { 0x1ad83b47c019927L,0x3c999d8c37f56f7L,0x2c5a31e05d23e10L, - 0x3e915ab1180576fL,0x1243cac822aa6e5L,0x372327a51a5594aL, - 0x0a4065c69c9c7f4L,0x0c06eb6c9f82789L,0x1ccdfa7a34eae41L } }, - /* 194 */ - { { 0x36a864d59cb1a7dL,0x19328dabbee3b85L,0x3acb1c22b0d84d8L, - 0x3af66037c743ba0L,0x07f94ced97e80a6L,0x29cb0457d60ab31L, - 0x107bb7a29cd1233L,0x028c3384a8aa31cL,0x1500229ca564ed8L }, - { 0x374bad52f1c180bL,0x2fa6635d26a8425L,0x08ab56dbd1bad08L, - 0x3902befaa6a5e31L,0x3153dc5fc6ed3e3L,0x2fa4fb422a2fa5eL, - 0x2e23bdadc7f0959L,0x0a77a3490a420b3L,0x016417523c6dc27L } }, - /* 195 */ - { { 0x0eeccf16c14a31eL,0x3894d2cb78f0b5dL,0x35997cec43c3488L, - 0x27645ab24dbe6ecL,0x29f7e4400421045L,0x1154d60dc745700L, - 0x14a4678c9c7c124L,0x2eb67325d5237b2L,0x14e4ca678183167L }, - { 0x33af0558d0312bfL,0x2fd3d5505879980L,0x05a7fa41781dbd1L, - 0x2a003bbc7549665L,0x079c3b8d033494dL,0x327db9a5b1417b0L, - 0x030aaa70ae1ade1L,0x018300a23c305daL,0x00c7f4cfe3ba62aL } }, - /* 196 */ - { { 0x18b447d057d6006L,0x25db9bf5c722c03L,0x2029abcf40f538bL, - 0x21bc40e9e0d79dfL,0x05e472c4b13bee3L,0x07f2c650829ab08L, - 0x0abf4943b045f63L,0x1ade79770767f00L,0x1b528c0bc70a555L }, - { 0x29d07ee8a8640b8L,0x04408f438d004aeL,0x255bbe24ae89256L, - 0x093e95e77371f39L,0x1377bbfe5e358e5L,0x30251f915f389c5L, - 0x29782664651c6c3L,0x305697ef63543d2L,0x08d6fcdd28fe2e1L } }, - /* 197 */ - { { 0x164a2f65c7202c8L,0x0d01496952c362dL,0x16721434fbf57d6L, - 0x1787660c28e1053L,0x15ef0fbe1811421L,0x1bd5fe7f1e9d635L, - 0x2269d35705dcf8eL,0x27e5d7752695b64L,0x0f18f015d7abdb4L }, - { 0x3131110b4799ce6L,0x2fee64b2f2df6c1L,0x0c9ff7ba21e235bL, - 0x04ec63d27fb07c0L,0x1abcf959b009d69L,0x350851ba3698654L, - 0x1f23f10e6872130L,0x0e1ad560ca05eb9L,0x143c9b5bb689ae7L } }, - /* 198 */ - { { 0x23328db48c74424L,0x05b8474672cbad0L,0x192a40d6e217326L, - 0x13032f71d4b94d0L,0x0d733bb01dd83a9L,0x2de914817188c14L, - 0x0011c8cd0d631a5L,0x1f3573370289669L,0x1e622f112cc646eL }, - { 0x3d6e29a3e1e4c4bL,0x2094e27ec552291L,0x05b54fd3e319d5fL, - 0x2682822e599f8dcL,0x3d8cbe8db8c4ce5L,0x3bb0f5d6f29d279L, - 0x1a313dcc4496eaaL,0x24d805f71c8ea28L,0x1a5250ff77a8cebL } }, - /* 199 */ - { { 0x15a0726fe29bd79L,0x12a0413e642cd29L,0x146daad56983657L, - 0x2e543507fbda41aL,0x06e6f7f450e580aL,0x03cdc62af1d6d45L, - 0x234087508cc97bfL,0x2244146e8b29295L,0x17275c39077e64dL }, - { 0x37cccaff77ca6bdL,0x037d06f6c637d7cL,0x0ff8019e01f7e0aL, - 0x112a9975cae7d1bL,0x06e3663e9be4f3dL,0x3be76db5e08b62bL, - 0x24a9aa5f37f9223L,0x322e9fc2b4e76afL,0x098a0a57c70f69cL } }, - /* 200 */ - { { 0x1c50cf400fd5286L,0x16e755ca92c0f36L,0x0f9e051ae73e1eaL, - 0x10a546ce093d798L,0x09fb4d667fe9b51L,0x3714215ac0d2cb4L, - 0x30022e4b537a80eL,0x22bb9a7b8404a32L,0x0ed7c8b9e5c6a54L }, - { 0x06007bcd933619bL,0x1d9a38ae77f865dL,0x15d3cc6e2a2e0ceL, - 0x17dfbafccbea7bbL,0x167cc4f6435a14fL,0x214305b1d72e263L, - 0x379c96cb2185fc7L,0x11d10261d29d917L,0x1397468f8ae27dbL } }, - /* 201 */ - { { 0x1de68adc88684f6L,0x3b6aad8669f6ff1L,0x1735b27a18f57c1L, - 0x1963b3627ac9634L,0x2d879f7eab27e7bL,0x1f56fbecf622271L, - 0x3ad73ca8fdc96d6L,0x15b5f21361ab8deL,0x1a4c7e91976ce8eL }, - { 0x001a5406319ffa6L,0x3993b04d3b01314L,0x296cd541242c0caL, - 0x3bafcb2bbb87da6L,0x028bee8059da259L,0x23a24392239e5e3L, - 0x227fd9e9484bebbL,0x18c6039491b43ecL,0x1b78be2a54a625dL } }, - /* 202 */ - { { 0x223554af472f13aL,0x264edd5ccfa4728L,0x29f096c168a2facL, - 0x0752c49d4d49abfL,0x3e77070ca7cfe76L,0x1f9f37da10c061cL, - 0x162ed466b6aaadcL,0x3e36368b757aa85L,0x016a81a2e0039faL }, - { 0x080759c4e3de3bfL,0x38b8454bcc222aaL,0x2d9aaa7eba5b0c1L, - 0x14e7e70472b2cb7L,0x3b0dc5c194c65d5L,0x28fd2d842ae6f61L, - 0x0b5f9fd32f8c96cL,0x0877d2610bf30a3L,0x0f431ae27ccb90eL } }, - /* 203 */ - { { 0x32a0a0d6a0ccd0aL,0x3bb209664ed554eL,0x06fd9de672a6a3eL, - 0x1203681773ec4d2L,0x16739874d8d9c51L,0x0a68d72712a9113L, - 0x177eadd9cf35b2eL,0x1c2875af66d7e24L,0x1d69af0f59d2a04L }, - { 0x2f844c7ba7535fdL,0x3530f6a10bfce6cL,0x09ede951974b45bL, - 0x25ff5114fb17f85L,0x1e6c37c0e6982e9L,0x0b0fbdaa98fdc17L, - 0x36a8d609b0f6a9dL,0x06de2fb74d6185dL,0x1764048a46aede1L } }, - /* 204 */ - { { 0x07c6ee551a251d1L,0x12fc48349e77f69L,0x138cec518a28befL, - 0x21ce202f9b930b5L,0x21be9b20b1b2b78L,0x1e5a867b1a733e3L, - 0x10bdeae41dfeae3L,0x20300959dbf27edL,0x16a8b815a0503e1L }, - { 0x0a085f653f5ef65L,0x3eefe5dec94414bL,0x07e3a3346fe661dL, - 0x3b86e57dfbe23aaL,0x15b65eaec25ddfdL,0x30b808ec881d39aL, - 0x283bb511869a154L,0x1f9f61806d5dd0bL,0x0151464652cfa87L } }, - /* 205 */ - { { 0x10853c857fa58f1L,0x2939a1329319c09L,0x2d0a1b81f40db58L, - 0x041563a32f41ee5L,0x242e388cfa4651eL,0x110d8220699011bL, - 0x2b8fd051b0d5394L,0x33f3b0afcd6cf89L,0x0fd4ae787095702L }, - { 0x079bc29df53d498L,0x0c713844dfd890fL,0x056c17a3cedf4cfL, - 0x071b36445764edaL,0x39228cddb246113L,0x3480afc6acc2914L, - 0x108612e97757b68L,0x09ad2999b79f398L,0x051c200fe654f60L } }, - /* 206 */ - { { 0x296103cb1a2b4b5L,0x332ffa10f025a3aL,0x072d986ffb5b98dL, - 0x3c85a74eb09a8dcL,0x2771371f12fa07aL,0x1f0a67be2ee16e6L, - 0x372efceae10d34eL,0x15bc4f52f71a788L,0x039378df75d8dd8L }, - { 0x1e902ffde7ff5d9L,0x2a1748c9682728cL,0x13a6f4192fcd0e9L, - 0x0dc56c1dacf5c6eL,0x26e711d1cf52a57L,0x30a4a0675c9aaa1L, - 0x015de60b61b1df2L,0x2791c89395d7320L,0x1dc68e893e118b7L } }, - /* 207 */ - { { 0x3924ff96ffeda73L,0x27d01a83688062dL,0x20eaf89584dfe70L, - 0x0ba0d568100da38L,0x0fd777d7c009511L,0x2fe3cb20967514aL, - 0x05311bb0c495652L,0x36755fd8c64a113L,0x0d5698d0e4f8466L }, - { 0x10d64fa015d204dL,0x09afe9b744314f8L,0x0e63a7698c947b6L, - 0x11c14cde95821feL,0x0df5c782f525a65L,0x157eebfd5638891L, - 0x2e383048aa1e418L,0x18f4d23c886391fL,0x04df25239591384L } }, - /* 208 */ - { { 0x2f4fd69d8695310L,0x3ac27dfa1da3a9dL,0x1812e0d532a8e28L, - 0x11315cab1e40e70L,0x0785d6293dda677L,0x369daec87e60038L, - 0x3c72172bfe2a5a3L,0x22a39bb456e428aL,0x04cd80e61bfd178L }, - { 0x1f4037016730056L,0x117fbf73b4f50eeL,0x363c1aa5074246fL, - 0x14bfe4ab9cc2bf5L,0x11bb2063f21e5c6L,0x0b489501bbc20c3L, - 0x15001c18306ecc1L,0x150913b766ce87cL,0x1f4e4eb25b8c0ccL } }, - /* 209 */ - { { 0x161a714a1db5c18L,0x139879d9dc1d33bL,0x3be57bf685de945L, - 0x14f48516f97a5c3L,0x3ee49a5f2221b0cL,0x12c4740ee4c6206L, - 0x02213700b91afa1L,0x002bf1abbf924fbL,0x13c50554e945262L }, - { 0x02c45e77364c92eL,0x000995cd4863a35L,0x1a0284d3f3c5e05L, - 0x0936fdd91af4a07L,0x2485f304f312f84L,0x049e944f86a23caL, - 0x20e0bc583f56311L,0x1c293b5e5431c69L,0x0c692855e104b7bL } }, - /* 210 */ - { { 0x106185c644614e7L,0x01b2b91d2690923L,0x12ea2587e5282e9L, - 0x02b44a15f356150L,0x0ba5593b5376399L,0x3574a919dc31fdcL, - 0x29a1bac2cf6dc4dL,0x2576959369158edL,0x1c8639f7e141878L }, - { 0x1c96b02f8589620L,0x11a28d079101501L,0x1a11096ad09c2feL, - 0x2627194abbafc8bL,0x3547e1b8fbc73c2L,0x1df6fdcf37be7e2L, - 0x13552d7073785a9L,0x0f4fc2a4a86a9f8L,0x15b227611403a39L } }, - /* 211 */ - { { 0x1a5a7b01fbfaf32L,0x298b42f99874862L,0x0f5ef5e3b44d5c5L, - 0x3b7d0eefd891e5cL,0x1260ae5a03ea001L,0x1a5f18b2a39d0a1L, - 0x1a7643eb899ebd2L,0x09698da800f99d4L,0x0eaef178c51ba07L }, - { 0x2cf8e9f9bd51f28L,0x3aef6ea1c48112aL,0x2d3a5bfc836539fL, - 0x334439bc23e1e02L,0x08241ab0e408a34L,0x22998a860413284L, - 0x2048d6843e71ce9L,0x3461e773a14508cL,0x1fa5cba23be1cf3L } }, - /* 212 */ - { { 0x3e8c9d22973a15cL,0x3b237750a5e7ccbL,0x0a390b6afb3e66fL, - 0x0daad97bc88e6bdL,0x266c5fcdb0bb1e4L,0x2bd21c2e3c98807L, - 0x344e243cffe8a35L,0x05c8996b8a1bcaeL,0x114da2e283a51ddL }, - { 0x29c9a56c1e3d708L,0x18b4fc72c3be992L,0x298497e875404feL, - 0x1acf3a91bebc1c0L,0x283886263138b7dL,0x070c24241e018d3L, - 0x03864727e842807L,0x2899fc2bde75f96L,0x104c1b86582b236L } }, - /* 213 */ - { { 0x2ff09eda526c894L,0x2fc48052b1f48ccL,0x0dcd3cd9293495aL, - 0x04a4b9ad55adbe5L,0x21036c31bffaaebL,0x01ffccb864de5baL, - 0x1d67b8a9d237e77L,0x0922f59696c360aL,0x1b348edb556db29L }, - { 0x2e9f9b2ded46575L,0x32822bfe9a6b3dbL,0x33a1f16d37d1496L, - 0x2c5e279740756baL,0x1c827cc454a507dL,0x259399dc178b38aL, - 0x0e46f229b6e4a52L,0x19214158ec2e930L,0x0a3e75c24484bc4L } }, - /* 214 */ - { { 0x3cb476fd2f6615dL,0x3e6de36636a6a43L,0x1f1cd2bdf1074b7L, - 0x21a6e55bcc78bf7L,0x3b596eadf2bda30L,0x156c94e3cf328bdL, - 0x0846db91c09f8b3L,0x190b91bcfdbcf1bL,0x1ff9bb9398e2a14L }, - { 0x118d4f5a17bd645L,0x0cfaaf6f5b55494L,0x06fc734d0957570L, - 0x17d7d4f10d401faL,0x3fd27dd1998ca06L,0x254b472a652766fL, - 0x2c101cddc4e3046L,0x2c01e132ad3ee06L,0x00346d079f94a56L } }, - /* 215 */ - { { 0x1eb8e4fa6bfdeddL,0x28a179e9d31be65L,0x14d13d09a252993L, - 0x3986697dd9e2f57L,0x20cebb340eaa10bL,0x36fdea0f4f6c20fL, - 0x0f23e1c633a78b1L,0x20de49992f0fb0cL,0x1c96630f8f107a0L }, - { 0x3f4cb4bdef86a80L,0x13b1e0fe0966aeeL,0x3604609532c81faL, - 0x3322e427a4a92fdL,0x31788416071bb7aL,0x286ae4a32875cc5L, - 0x0455a57f7f14becL,0x3a266ffa805b97eL,0x02d7b8c76b9bf21L } }, - /* 216 */ - { { 0x28605634b9f8e7dL,0x05dadd8ff162a11L,0x1a7e2feed68a201L, - 0x0f99460c6439e97L,0x2e9377ad6cc6776L,0x1c0c8c85f5f4040L, - 0x0bb505ccfc47207L,0x09da55cfb80c54dL,0x0f31bf1ef8c0f1aL }, - { 0x35f5c4b0c935667L,0x14b0e41834ae2d8L,0x2c2e37c3a574741L, - 0x1302dcb8337bfeaL,0x1f4f60247fd5fccL,0x2785bccedd0fe6eL, - 0x34ef9c05c2e3547L,0x2b38e888d311cc1L,0x1244092f279495aL } }, - /* 217 */ - { { 0x3fd7851b30f9170L,0x2a87a4dff396c56L,0x15e0928437b9715L, - 0x1670cbc49cf3ff5L,0x248be1e3488acd2L,0x296f18ad685173cL, - 0x156f463a3408607L,0x3870d8a5bac5460L,0x1e7397fad192774L }, - { 0x22f99f49c8225b5L,0x3f39251addf134dL,0x35308541e91b33eL, - 0x0d0e3cf5a4d1477L,0x2e727b54e0bd2d9L,0x188b65002d778b5L, - 0x36a94b42d929c27L,0x3c814dab39c8d5bL,0x04464a18cd5fccaL } }, - /* 218 */ - { { 0x1be0aababa95d63L,0x203185ed2cd1b63L,0x38630e0d8142927L, - 0x0aad5bbc13190c3L,0x1785e3633875be0L,0x04b24f930a3fae5L, - 0x2f82a3d5401795cL,0x2bf5a27fd47078dL,0x16b3c48c89510eeL }, - { 0x1287ebad4f064beL,0x1f555553af6a65eL,0x1ef2623727ea1a7L, - 0x24627cd9b1919d1L,0x1c59d6ebda911f5L,0x1493484df950d73L, - 0x15b38d3a84daea7L,0x0f1271ec774710eL,0x01cca13e7041a82L } }, - /* 219 */ - { { 0x399860c874d64b0L,0x16c248594f38318L,0x0000eaa11986337L, - 0x0258873457459c0L,0x277d70dcd62c679L,0x016f5336f875f75L, - 0x2f8f30eff0f2703L,0x16de01dbb1884d8L,0x1d8812048167e44L }, - { 0x1749a0e161f9758L,0x2457fa8f13f38a0L,0x0e41911dd8afe60L, - 0x2b1e6946827d4dfL,0x02ca5cf8efe36a8L,0x12415fd59fed52dL, - 0x244b641bdcae07eL,0x1960edc7fc31690L,0x1064815a5364b60L } }, - /* 220 */ - { { 0x0c69c3eef39cc39L,0x011593e98d5b45eL,0x3542412fb990983L, - 0x34de76eca96f4f0L,0x0e7e75e3da1d531L,0x2c051ec52197c62L, - 0x129ab02dac4e220L,0x1d3bfd6794728cfL,0x0f1c964f7fe37b0L }, - { 0x080c0a60e301262L,0x1601814e4288b5cL,0x3f9acc8a90299a4L, - 0x15c5303c70b699dL,0x26e66d9f7dfae90L,0x1e11a490d997fc5L, - 0x0c307cc866dd8c4L,0x1439316bfa63f13L,0x03960e3ba63e0bfL } }, - /* 221 */ - { { 0x2785136959ecdb3L,0x2bd85fe7a566f86L,0x32b8cde0dc88289L, - 0x2c1f01e78554516L,0x350e22415fe9070L,0x1635b50bddfc134L, - 0x3b629ab3ab73723L,0x3f49453f506e6e9L,0x1937b32d80e7400L }, - { 0x1d80d4d7147886fL,0x33b5855db2072b9L,0x0692642717bbe08L, - 0x262aed2f487853aL,0x26530308b9dcdf1L,0x2674671d962f991L, - 0x0ab126fbf192dadL,0x378c5568f46ccc1L,0x00e943f4be5fa24L } }, - /* 222 */ - { { 0x14240587fe9ea48L,0x13e09586d5d21b1L,0x013c78719740af2L, - 0x1e5c3ae1d3674b1L,0x0b62ba3aa27a9beL,0x306fc2b10ffbe38L, - 0x3130e10a23f2862L,0x33afd4709dbcd2bL,0x185f6cd1e9aae55L }, - { 0x0defa7f40369093L,0x076759616078289L,0x3f33e512ed9e11fL, - 0x167b448225a6402L,0x28b73c399bf8a84L,0x3dbd53fa0c91557L, - 0x25235554a305698L,0x0ecc4aa75b694f0L,0x16ae6a6f9042a09L } }, - /* 223 */ - { { 0x2e123c9152cdd35L,0x390ea21900bbc6cL,0x30dfb9ce5bd5ae6L, - 0x129d601245224afL,0x3f502eec2b4acb8L,0x28cfbd3a31fd57fL, - 0x1d20019c8a7b93aL,0x2f3ac1ac40d5ff6L,0x0273e319ff00ba3L }, - { 0x02c2f77abe360a3L,0x3d7212b7fbf2986L,0x0ca6650b6fcc57eL, - 0x15aabc2c80a693cL,0x0a24ef1563f4f8eL,0x3a917c4d7214228L, - 0x036dbed8f62fd91L,0x040efcb248e80a0L,0x18a4a9ca4c01a4dL } }, - /* 224 */ - { { 0x23fb7985448e339L,0x1dc33c628e65d8aL,0x174d7a69170cde8L, - 0x164ad819eb04581L,0x0848138ab4bb05cL,0x24279e537834b6cL, - 0x0315f7149dab924L,0x289620e8cdad9e4L,0x13ccd9074d9a335L }, - { 0x039c5e0ac1b784dL,0x17231bb949eb87aL,0x2146a1c88ec0ab6L, - 0x2411b06fd634f21L,0x33fda502a2201f7L,0x096e4195c73b189L, - 0x16dfcdff3f88eb2L,0x29731b07c326315L,0x0acaa3222aa484fL } }, - /* 225 */ - { { 0x3e74bc3c9b4dfd6L,0x2a014fe39d8a4c5L,0x1c059d8c352025bL, - 0x332e16882d00c1fL,0x2238713591c9036L,0x2a57ed3bcb18fc2L, - 0x10c6c61a99d9d8cL,0x259a0f5f13ce661L,0x169162969c96829L }, - { 0x113c267cb63ee53L,0x04b985d7ab0d4dfL,0x1a11191abfca67bL, - 0x277b86bda7eccdaL,0x011dc11e75ad064L,0x2e7e5d9535e9bc0L, - 0x2b133280f030b8dL,0x3318a8800068fc2L,0x194e17c98d239d8L } }, - /* 226 */ - { { 0x20d80b41d8fe898L,0x28a2dcc86114d1cL,0x038504f217408d7L, - 0x35459aa9abfc7cfL,0x0cc560e355d381cL,0x39878b367379821L, - 0x34951acb041f0a5L,0x2b0b188445bd766L,0x0c4509e16d37ee2L }, - { 0x02a20c42c6fd79eL,0x1fb938ebde2c3aeL,0x23c1bad819ca95bL, - 0x37a615495a4f66dL,0x2f9c19d0f10d674L,0x1f179aa45f7992cL, - 0x22db6fa03fabaf4L,0x3463a162f12b4b3L,0x0c976c2380a1fc9L } }, - /* 227 */ - { { 0x1171ef8b064f114L,0x2c55953cbc3d324L,0x185457b262b783cL, - 0x0043cd24db0c149L,0x299a41fed468c67L,0x1fdfdaa7bc9b4bfL, - 0x1bfc1bf6da2267aL,0x3b500958ee36e80L,0x00e14b36c85c340L }, - { 0x257e26425db67e6L,0x3d3a25fcba417d7L,0x2514026c426885dL, - 0x188fa1d424de0cbL,0x03c538691312be2L,0x15cd3e7615ad6f6L, - 0x2a48615b1cae559L,0x2ed61681eff8b56L,0x1d07a4c96f0ce8aL } }, - /* 228 */ - { { 0x3f54d05523aa2e9L,0x107833b4f42181eL,0x36e27f9bfb69c88L, - 0x11058af7e155a0fL,0x107b0dcc9dcb07fL,0x15e94db98b45e0eL, - 0x347d3ca2cbb8ab6L,0x18dc262e68349f3L,0x1f2ff154d685eeaL }, - { 0x28b768a56b232acL,0x35b8d8fca94aad5L,0x3a168837fc604e8L, - 0x20f4429da46eba1L,0x0f9455fbeebc58aL,0x359538bab5792bcL, - 0x3c82551a20d6c37L,0x2e4c63103f2e769L,0x0b26d7b3cd760d9L } }, - /* 229 */ - { { 0x3090c3ebb2eaf45L,0x1364718bfee4bdeL,0x3ea4a736f23ded2L, - 0x2f5bfc3f78efca8L,0x1ca1102f5b5b99eL,0x1f80caa2f28ad57L, - 0x3f17a8f6203cd80L,0x156c55042d122a2L,0x109b86660a7e1dcL }, - { 0x148b1da02a2fbd8L,0x217a2cec8ba296cL,0x20e48712b509fedL, - 0x1231a8f94584de2L,0x01633b503685601L,0x15449c45c402487L, - 0x131047939251432L,0x382eded24c7481fL,0x0ea623e722b8542L } }, - /* 230 */ - { { 0x04823d324972688L,0x20f04800fd5d882L,0x26906d0d452858bL, - 0x210b1bdd1f86535L,0x10146d89a842195L,0x1146ef0b23e28baL, - 0x3284fa29ec1de77L,0x3913fd88adae3dfL,0x06083f1dbe97b71L }, - { 0x1649333999dd56bL,0x2b02ea5e91f7a66L,0x18aebbe8fb202cfL, - 0x363d875ef299983L,0x185adc14d47c29dL,0x3e7f5071bd7ed47L, - 0x113e6ce65ac7884L,0x274f8739a7753fdL,0x0231ace591effe5L } }, - /* 231 */ - { { 0x267a438a9fda771L,0x3d94b2198c4038bL,0x1e48e133f23b626L, - 0x3c80d74b47f7ec6L,0x28d13e878599f88L,0x2d47381c5c8e844L, - 0x19ba82890aa292fL,0x052d397ce9c3aefL,0x155dde826733745L }, - { 0x0b2b77ed6f59a95L,0x214f8c080810802L,0x2ac1ebac779793fL, - 0x266d5ad99d94894L,0x19722a5006ecdcbL,0x138aeb412af6e7eL, - 0x34dd4d26210f3f0L,0x2e034329683fcc0L,0x041333d8080dac0L } }, - /* 232 */ - { { 0x051070935a85a06L,0x19b9d90bbc6d13aL,0x0b71a07b3a6d4e1L, - 0x000c0ca79aa12a4L,0x13d555259d6dd6cL,0x3e2b41788312e99L, - 0x34cccdee3b26af6L,0x19090838f5504aaL,0x1bd79798934a940L }, - { 0x2a1d1848e0c7ff0L,0x217bf2550ecd03cL,0x31aef51d318bbaeL, - 0x139d61e3e9ba590L,0x3c2895f52e5d3edL,0x3c4419f134a8a76L, - 0x3f4ee53af278771L,0x1d369b337a59279L,0x19235188da1a56dL } }, - /* 233 */ - { { 0x083212003d310edL,0x3ba33261ec0c46cL,0x1d2684c558a8d20L, - 0x33adc59fb227952L,0x04bf55bb55e25f3L,0x1872405eb3c453dL, - 0x3343c0819edc770L,0x2d7b5d669139b7aL,0x07858df9f7e04c9L }, - { 0x3a47ebb3bf13222L,0x147737a81f68453L,0x3ac3c0d8242f1e4L, - 0x134dbae1c786fa7L,0x2bea3190d93257dL,0x3af8accfd279dd6L, - 0x110096406d191f4L,0x2b1e19eab14f030L,0x1f45215cf8bd381L } }, - /* 234 */ - { { 0x07e8a8efa493b79L,0x389c2d3ac70ab0eL,0x3fa09ff22320b20L, - 0x2baa470e4f67ce4L,0x2138a8d965ee1baL,0x1ef543937b6a586L, - 0x23c8e069ab238c9L,0x1305bfda352288dL,0x158af8e00e5ce4cL }, - { 0x0cdcf06cfc509a1L,0x1047bf09b301d5bL,0x1fd64d9c57f060fL, - 0x14ccba672b1b433L,0x18b8e9510a95148L,0x04370ff563e6acfL, - 0x2f3509a7e98709bL,0x04b1e0e4210f5d7L,0x1b628ccc9d05a93L } }, - /* 235 */ - { { 0x1934f00e341463fL,0x229b3854369e807L,0x20fc4109553f14cL, - 0x16aa4fd2a476d21L,0x32cd58067c23bdeL,0x10cf72027d1f1e1L, - 0x232a7d1d3300548L,0x176a4302f9fe5d6L,0x12e08b777d588c7L }, - { 0x3c1281761a10d37L,0x2d86057143d6977L,0x15db79477c60ed7L, - 0x1dccf14c42ca2beL,0x053118267a0aa2bL,0x2d06567e417eaaeL, - 0x337784f40e98166L,0x1ab32732d09485aL,0x0c56835d77c6986L } }, - /* 236 */ - { { 0x1d714cb2b450a66L,0x222171f6ff7053aL,0x0d85b466a0c0131L, - 0x2656f7f0699956aL,0x0e67792d102a21eL,0x15429e5de835f26L, - 0x34d3372a01bb57bL,0x352550b1188cd75L,0x08b7be4e1c088daL }, - { 0x073b03f95812273L,0x1bb4cbb8fdd5fc6L,0x0eae6da6217a2e2L, - 0x1d098767d3cb1c4L,0x1b7c1da2d9b50b5L,0x12a1779d0e5c7eaL, - 0x22137b22c4fb87cL,0x0649bdcb0d147b0L,0x1731345668c77baL } }, - /* 237 */ - { { 0x23e8c7a8a3ba183L,0x33aeeff8e27e9cfL,0x06870f9ba60f4e8L, - 0x0d72d806a0e3a91L,0x212e52db455176eL,0x3dc4afc7e42f709L, - 0x2054cd95f9e4598L,0x3502e6f4c803efaL,0x17a2cf19bf6dd5fL }, - { 0x1cf6ca266736febL,0x21bd2779f3f8bdcL,0x3ce8fc290563bdeL, - 0x339c9adb93f182aL,0x13f29235baae8a3L,0x143fe97b48e0911L, - 0x3ef744a4b557f56L,0x1b74a8514f95044L,0x1b07c676a533e42L } }, - /* 238 */ - { { 0x1e603f235d96872L,0x288f30fe96e32bdL,0x071be988dc5fab1L, - 0x22750c302f55166L,0x0764d9cc3e32e84L,0x0b031035fb09a78L, - 0x3b83b4f7238212fL,0x29044b651860e21L,0x010281fa6712f18L }, - { 0x028048f64858b37L,0x0526bcd5f797660L,0x0791619ebb18e0eL, - 0x2ce7cac2e82c886L,0x21039cbae210200L,0x255e74756a1fab9L, - 0x08515e4efdcddb3L,0x1e2a86ce23aa89eL,0x02c1a552c3cc818L } }, - /* 239 */ - { { 0x2c7f5000ea723dcL,0x3c13d10ac548c5eL,0x1445be885c860a5L, - 0x0fffc465c098f52L,0x0c4c58cea61f999L,0x273580db0fee917L, - 0x3923bbe6d151e6bL,0x3f519d68eac555eL,0x1474ec07c52ceb2L }, - { 0x06a3d32ed88239dL,0x2e2b9a0d6b9a531L,0x23259feeb2e70d1L, - 0x0710ef02ed7d3f7L,0x38f62a705223bf7L,0x3f9e6694f34882dL, - 0x2b7f932224860e9L,0x2562f61561c0c92L,0x10f8e0f7330b594L } }, - /* 240 */ - { { 0x335c7bb3c67d520L,0x12562c8ff2a7b2bL,0x31948bbaa808d8fL, - 0x33884d7a2b81de3L,0x1c888eff7418c30L,0x1cc512af376366aL, - 0x06a53472075df0fL,0x1ff16d527225514L,0x11c4ef389795fbbL }, - { 0x3e2c9ac43f5e698L,0x1ff2f38e2978e8fL,0x090e3089c2e1ce7L, - 0x3feb0756005b417L,0x0381b9d2a5a74f3L,0x17ce582ebbb6888L, - 0x37abbed958b143fL,0x2dc6197ff414436L,0x0ce8e97e6807a05L } }, - /* 241 */ - { { 0x251e61b8ce86a83L,0x10567efdf9c5808L,0x3dd748f03377860L, - 0x0dd1414890bf049L,0x0934ea09b87cb2cL,0x119e5106f52543dL, - 0x3a416a5146c403cL,0x23ac7a2b51c408eL,0x1b389b81a60af63L }, - { 0x299934ee8150c69L,0x1d642389f052f39L,0x28916a0194ff74fL, - 0x0c86f546dd97702L,0x21877963038f49dL,0x34ed29a1af0cc17L, - 0x0af189fe2f3fbffL,0x0426c5026cddf5fL,0x1b3029ea13b9b8fL } }, - /* 242 */ - { { 0x37938d225a2fd88L,0x3cbdf33ae8180fbL,0x1c80d7a6dff4890L, - 0x0d8a20fe61930f8L,0x2998e530500c78fL,0x097771cfb64ad64L, - 0x13708a018a8f1b3L,0x0a2edb7ff661f57L,0x059dcd3554f0d1fL }, - { 0x3c6e41d23a74e7dL,0x187af976ccb7d85L,0x3fa79e7ffa0b94bL, - 0x2dcbaede834f0bfL,0x201adf9c3473662L,0x119e4992a19057bL, - 0x209c571502c3265L,0x242185a444d24beL,0x195897f34aa2474L } }, - /* 243 */ - { { 0x045d359abadc253L,0x12e4b31e5f25792L,0x35bd9a218212e05L, - 0x17a94ae209c8aa6L,0x22e61c6769bb80aL,0x22c3e2cfa8e39e3L, - 0x1d854cfb274b1a0L,0x0b5cedaa90b8f6eL,0x1638ba225235601L }, - { 0x0ec0e6f75c8c576L,0x0839f392f1f749fL,0x20c869d80726abbL, - 0x1aa2808fadc2562L,0x276110b15a908c6L,0x21bd869b2a7d43aL, - 0x0a69d8668c99941L,0x2843e777c8bb4a8L,0x1e0bfee1897bbf8L } }, - /* 244 */ - { { 0x2d8681848319e4fL,0x1bdad56961be809L,0x1886267132656beL, - 0x316614a73eafbd7L,0x162b29cfbac252aL,0x0a98d6379f3117cL, - 0x00ac70ee050609aL,0x2c7c3df2e7290a5L,0x1adfb44aaeca885L }, - { 0x2b7a936e798678eL,0x07840e655010e19L,0x1e37816860b7ca0L, - 0x20edd17615fc924L,0x0a4705ed6eeffd4L,0x0a9743dd76ecd8aL, - 0x09fee357d68d49bL,0x35a1b46a14a688eL,0x1addbbc25491a7fL } }, - /* 245 */ - { { 0x10cba20969686a3L,0x2c71578f014fd78L,0x313426f47102308L, - 0x2c5240cc0e05c4aL,0x32d01527b1f9165L,0x2a68d38916dc805L, - 0x3e35c86fcf6647aL,0x38e0947d52e52c2L,0x0e3fccb22a55a15L }, - { 0x271e4ec5b4dc0beL,0x0d89236c735712aL,0x3f43046e1007bb1L, - 0x35f6a72668fcdafL,0x28349bc505a6806L,0x04f8214272ff1bbL, - 0x3448c126871e73eL,0x2ebe579aa889d9fL,0x1b9ba77787c2da7L } }, - /* 246 */ - { { 0x2be58eec5a73375L,0x37da75ea2b10e06L,0x150aceca835a175L, - 0x027d41f4c3cb3ccL,0x3c60b0424b87b06L,0x043e43b26b94e8aL, - 0x1689bb4931e1824L,0x06a3914b1f43eb7L,0x013ab4534914763L }, - { 0x32dd8568c84f3afL,0x3702486eab8cfabL,0x2a858b96b070829L, - 0x103a2a094591950L,0x05c35322b42260dL,0x27b6834ae797b6bL, - 0x22b90abca795603L,0x14c0a1af41f1ae5L,0x10a2e22dac7b1ecL } }, - /* 247 */ - { { 0x25fc09d239d8f0aL,0x0b80f2ae2840859L,0x17680173477b92bL, - 0x27e38d8581390daL,0x19eb061beab38edL,0x3a1159c1e6c0247L, - 0x21a2e0cd4226543L,0x00c3e83ddfb1cbfL,0x0931d242162760aL }, - { 0x29f834cf8646bc3L,0x25294902ba5be7eL,0x3890379177d17dfL, - 0x113ffad9b364070L,0x077b924659dfd06L,0x3660753e06bb0bbL, - 0x37b0932df3b7f2cL,0x2762f26f0fda7cdL,0x125daef34f3dd85L } }, - /* 248 */ - { { 0x008451ba2c123bcL,0x20e9a02063e952bL,0x170298957b8ad1eL, - 0x0d3c3c4bc595b75L,0x30a9fa14dcc7f2eL,0x0bf9e0b07daa70cL, - 0x1f54ddefc9a2bbbL,0x0294f4c671a5dc2L,0x1dc0b8238cbd646L }, - { 0x249290144dfb6f6L,0x35f2d1b900749bdL,0x240e48537ad8270L, - 0x2d5c3636f6469c2L,0x2f170d58b84d661L,0x0d13874b289c88eL, - 0x1de1faeeb4cf146L,0x17a9c8957f256aeL,0x1f8cd6e110adbdcL } }, - /* 249 */ - { { 0x257c6b978b8a0a7L,0x12badba0cfb7a8aL,0x17c14bd13fe724bL, - 0x223f0ba3b927918L,0x1fb147eefc41868L,0x3998b3ee34e6292L, - 0x0ba2ece9f191f12L,0x35435861c8a2656L,0x02dbd6d0f1b00b8L }, - { 0x15cfdfe24c93cc9L,0x35de02e79c639e2L,0x3a5838baf7eb29eL, - 0x1f93772fda40722L,0x3a180d6bb022538L,0x251f1f0992c942fL, - 0x23f3cd6d68e548cL,0x0f34a0a9ed8ca64L,0x00fb8f036132d10L } }, - /* 250 */ - { { 0x198b3f08cd9d494L,0x0196e653d3e7ce0L,0x22203c738fa99b2L, - 0x0536348a72dd992L,0x0c51c54b3199f4cL,0x084e8ccb76b5d71L, - 0x0c7b2f9a32ce0bdL,0x3c82bce88421622L,0x0d16defa3625b1fL }, - { 0x0e0054819a296ebL,0x13fc5746a44c4d1L,0x2d2bfeaa454f1d9L, - 0x00d3502f5ff5f7aL,0x21801a4afae65a8L,0x178379dd813c51fL, - 0x172ca0983048f9aL,0x3445e8ec67297fdL,0x0e0a237dba71821L } }, - /* 251 */ - { { 0x1babf8491630ee8L,0x16270817ad4c07bL,0x2b2da051f47bde6L, - 0x25884aefa067df4L,0x294292124aeaa9fL,0x110d796f73b4f57L, - 0x11f66f691f5b89fL,0x3c368658130ce50L,0x0e6b7fc09ca4356L }, - { 0x294e413f74f811cL,0x0b60c77e36376c4L,0x3217963418c91a4L, - 0x06223af37b09fd5L,0x2ea305bc95fde52L,0x319a2d87f75781bL, - 0x011861ed1e6088aL,0x33af0ccebc05baeL,0x1c95ecb192d15ddL } }, - /* 252 */ - { { 0x27b37a3e0bde442L,0x10ffa19bde9cfa4L,0x1d208ed10c2ee05L, - 0x1069985e8cb4c36L,0x0d1d5cf8baf79c3L,0x0eaf3e2f9cd9e1cL, - 0x2b5e7b02d0dce9eL,0x1c317f88f4b75dcL,0x10b29fceea01ffcL }, - { 0x1bcae4d62d803ffL,0x3a44ff6f0c1aa4cL,0x27abd8c1066293eL, - 0x0ab9e9b5962bc77L,0x2102f4e06d48578L,0x0dbebf9a449964bL, - 0x37121391a3127f1L,0x058d11ae4d10220L,0x0ba53bb4380a31eL } }, - /* 253 */ - { { 0x2e517fcca5636b0L,0x1b8085aae8571d8L,0x3d7c212e7b2d429L, - 0x1b55c5eb6116aa3L,0x398b2f3579517ceL,0x3d66c1f39d8ae16L, - 0x3ef6f042f996b5dL,0x2d227cdccaaefcdL,0x15da5d145ea4542L }, - { 0x277c55eaa7f6e3fL,0x36669ea92816f07L,0x3d77458282273f4L, - 0x3eddedd23ee95b5L,0x20629f5d1db0895L,0x16600fec7121333L, - 0x20b8d0f5b1c90a3L,0x04fc90eb13ca45cL,0x0e98c10bfe872acL } }, - /* 254 */ - { { 0x11c4785c06c4fd6L,0x2e40974970ae767L,0x1eb1d4982f24bf4L, - 0x30ae93fbcac104dL,0x398de07ab3ab3edL,0x25bd2df556948e7L, - 0x04c815d5fc49ab0L,0x1acaf1428a580e1L,0x047db1148d01567L }, - { 0x09f9cc510f3bad9L,0x2223f008a407531L,0x15ebc47b44df490L, - 0x31bce7cada245e9L,0x304e9962a20b2ebL,0x1cf756dc31638ebL, - 0x29f76c52ab7c1b5L,0x328ecad52b75a8cL,0x10859dad1eb82f4L } }, - /* 255 */ - { { 0x22c4128a182d1adL,0x05e5b88245b1159L,0x0272ba681647775L, - 0x3eae4b217069dc1L,0x3aefb2e07fac8b0L,0x2186ccb481eacb7L, - 0x2ed145c73530a07L,0x292758f6fb59622L,0x0bd547bcdca0a53L }, - { 0x3c1382f87056b51L,0x247b6c4c3e644a9L,0x1e46d3805b42c3dL, - 0x3aff4c6a657df1fL,0x0cd3fb8aa456101L,0x3ac5ef387bf48adL, - 0x2c0c32fe391df79L,0x3bbd2d353031985L,0x11219f023be711bL } }, -}; - -/* Multiply the base point of P521 by the scalar and return the result. - * If map is true then convert result to affine coordinates. - * - * Stripe implementation. - * Pre-generated: 2^0, 2^65, ... - * 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_521_ecc_mulmod_base_9(sp_point_521* r, const sp_digit* k, - int map, int ct, void* heap) -{ - return sp_521_ecc_mulmod_stripe_9(r, &p521_base, p521_table, - k, map, ct, heap); -} - -#endif - -/* Multiply the base point of P521 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_521(const mp_int* km, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 1); - SP_DECL_VAR(sp_digit, k, 9); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(k, 9, km); - - err = sp_521_ecc_mulmod_base_9(point, k, map, 1, heap); - } - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Multiply the base point of P521 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 multiply result. - * inMont Point to add is in montgomery 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_521(const mp_int* km, const ecc_point* am, - int inMont, ecc_point* r, int map, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 2); - SP_DECL_VAR(sp_digit, k, 9 + 9 * 2 * 6); - sp_point_521* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9 + 9 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - addP = point + 1; - tmp = k + 9; - - sp_521_from_mp(k, 9, km); - sp_521_point_from_ecc_point_9(addP, am); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_9(addP->x, addP->x, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_9(addP->y, addP->y, p521_mod); - } - if ((err == MP_OKAY) && (!inMont)) { - err = sp_521_mod_mul_norm_9(addP->z, addP->z, p521_mod); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_9(point, k, 0, 0, heap); - } - if (err == MP_OKAY) { - sp_521_proj_point_add_9(point, point, addP, tmp); - - if (map) { - sp_521_map_9(point, point, tmp); - } - - err = sp_521_point_to_ecc_point_9(point, r); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ - defined(HAVE_ECC_VERIFY) -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ -#ifndef WC_NO_RNG -/* Add 1 to a. (a = a + 1) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_521_add_one_9(sp_digit* a) -{ - a[0]++; - sp_521_norm_9(a); -} - -#endif -/* 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_521_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 >= 50U) { - r[j] &= 0x3ffffffffffffffL; - s = 58U - 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; - } -} - -/* Generates a scalar that is in the range 1..order-1. - * - * rng Random number generator. - * k Scalar value. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. - */ -static int sp_521_ecc_gen_k_9(WC_RNG* rng, sp_digit* k) -{ -#ifndef WC_NO_RNG - int err; - byte buf[66]; - - do { - err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); - if (err == 0) { - buf[0] &= 0x1; - sp_521_from_bin(k, 9, buf, (int)sizeof(buf)); - if (sp_521_cmp_9(k, p521_order2) <= 0) { - sp_521_add_one_9(k); - break; - } - } - } - while (err == 0); - - return err; -#else - (void)rng; - (void)k; - return NOT_COMPILED_IN; -#endif -} - -/* Makes a random EC key pair. - * - * rng Random number generator. - * priv Generated private value. - * pub Generated public point. - * heap Heap to use for allocation. - * returns ECC_INF_E when the point does not have the correct order, RNG - * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) -{ -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_DECL_VAR(sp_point_521, point, 2); -#else - SP_DECL_VAR(sp_point_521, point, 1); -#endif - SP_DECL_VAR(sp_digit, k, 9); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_521* infinity = NULL; -#endif - int err = MP_OKAY; - - - (void)heap; - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - SP_ALLOC_VAR(sp_point_521, point, 2, heap, DYNAMIC_TYPE_ECC); -#else - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); -#endif - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - infinity = point + 1; - #endif - - err = sp_521_ecc_gen_k_9(rng, k); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, NULL); - } - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_9(infinity, point, p521_order, 1, 1, NULL); - } - if (err == MP_OKAY) { - if (sp_521_iszero_9(point->x) || sp_521_iszero_9(point->y)) { - err = ECC_INF_E; - } - } -#endif - - if (err == MP_OKAY) { - err = sp_521_to_mp(k, priv); - } - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_9(point, pub); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - /* point is not sensitive, so no need to zeroize */ - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_key_gen_521_ctx { - int state; - sp_521_ecc_mulmod_9_ctx mulmod_ctx; - sp_digit k[9]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_521 point[2]; -#else - sp_point_521 point[1]; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ -} sp_ecc_key_gen_521_ctx; - -int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, - ecc_point* pub, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_521* infinity = ctx->point + 1; -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - - typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) - >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - err = sp_521_ecc_gen_k_9(rng, ctx->k); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - ctx->state = 1; - } - break; - case 1: - err = sp_521_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - err = FP_WOULDBLOCK; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - #else - ctx->state = 3; - #endif - } - break; - #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - case 2: - err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p521_order, 1, 1); - if (err == MP_OKAY) { - if (sp_521_iszero_9(ctx->point->x) || - sp_521_iszero_9(ctx->point->y)) { - err = ECC_INF_E; - } - else { - err = FP_WOULDBLOCK; - ctx->state = 3; - } - } - break; - #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ - case 3: - err = sp_521_to_mp(ctx->k, priv); - if (err == MP_OKAY) { - err = sp_521_point_to_ecc_point_9(ctx->point, pub); - } - break; - } - - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#ifdef HAVE_ECC_DHE -/* Write r as big endian to byte array. - * Fixed length number of bytes written: 66 - * - * r A single precision integer. - * a Byte array. - */ -static void sp_521_to_bin_9(sp_digit* r, byte* a) -{ - int i; - int j; - int s = 0; - int b; - - for (i=0; i<8; i++) { - r[i+1] += r[i] >> 58; - r[i] &= 0x3ffffffffffffffL; - } - j = 528 / 8 - 1; - a[j] = 0; - for (i=0; i<9 && j>=0; i++) { - b = 0; - /* lint allow cast of mismatch sp_digit and int */ - a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ - b += 8 - s; - if (j < 0) { - break; - } - while (b < 58) { - a[j--] = (byte)(r[i] >> b); - b += 8; - if (j < 0) { - break; - } - } - s = 8 - (b - 58); - if (j >= 0) { - a[j] = 0; - } - if (s != 0) { - j++; - } - } -} - -/* Multiply the point by the scalar and serialize the X ordinate. - * The number is 0 padded to maximum size on output. - * - * priv Scalar to multiply the point by. - * pub Point to multiply. - * out Buffer to hold X ordinate. - * outLen On entry, size of the buffer in bytes. - * On exit, length of data in buffer in bytes. - * heap Heap to use for allocation. - * 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_521(const mp_int* priv, const ecc_point* pub, byte* out, - word32* outLen, void* heap) -{ - SP_DECL_VAR(sp_point_521, point, 1); - SP_DECL_VAR(sp_digit, k, 9); - int err = MP_OKAY; - - if (*outLen < 65U) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 9, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(k, 9, priv); - sp_521_point_from_ecc_point_9(point, pub); - err = sp_521_ecc_mulmod_9(point, point, k, 1, 1, heap); - } - if (err == MP_OKAY) { - sp_521_to_bin_9(point->x, out); - *outLen = 66; - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sec_gen_521_ctx { - int state; - union { - sp_521_ecc_mulmod_9_ctx mulmod_ctx; - }; - sp_digit k[9]; - sp_point_521 point; -} sp_ecc_sec_gen_521_ctx; - -int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, - const ecc_point* pub, byte* out, word32* outLen, void* heap) -{ - int err = FP_WOULDBLOCK; - sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - if (*outLen < 32U) { - err = BUFFER_E; - } - - switch (ctx->state) { - case 0: - sp_521_from_mp(ctx->k, 9, priv); - sp_521_point_from_ecc_point_9(&ctx->point, pub); - ctx->state = 1; - break; - case 1: - err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &ctx->point, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - sp_521_to_bin_9(ctx->point.x, out); - *outLen = 66; - } - break; - } - - if (err == MP_OKAY && ctx->state != 1) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_DHE */ - -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -SP_NOINLINE static void sp_521_rshift_9(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<8; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (58 - n))) & 0x3ffffffffffffffL); - } -#else - for (i=0; i<8; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (58 - n)) & 0x3ffffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (58 - n)) & 0x3ffffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (58 - n)) & 0x3ffffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (58 - n)) & 0x3ffffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (58 - n)) & 0x3ffffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (58 - n)) & 0x3ffffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (58 - n)) & 0x3ffffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (58 - n)) & 0x3ffffffffffffffL); - } -#endif /* WOLFSSL_SP_SMALL */ - r[8] = a[8] >> n; -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* 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_521_mul_d_9(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 9; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x3ffffffffffffffL); - t >>= 58; - } - r[9] = (sp_digit)t; -#else - sp_int128 tb = b; - sp_int128 t[9]; - - t[ 0] = tb * a[ 0]; - t[ 1] = tb * a[ 1]; - t[ 2] = tb * a[ 2]; - t[ 3] = tb * a[ 3]; - t[ 4] = tb * a[ 4]; - t[ 5] = tb * a[ 5]; - t[ 6] = tb * a[ 6]; - t[ 7] = tb * a[ 7]; - t[ 8] = tb * a[ 8]; - r[ 0] = (sp_digit) (t[ 0] & 0x3ffffffffffffffL); - r[ 1] = (sp_digit)((t[ 0] >> 58) + (t[ 1] & 0x3ffffffffffffffL)); - r[ 2] = (sp_digit)((t[ 1] >> 58) + (t[ 2] & 0x3ffffffffffffffL)); - r[ 3] = (sp_digit)((t[ 2] >> 58) + (t[ 3] & 0x3ffffffffffffffL)); - r[ 4] = (sp_digit)((t[ 3] >> 58) + (t[ 4] & 0x3ffffffffffffffL)); - r[ 5] = (sp_digit)((t[ 4] >> 58) + (t[ 5] & 0x3ffffffffffffffL)); - r[ 6] = (sp_digit)((t[ 5] >> 58) + (t[ 6] & 0x3ffffffffffffffL)); - r[ 7] = (sp_digit)((t[ 6] >> 58) + (t[ 7] & 0x3ffffffffffffffL)); - r[ 8] = (sp_digit)((t[ 7] >> 58) + (t[ 8] & 0x3ffffffffffffffL)); - r[ 9] = (sp_digit) (t[ 8] >> 58); -#endif /* WOLFSSL_SP_SMALL */ -} - -SP_NOINLINE static void sp_521_lshift_18(sp_digit* r, const sp_digit* a, - byte n) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - r[18] = a[17] >> (58 - n); - for (i=17; i>0; i--) { - r[i] = (sp_digit)(((a[i] << n) | (a[i-1] >> (58 - n))) & 0x3ffffffffffffffL); - } -#else - sp_int_digit s; - sp_int_digit t; - - s = (sp_int_digit)a[17]; - r[18] = s >> (58U - n); - s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); - r[17] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); - r[16] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); - r[15] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); - r[14] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); - r[13] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); - r[12] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); - r[11] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); - r[10] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); - r[9] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); - r[8] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); - r[7] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); - r[6] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); - r[5] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); - r[4] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); - r[3] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); - r[2] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); - s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); - r[1] = (sp_digit)(((s << n) | (t >> (58U - n))) & 0x3ffffffffffffffUL); -#endif /* WOLFSSL_SP_SMALL */ - r[0] = (sp_digit)((a[0] << n) & 0x3ffffffffffffffL); -} - -/* 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. - * - * Simplified based on top word of divisor being (1 << 58) - 1 - * - * 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_521_div_9(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - SP_DECL_VAR(sp_digit, t1, 4 * 9 + 3); - int i; - sp_digit r1; - sp_digit mask; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 9 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 18 + 1; - sd = t2 + 9 + 1; - - sp_521_mul_d_9(sd, d, (sp_digit)1 << 1); - sp_521_lshift_18(t1, a, 1); - t1[9 + 9] += t1[9 + 9 - 1] >> 58; - t1[9 + 9 - 1] &= 0x3ffffffffffffffL; - for (i=8; i>=0; i--) { - r1 = t1[9 + i]; - sp_521_mul_d_9(t2, sd, r1); - (void)sp_521_sub_9(&t1[i], &t1[i], t2); - t1[9 + i] -= t2[9]; - sp_521_norm_9(&t1[i + 1]); - - mask = ~((t1[9 + i] - 1) >> 63); - sp_521_cond_sub_9(t1 + i, t1 + i, sd, mask); - sp_521_norm_9(&t1[i + 1]); - } - sp_521_norm_9(t1); - /* Correction: at loop i=0, sp_521_norm_9(&t1[1]) skips t1[0], so a - * borrow there is invisible to the correction mask that checks t1[9]. - * After the outer sp_521_norm_9(t1) the borrow lands in t1[8]. - * Add sd back when t1[8] is negative. */ - mask = (sp_digit)(t1[8] >> 63); - for (i = 0; i < 9; i++) - t1[i] += sd[i] & mask; - sp_521_norm_9(t1); - sp_521_rshift_9(r, t1, 1); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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_521_mod_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - return sp_521_div_9(a, m, NULL, r); -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply two number mod the order of P521 curve. (r = a * b mod order) - * - * r Result of the multiplication. - * a First operand of the multiplication. - * b Second operand of the multiplication. - */ -static void sp_521_mont_mul_order_9(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_521_mul_9(r, a, b); - sp_521_mont_reduce_order_9(r, p521_order, p521_mp_order); -} - -#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL)) -#ifdef WOLFSSL_SP_SMALL -/* Order-2 for the P521 curve. */ -static const word64 p521_order_minus_2[9] = { - 0xbb6fb71e91386407U,0x3bb5c9b8899c47aeU,0x7fcc0148f709a5d0U, - 0x51868783bf2f966bU,0xfffffffffffffffaU,0xffffffffffffffffU, - 0xffffffffffffffffU,0xffffffffffffffffU,0x00000000000001ffU -}; -#else -/* The low half of the order-2 of the P521 curve. */ -static const word64 p521_order_low[5] = { - 0xbb6fb71e91386407U,0x3bb5c9b8899c47aeU,0x7fcc0148f709a5d0U, - 0x51868783bf2f966bU,0xfffffffffffffffaU -}; -#endif /* WOLFSSL_SP_SMALL */ - -/* Square number mod the order of P521 curve. (r = a * a mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_521_mont_sqr_order_9(sp_digit* r, const sp_digit* a) -{ - sp_521_sqr_9(r, a); - sp_521_mont_reduce_order_9(r, p521_order, p521_mp_order); -} - -#ifndef WOLFSSL_SP_SMALL -/* Square number mod the order of P521 curve a number of times. - * (r = a ^ n mod order) - * - * r Result of the squaring. - * a Number to square. - */ -static void sp_521_mont_sqr_n_order_9(sp_digit* r, const sp_digit* a, int n) -{ - int i; - - sp_521_mont_sqr_order_9(r, a); - for (i=1; i= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: - XMEMCPY(t, a, sizeof(sp_digit) * 9); - ctx->i = 519; - ctx->state = 1; - break; - case 1: - sp_521_mont_sqr_order_9(t, t); - ctx->state = 2; - break; - case 2: - if ((p521_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { - sp_521_mont_mul_order_9(t, t, a); - } - ctx->i--; - ctx->state = (ctx->i >= 0) ? 1 : 3; - break; - case 3: - XMEMCPY(r, t, sizeof(sp_digit) * 9U); - err = MP_OKAY; - break; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -static void sp_521_mont_inv_order_9(sp_digit* r, const sp_digit* a, - sp_digit* td) -{ -#ifdef WOLFSSL_SP_SMALL - sp_digit* t = td; - int i; - - XMEMCPY(t, a, sizeof(sp_digit) * 9); - for (i=519; i>=0; i--) { - sp_521_mont_sqr_order_9(t, t); - if ((p521_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_521_mont_mul_order_9(t, t, a); - } - } - XMEMCPY(r, t, sizeof(sp_digit) * 9U); -#else - sp_digit* t = td; - sp_digit* t2 = td + 2 * 9; - sp_digit* t3 = td + 4 * 9; - int i; - - /* t = a^2 */ - sp_521_mont_sqr_order_9(t, a); - /* t = a^3 = t * a */ - sp_521_mont_mul_order_9(t, t, a); - /* t= a^c = t ^ 2 ^ 2 */ - sp_521_mont_sqr_n_order_9(t2, t, 2); - /* t = a^f = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - - /* t3 = a^1e */ - sp_521_mont_sqr_order_9(t3, t); - /* t3 = a^1f = t3 * a */ - sp_521_mont_mul_order_9(t3, t3, a); - - /* t2= a^f0 = t ^ 2 ^ 4 */ - sp_521_mont_sqr_n_order_9(t2, t, 4); - /* t = a^ff = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - /* t2= a^ff00 = t ^ 2 ^ 8 */ - sp_521_mont_sqr_n_order_9(t2, t, 8); - /* t3= a^ffff = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - /* t2= a^ffff0000 = t ^ 2 ^ 16 */ - sp_521_mont_sqr_n_order_9(t2, t, 16); - /* t = a^ffffffff = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - - /* t2= a^ffffffff00000000 = t ^ 2 ^ 32 */ - sp_521_mont_sqr_n_order_9(t2, t, 32); - /* t = a^ffffffffffffffff = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - /* t2= a^ffffffffffffffff0000000000000000 = t ^ 2 ^ 64 */ - sp_521_mont_sqr_n_order_9(t2, t, 64); - /* t = a^ffffffffffffffffffffffffffffffff = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - /* t2= a^ffffffffffffffffffffffffffffffff00000000000000000000000000000000 = t ^ 2 ^ 128 */ - sp_521_mont_sqr_n_order_9(t2, t, 128); - /* t = a^ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ - sp_521_mont_mul_order_9(t, t2, t); - - /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 */ - sp_521_mont_sqr_n_order_9(t2, t, 5); - /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t * t3 */ - sp_521_mont_mul_order_9(t2, t2, t3); - - for (i=259; i>=1; i--) { - sp_521_mont_sqr_order_9(t2, t2); - if ((p521_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { - sp_521_mont_mul_order_9(t2, t2, a); - } - } - sp_521_mont_sqr_order_9(t2, t2); - sp_521_mont_mul_order_9(r, t2, a); -#endif /* WOLFSSL_SP_SMALL */ -} - -#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */ -#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_521_calc_s_9(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; - sp_int64 c; - sp_digit* kInv = k; - - /* Conv k to Montgomery form (mod order) */ - sp_521_mul_9(k, k, p521_norm_order); - err = sp_521_mod_9(k, k, p521_order); - if (err == MP_OKAY) { - sp_521_norm_9(k); - - /* kInv = 1/k mod order */ - sp_521_mont_inv_order_9(kInv, k, tmp); - sp_521_norm_9(kInv); - - /* s = r * x + e */ - sp_521_mul_9(x, x, r); - err = sp_521_mod_9(x, x, p521_order); - } - if (err == MP_OKAY) { - sp_521_norm_9(x); - carry = sp_521_add_9(s, e, x); - sp_521_cond_sub_9(s, s, p521_order, 0 - carry); - sp_521_norm_9(s); - c = sp_521_cmp_9(s, p521_order); - sp_521_cond_sub_9(s, s, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(s); - - /* s = s * k^-1 mod order */ - sp_521_mont_mul_order_9(s, s, kInv); - sp_521_norm_9(s); - } - - return err; -} - -/* Sign the hash using the private key. - * e = [hash, 521 bits] from binary - * r = (k.G)->x mod order - * s = (r * x + e) / k mod order - * The hash is truncated to the first 521 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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. - */ -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ - SP_DECL_VAR(sp_digit, e, 7 * 2 * 9); - SP_DECL_VAR(sp_point_521, point, 1); - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, e, 7 * 2 * 9, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - x = e + 2 * 9; - k = e + 4 * 9; - r = e + 6 * 9; - tmp = e + 8 * 9; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_9(rng, k); - } - else { - sp_521_from_mp(k, 9, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); - sp_521_norm_9(r); - c = sp_521_cmp_9(r, p521_order); - sp_521_cond_sub_9(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(r); - - if (!sp_521_iszero_9(r)) { - /* x is modified in calculation of s. */ - sp_521_from_mp(x, 9, priv); - /* s ptr == e ptr, e is modified in calculation of s. */ - sp_521_from_bin(e, 9, hash, (int)hashLen); - - /* Take 521 leftmost bits of hash. */ - if (hashLen == 66U) { - sp_521_rshift_9(e, e, 7); - e[8] |= ((sp_digit)hash[0]) << 49; - } - - err = sp_521_calc_s_9(s, r, k, x, e, tmp); - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (!sp_521_iszero_9(s))) { - break; - } - } - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - - SP_ZEROFREE_VAR(sp_point_521, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_digit, e, 7 * 2 * 9, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_sign_521_ctx { - int state; - union { - sp_521_ecc_mulmod_9_ctx mulmod_ctx; - sp_521_mont_inv_order_9_ctx mont_inv_order_ctx; - }; - sp_digit e[2*9]; - sp_digit x[2*9]; - sp_digit k[2*9]; - sp_digit r[2*9]; - sp_digit tmp[3 * 2*9]; - sp_point_521 point; - sp_digit* s; - sp_digit* kInv; - int i; -} sp_ecc_sign_521_ctx; - -int sp_ecc_sign_521_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_521_ctx* ctx = (sp_ecc_sign_521_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - ctx->s = ctx->e; - ctx->kInv = ctx->k; - - ctx->i = SP_ECC_MAX_SIG_GEN; - ctx->state = 1; - break; - case 1: /* GEN */ - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_9(rng, ctx->k); - } - else { - sp_521_from_mp(ctx->k, 9, km); - mp_zero(km); - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 2; - break; - case 2: /* MULMOD */ - err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - &ctx->point, &p521_base, ctx->k, 1, 1, heap); - if (err == MP_OKAY) { - ctx->state = 3; - } - break; - case 3: /* MODORDER */ - { - sp_int64 c; - /* r = point->x mod order */ - XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 9U); - sp_521_norm_9(ctx->r); - c = sp_521_cmp_9(ctx->r, p521_order); - sp_521_cond_sub_9(ctx->r, ctx->r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(ctx->r); - - if (hashLen > 66U) { - hashLen = 66U; - } - sp_521_from_mp(ctx->x, 9, priv); - sp_521_from_bin(ctx->e, 9, hash, (int)hashLen); - if (hashLen == 66U) { - sp_521_rshift_9(ctx->e, ctx->e, 7); - ctx->e[8] |= ((sp_digit)hash[0]) << 49; - } - ctx->state = 4; - break; - } - case 4: /* KMODORDER */ - /* Conv k to Montgomery form (mod order) */ - sp_521_mul_9(ctx->k, ctx->k, p521_norm_order); - err = sp_521_mod_9(ctx->k, ctx->k, p521_order); - if (err == MP_OKAY) { - sp_521_norm_9(ctx->k); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 5; - } - break; - case 5: /* KINV */ - /* kInv = 1/k mod order */ - err = sp_521_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); - if (err == MP_OKAY) { - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 6; - } - break; - case 6: /* KINVNORM */ - sp_521_norm_9(ctx->kInv); - ctx->state = 7; - break; - case 7: /* R */ - /* s = r * x + e */ - sp_521_mul_9(ctx->x, ctx->x, ctx->r); - ctx->state = 8; - break; - case 8: /* S1 */ - err = sp_521_mod_9(ctx->x, ctx->x, p521_order); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* S2 */ - { - sp_digit carry; - sp_int64 c; - sp_521_norm_9(ctx->x); - carry = sp_521_add_9(ctx->s, ctx->e, ctx->x); - sp_521_cond_sub_9(ctx->s, ctx->s, - p521_order, 0 - carry); - sp_521_norm_9(ctx->s); - c = sp_521_cmp_9(ctx->s, p521_order); - sp_521_cond_sub_9(ctx->s, ctx->s, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(ctx->s); - - /* s = s * k^-1 mod order */ - sp_521_mont_mul_order_9(ctx->s, ctx->s, ctx->kInv); - sp_521_norm_9(ctx->s); - - /* Check that signature is usable. */ - if (sp_521_iszero_9(ctx->s) == 0) { - ctx->state = 10; - break; - } - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - ctx->i = 1; - #endif - - /* not usable gen, try again */ - ctx->i--; - if (ctx->i == 0) { - err = RNG_FAILURE_E; - } - ctx->state = 1; - break; - } - case 10: /* RES */ - err = sp_521_to_mp(ctx->r, rm); - if (err == MP_OKAY) { - err = sp_521_to_mp(ctx->s, sm); - } - break; - } - - if (err == MP_OKAY && ctx->state != 10) { - err = FP_WOULDBLOCK; - } - if (err != FP_WOULDBLOCK) { - XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 9U); - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_SIGN */ - -#ifndef WOLFSSL_SP_SMALL -static const char sp_521_tab64_9[64] = { - 64, 1, 59, 2, 60, 48, 54, 3, - 61, 40, 49, 28, 55, 34, 43, 4, - 62, 52, 38, 41, 50, 19, 29, 21, - 56, 31, 35, 12, 44, 15, 23, 5, - 63, 58, 47, 53, 39, 27, 33, 42, - 51, 37, 18, 20, 30, 11, 14, 22, - 57, 46, 26, 32, 36, 17, 10, 13, - 45, 25, 16, 9, 24, 8, 7, 6}; - -static int sp_521_num_bits_58_9(sp_digit v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - return sp_521_tab64_9[((word64)((v - (v >> 1))*0x07EDD5E59A4E28C2)) >> 58]; -} - -static int sp_521_num_bits_9(const sp_digit* a) -{ - int i; - int r = 0; - - for (i = 8; i >= 0; i--) { - if (a[i] != 0) { - r = sp_521_num_bits_58_9(a[i]); - r += i * 58; - break; - } - } - - return r; -} - -/* 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. - * @return MEMEORY_E when dynamic memory allocation fails. - */ -static int sp_521_mod_inv_9(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int err = MP_OKAY; - SP_DECL_VAR(sp_digit, u, 9 * 4); - sp_digit* v = NULL; - sp_digit* b = NULL; - sp_digit* d = NULL; - int ut; - int vt; - - SP_ALLOC_VAR(sp_digit, u, 9 * 4, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - v = u + 9; - b = u + 2 * 9; - d = u + 3 * 9; - - XMEMCPY(u, m, sizeof(sp_digit) * 9); - XMEMCPY(v, a, sizeof(sp_digit) * 9); - - ut = sp_521_num_bits_9(u); - vt = sp_521_num_bits_9(v); - - XMEMSET(b, 0, sizeof(sp_digit) * 9); - if ((v[0] & 1) == 0) { - sp_521_rshift1_9(v, v); - XMEMCPY(d, m, sizeof(sp_digit) * 9); - d[0]++; - sp_521_rshift1_9(d, d); - vt--; - - while ((v[0] & 1) == 0) { - sp_521_rshift1_9(v, v); - if (d[0] & 1) - sp_521_add_9(d, d, m); - sp_521_rshift1_9(d, d); - vt--; - } - } - else { - XMEMSET(d+1, 0, sizeof(sp_digit) * (9 - 1)); - d[0] = 1; - } - - while (ut > 1 && vt > 1) { - if ((ut > vt) || ((ut == vt) && - (sp_521_cmp_9(u, v) >= 0))) { - sp_521_sub_9(u, u, v); - sp_521_norm_9(u); - - sp_521_sub_9(b, b, d); - sp_521_norm_9(b); - if (b[8] < 0) - sp_521_add_9(b, b, m); - sp_521_norm_9(b); - ut = sp_521_num_bits_9(u); - - do { - sp_521_rshift1_9(u, u); - if (b[0] & 1) - sp_521_add_9(b, b, m); - sp_521_rshift1_9(b, b); - ut--; - } - while (ut > 0 && (u[0] & 1) == 0); - } - else { - sp_521_sub_9(v, v, u); - sp_521_norm_9(v); - - sp_521_sub_9(d, d, b); - sp_521_norm_9(d); - if (d[8] < 0) - sp_521_add_9(d, d, m); - sp_521_norm_9(d); - vt = sp_521_num_bits_9(v); - - do { - sp_521_rshift1_9(v, v); - if (d[0] & 1) - sp_521_add_9(d, d, m); - sp_521_rshift1_9(d, d); - vt--; - } - while (vt > 0 && (v[0] & 1) == 0); - } - } - - if (ut == 1) - XMEMCPY(r, b, sizeof(sp_digit) * 9); - else - XMEMCPY(r, d, sizeof(sp_digit) * 9); - } - SP_FREE_VAR(u, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -#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_521_add_points_9(sp_point_521* p1, const sp_point_521* p2, - sp_digit* tmp) -{ - - sp_521_proj_point_add_9(p1, p1, p2, tmp); - if (sp_521_iszero_9(p1->z)) { - if (sp_521_iszero_9(p1->x) && sp_521_iszero_9(p1->y)) { - sp_521_proj_point_dbl_9(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; - XMEMCPY(p1->z, p521_norm_mod, sizeof(p521_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 Temporary number. - * heap Heap to use for allocation. - * returns MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -static int sp_521_calc_vfy_point_9(sp_point_521* p1, sp_point_521* p2, - sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) -{ - int err; - -#ifndef WOLFSSL_SP_SMALL - err = sp_521_mod_inv_9(s, s, p521_order); - if (err == MP_OKAY) -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_521_mul_9(s, s, p521_norm_order); - err = sp_521_mod_9(s, s, p521_order); - } - if (err == MP_OKAY) { - sp_521_norm_9(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_521_mont_inv_order_9(s, s, tmp); - sp_521_mont_mul_order_9(u1, u1, s); - sp_521_mont_mul_order_9(u2, u2, s); - } -#else - { - sp_521_mont_mul_order_9(u1, u1, s); - sp_521_mont_mul_order_9(u2, u2, s); - } -#endif /* WOLFSSL_SP_SMALL */ - { - err = sp_521_ecc_mulmod_base_9(p1, u1, 0, 0, heap); - } - } - if ((err == MP_OKAY) && sp_521_iszero_9(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_9(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_521_iszero_9(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - sp_521_add_points_9(p1, p2, tmp); - } - - return err; -} - -#ifdef HAVE_ECC_VERIFY -/* Verify the signature values with the hash and public key. - * e = Truncate(hash, 521) - * u1 = e/s mod order - * u2 = r/s mod order - * r == (u1.G + u2.Q)->x mod order - * Optimization: Leave point in projective form. - * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') - * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' - * The hash is truncated to the first 521 bits. - * - * hash Hash to sign. - * hashLen Length of the hash data. - * rng Random number generator. - * priv Private part of key - scalar. - * 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 MEMORY_E when memory allocation fails and MP_OKAY on success. - */ -int sp_ecc_verify_521(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) -{ - SP_DECL_VAR(sp_digit, u1, 18 * 9); - SP_DECL_VAR(sp_point_521, p1, 2); - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, u1, 18 * 9, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p1, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - u2 = u1 + 2 * 9; - s = u1 + 4 * 9; - tmp = u1 + 6 * 9; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 9, hash, (int)hashLen); - sp_521_from_mp(u2, 9, rm); - sp_521_from_mp(s, 9, sm); - sp_521_from_mp(p2->x, 9, pX); - sp_521_from_mp(p2->y, 9, pY); - sp_521_from_mp(p2->z, 9, pZ); - - if (hashLen == 66U) { - sp_521_rshift_9(u1, u1, 7); - u1[8] |= ((sp_digit)hash[0]) << 49; - } - - err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 9, rm); - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 9, rm); - carry = sp_521_add_9(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_9(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_9(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_9(p1->x, u1) == 0); - } - } - } - - SP_FREE_VAR(p1, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(u1, heap, DYNAMIC_TYPE_ECC); - return err; -} - -#ifdef WOLFSSL_SP_NONBLOCK -typedef struct sp_ecc_verify_521_ctx { - int state; - union { - sp_521_ecc_mulmod_9_ctx mulmod_ctx; - sp_521_mont_inv_order_9_ctx mont_inv_order_ctx; - sp_521_proj_point_dbl_9_ctx dbl_ctx; - sp_521_proj_point_add_9_ctx add_ctx; - }; - sp_digit u1[2*9]; - sp_digit u2[2*9]; - sp_digit s[2*9]; - sp_digit tmp[2*9 * 6]; - sp_point_521 p1; - sp_point_521 p2; -} sp_ecc_verify_521_ctx; - -int sp_ecc_verify_521_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_521_ctx* ctx = (sp_ecc_verify_521_ctx*)sp_ctx->data; - - typedef char ctx_size_test[sizeof(sp_ecc_verify_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - switch (ctx->state) { - case 0: /* INIT */ - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(ctx->u1, 9, hash, (int)hashLen); - sp_521_from_mp(ctx->u2, 9, rm); - sp_521_from_mp(ctx->s, 9, sm); - sp_521_from_mp(ctx->p2.x, 9, pX); - sp_521_from_mp(ctx->p2.y, 9, pY); - sp_521_from_mp(ctx->p2.z, 9, pZ); - if (hashLen == 66U) { - sp_521_rshift_9(ctx->u1, ctx->u1, 7); - ctx->u1[8] |= ((sp_digit)hash[0]) << 49; - } - ctx->state = 1; - break; - case 1: /* NORMS0 */ - sp_521_mul_9(ctx->s, ctx->s, p521_norm_order); - err = sp_521_mod_9(ctx->s, ctx->s, p521_order); - if (err == MP_OKAY) - ctx->state = 2; - break; - case 2: /* NORMS1 */ - sp_521_norm_9(ctx->s); - XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); - ctx->state = 3; - break; - case 3: /* NORMS2 */ - err = sp_521_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 4; - } - break; - case 4: /* NORMS3 */ - sp_521_mont_mul_order_9(ctx->u1, ctx->u1, ctx->s); - ctx->state = 5; - break; - case 5: /* NORMS4 */ - sp_521_mont_mul_order_9(ctx->u2, ctx->u2, ctx->s); - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 6; - break; - case 6: /* MULBASE */ - err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p521_base, ctx->u1, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_521_iszero_9(ctx->p1.z)) { - ctx->p1.infinity = 1; - } - XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); - ctx->state = 7; - } - break; - case 7: /* MULMOD */ - err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap); - if (err == MP_OKAY) { - if (sp_521_iszero_9(ctx->p2.z)) { - ctx->p2.infinity = 1; - } - XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); - ctx->state = 8; - } - break; - case 8: /* ADD */ - err = sp_521_proj_point_add_9_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); - if (err == MP_OKAY) - ctx->state = 9; - break; - case 9: /* MONT */ - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(ctx->u2, 9, rm); - err = sp_521_mod_mul_norm_9(ctx->u2, ctx->u2, p521_mod); - if (err == MP_OKAY) - ctx->state = 10; - break; - case 10: /* SQR */ - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_9(ctx->p1.z, ctx->p1.z, p521_mod, p521_mp_mod); - ctx->state = 11; - break; - case 11: /* MUL */ - sp_521_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, p521_mp_mod); - ctx->state = 12; - break; - case 12: /* RES */ - { - sp_int64 c = 0; - err = MP_OKAY; /* math okay, now check result */ - *res = (int)(sp_521_cmp_9(ctx->p1.x, ctx->u1) == 0); - if (*res == 0) { - sp_digit carry; - - /* Reload r and add order. */ - sp_521_from_mp(ctx->u2, 9, rm); - carry = sp_521_add_9(ctx->u2, ctx->u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_9(ctx->u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_9(ctx->u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_9(ctx->u2, ctx->u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_521_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, - p521_mp_mod); - *res = (int)(sp_521_cmp_9(ctx->p1.x, ctx->u1) == 0); - } - } - break; - } - } /* switch */ - - if (err == MP_OKAY && ctx->state != 12) { - err = FP_WOULDBLOCK; - } - - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ -#endif /* HAVE_ECC_VERIFY */ - -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* Check that the x and y ordinates 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_521_ecc_is_point_9(const sp_point_521* point, - void* heap) -{ - SP_DECL_VAR(sp_digit, t1, 9 * 4); - sp_digit* t2 = NULL; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 9 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 9; - - /* y^2 - x^3 - a.x = b */ - sp_521_sqr_9(t1, point->y); - (void)sp_521_mod_9(t1, t1, p521_mod); - sp_521_sqr_9(t2, point->x); - (void)sp_521_mod_9(t2, t2, p521_mod); - sp_521_mul_9(t2, t2, point->x); - (void)sp_521_mod_9(t2, t2, p521_mod); - sp_521_mont_sub_9(t1, t1, t2, p521_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - sp_521_mont_add_9(t1, t1, point->x, p521_mod); - sp_521_mont_add_9(t1, t1, point->x, p521_mod); - sp_521_mont_add_9(t1, t1, point->x, p521_mod); - - - if (sp_521_cmp_9(t1, p521_b) != 0) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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_521(const mp_int* pX, const mp_int* pY) -{ - SP_DECL_VAR(sp_point_521, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_521, pub, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(pub->x, 9, pX); - sp_521_from_mp(pub->y, 9, pY); - sp_521_from_bin(pub->z, 9, one, (int)sizeof(one)); - - err = sp_521_ecc_is_point_9(pub, NULL); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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_521(const mp_int* pX, const mp_int* pY, - const mp_int* privm, void* heap) -{ - SP_DECL_VAR(sp_digit, priv, 9); - SP_DECL_VAR(sp_point_521, pub, 2); - sp_point_521* 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) > 521) || - (mp_count_bits(pY) > 521) || - ((privm != NULL) && (mp_count_bits(privm) > 521)))) { - err = ECC_OUT_OF_RANGE_E; - } - - SP_ALLOC_VAR(sp_digit, priv, 9, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, pub, 2, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - p = pub + 1; - - sp_521_from_mp(pub->x, 9, pX); - sp_521_from_mp(pub->y, 9, pY); - sp_521_from_bin(pub->z, 9, one, (int)sizeof(one)); - if (privm) - sp_521_from_mp(priv, 9, privm); - - /* Check point at infinitiy. */ - if ((sp_521_iszero_9(pub->x) != 0) && - (sp_521_iszero_9(pub->y) != 0)) { - err = ECC_INF_E; - } - } - - /* Check range of X and Y */ - if ((err == MP_OKAY) && - ((sp_521_cmp_9(pub->x, p521_mod) >= 0) || - (sp_521_cmp_9(pub->y, p521_mod) >= 0))) { - err = ECC_OUT_OF_RANGE_E; - } - - if (err == MP_OKAY) { - /* Check point is on curve */ - err = sp_521_ecc_is_point_9(pub, heap); - } - - if (err == MP_OKAY) { - /* Point * order = infinity */ - err = sp_521_ecc_mulmod_9(p, pub, p521_order, 1, 1, heap); - } - /* Check result is infinity */ - if ((err == MP_OKAY) && ((sp_521_iszero_9(p->x) == 0) || - (sp_521_iszero_9(p->y) == 0))) { - err = ECC_INF_E; - } - - if (privm) { - if (err == MP_OKAY) { - /* Base * private = point */ - err = sp_521_ecc_mulmod_base_9(p, priv, 1, 1, heap); - } - /* Check result is public key */ - if ((err == MP_OKAY) && - ((sp_521_cmp_9(p->x, pub->x) != 0) || - (sp_521_cmp_9(p->y, pub->y) != 0))) { - err = ECC_PRIV_KEY_E; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL -/* Add two projective EC points together. - * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) - * - * pX First EC point's X ordinate. - * pY First EC point's Y ordinate. - * pZ First EC point's Z ordinate. - * qX Second EC point's X ordinate. - * qY Second EC point's Y ordinate. - * qZ Second EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_proj_add_point_521(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) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 6); - SP_DECL_VAR(sp_point_521, p, 2); - sp_point_521* q = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 6, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p, 2, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - q = p + 1; - - sp_521_from_mp(p->x, 9, pX); - sp_521_from_mp(p->y, 9, pY); - sp_521_from_mp(p->z, 9, pZ); - sp_521_from_mp(q->x, 9, qX); - sp_521_from_mp(q->y, 9, qY); - sp_521_from_mp(q->z, 9, qZ); - p->infinity = sp_521_iszero_9(p->x) & - sp_521_iszero_9(p->y); - q->infinity = sp_521_iszero_9(q->x) & - sp_521_iszero_9(q->y); - - sp_521_proj_point_add_9(p, p, q, tmp); - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Double a projective EC point. - * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * rX Resultant EC point's X ordinate. - * rY Resultant EC point's Y ordinate. - * rZ Resultant EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_proj_dbl_point_521(mp_int* pX, mp_int* pY, mp_int* pZ, - mp_int* rX, mp_int* rY, mp_int* rZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 2); - SP_DECL_VAR(sp_point_521, p, 1); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(p->x, 9, pX); - sp_521_from_mp(p->y, 9, pY); - sp_521_from_mp(p->z, 9, pZ); - p->infinity = sp_521_iszero_9(p->x) & - sp_521_iszero_9(p->y); - - sp_521_proj_point_dbl_9(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(p->x, rX); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, rY); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, rZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Map a projective EC point to affine in place. - * pZ will be one. - * - * pX EC point's X ordinate. - * pY EC point's Y ordinate. - * pZ EC point's Z ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_map_521(mp_int* pX, mp_int* pY, mp_int* pZ) -{ - SP_DECL_VAR(sp_digit, tmp, 2 * 9 * 5); - SP_DECL_VAR(sp_point_521, p, 1); - int err = MP_OKAY; - - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 9 * 5, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_521, p, 1, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - sp_521_from_mp(p->x, 9, pX); - sp_521_from_mp(p->y, 9, pY); - sp_521_from_mp(p->z, 9, pZ); - p->infinity = sp_521_iszero_9(p->x) & - sp_521_iszero_9(p->y); - - sp_521_map_9(p, p, tmp); - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(p->x, pX); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->y, pY); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(p->z, pZ); - } - - SP_FREE_VAR(p, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifdef HAVE_COMP_KEY -/* Square root power for the P521 curve. */ -static const word64 p521_sqrt_power[9] = { - 0x0000000000000000,0x0000000000000000,0x0000000000000000, - 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000, - 0x0000000000000080 -}; - -/* Find the square root of a number mod the prime of the curve. - * - * y The number to operate on and the result. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -static int sp_521_mont_sqrt_9(sp_digit* y) -{ - SP_DECL_VAR(sp_digit, t, 2 * 9); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, t, 2 * 9, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - - { - int i; - - XMEMCPY(t, y, sizeof(sp_digit) * 9); - for (i=518; i>=0; i--) { - sp_521_mont_sqr_9(t, t, p521_mod, p521_mp_mod); - if (p521_sqrt_power[i / 64] & ((sp_digit)1 << (i % 64))) - sp_521_mont_mul_9(t, t, y, p521_mod, p521_mp_mod); - } - XMEMCPY(y, t, sizeof(sp_digit) * 9); - } - } - - SP_FREE_VAR(t, NULL, DYNAMIC_TYPE_ECC); - - return err; -} - - -/* Uncompress the point given the X ordinate. - * - * xm X ordinate. - * odd Whether the Y ordinate is odd. - * ym Calculated Y ordinate. - * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. - */ -int sp_ecc_uncompress_521(mp_int* xm, int odd, mp_int* ym) -{ - SP_DECL_VAR(sp_digit, x, 4 * 9); - sp_digit* y = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, x, 4 * 9, NULL, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - y = x + 2 * 9; - - sp_521_from_mp(x, 9, xm); - err = sp_521_mod_mul_norm_9(x, x, p521_mod); - } - if (err == MP_OKAY) { - /* y = x^3 */ - { - sp_521_mont_sqr_9(y, x, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(y, y, x, p521_mod, p521_mp_mod); - } - /* y = x^3 - 3x */ - sp_521_mont_sub_9(y, y, x, p521_mod); - sp_521_mont_sub_9(y, y, x, p521_mod); - sp_521_mont_sub_9(y, y, x, p521_mod); - /* y = x^3 - 3x + b */ - err = sp_521_mod_mul_norm_9(x, p521_b, p521_mod); - } - if (err == MP_OKAY) { - sp_521_mont_add_9(y, y, x, p521_mod); - /* y = sqrt(x^3 - 3x + b) */ - err = sp_521_mont_sqrt_9(y); - } - if (err == MP_OKAY) { - XMEMSET(y + 9, 0, 9U * sizeof(sp_digit)); - sp_521_mont_reduce_9(y, p521_mod, p521_mp_mod); - if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { - sp_521_mont_sub_9(y, p521_mod, y, p521_mod); - } - - err = sp_521_to_mp(y, ym); - } - - SP_FREE_VAR(x, NULL, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* WOLFSSL_SP_521 */ -#ifdef WOLFCRYPT_HAVE_SAKKE -#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) -{ - sp_int128 t0; - sp_int128 t1; - sp_digit t[9]; - - t0 = ((sp_int128)a[ 0]) * b[ 0]; - t1 = ((sp_int128)a[ 0]) * b[ 1] - + ((sp_int128)a[ 1]) * b[ 0]; - t[ 0] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 0]) * b[ 2] - + ((sp_int128)a[ 1]) * b[ 1] - + ((sp_int128)a[ 2]) * b[ 0]; - t[ 1] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 0]) * b[ 3] - + ((sp_int128)a[ 1]) * b[ 2] - + ((sp_int128)a[ 2]) * b[ 1] - + ((sp_int128)a[ 3]) * b[ 0]; - t[ 2] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 0]) * b[ 4] - + ((sp_int128)a[ 1]) * b[ 3] - + ((sp_int128)a[ 2]) * b[ 2] - + ((sp_int128)a[ 3]) * b[ 1] - + ((sp_int128)a[ 4]) * b[ 0]; - t[ 3] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 0]) * b[ 5] - + ((sp_int128)a[ 1]) * b[ 4] - + ((sp_int128)a[ 2]) * b[ 3] - + ((sp_int128)a[ 3]) * b[ 2] - + ((sp_int128)a[ 4]) * b[ 1] - + ((sp_int128)a[ 5]) * b[ 0]; - t[ 4] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 0]) * b[ 6] - + ((sp_int128)a[ 1]) * b[ 5] - + ((sp_int128)a[ 2]) * b[ 4] - + ((sp_int128)a[ 3]) * b[ 3] - + ((sp_int128)a[ 4]) * b[ 2] - + ((sp_int128)a[ 5]) * b[ 1] - + ((sp_int128)a[ 6]) * b[ 0]; - t[ 5] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 0]) * b[ 7] - + ((sp_int128)a[ 1]) * b[ 6] - + ((sp_int128)a[ 2]) * b[ 5] - + ((sp_int128)a[ 3]) * b[ 4] - + ((sp_int128)a[ 4]) * b[ 3] - + ((sp_int128)a[ 5]) * b[ 2] - + ((sp_int128)a[ 6]) * b[ 1] - + ((sp_int128)a[ 7]) * b[ 0]; - t[ 6] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 0]) * b[ 8] - + ((sp_int128)a[ 1]) * b[ 7] - + ((sp_int128)a[ 2]) * b[ 6] - + ((sp_int128)a[ 3]) * b[ 5] - + ((sp_int128)a[ 4]) * b[ 4] - + ((sp_int128)a[ 5]) * b[ 3] - + ((sp_int128)a[ 6]) * b[ 2] - + ((sp_int128)a[ 7]) * b[ 1] - + ((sp_int128)a[ 8]) * b[ 0]; - t[ 7] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 1]) * b[ 8] - + ((sp_int128)a[ 2]) * b[ 7] - + ((sp_int128)a[ 3]) * b[ 6] - + ((sp_int128)a[ 4]) * b[ 5] - + ((sp_int128)a[ 5]) * b[ 4] - + ((sp_int128)a[ 6]) * b[ 3] - + ((sp_int128)a[ 7]) * b[ 2] - + ((sp_int128)a[ 8]) * b[ 1]; - t[ 8] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 2]) * b[ 8] - + ((sp_int128)a[ 3]) * b[ 7] - + ((sp_int128)a[ 4]) * b[ 6] - + ((sp_int128)a[ 5]) * b[ 5] - + ((sp_int128)a[ 6]) * b[ 4] - + ((sp_int128)a[ 7]) * b[ 3] - + ((sp_int128)a[ 8]) * b[ 2]; - r[ 9] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 3]) * b[ 8] - + ((sp_int128)a[ 4]) * b[ 7] - + ((sp_int128)a[ 5]) * b[ 6] - + ((sp_int128)a[ 6]) * b[ 5] - + ((sp_int128)a[ 7]) * b[ 4] - + ((sp_int128)a[ 8]) * b[ 3]; - r[10] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 4]) * b[ 8] - + ((sp_int128)a[ 5]) * b[ 7] - + ((sp_int128)a[ 6]) * b[ 6] - + ((sp_int128)a[ 7]) * b[ 5] - + ((sp_int128)a[ 8]) * b[ 4]; - r[11] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 5]) * b[ 8] - + ((sp_int128)a[ 6]) * b[ 7] - + ((sp_int128)a[ 7]) * b[ 6] - + ((sp_int128)a[ 8]) * b[ 5]; - r[12] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 6]) * b[ 8] - + ((sp_int128)a[ 7]) * b[ 7] - + ((sp_int128)a[ 8]) * b[ 6]; - r[13] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = ((sp_int128)a[ 7]) * b[ 8] - + ((sp_int128)a[ 8]) * b[ 7]; - r[14] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 8]) * b[ 8]; - r[15] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - r[16] = (sp_digit)(t0 & 0x1ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 57); - XMEMCPY(r, t, sizeof(t)); -} - -/* 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) -{ - sp_int128 t0; - sp_int128 t1; - sp_digit t[9]; - - t0 = ((sp_int128)a[ 0]) * a[ 0]; - t1 = (((sp_int128)a[ 0]) * a[ 1]) * 2; - t[ 0] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 0]) * a[ 2]) * 2 - + ((sp_int128)a[ 1]) * a[ 1]; - t[ 1] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 0]) * a[ 3] - + ((sp_int128)a[ 1]) * a[ 2]) * 2; - t[ 2] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 0]) * a[ 4] - + ((sp_int128)a[ 1]) * a[ 3]) * 2 - + ((sp_int128)a[ 2]) * a[ 2]; - t[ 3] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 0]) * a[ 5] - + ((sp_int128)a[ 1]) * a[ 4] - + ((sp_int128)a[ 2]) * a[ 3]) * 2; - t[ 4] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 0]) * a[ 6] - + ((sp_int128)a[ 1]) * a[ 5] - + ((sp_int128)a[ 2]) * a[ 4]) * 2 - + ((sp_int128)a[ 3]) * a[ 3]; - t[ 5] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 0]) * a[ 7] - + ((sp_int128)a[ 1]) * a[ 6] - + ((sp_int128)a[ 2]) * a[ 5] - + ((sp_int128)a[ 3]) * a[ 4]) * 2; - t[ 6] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 0]) * a[ 8] - + ((sp_int128)a[ 1]) * a[ 7] - + ((sp_int128)a[ 2]) * a[ 6] - + ((sp_int128)a[ 3]) * a[ 5]) * 2 - + ((sp_int128)a[ 4]) * a[ 4]; - t[ 7] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 1]) * a[ 8] - + ((sp_int128)a[ 2]) * a[ 7] - + ((sp_int128)a[ 3]) * a[ 6] - + ((sp_int128)a[ 4]) * a[ 5]) * 2; - t[ 8] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 2]) * a[ 8] - + ((sp_int128)a[ 3]) * a[ 7] - + ((sp_int128)a[ 4]) * a[ 6]) * 2 - + ((sp_int128)a[ 5]) * a[ 5]; - r[ 9] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 3]) * a[ 8] - + ((sp_int128)a[ 4]) * a[ 7] - + ((sp_int128)a[ 5]) * a[ 6]) * 2; - r[10] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 4]) * a[ 8] - + ((sp_int128)a[ 5]) * a[ 7]) * 2 - + ((sp_int128)a[ 6]) * a[ 6]; - r[11] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 5]) * a[ 8] - + ((sp_int128)a[ 6]) * a[ 7]) * 2; - r[12] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = (((sp_int128)a[ 6]) * a[ 8]) * 2 - + ((sp_int128)a[ 7]) * a[ 7]; - r[13] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - t1 = (((sp_int128)a[ 7]) * a[ 8]) * 2; - r[14] = (sp_digit)(t0 & 0x1ffffffffffffffL); t1 += t0 >> 57; - t0 = ((sp_int128)a[ 8]) * a[ 8]; - r[15] = (sp_digit)(t1 & 0x1ffffffffffffffL); t0 += t1 >> 57; - r[16] = (sp_digit)(t0 & 0x1ffffffffffffffL); - r[17] = (sp_digit)(t0 >> 57); - XMEMCPY(r, t, sizeof(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. - */ -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 imax; - int k; - sp_uint128 c; - sp_uint128 lo; - - c = ((sp_uint128)a[17]) * b[17]; - r[35] = (sp_digit)(c >> 57); - c &= 0x1ffffffffffffffL; - for (k = 33; k >= 0; k--) { - if (k >= 18) { - i = k - 17; - imax = 17; - } - else { - i = 0; - imax = k; - } - lo = 0; - for (; i <= imax; i++) { - lo += ((sp_uint128)a[i]) * b[k - i]; - } - c += lo >> 57; - r[k + 2] += (sp_digit)(c >> 57); - r[k + 1] = (sp_digit)(c & 0x1ffffffffffffffL); - c = lo & 0x1ffffffffffffffL; - } - r[0] = (sp_digit)c; -} - -/* 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 imax; - int k; - sp_uint128 c; - sp_uint128 t; - - c = ((sp_uint128)a[17]) * a[17]; - r[35] = (sp_digit)(c >> 57); - c = (c & 0x1ffffffffffffffL) << 57; - for (k = 33; k >= 0; k--) { - i = (k + 1) / 2; - if ((k & 1) == 0) { - c += ((sp_uint128)a[i]) * a[i]; - i++; - } - if (k < 17) { - imax = k; - } - else { - imax = 17; - } - t = 0; - for (; i <= imax; i++) { - t += ((sp_uint128)a[i]) * a[k - i]; - } - c += t * 2; - - 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 Montgomery 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 Montgomery 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, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Y ordinate */ - { - 0x1573fd71bef16d7L,0x0dab83533ee6f3aL,0x156b56ed18dab6eL, - 0x0fd3973353017b5L,0x05a4d5f213515adL,0x0554c4a496cbcfeL, - 0x0bf82b1bc7a0059L,0x0d995ad2d6b6ecaL,0x170dae117ad547cL, - 0x0b67f8654f0195cL,0x06333e68502cb90L,0x0bcbe1bcabecd6bL, - 0x14654ec2b9e7f7fL,0x0f0a08bc7af534fL,0x0641a58f5de3608L, - 0x1426ba7d0402c05L,0x1f1f9f1f0533634L,0x0054124831fb004L, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* Z ordinate */ - { - 0x000000000000001L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - 0x000000000000000L,0x000000000000000L,0x000000000000000L, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, - (sp_digit)0, (sp_digit)0, (sp_digit)0 - }, - /* infinity */ - 0 -}; - -/* Normalize the values in each word to 57 bits. - * - * 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[17] += a[16] >> 57; a[16] &= 0x1ffffffffffffffL; -#endif /* WOLFSSL_SP_SMALL */ -} - -/* 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 - sp_int128 tb = b; - sp_int128 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 - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 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 */ -} - -/* 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_36(sp_digit* r, const sp_digit* a, - sp_digit b) -{ -#ifdef WOLFSSL_SP_SMALL - sp_int128 tb = b; - sp_int128 t = 0; - int i; - - for (i = 0; i < 36; i++) { - t += tb * a[i]; - r[i] = (sp_digit)(t & 0x1ffffffffffffffL); - t >>= 57; - } - r[36] = (sp_digit)t; -#else - sp_int128 tb = b; - sp_int128 t = 0; - sp_digit t2; - sp_int128 p[4]; - int i; - - for (i = 0; i < 36; 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; - } - r[36] = (sp_digit)(t & 0x1ffffffffffffffL); -#endif /* WOLFSSL_SP_SMALL */ -} - -#ifdef 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) -{ - int i; - - for (i = 0; i < 18; i++) { - r[i] = a[i] + (b[i] & m); - } -} -#endif /* WOLFSSL_SP_SMALL */ - -#ifndef 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) -{ - 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 /* WOLFSSL_SP_SMALL */ - -SP_NOINLINE static void sp_1024_rshift_18(sp_digit* r, const sp_digit* a, - byte n) -{ - int i; - -#ifdef WOLFSSL_SP_SMALL - for (i=0; i<17; i++) { - r[i] = (sp_digit)(((a[i] >> n) | (a[i + 1] << (57 - n))) & 0x1ffffffffffffffL); - } -#else - for (i=0; i<16; i += 8) { - r[i+0] = (a[i+0] >> n) | (sp_digit)((a[i+1] << (57 - n)) & 0x1ffffffffffffffL); - r[i+1] = (a[i+1] >> n) | (sp_digit)((a[i+2] << (57 - n)) & 0x1ffffffffffffffL); - r[i+2] = (a[i+2] >> n) | (sp_digit)((a[i+3] << (57 - n)) & 0x1ffffffffffffffL); - r[i+3] = (a[i+3] >> n) | (sp_digit)((a[i+4] << (57 - n)) & 0x1ffffffffffffffL); - r[i+4] = (a[i+4] >> n) | (sp_digit)((a[i+5] << (57 - n)) & 0x1ffffffffffffffL); - r[i+5] = (a[i+5] >> n) | (sp_digit)((a[i+6] << (57 - n)) & 0x1ffffffffffffffL); - r[i+6] = (a[i+6] >> n) | (sp_digit)((a[i+7] << (57 - n)) & 0x1ffffffffffffffL); - r[i+7] = (a[i+7] >> n) | (sp_digit)((a[i+8] << (57 - n)) & 0x1ffffffffffffffL); - } - r[16] = (a[16] >> n) | (sp_digit)((a[17] << (57 - n)) & 0x1ffffffffffffffL); -#endif /* WOLFSSL_SP_SMALL */ - r[17] = a[17] >> n; -} - -static WC_INLINE sp_digit sp_1024_div_word_18(sp_digit d1, sp_digit d0, - sp_digit div) -{ -#ifdef SP_USE_DIVTI3 - sp_int128 d = ((sp_int128)d1 << 57) + d0; - - return d / div; -#elif defined(__x86_64__) || defined(__i386__) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_uint64 lo = (sp_uint64)d; - sp_digit hi = (sp_digit)(d >> 64); - - __asm__ __volatile__ ( - "idiv %2" - : "+a" (lo) - : "d" (hi), "r" (div) - : "cc" - ); - - return (sp_digit)lo; -#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV) - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit dv = (div >> 1) + 1; - sp_digit t1 = (sp_digit)(d >> 57); - sp_digit t0 = (sp_digit)(d & 0x1ffffffffffffffL); - sp_digit t2; - sp_digit sign; - sp_digit r; - int i; - sp_int128 m; - - r = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - t1 -= dv & (0 - r); - for (i = 55; i >= 1; i--) { - t1 += t1 + (((sp_uint64)t0 >> 56) & 1); - t0 <<= 1; - t2 = (sp_digit)(((sp_uint64)(dv - t1)) >> 63); - r += r + t2; - t1 -= dv & (0 - t2); - t1 += t2; - } - r += r + 1; - - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 57); - m = d - ((sp_int128)r * div); - r += (sp_digit)(m >> 114) - (sp_digit)(d >> 114); - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - - m = d - ((sp_int128)r * div); - sign = (sp_digit)(0 - ((sp_uint64)m >> 63)) * 2 + 1; - m *= sign; - t2 = (sp_digit)(((sp_uint64)(div - m)) >> 63); - r += sign * t2; - return r; -#else - sp_int128 d = ((sp_int128)d1 << 57) + d0; - sp_digit r = 0; - sp_digit t; - sp_digit dv = (div >> 26) + 1; - - t = (sp_digit)(d >> 52); - t = (t / dv) << 26; - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)(d >> 21); - t = t / (dv << 5); - r += t; - d -= (sp_int128)t * div; - t = (sp_digit)d; - t = t / div; - r += t; - d -= (sp_int128)t * div; - return r; -#endif -} -static WC_INLINE sp_digit sp_1024_word_div_word_18(sp_digit d, sp_digit div) -{ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(SP_DIV_WORD_USE_DIV) - return d / div; -#else - return (sp_digit)((sp_uint64)(div - d) >> 63); -#endif -} -/* 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_1024_div_18(const sp_digit* a, const sp_digit* d, - const sp_digit* m, sp_digit* r) -{ - int i; - SP_DECL_VAR(sp_digit, t1, 4 * 18 + 3); - sp_digit dv; - sp_digit r1; - sp_digit* t2 = NULL; - sp_digit* sd = NULL; - int err = MP_OKAY; - - (void)m; - - SP_ALLOC_VAR(sp_digit, t1, 4 * 18 + 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (err == MP_OKAY) { - t2 = t1 + 36 + 1; - sd = t2 + 18 + 1; - - sp_1024_mul_d_18(sd, d, (sp_digit)1 << 2); - sp_1024_mul_d_36(t1, a, (sp_digit)1 << 2); - dv = sd[17]; - t1[18 + 18] += t1[18 + 18 - 1] >> 57; - t1[18 + 18 - 1] &= 0x1ffffffffffffffL; - for (i=18; i>=0; i--) { - r1 = sp_1024_div_word_18(t1[18 + i], t1[18 + i - 1], dv); - - sp_1024_mul_d_18(t2, sd, r1); - (void)sp_1024_sub_18(&t1[i], &t1[i], t2); - sp_1024_norm_18(&t1[i]); - t1[18 + i] -= t2[18]; - t1[18 + i] += t1[18 + i - 1] >> 57; - t1[18 + i - 1] &= 0x1ffffffffffffffL; - r1 = sp_1024_div_word_18(-t1[18 + i], -t1[18 + i - 1], dv); - r1 -= t1[18 + i]; - sp_1024_mul_d_18(t2, sd, 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 = sp_1024_word_div_word_18(t1[18 - 1], dv); - - sp_1024_mul_d_18(t2, sd, r1); - 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, sd, r[17] >> 63); - - sp_1024_norm_18(r); - sp_1024_rshift_18(r, r, 2); - } - - SP_FREE_VAR(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - 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 Montgomery 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - (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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) -/* 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - /* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else - /* Clear point data if requested. */ - if ((p != NULL) && clear) { - 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 i; - sp_digit j = (sp_digit)0 - (sp_digit)a->used; - int o = 0; - - for (i = 0; i < size; i++) { - sp_digit mask = (sp_digit)0 - (j >> 56); - r[i] = a->dp[o] & mask; - j++; - o += (int)(j >> 56); - } -#elif DIGIT_BIT > 57 - unsigned int i; - int j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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] = (sp_digit)0; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - unsigned int i; - int j = 0; - int s = 0; - - r[0] = 0; - for (i = 0; i < (unsigned int)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]) & ~(((sp_digit)0 - r) >> 56); - } -#else - int i; - - r |= (a[17] - b[17]) & (0 - (sp_digit)1); - r |= (a[16] - b[16]) & ~(((sp_digit)0 - r) >> 56); - for (i = 8; i >= 0; i -= 8) { - r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 56); - r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 56); - } -#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 - sp_int128 tb = b; - sp_int128 t[4]; - int i; - - t[0] = 0; - for (i = 0; i < 16; i += 4) { - t[0] += (tb * a[i+0]) + r[i+0]; - t[1] = (tb * a[i+1]) + r[i+1]; - t[2] = (tb * a[i+2]) + r[i+2]; - t[3] = (tb * a[i+3]) + r[i+3]; - r[i+0] = (sp_digit)(t[0] & 0x1ffffffffffffffL); - t[1] += t[0] >> 57; - r[i+1] = (sp_digit)(t[1] & 0x1ffffffffffffffL); - t[2] += t[1] >> 57; - r[i+2] = (sp_digit)(t[2] & 0x1ffffffffffffffL); - t[3] += t[2] >> 57; - r[i+3] = (sp_digit)(t[3] & 0x1ffffffffffffffL); - t[0] = t[3] >> 57; - } - t[0] += (tb * a[16]) + r[16]; - t[1] = (tb * a[17]) + r[17]; - r[16] = (sp_digit)(t[0] & 0x1ffffffffffffffL); - t[1] += t[0] >> 57; - r[17] = (sp_digit)(t[1] & 0x1ffffffffffffffL); - r[18] += (sp_digit)(t[1] >> 57); -#else - sp_int128 tb = b; - sp_int128 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 */ -} - -/* 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; - sp_uint64 n; - - n = a[17] >> 55; - for (i = 0; i < 17; i++) { - n += (sp_uint64)a[18 + i] << 2; - r[i] = (sp_digit)(n & 0x1ffffffffffffffL); - n >>= 57; - } - n += (sp_uint64)a[35] << 2; - r[17] = n; -#else - sp_uint64 n; - int i; - - n = (sp_uint64)a[17]; - n = n >> 55U; - for (i = 0; i < 16; i += 8) { - n += (sp_uint64)a[i+18] << 2U; r[i+0] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+19] << 2U; r[i+1] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+20] << 2U; r[i+2] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+21] << 2U; r[i+3] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+22] << 2U; r[i+4] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+23] << 2U; r[i+5] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+24] << 2U; r[i+6] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)a[i+25] << 2U; r[i+7] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - } - n += (sp_uint64)a[34] << 2U; r[16] = (sp_digit)(n & 0x1ffffffffffffffUL); n >>= 57U; - n += (sp_uint64)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_digit over; - - sp_1024_norm_18(a + 18); - - if (mp != 1) { - for (i=0; i<17; i++) { - mu = (sp_digit)((a[i] * mp) & 0x1ffffffffffffffL); - sp_1024_mul_add_18(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)((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 = (sp_digit)(a[i] & 0x1ffffffffffffffL); - sp_1024_mul_add_18(a+i, m, mu); - a[i+1] += a[i] >> 57; - } - mu = (sp_digit)(a[i] & 0x7fffffffffffffL); - sp_1024_mul_add_18(a+i, m, mu); - a[i+1] += a[i] >> 57; - a[i] &= 0x1ffffffffffffffL; - } - sp_1024_mont_shift_18(a, a); - over = a[17] - m[17]; - sp_1024_cond_sub_18(a, a, m, ~((over - 1) >> 63)); - sp_1024_norm_18(a); -} - -/* Multiply two Montgomery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montgomery form. - * b Second number to multiply in Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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 Montgomery form. - * m Modulus (prime). - * mp Montgomery multiplier. - */ -SP_NOINLINE 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 word8 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[32 * 2 * 18]; - int i; - int j; - sp_digit* table[32]; - - for (i = 0; i < 32; i++) { - table[i] = &td[2 * 18 * i]; - } - 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; - sp_int64 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(sp_digit) * 18U); - 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, (sp_digit)~(n >> 56)); - 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(sp_digit) * 18U); - 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, (sp_digit)~(n >> 56)); - sp_1024_norm_18(r->y); - - XMEMSET(r->z, 0, sizeof(r->z) / 2); - r->z[0] = 1; -} - -/* Add two Montgomery form numbers (r = a + b % m). - * - * r Result of addition. - * a First number to add in Montgomery form. - * b Second number to add in Montgomery 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) -{ - sp_digit over; - (void)sp_1024_add_18(r, a, b); - sp_1024_norm_18(r); - over = r[17] - m[17]; - sp_1024_cond_sub_18(r, r, m, ~((over - 1) >> 63)); - sp_1024_norm_18(r); -} - -/* Double a Montgomery form number (r = a + a % m). - * - * r Result of doubling. - * a Number to double in Montgomery form. - * m Modulus (prime). - */ -static void sp_1024_mont_dbl_18(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_1024_add_18(r, a, a); - sp_1024_norm_18(r); - over = r[17] - m[17]; - sp_1024_cond_sub_18(r, r, m, ~((over - 1) >> 63)); - sp_1024_norm_18(r); -} - -/* Triple a Montgomery form number (r = a + a + a % m). - * - * r Result of Tripling. - * a Number to triple in Montgomery form. - * m Modulus (prime). - */ -static void sp_1024_mont_tpl_18(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - sp_digit over; - (void)sp_1024_add_18(r, a, a); - sp_1024_norm_18(r); - over = r[17] - m[17]; - sp_1024_cond_sub_18(r, r, m, ~((over - 1) >> 63)); - sp_1024_norm_18(r); - (void)sp_1024_add_18(r, r, a); - sp_1024_norm_18(r); - over = r[17] - m[17]; - sp_1024_cond_sub_18(r, r, m, ~((over - 1) >> 63)); - sp_1024_norm_18(r); -} - -/* Subtract two Montgomery form numbers (r = a - b % m). - * - * r Result of subtration. - * a Number to subtract from in Montgomery form. - * b Number to subtract with in Montgomery form. - * m Modulus (prime). - */ -static void sp_1024_mont_sub_18(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m) -{ - (void)sp_1024_sub_18(r, a, b); - sp_1024_norm_18(r); - sp_1024_cond_add_18(r, r, m, r[17] >> 55); - sp_1024_norm_18(r); -} - -/* Shift number left one bit. - * Bottom bit is lost. - * - * r Result of shift. - * a Number to shift. - */ -SP_NOINLINE static void sp_1024_rshift1_18(sp_digit* r, const sp_digit* a) -{ -#ifdef WOLFSSL_SP_SMALL - int i; - - for (i=0; i<17; i++) { - r[i] = (a[i] >> 1) + (sp_digit)((a[i + 1] << 56) & 0x1ffffffffffffffL); - } -#else - r[0] = (a[0] >> 1) + (sp_digit)((a[1] << 56) & 0x1ffffffffffffffL); - r[1] = (a[1] >> 1) + (sp_digit)((a[2] << 56) & 0x1ffffffffffffffL); - r[2] = (a[2] >> 1) + (sp_digit)((a[3] << 56) & 0x1ffffffffffffffL); - r[3] = (a[3] >> 1) + (sp_digit)((a[4] << 56) & 0x1ffffffffffffffL); - r[4] = (a[4] >> 1) + (sp_digit)((a[5] << 56) & 0x1ffffffffffffffL); - r[5] = (a[5] >> 1) + (sp_digit)((a[6] << 56) & 0x1ffffffffffffffL); - r[6] = (a[6] >> 1) + (sp_digit)((a[7] << 56) & 0x1ffffffffffffffL); - r[7] = (a[7] >> 1) + (sp_digit)((a[8] << 56) & 0x1ffffffffffffffL); - r[8] = (a[8] >> 1) + (sp_digit)((a[9] << 56) & 0x1ffffffffffffffL); - r[9] = (a[9] >> 1) + (sp_digit)((a[10] << 56) & 0x1ffffffffffffffL); - r[10] = (a[10] >> 1) + (sp_digit)((a[11] << 56) & 0x1ffffffffffffffL); - r[11] = (a[11] >> 1) + (sp_digit)((a[12] << 56) & 0x1ffffffffffffffL); - r[12] = (a[12] >> 1) + (sp_digit)((a[13] << 56) & 0x1ffffffffffffffL); - r[13] = (a[13] >> 1) + (sp_digit)((a[14] << 56) & 0x1ffffffffffffffL); - r[14] = (a[14] >> 1) + (sp_digit)((a[15] << 56) & 0x1ffffffffffffffL); - r[15] = (a[15] >> 1) + (sp_digit)((a[16] << 56) & 0x1ffffffffffffffL); - r[16] = (a[16] >> 1) + (sp_digit)((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_mont_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. - */ -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_mont_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); -} - -#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; - -/* Double the Montgomery form projective point p. - * - * r Result of doubling point. - * p Point to double. - * t Temporary ordinate data. - */ -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_mont_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 */ -/* 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; -} - -/* 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; -} - - -/* Add two Montgomery form projective points. - * - * 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_18(sp_point_1024* r, - const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) -{ - sp_digit* t6 = t; - sp_digit* t1 = t + 2*18; - sp_digit* t2 = t + 4*18; - sp_digit* t3 = t + 6*18; - sp_digit* t4 = t + 8*18; - sp_digit* t5 = t + 10*18; - - /* 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, p->x, p1024_mod, p1024_mp_mod); - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_18(t2, p->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(t4, t2, p->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, p->y, p1024_mod, p1024_mp_mod); - /* S2 = Y2*Z1^3 */ - sp_1024_mont_mul_18(t4, t4, q->y, p1024_mod, p1024_mp_mod); - - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_1024_cmp_equal_18(t2, t1) & - sp_1024_cmp_equal_18(t4, t3)) { - sp_1024_proj_point_dbl_18(r, p, t); - } - else { - sp_digit* x = t6; - sp_digit* y = t1; - sp_digit* z = t2; - - /* 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); - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - 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); - /* Z3 = H*Z1*Z2 */ - sp_1024_mont_mul_18(z, p->z, t2, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(z, z, q->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_sqr_18(x, t4, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_18(x, x, t5, p1024_mod); - sp_1024_mont_mul_18(t5, t5, t3, p1024_mod, p1024_mp_mod); - sp_1024_mont_dbl_18(t3, y, p1024_mod); - sp_1024_mont_sub_18(x, x, t3, 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_sub_18(y, y, t5, p1024_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 18; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 18; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 18; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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* t6; - sp_digit* x; - sp_digit* y; - sp_digit* z; -} sp_1024_proj_point_add_18_ctx; - -/* Add two Montgomery form projective points. - * - * r Result of addition. - * p First point to add. - * q Second point to add. - * t Temporary ordinate data. - */ -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; - - typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_18_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; - (void)sizeof(ctx_size_test); - - /* Ensure only the first point is the same as the result. */ - if (q == r) { - const sp_point_1024* a = p; - p = q; - q = a; - } - - switch (ctx->state) { - case 0: /* INIT */ - ctx->t6 = t; - ctx->t1 = t + 2*18; - ctx->t2 = t + 4*18; - ctx->t3 = t + 6*18; - ctx->t4 = t + 8*18; - ctx->t5 = t + 10*18; - ctx->x = ctx->t6; - ctx->y = ctx->t1; - ctx->z = ctx->t2; - - ctx->state = 1; - break; - case 1: - /* U1 = X1*Z2^2 */ - sp_1024_mont_sqr_18(ctx->t1, q->z, p1024_mod, p1024_mp_mod); - ctx->state = 2; - break; - case 2: - sp_1024_mont_mul_18(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); - ctx->state = 3; - break; - case 3: - sp_1024_mont_mul_18(ctx->t1, ctx->t1, p->x, p1024_mod, p1024_mp_mod); - ctx->state = 4; - break; - case 4: - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_18(ctx->t2, p->z, p1024_mod, p1024_mp_mod); - ctx->state = 5; - break; - case 5: - sp_1024_mont_mul_18(ctx->t4, ctx->t2, p->z, p1024_mod, p1024_mp_mod); - ctx->state = 6; - break; - case 6: - sp_1024_mont_mul_18(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); - ctx->state = 7; - break; - case 7: - /* S1 = Y1*Z2^3 */ - sp_1024_mont_mul_18(ctx->t3, ctx->t3, p->y, p1024_mod, p1024_mp_mod); - ctx->state = 8; - break; - case 8: - /* S2 = Y2*Z1^3 */ - sp_1024_mont_mul_18(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); - ctx->state = 9; - break; - case 9: - /* Check double */ - if ((~p->infinity) & (~q->infinity) & - sp_1024_cmp_equal_18(ctx->t2, ctx->t1) & - sp_1024_cmp_equal_18(ctx->t4, ctx->t3)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - sp_1024_proj_point_dbl_18(r, p, t); - ctx->state = 25; - } - else { - ctx->state = 10; - } - break; - case 10: - /* H = U2 - U1 */ - sp_1024_mont_sub_18(ctx->t2, ctx->t2, ctx->t1, p1024_mod); - ctx->state = 11; - break; - case 11: - /* R = S2 - S1 */ - sp_1024_mont_sub_18(ctx->t4, ctx->t4, ctx->t3, p1024_mod); - ctx->state = 12; - break; - case 12: - /* X3 = R^2 - H^3 - 2*U1*H^2 */ - sp_1024_mont_sqr_18(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); - ctx->state = 13; - break; - case 13: - sp_1024_mont_mul_18(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); - ctx->state = 14; - break; - case 14: - sp_1024_mont_mul_18(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); - ctx->state = 15; - break; - case 15: - /* Z3 = H*Z1*Z2 */ - sp_1024_mont_mul_18(ctx->z, p->z, ctx->t2, p1024_mod, p1024_mp_mod); - ctx->state = 16; - break; - case 16: - sp_1024_mont_mul_18(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); - ctx->state = 17; - break; - case 17: - sp_1024_mont_sqr_18(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); - ctx->state = 18; - break; - case 18: - sp_1024_mont_sub_18(ctx->x, ctx->x, ctx->t5, p1024_mod); - ctx->state = 19; - break; - case 19: - sp_1024_mont_mul_18(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); - ctx->state = 20; - break; - case 20: - sp_1024_mont_dbl_18(ctx->t3, ctx->y, p1024_mod); - sp_1024_mont_sub_18(ctx->x, ctx->x, ctx->t3, p1024_mod); - ctx->state = 21; - break; - case 21: - /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_1024_mont_sub_18(ctx->y, ctx->y, ctx->x, p1024_mod); - ctx->state = 22; - break; - case 22: - sp_1024_mont_mul_18(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); - ctx->state = 23; - break; - case 23: - sp_1024_mont_sub_18(ctx->y, ctx->y, ctx->t5, p1024_mod); - ctx->state = 24; - break; - case 24: - { - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 18; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (ctx->x[i] & maskt); - } - for (i = 0; i < 18; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (ctx->y[i] & maskt); - } - for (i = 0; i < 18; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (ctx->z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - ctx->state = 25; - break; - } - case 25: - err = MP_OKAY; - break; - } - - if (err == MP_OKAY && ctx->state != 25) { - err = FP_WOULDBLOCK; - } - return err; -} -#endif /* WOLFSSL_SP_NONBLOCK */ - -#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. - */ -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) -{ - SP_DECL_VAR(sp_point_1024, t, 3); - SP_DECL_VAR(sp_digit, tmp, 2 * 18 * 37); - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - - SP_ALLOC_VAR(sp_point_1024, t, 3, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 18 * 37, heap, DYNAMIC_TYPE_ECC); - - 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)); - } - } - - SP_ZEROFREE_VAR(sp_digit, tmp, 2 * 18 * 37, heap, DYNAMIC_TYPE_ECC); - SP_ZEROFREE_VAR(sp_point_1024, t, 3, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -#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 * 37]; - 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 */ - -#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 i, - 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; - volatile int n = i - 1; - - 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); - /* B = 2.(B - X) */ - sp_1024_mont_sub_18(t2, b, x, p1024_mod); - sp_1024_mont_dbl_18(b, t2, p1024_mod); - /* Z = Z*Y */ - sp_1024_mont_mul_18(z, z, y, p1024_mod, p1024_mp_mod); - /* t1 = 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_mul_18(y, b, a, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_18(y, y, t1, p1024_mod); - n = n - 1; - } -#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); - /* B = 2.(B - X) */ - sp_1024_mont_sub_18(t2, b, x, p1024_mod); - sp_1024_mont_dbl_18(b, t2, p1024_mod); - /* Z = Z*Y */ - sp_1024_mont_mul_18(z, z, y, p1024_mod, p1024_mp_mod); - /* t1 = Y^4 */ - sp_1024_mont_sqr_18(t1, t1, p1024_mod, p1024_mp_mod); - /* y = 2*A*(B - X) - Y^4 */ - sp_1024_mont_mul_18(y, b, a, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_18(y, y, t1, p1024_mod); -#endif /* WOLFSSL_SP_SMALL */ - /* Y = Y/2 */ - sp_1024_mont_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(t1, y, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(b, t1, 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(t2, b, p1024_mod); - sp_1024_mont_sub_18(x, x, t2, p1024_mod); - /* B = 2.(B - X) */ - sp_1024_mont_sub_18(t2, b, x, p1024_mod); - sp_1024_mont_dbl_18(b, t2, p1024_mod); - /* Z = Z*Y */ - sp_1024_mont_mul_18(r[j].z, z, y, p1024_mod, p1024_mp_mod); - z = r[j].z; - /* t1 = Y^4 */ - sp_1024_mont_sqr_18(t1, t1, p1024_mod, p1024_mp_mod); - if (i != n) { - /* 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_mul_18(y, b, a, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_18(y, y, t1, p1024_mod); - /* Y = Y/2 */ - sp_1024_mont_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* xa = ra->x; - sp_digit* ya = ra->y; - sp_digit* za = ra->z; - sp_digit* xs = rs->x; - sp_digit* ys = rs->y; - sp_digit* zs = rs->z; - - - XMEMCPY(xa, p->x, sizeof(p->x) / 2); - XMEMCPY(ya, p->y, sizeof(p->y) / 2); - XMEMCPY(za, 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, xa, p1024_mod, p1024_mp_mod); - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_18(t2, za, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(t4, t2, za, 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, ya, 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(za, za, q->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(za, za, t2, p1024_mod, p1024_mp_mod); - XMEMCPY(zs, za, 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(xa, 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(ya, 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(xa, xa, t5, p1024_mod); - sp_1024_mont_sub_18(xs, xs, t5, p1024_mod); - sp_1024_mont_dbl_18(t1, ya, p1024_mod); - sp_1024_mont_sub_18(xa, xa, 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, ya, xs, p1024_mod); - sp_1024_mont_sub_18(ya, ya, xa, p1024_mod); - sp_1024_mont_mul_18(ya, ya, 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(ya, ya, 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. */ - word8 i; - /* Use the negative of the point. */ - word8 neg; -} ecc_recode_1024; - -/* The index into pre-computation table to use. */ -static const word8 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 word8 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; - word8 y; - int carry = 0; - int o; - sp_digit n; - - j = 0; - n = k[j]; - o = 0; - for (i=0; i<147; i++) { - y = (word8)(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 |= (word8)((n << (57 - o)) & 0x7f); - o -= 50; - n >>= o; - } - - y = (word8)(y + 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) -{ - SP_DECL_VAR(sp_point_1024, t, 65+2); - SP_DECL_VAR(sp_digit, tmp, 2 * 18 * 37); - 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; - - SP_ALLOC_VAR(sp_point_1024, t, 65+2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, tmp, 2 * 18 * 37, heap, DYNAMIC_TYPE_ECC); - 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)); - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - - 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) -{ - sp_digit* t2 = t; - sp_digit* t3 = t + 2*18; - sp_digit* t6 = t + 4*18; - sp_digit* t1 = t + 6*18; - sp_digit* t4 = t + 8*18; - sp_digit* t5 = t + 10*18; - - /* Calculate values to subtract from P->x and P->y. */ - /* U2 = X2*Z1^2 */ - sp_1024_mont_sqr_18(t2, p->z, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(t4, t2, p->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); - - if ((~p->infinity) & (~q->infinity) & - sp_1024_cmp_equal_18(p->x, t2) & - sp_1024_cmp_equal_18(p->y, t4)) { - sp_1024_proj_point_dbl_18(r, p, t); - } - else { - sp_digit* x = t2; - sp_digit* y = t3; - sp_digit* z = t6; - - /* H = U2 - X1 */ - sp_1024_mont_sub_18(t2, t2, p->x, p1024_mod); - /* R = S2 - Y1 */ - sp_1024_mont_sub_18(t4, t4, p->y, p1024_mod); - /* Z3 = H*Z1 */ - sp_1024_mont_mul_18(z, p->z, t2, p1024_mod, p1024_mp_mod); - /* X3 = R^2 - H^3 - 2*X1*H^2 */ - sp_1024_mont_sqr_18(t1, t2, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(t3, p->x, t1, p1024_mod, p1024_mp_mod); - sp_1024_mont_mul_18(t1, t1, t2, p1024_mod, p1024_mp_mod); - sp_1024_mont_sqr_18(t2, t4, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_18(t2, t2, t1, p1024_mod); - sp_1024_mont_dbl_18(t5, t3, p1024_mod); - sp_1024_mont_sub_18(x, t2, t5, 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(t1, t1, p->y, p1024_mod, p1024_mp_mod); - sp_1024_mont_sub_18(y, t3, t1, p1024_mod); - { - int i; - sp_digit maskp = (sp_digit)(0 - (q->infinity & (!p->infinity))); - sp_digit maskq = (sp_digit)(0 - (p->infinity & (!q->infinity))); - sp_digit maskt = ~(maskp | maskq); - sp_digit inf = (sp_digit)(p->infinity & q->infinity); - - for (i = 0; i < 18; i++) { - r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | - (x[i] & maskt); - } - for (i = 0; i < 18; i++) { - r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | - (y[i] & maskt); - } - for (i = 0; i < 18; i++) { - r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | - (z[i] & maskt); - } - r->z[0] |= inf; - r->infinity = (int)inf; - } - } -} - -#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) -{ - SP_DECL_VAR(sp_point_1024, t, 3); - sp_point_1024* s1 = NULL; - sp_point_1024* s2 = NULL; - int i; - int j; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_point_1024, t, 3, heap, DYNAMIC_TYPE_ECC); - 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)); - } - } - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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) -{ - SP_DECL_VAR(sp_point_1024, rt, 2); - SP_DECL_VAR(sp_digit, t, 2 * 18 * 37); - 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; - - - SP_ALLOC_VAR(sp_point_1024, rt, 2, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 2 * 18 * 37, heap, DYNAMIC_TYPE_ECC); - 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)); - } - } - - SP_FREE_VAR(rt, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - - 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. */ - word32 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 - #ifndef WOLFSSL_MUTEX_INITIALIZER - static volatile int initCacheMutex_1024 = 0; - #endif - static wolfSSL_Mutex sp_cache_1024_lock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(sp_cache_1024_lock); -#endif - -/* Get the cache entry for the point. - * - * g [in] Point scalar multiplying. - * 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; - word32 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_DECL_VAR(sp_digit, tmp, 2 * 18 * 38); - sp_cache_1024_t* cache; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_digit, tmp, 2 * 18 * 38, heap, DYNAMIC_TYPE_ECC); -#ifndef HAVE_THREAD_LS - if (err == MP_OKAY) { - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (initCacheMutex_1024 == 0) { - wc_InitMutex(&sp_cache_1024_lock); - initCacheMutex_1024 = 1; - } - #endif - 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); - } - } - - SP_FREE_VAR(tmp, heap, DYNAMIC_TYPE_ECC); - 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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, k, 18); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 18, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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); -} - -#ifdef WOLFSSL_SP_NONBLOCK -static int sp_1024_ecc_mulmod_base_18_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, - const sp_digit* k, int map, int ct, void* heap) -{ - /* No pre-computed values. */ - return sp_1024_ecc_mulmod_18_nb(sp_ctx, r, &p1024_base, k, map, ct, heap); -} -#endif /* WOLFSSL_SP_NONBLOCK */ - - -#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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, k, 18); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 18, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 multiply result. - * inMont Point to add is in montgomery 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) -{ - SP_DECL_VAR(sp_point_1024, point, 2); - SP_DECL_VAR(sp_digit, k, 18 + 18 * 2 * 37); - sp_point_1024* addP = NULL; - sp_digit* tmp = NULL; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 2, NULL, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 18 + 18 * 2 * 37, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(k, NULL, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, NULL, DYNAMIC_TYPE_ECC); - - 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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, t, 38 * 2 * 18); - 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 = WC_NO_ERR_TRACE(LENGTH_ONLY_E); - } - if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { - err = BUFFER_E; - } - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, t, 38 * 2 * 18, heap, DYNAMIC_TYPE_ECC); - 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; - } - - SP_FREE_VAR(t, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - - 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 = WC_NO_ERR_TRACE(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) -{ - SP_DECL_VAR(sp_point_1024, point, 1); - SP_DECL_VAR(sp_digit, k, 18); - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, point, 1, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_digit, k, 18, heap, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(point, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(k, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Multiply p* in projective coordinates 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 coordinates. - * - * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td; - sp_digit* t; - sp_digit* tx; - sp_digit* ty; - sp_digit* b; - sp_digit* e; -#else - sp_digit t[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 40 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - tx = td + 36 * 18 * 2; - ty = td + 37 * 18 * 2; - b = td + 38 * 18 * 2; - e = td + 39 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td; - sp_digit* t; - sp_digit* tx; - sp_digit* ty; -#else - sp_digit t[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 38 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - tx = td + 36 * 18 * 2; - ty = td + 37 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return err; -} - -#endif /* WOLFSSL_SP_SMALL */ -/* Multiply p* by q* in projective coordinates. - * - * 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_mont_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_mont_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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td = NULL; - sp_digit* t; - sp_digit* vx; - sp_digit* vy; - sp_digit* qx_px; -#else - sp_digit t[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - vx = td + 36 * 18 * 2; - vy = td + 37 * 18 * 2; - qx_px = td + 38 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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_mont_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_mont_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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - vx = td + 36 * 18 * 2; - vy = td + 37 * 18 * 2; - pre_vx = (sp_digit(*)[36])(td + 38 * 18 * 2); - pre_vy = (sp_digit(*)[36])(td + 54 * 18 * 2); - pre_nvy = (sp_digit(*)[36])(td + 70 * 18 * 2); - pre_p = (sp_point_1024*)(td + 86 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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 = WC_NO_ERR_TRACE(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 + 33 * 2 * 18; - sp_digit* t2 = t + 34 * 2 * 18; - sp_digit* l = t + 35 * 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 + 33 * 2 * 18; - sp_digit* c = t + 34 * 2 * 18; - sp_digit* l = t + 35 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - sp_digit* td = NULL; - sp_digit* t; - sp_point_1024* pre_p; -#else - sp_digit t[36 * 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 = WC_NO_ERR_TRACE(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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - pre_p = (sp_point_1024*)(td + 36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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[36 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - if (err == MP_OKAY) { - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - t = td; - vx = td + 36 * 18 * 2; - vy = td + 37 * 18 * 2; - pre_vx = (sp_digit(*)[36])(td + 38 * 18 * 2); - pre_vy = (sp_digit(*)[36])(td + 54 * 18 * 2); - pre_nvy = (sp_digit(*)[36])(td + 70 * 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_SP_NO_MALLOC)) || \ - defined(WOLFSSL_SP_SMALL_STACK) - 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 */ -#if defined(HAVE_ECC_CHECK_KEY) || !defined(NO_ECC_CHECK_PUBKEY_ORDER) -/* 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 ordinates 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) -{ - SP_DECL_VAR(sp_digit, t1, 18 * 4); - sp_digit* t2 = NULL; - sp_int64 n; - int err = MP_OKAY; - - (void)heap; - - SP_ALLOC_VAR(sp_digit, t1, 18 * 4, heap, DYNAMIC_TYPE_ECC); - if (err == MP_OKAY) { - t2 = t1 + 2 * 18; - - /* y^2 - x^3 - a.x = b */ - 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); - sp_1024_mont_sub_18(t1, t1, t2, p1024_mod); - - /* y^2 - x^3 + 3.x = b, when a = -3 */ - 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, (sp_digit)~(n >> 56)); - sp_1024_norm_18(t1); - if (!sp_1024_iszero_18(t1)) { - err = MP_VAL; - } - } - - SP_FREE_VAR(t1, heap, DYNAMIC_TYPE_ECC); - - return err; -} - -/* Check that the x and y ordinates 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) -{ - SP_DECL_VAR(sp_point_1024, pub, 1); - const byte one[1] = { 1 }; - int err = MP_OKAY; - - SP_ALLOC_VAR(sp_point_1024, pub, 1, NULL, DYNAMIC_TYPE_ECC); - 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); - } - - SP_FREE_VAR(pub, NULL, DYNAMIC_TYPE_ECC); - - 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) -{ - SP_DECL_VAR(sp_digit, priv, 18); - SP_DECL_VAR(sp_point_1024, pub, 2); - 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; - } - - SP_ALLOC_VAR(sp_digit, priv, 18, heap, DYNAMIC_TYPE_ECC); - SP_ALLOC_VAR(sp_point_1024, pub, 2, heap, DYNAMIC_TYPE_ECC); - 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; - } - } - - SP_FREE_VAR(pub, heap, DYNAMIC_TYPE_ECC); - SP_FREE_VAR(priv, heap, DYNAMIC_TYPE_ECC); - - return err; -} -#endif -#endif /* WOLFSSL_SP_1024 */ -#endif /* WOLFCRYPT_HAVE_SAKKE */ -#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 */ diff --git a/wolfssl-src/src/lib.rs b/wolfssl-src/src/lib.rs index 74e5b5a..17cf2f8 100644 --- a/wolfssl-src/src/lib.rs +++ b/wolfssl-src/src/lib.rs @@ -16,8 +16,7 @@ //! The builder discovers wolfSSL sources in order: //! 1. `source_dir()` programmatic override //! 2. `WOLFSSL_SRC` environment variable -//! 3. Bundled submodule at `wolfssl-src/wolfssl/` (present after `git submodule update --init`) -//! 4. `pkg-config` (looks for a `wolfssl` package whose prefix contains source files) +//! 3. `pkg-config` (looks for a `wolfssl` package whose prefix contains source files) use std::collections::HashSet; use std::env; @@ -53,7 +52,7 @@ impl Build { } /// Set the path to the wolfSSL source tree. - /// If not set, defaults to `WOLFSSL_SRC` env var, then the bundled submodule, then `pkg-config`. + /// If not set, defaults to `WOLFSSL_SRC` env var, then `pkg-config`. pub fn source_dir(&mut self, dir: PathBuf) -> &mut Self { self.source_dir = Some(dir); self @@ -70,13 +69,8 @@ impl Build { let wolfssl_dir = self.resolve_source_dir(); let settings_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - // Select user_settings header based on active feature. - // Priority: cryptocb-pure > cryptocb-only > riscv-bare-metal > default. - let user_settings_name = if cfg!(feature = "cryptocb-pure") { - "user_settings_cryptocb_pure.h" - } else if cfg!(feature = "cryptocb-only") { - "user_settings_cryptocb_only.h" - } else if cfg!(feature = "riscv-bare-metal") { + // Select user_settings header based on target + let user_settings_name = if cfg!(feature = "riscv-bare-metal") { "user_settings_riscv.h" } else { "user_settings.h" @@ -99,32 +93,15 @@ impl Build { let wolfcrypt_src = wolfssl_dir.join("wolfcrypt").join("src"); let ssl_src = wolfssl_dir.join("src"); - let mut wolfcrypt_sources: Vec<&str> = if cfg!(feature = "cryptocb-pure") { - CRYPTOCB_PURE_CORE_SOURCES.to_vec() - } else if cfg!(feature = "cryptocb-only") { - CRYPTOCB_ONLY_CORE_SOURCES.to_vec() - } else { - CORE_WOLFCRYPT_SOURCES.to_vec() - }; + let mut wolfcrypt_sources: Vec<&str> = CORE_WOLFCRYPT_SOURCES.to_vec(); if self.fips { wolfcrypt_sources.extend_from_slice(FIPS_WOLFCRYPT_SOURCES); } - if cfg!(feature = "cryptocb-pure") { - append_cryptocb_pure_sources(&defines, &mut wolfcrypt_sources); - } else if cfg!(feature = "cryptocb-only") { - append_cryptocb_only_sources(&defines, &mut wolfcrypt_sources); - } else { - append_conditional_wolfcrypt_sources(&defines, &mut wolfcrypt_sources); - } - // cryptocb-only and cryptocb-pure: no SSL layer (no OPENSSL_EXTRA). - // riscv-bare-metal: also no SSL layer (bare-metal builds are cryptocb-based). - // Full builds: compile all ssl/ sources. - let ssl_srcs: &[&str] = if cfg!(any( - feature = "cryptocb-pure", - feature = "cryptocb-only", - feature = "riscv-bare-metal", - )) { - &[] + append_conditional_wolfcrypt_sources(&defines, &mut wolfcrypt_sources); + // For riscv-bare-metal, compile ssl.c only (it includes pk.c, pk_ec.c, + // ssl_bn.c, etc. internally as one compilation unit). + let ssl_srcs: &[&str] = if cfg!(feature = "riscv-bare-metal") { + &["ssl.c"] } else { ssl_sources(&defines) }; @@ -133,32 +110,23 @@ impl Build { let mut build = cc::Build::new(); build.include(&wolfssl_dir); - // For bare-metal features, shadow the default user_settings.h with the - // selected header so wolfSSL picks it up via -I ordering. - // Priority: cryptocb-pure > cryptocb-only > riscv-bare-metal. - if cfg!(any(feature = "riscv-bare-metal", feature = "cryptocb-only", feature = "cryptocb-pure")) { + // For riscv-bare-metal, place a copy of user_settings_riscv.h as + // user_settings.h in OUT_DIR so it shadows the default. + if cfg!(feature = "riscv-bare-metal") { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let src_name = if cfg!(feature = "cryptocb-pure") { - "user_settings_cryptocb_pure.h" - } else if cfg!(feature = "cryptocb-only") { - "user_settings_cryptocb_only.h" - } else { - "user_settings_riscv.h" - }; - let src = settings_dir.join(src_name); - let dst = out_dir.join("user_settings.h"); - std::fs::copy(&src, &dst) - .unwrap_or_else(|e| panic!("failed to copy {src_name}: {e}")); - // OUT_DIR comes first so its user_settings.h takes precedence. + let riscv_src = settings_dir.join("user_settings_riscv.h"); + let riscv_dst = out_dir.join("user_settings.h"); + std::fs::copy(&riscv_src, &riscv_dst) + .expect("failed to copy user_settings_riscv.h"); + // OUT_DIR comes first so its user_settings.h takes precedence build.include(&out_dir); - // Add bare-metal stub headers (stdio.h, etc.) if available. + // Add bare-metal stub headers (stdio.h, etc.) if available if let Ok(stubs) = env::var("WOLFSSL_BARE_METAL_STUBS") { build.include(stubs); } - // Compile bare-metal helper functions (string stubs used by both - // user_settings_riscv.h and user_settings_cryptocb_only.h). + // Compile bare-metal helper functions let helpers = settings_dir.join("riscv_bare_metal_helpers.c"); if helpers.exists() { build.file(&helpers); @@ -172,21 +140,11 @@ impl Build { build.define("HAVE_FIPS", None); } - // Patch overlay: prefer files in `patches/` over the upstream source. - // This carries local fixes (e.g. sp_521_div_9 quotient-correction) without - // modifying the upstream wolfSSL tree. - let patches_dir = settings_dir.join("patches"); for src in &wolfcrypt_sources { - let patched = patches_dir.join(src); - let path = if patched.exists() { - patched - } else { - let upstream = wolfcrypt_src.join(src); - if !upstream.exists() { - panic!("required wolfcrypt source not found: {}", upstream.display()); - } - upstream - }; + let path = wolfcrypt_src.join(src); + if !path.exists() { + panic!("required wolfcrypt source not found: {}", path.display()); + } build.file(&path); println!("cargo:rerun-if-changed={}", path.display()); } @@ -204,7 +162,6 @@ impl Build { build.compile("wolfssl"); println!("cargo:rerun-if-changed={}", user_settings_path.display()); - println!("cargo:rerun-if-changed={}", patches_dir.display()); if self.fips { println!("cargo:rerun-if-changed={}", settings_dir.join("user_settings_fips.h").display()); } @@ -228,31 +185,23 @@ impl Build { // 2. WOLFSSL_SRC env var if let Ok(dir) = env::var("WOLFSSL_SRC") { - if !dir.is_empty() { - let path = PathBuf::from(&dir); - if !path.exists() { - panic!("WOLFSSL_SRC={dir} does not exist"); - } - return path; + let path = PathBuf::from(&dir); + if !path.exists() { + panic!("WOLFSSL_SRC={dir} does not exist"); } + return path; } - // 3. Bundled submodule (wolfssl-src/wolfssl/ inside this crate) - let bundled = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("wolfssl"); - if bundled.join("wolfcrypt/src").exists() { - return bundled; - } - - // 4. pkg-config + // 3. pkg-config if let Some(dir) = Self::find_via_pkg_config() { return dir; } panic!( "wolfSSL source not found. Either:\n \ - - Run: git submodule update --init\n \ - Set WOLFSSL_SRC to the path of your wolfssl checkout\n \ - - Install wolfssl-dev so that pkg-config can find it" + - Install wolfssl-dev so that pkg-config can find it\n \ + - Clone it: git clone https://github.com/wolfSSL/wolfssl.git" ); } @@ -394,120 +343,6 @@ const FIPS_WOLFCRYPT_SOURCES: &[&str] = &[ "wolfcrypt_last.c", ]; -/// Core source files for a `cryptocb-only` build. -/// -/// Excludes everything that is not needed when all cryptographic operations -/// are handled by CryptoCb callbacks: -/// -/// - `sp_int.c`, `sp_c32.c`, `sp_c64.c` โ€” SP big-integer math (the largest -/// contributors to code size; only needed for software ECC/RSA/DH). -/// - `wolfmath.c` โ€” legacy mp_int math (same reason). -/// - `arc4.c`, `blake2b.c`, `blake2s.c`, `camellia.c`, `cmac.c` โ€” unused -/// algorithms. -/// - `dsa.c`, `md4.c`, `md5.c` โ€” disabled by NO_DSA / NO_MD4 / NO_MD5. -/// - `pkcs7.c`, `pkcs12.c`, `srp.c` โ€” certificate containers not used in -/// firmware. -/// -/// Keeps: `cryptocb.c` (mandatory), `wc_port.c` (platform), `error.c`, -/// `memory.c`, `logging.c`, `random.c` (DRBG structure), `hash.c` (routing), -/// `sha.c`, `sha256.c`, `aes.c`, `asn.c`, `coding.c`, `signature.c`, -/// `wc_encrypt.c`, `cpuid.c`. -const CRYPTOCB_ONLY_CORE_SOURCES: &[&str] = &[ - "aes.c", - "asn.c", - "coding.c", - "cpuid.c", - "cryptocb.c", - "error.c", - "hash.c", - "logging.c", - "memory.c", - "random.c", - "sha.c", - "sha256.c", - "signature.c", - "wc_encrypt.c", - "wc_port.c", -]; - -/// Core source files for a `cryptocb-pure` build. -/// -/// Subset of [`CRYPTOCB_ONLY_CORE_SOURCES`] โ€” removes everything not needed -/// when wolfSSL is used purely as a CryptoCb routing layer with no higher-level -/// API calls (no OpenSSL compat, no HKDF, no ASN.1 parser, no CPU feature -/// detection, no high-level encrypt/signature wrappers): -/// -/// - `asn.c` โ€” ASN.1 parser (absent: no WOLFSSL_ASN_TEMPLATE, no key import/export) -/// - `coding.c` โ€” base64 encoding (absent: not needed for callback dispatch) -/// - `cpuid.c` โ€” CPU feature detection (absent: not needed for bare-metal CryptoCb) -/// - `signature.c` โ€” signature wrappers (absent: NO_SIG_WRAPPER is defined) -/// - `wc_encrypt.c` โ€” high-level encrypt wrappers (absent: not needed for CryptoCb) -/// -/// The ssl.c layer is also excluded (no OPENSSL_EXTRA). -const CRYPTOCB_PURE_CORE_SOURCES: &[&str] = &[ - "aes.c", - "cryptocb.c", - "error.c", - "hash.c", - "logging.c", - "memory.c", - "random.c", - "sha.c", - "sha256.c", - "wc_port.c", -]; - -/// Append the minimal set of conditional wolfcrypt sources for a -/// `cryptocb-only` build. -/// -/// Only sources that provide type definitions or CryptoCb dispatch glue -/// for algorithms used by wolfcrypt-dpe are included. All heavy algorithm -/// implementations (RSA, DH, Dilithium, ML-KEM, SHA-3, Ed25519, ChaCha, etc.) -/// are omitted. -fn append_cryptocb_only_sources(defines: &HashSet, sources: &mut Vec<&'static str>) { - // HMAC: needed for the Hmac struct layout and CryptoCb HMAC dispatch glue. - if !defines.contains("NO_HMAC") { - sources.push("hmac.c"); - } - // SHA-384/SHA-512: needed for the wc_Sha384/wc_Sha512 struct layouts. - if defines.contains("WOLFSSL_SHA512") || defines.contains("WOLFSSL_SHA384") { - sources.push("sha512.c"); - } - // ECC: needed for the ecc_key struct layout and CryptoCb ECC dispatch glue. - if defines.contains("HAVE_ECC") { - sources.push("ecc.c"); - } - // HKDF: pure HMAC-based KDF; HMAC calls go through CryptoCb. - if defines.contains("HAVE_HKDF") { - sources.push("kdf.c"); - } - // EVP API: required when OPENSSL_EXTRA is set for wolfcrypt-rs Rust bindings. - if defines.contains("OPENSSL_EXTRA") || defines.contains("OPENSSL_ALL") { - sources.push("evp.c"); - } -} - -/// Append conditional wolfcrypt sources for a `cryptocb-pure` build. -/// -/// Same algorithm-type guards as `cryptocb-only` but with OPENSSL_EXTRA and -/// HAVE_HKDF absent, so `evp.c` and `kdf.c` are never added. -fn append_cryptocb_pure_sources(defines: &HashSet, sources: &mut Vec<&'static str>) { - // HMAC: needed for the Hmac struct layout and CryptoCb HMAC dispatch glue. - if !defines.contains("NO_HMAC") { - sources.push("hmac.c"); - } - // SHA-384/512: needed for the wc_Sha384/wc_Sha512 struct layouts. - if defines.contains("WOLFSSL_SHA512") || defines.contains("WOLFSSL_SHA384") { - sources.push("sha512.c"); - } - // ECC: needed for the ecc_key struct layout and CryptoCb ECC dispatch glue. - if defines.contains("HAVE_ECC") { - sources.push("ecc.c"); - } - // No evp.c: OPENSSL_EXTRA is not defined in user_settings_cryptocb_pure.h. - // No kdf.c: HAVE_HKDF is not defined in user_settings_cryptocb_pure.h. -} - fn append_conditional_wolfcrypt_sources(defines: &HashSet, sources: &mut Vec<&'static str>) { if defines.contains("HAVE_CHACHA") { sources.push("chacha.c"); diff --git a/wolfssl-src/user_settings.h b/wolfssl-src/user_settings.h index 0c0c3ed..ad086d1 100644 --- a/wolfssl-src/user_settings.h +++ b/wolfssl-src/user_settings.h @@ -105,12 +105,6 @@ #define WC_RSA_BLINDING #define WC_RSA_NO_PADDING #define WC_RSA_PSS -/* Allow wc_RsaPrivateDecrypt_ex to return 0 bytes for valid empty OAEP plaintext - * instead of RSA_BUFFER_E. Required for Wycheproof OAEP zero-length test vectors. */ -#define WOLFSSL_RSA_DECRYPT_TO_0_LEN - -/* TLS 1.3 */ -#define WOLFSSL_TLS13 /* TLS extensions and SNI โ€” required by OPENSSL_ALL for struct layout * in ssl.c even though we don't compile the TLS protocol files. */ diff --git a/wolfssl-src/user_settings_cryptocb_only.h b/wolfssl-src/user_settings_cryptocb_only.h deleted file mode 100644 index dbf5675..0000000 --- a/wolfssl-src/user_settings_cryptocb_only.h +++ /dev/null @@ -1,208 +0,0 @@ -/* Copyright wolfSSL, Inc. - * SPDX-License-Identifier: MIT */ - -/* user_settings_cryptocb_only.h - * - * wolfSSL minimal configuration: CryptoCb callback infrastructure only. - * - * Intended for use when ALL cryptographic operations are dispatched to - * hardware (e.g. Caliptra accelerators) via the wolfSSL CryptoCb mechanism. - * Software implementations of SHA, AES, ECC, and all big-integer math are - * excluded. Operations without a registered CryptoCb handler fail with - * CRYPTOCB_UNAVAILABLE rather than falling back to software. - * - * This produces the smallest wolfSSL library that still supports the full - * CryptoCb protocol โ€” the type definitions, callback dispatch glue, DRBG - * structure, and HKDF are kept; SP math (sp_int.c, sp_c32.c, sp_c64.c), - * wolfmath.c, and all algorithm implementations are excluded. - * - * Platform stubs are sized for RISC-V bare-metal (no libc, no filesystem). - * Activate via the `cryptocb-only` Cargo feature in wolfssl-src. - */ - -#ifndef WOLFSSL_USER_SETTINGS_CRYPTOCB_ONLY_H -#define WOLFSSL_USER_SETTINGS_CRYPTOCB_ONLY_H - -/* ================================================================ - * CryptoCb configuration โ€” the whole point of this file - * ================================================================ */ - -/* Enable the CryptoCb callback infrastructure. */ -#define WOLF_CRYPTO_CB - -/* Disable software ECC and RSA implementations. - * This wolfSSL version provides per-algorithm CryptoCb-only guards rather - * than a single WOLF_CRYPTO_CB_ONLY. With these two defines, the software - * math paths inside ecc.c and rsa.c are excluded from compilation, which - * means those files no longer reference sp_int / wolfmath symbols even when - * WOLFSSL_SP_MATH_ALL is absent. SHA, AES, and HMAC lack _ONLY variants in - * this version; their software implementations are small and are compiled in - * but will never execute when CryptoCb handles everything. */ -#define WOLF_CRYPTO_CB_ONLY_ECC -#define WOLF_CRYPTO_CB_ONLY_RSA - -/* ================================================================ - * Bare-metal platform settings - * (same as user_settings_riscv.h โ€” required for riscv32 targets) - * ================================================================ */ - -#define SINGLE_THREADED -#define NO_FILESYSTEM -#define NO_WRITEV -#define WOLFSSL_USER_IO -#define NO_MAIN_DRIVER - -/* Session cache not needed on bare-metal. */ -#define NO_SESSION_CACHE - -/* Custom memory allocation โ€” firmware provides its own malloc/free. */ -#define XMALLOC_USER - -/* RNG entropy from the Caliptra hardware TRNG (iTRNG / CSRNG). - * - * The Caliptra hardware implements an AES-256-CTR-DRBG (SP 800-90A) in - * silicon. FIPS 140-3 / SP 800-90C requires using the hardware DRBG - * directly rather than stacking a second software DRBG on top of it. - * - * CUSTOM_RAND_GENERATE_BLOCK bypasses wolfSSL's HASH-DRBG entirely: - * wc_RNG_GenerateBlock() calls caliptra_generate_random_block() directly. - * caliptra_generate_random_block() is implemented in caliptra_seed.c - * (forwarded from hw_rng.rs via the Caliptra ITRNG driver). */ -int caliptra_generate_random_block(unsigned char* output, unsigned int sz); -#define CUSTOM_RAND_GENERATE_BLOCK caliptra_generate_random_block - -/* No libc headers โ€” provide everything via builtins and inline macros. */ -#define NO_STDLIB_H -#define STRING_USER -#define XMEMCPY(d,s,n) __builtin_memcpy((d),(s),(n)) -#define XMEMSET(d,v,n) __builtin_memset((d),(v),(n)) -#define XMEMCMP(a,b,n) __builtin_memcmp((a),(b),(n)) -#define XMEMMOVE(d,s,n) __builtin_memmove((d),(s),(n)) -#define XSTRLEN(s) __builtin_strlen(s) -#define XSTRNCPY(d,s,n) __builtin_strncpy((d),(s),(n)) -#define XSTRNCMP(a,b,n) __builtin_strncmp((a),(b),(n)) -#define XSTRCMP(a,b) __builtin_strcmp((a),(b)) -#include -#include -typedef long time_t; - -/* compat_shim.c calls memcpy/memset/memcmp directly (not via XMEMCPY macros). - * Map them to compiler builtins so there is no dependency on libc string.h. */ -#define memcpy __builtin_memcpy -#define memset __builtin_memset -#define memcmp __builtin_memcmp -#define memmove __builtin_memmove - -#define XSNPRINTF(buf,sz,...) 0 -#define XSTRTOK(s,d,c) ((char*)0) -#define XATOI(s) 0 -#define XSTRSTR(h,n) wolfssl_strstr((h),(n)) -#define XSTRNCASECMP(a,b,n) wolfssl_strncasecmp((a),(b),(n)) - -const char *wolfssl_strstr(const char *h, const char *n); -int wolfssl_strncasecmp(const char *a, const char *b, size_t n); - -#define WOLFSSL_IP4 2 -#define WOLFSSL_IP6 10 -#define XINET_PTON(af,src,dst) 0 - -#define CTYPE_USER -#define XTOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : (c)) -#define XISALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) -#define XISDIGIT(c) ((c) >= '0' && (c) <= '9') -#define XISALNUM(c) (XISALPHA(c) || XISDIGIT(c)) -#define XISASCII(c) ((c) >= 0 && (c) <= 127) -#define XISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r') -#define XTOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c)) -#define XSTRNCAT(d,s,n) wolfssl_strncat((d),(s),(n)) -#define XSTRNSTR(h,n,l) wolfssl_strnstr((h),(n),(l)) -#define XSTRCASECMP(a,b) wolfssl_strcasecmp((a),(b)) -#define XSTRCAT(d,s) wolfssl_strncat((d),(s),0x7FFFFFFF) -#define XSTRCHR(s,c) wolfssl_strchr((s),(c)) - -char *wolfssl_strncat(char *d, const char *s, size_t n); -const char *wolfssl_strnstr(const char *h, const char *n, size_t len); -int wolfssl_strcasecmp(const char *a, const char *b); -char *wolfssl_strchr(const char *s, int c); - -#define WOLFSSL_NO_ASSERT_H -#define NO_STDIO_FILESYSTEM -#define WOLFSSL_NO_LOGGING -/* logging.h has an unconditional #else { #include } fallback for - * printf. WOLFSSL_USER_LOG short-circuits it ("user provides their own - * logging headers") so no libc headers are pulled in on bare-metal. */ -#define WOLFSSL_USER_LOG -#define NO_WOLFSSL_DIR -#define WOLFSSL_NO_SOCK -#define NO_ASN_TIME -#define USER_TIME -#ifndef XTIME -#define XTIME(t) (0) -#endif -#ifndef XGMTIME -#define XGMTIME(c, t) (NULL) -#endif -#define NO_WOLFSSL_STUB - -/* ================================================================ - * Algorithm type definitions - * - * These defines preserve the struct layouts used inside wc_CryptoInfo, - * which is the struct passed to the CryptoCb callback. The software - * implementations of these algorithms are excluded by WOLF_CRYPTO_CB_ONLY; - * only the type definitions and CryptoCb dispatch glue are compiled in. - * - * SP math (WOLFSSL_SP_MATH_ALL, WOLFSSL_SP_384, SP_INT_BITS, etc.) is - * intentionally absent โ€” it is not needed when all operations go through - * CryptoCb, and omitting it excludes sp_int.c / sp_c32.c / sp_c64.c / - * wolfmath.c from the build, which are the largest contributors to code size. - * ================================================================ */ - -/* ECC type definitions (ecc_key struct, wc_EccInfo in wc_CryptoInfo). */ -#define HAVE_ECC -#define ECC_TIMING_RESISTANT - -/* SHA type definitions (wc_Sha256/384/512 structs, wc_HashInfo). */ -#define WOLFSSL_SHA224 -#define WOLFSSL_SHA384 -#define WOLFSSL_SHA512 - -/* HKDF โ€” pure HMAC-based key derivation; HMAC itself goes through CryptoCb. */ -#define HAVE_HKDF -/* One-step KDA KDF (NIST SP 800-56Cr2 ยง4.1) โ€” used by compat_shim.c's - * SSKDF_digest wrapper and potentially by wolfcrypt-dpe for DICE. */ -#define WC_KDF_NIST_SP_800_56C - -/* ASN.1: use the older sequential parser instead of the template engine. - * wolfSSL auto-enables WOLFSSL_ASN_TEMPLATE in settings.h unless - * WOLFSSL_ASN_ORIGINAL is explicitly defined. WOLFSSL_ASN_ORIGINAL selects - * the sequential parser (GetSequence/GetInt) which is sufficient for the - * ECDSA DER sig encode/decode we actually need and excludes the larger - * GetASN_Items/SetASN_Items/SizeASN_Items template infrastructure. */ -#define WOLFSSL_ASN_ORIGINAL - -/* ================================================================ - * Disabled algorithms - * ================================================================ */ - -#define NO_RSA -#define NO_DH -#define NO_DES3 -#define NO_MD4 -#define NO_MD5 -#define NO_SHA /* SHA-1 unused in DPE; all hashing is SHA-256/384 */ -#define NO_RC4 -#define NO_PSK -#define NO_PWDBASED -#define NO_DSA -#define NO_OLD_TLS -#define NO_SESSION_CACHE -#define NO_ERROR_STRINGS -#define NO_WOLFSSL_MEMORY -#define NO_SIG_WRAPPER -#define NO_CODING /* base64 encode/decode unused in DPE */ -/* BIO (ssl.c amalgamation includes bio.c when OPENSSL_EXTRA && !NO_BIO). - * bio.c uses vsnprintf from stdio.h which is unavailable on bare-metal. */ -#define NO_BIO - -#endif /* WOLFSSL_USER_SETTINGS_CRYPTOCB_ONLY_H */ diff --git a/wolfssl-src/user_settings_cryptocb_pure.h b/wolfssl-src/user_settings_cryptocb_pure.h deleted file mode 100644 index 890ab11..0000000 --- a/wolfssl-src/user_settings_cryptocb_pure.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright wolfSSL, Inc. - * SPDX-License-Identifier: MIT */ - -/* user_settings_cryptocb_pure.h - * - * wolfSSL absolute-minimum configuration: CryptoCb callback routing only. - * - * Intended for builds where ALL cryptographic operations are dispatched to - * hardware via the wolfSSL CryptoCb mechanism AND no higher-level wolfSSL - * APIs (EVP, HKDF, ASN, TLS extensions) are needed. This is the minimal - * configuration for a firmware image that uses wolfSSL purely as a routing - * layer between callers and a hardware crypto backend. - * - * Compared to user_settings_cryptocb_only.h, this removes: - * - OPENSSL_EXTRA / HAVE_TLS_EXTENSIONS / HAVE_SNI (no EVP/OpenSSL compat) - * - HAVE_HKDF / WC_KDF_NIST_SP_800_56C (no key derivation) - * - WOLFSSL_ASN_TEMPLATE (no ASN.1 parser) - * - WOLFSSL_SHA224 (not dispatched) - * - * C source reduction vs cryptocb-only: - * Removed: asn.c, coding.c, cpuid.c, signature.c, wc_encrypt.c, ssl.c, - * evp.c (no OPENSSL_EXTRA), kdf.c (no HAVE_HKDF). - * - * Activate via the `cryptocb-pure` Cargo feature in wolfssl-src. - */ - -#ifndef WOLFSSL_USER_SETTINGS_CRYPTOCB_PURE_H -#define WOLFSSL_USER_SETTINGS_CRYPTOCB_PURE_H - -/* ================================================================ - * CryptoCb configuration โ€” the whole point of this file - * ================================================================ */ - -/* Enable the CryptoCb callback infrastructure. */ -#define WOLF_CRYPTO_CB - -/* Disable software ECC and RSA implementations. - * These flags exclude the SP math code paths from ecc.c and rsa.c so that - * sp_int.c / sp_c32.c / sp_c64.c / wolfmath.c are not referenced. */ -#define WOLF_CRYPTO_CB_ONLY_ECC -#define WOLF_CRYPTO_CB_ONLY_RSA - -/* ================================================================ - * Bare-metal platform settings - * ================================================================ */ - -#define SINGLE_THREADED -#define NO_FILESYSTEM -#define NO_WRITEV -#define WOLFSSL_USER_IO -#define NO_MAIN_DRIVER - -/* Custom memory allocation โ€” firmware provides its own malloc/free. */ -#define XMALLOC_USER - -/* RNG entropy from the Caliptra hardware TRNG (iTRNG / CSRNG). - * - * The Caliptra hardware implements an AES-256-CTR-DRBG (SP 800-90A) in - * silicon. FIPS 140-3 / SP 800-90C requires using the hardware DRBG - * directly rather than stacking a second software DRBG on top of it. - * - * CUSTOM_RAND_GENERATE_BLOCK bypasses wolfSSL's HASH-DRBG entirely: - * wc_RNG_GenerateBlock() calls caliptra_generate_random_block() directly. - * caliptra_generate_random_block() is implemented in caliptra_seed.c - * (forwarded from hw_rng.rs via the Caliptra ITRNG driver). */ -int caliptra_generate_random_block(unsigned char* output, unsigned int sz); -#define CUSTOM_RAND_GENERATE_BLOCK caliptra_generate_random_block - -/* No libc headers โ€” provide everything via builtins and inline macros. */ -#define NO_STDLIB_H -#define STRING_USER -#define XMEMCPY(d,s,n) __builtin_memcpy((d),(s),(n)) -#define XMEMSET(d,v,n) __builtin_memset((d),(v),(n)) -#define XMEMCMP(a,b,n) __builtin_memcmp((a),(b),(n)) -#define XMEMMOVE(d,s,n) __builtin_memmove((d),(s),(n)) -#define XSTRLEN(s) __builtin_strlen(s) -#define XSTRNCPY(d,s,n) __builtin_strncpy((d),(s),(n)) -#define XSTRNCMP(a,b,n) __builtin_strncmp((a),(b),(n)) -#define XSTRCMP(a,b) __builtin_strcmp((a),(b)) -#include -#include -typedef long time_t; - -/* compat_shim.c calls memcpy/memset/memcmp directly (not via XMEMCPY macros). - * Map them to compiler builtins so there is no dependency on libc string.h. */ -#define memcpy __builtin_memcpy -#define memset __builtin_memset -#define memcmp __builtin_memcmp -#define memmove __builtin_memmove - -#define XSNPRINTF(buf,sz,...) 0 -#define XSTRTOK(s,d,c) ((char*)0) -#define XATOI(s) 0 -#define XSTRSTR(h,n) wolfssl_strstr((h),(n)) -#define XSTRNCASECMP(a,b,n) wolfssl_strncasecmp((a),(b),(n)) - -const char *wolfssl_strstr(const char *h, const char *n); -int wolfssl_strncasecmp(const char *a, const char *b, size_t n); - -#define WOLFSSL_IP4 2 -#define WOLFSSL_IP6 10 -#define XINET_PTON(af,src,dst) 0 - -#define CTYPE_USER -#define XTOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : (c)) -#define XISALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) -#define XISDIGIT(c) ((c) >= '0' && (c) <= '9') -#define XISALNUM(c) (XISALPHA(c) || XISDIGIT(c)) -#define XISASCII(c) ((c) >= 0 && (c) <= 127) -#define XISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r') -#define XTOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c)) -#define XSTRNCAT(d,s,n) wolfssl_strncat((d),(s),(n)) -#define XSTRNSTR(h,n,l) wolfssl_strnstr((h),(n),(l)) -#define XSTRCASECMP(a,b) wolfssl_strcasecmp((a),(b)) -#define XSTRCAT(d,s) wolfssl_strncat((d),(s),0x7FFFFFFF) -#define XSTRCHR(s,c) wolfssl_strchr((s),(c)) - -char *wolfssl_strncat(char *d, const char *s, size_t n); -const char *wolfssl_strnstr(const char *h, const char *n, size_t len); -int wolfssl_strcasecmp(const char *a, const char *b); -char *wolfssl_strchr(const char *s, int c); - -#define WOLFSSL_NO_ASSERT_H -#define NO_STDIO_FILESYSTEM -#define WOLFSSL_NO_LOGGING -/* logging.h has an unconditional #else { #include } fallback for - * printf. WOLFSSL_USER_LOG short-circuits it so no libc headers are pulled - * in on bare-metal. */ -#define WOLFSSL_USER_LOG -#define NO_WOLFSSL_DIR -#define WOLFSSL_NO_SOCK -#define NO_ASN_TIME -#define USER_TIME -#ifndef XTIME -#define XTIME(t) (0) -#endif -#ifndef XGMTIME -#define XGMTIME(c, t) (NULL) -#endif -#define NO_WOLFSSL_STUB - -/* ASN.1: use the older sequential parser instead of the template engine. - * wolfSSL auto-enables WOLFSSL_ASN_TEMPLATE in settings.h unless - * WOLFSSL_ASN_ORIGINAL is explicitly defined. */ -#define WOLFSSL_ASN_ORIGINAL - -/* ================================================================ - * Algorithm type definitions - * - * These defines preserve the struct layouts used inside wc_CryptoInfo, - * which is the struct passed to the CryptoCb callback. Only the types - * that wolfcrypt-dpe-hw actually dispatches are included. SP math - * (WOLFSSL_SP_MATH_ALL etc.) is intentionally absent. - * ================================================================ */ - -/* ECC type definitions (ecc_key struct, wc_EccInfo in wc_CryptoInfo). */ -#define HAVE_ECC -#define ECC_TIMING_RESISTANT - -/* AES-GCM type definitions (wc_Aes struct, wc_AesInfo/aesgcm_enc/aesgcm_dec - * sub-structs in wc_CryptoInfo cipher union, wc_CryptoCb_AesAuthEnc/Dec). - * Required by hw_aes.rs cipher callback dispatch. */ -#define HAVE_AESGCM - -/* SHA-384/512 type definitions (wc_Sha384/wc_Sha512 structs, wc_HashInfo). - * SHA-224 is intentionally absent โ€” it is not dispatched by wolfcrypt-dpe-hw. */ -#define WOLFSSL_SHA384 -#define WOLFSSL_SHA512 - -/* ================================================================ - * Disabled algorithms - * ================================================================ */ - -#define NO_RSA -#define NO_DH -#define NO_DES3 -#define NO_MD4 -#define NO_MD5 -#define NO_SHA /* SHA-1 unused in DPE; all hashing is SHA-256/384 */ -#define NO_RC4 -#define NO_PSK -#define NO_PWDBASED -#define NO_DSA -#define NO_OLD_TLS -#define NO_SESSION_CACHE -#define NO_ERROR_STRINGS -#define NO_WOLFSSL_MEMORY -#define NO_SIG_WRAPPER -#define NO_CODING /* base64 encode/decode unused in DPE */ -/* BIO uses vsnprintf from stdio.h which is unavailable on bare-metal. */ -#define NO_BIO - -#endif /* WOLFSSL_USER_SETTINGS_CRYPTOCB_PURE_H */ diff --git a/wolfssl-src/wolfssl b/wolfssl-src/wolfssl deleted file mode 160000 index 0c9b639..0000000 --- a/wolfssl-src/wolfssl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0c9b6397be463c0e5bd7d0c8c1bd8619dc9b3aa8