diff --git a/.clang-format b/.clang-format index b01602a2b9..32b8bd5cfd 100644 --- a/.clang-format +++ b/.clang-format @@ -599,6 +599,8 @@ TypeNames: - "ossl_finish_mutate_cb" - "OSSL_FIPS_IND" - "OSSL_FIPS_IND_CHECK_CB" + - "OSSL_FN_CTX" + - "OSSL_FN_ULONG" - "OSSL_FUNC" - "OSSL_HANDSHAKE_STATE" - "OSSL_HASH" @@ -1375,7 +1377,6 @@ StatementMacros: - "static_ASN1_SEQUENCE_END_cb" - "static_ASN1_SEQUENCE_END_name" - "static_ASN1_SEQUENCE_END_ref" - - "PROV_CIPHER_HW_aes_mode" - "PROV_CIPHER_HW_aria_mode" - "PROV_CIPHER_HW_camellia_mode" - "PROV_CIPHER_HW_des_mode" diff --git a/.github/workflows/avx512-sde.yml b/.github/workflows/avx512-sde.yml deleted file mode 100644 index 1b94df9922..0000000000 --- a/.github/workflows/avx512-sde.yml +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# Copyright (c) 2026 Intel Corporation. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -# Run AVX512-specific tests under Intel SDE. -# -# GitHub Actions runners currently do not have AVX512 hardware. -# Intel SDE emulates AVX512 instructions and spoofs CPUID, -# so AVX512 code paths are exercised. -# -# To update Intel SDE: find the new mirror ID and file date from -# https://www.intel.com/content/www/us/en/download/684897 -# and update the three env vars below. - -name: AVX512 tests via Intel SDE - -on: - schedule: - - cron: '30 02 * * *' - workflow_dispatch: - -permissions: - contents: read - -env: - SDE_VERSION: 10.8.0 - SDE_DATE: 2026-03-15 - SDE_MIRROR_ID: 915934 - -jobs: - linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - - name: install NASM - run: sudo apt-get install -y nasm - - - name: install Intel SDE - run: | - SDE_URL="https://downloadmirror.intel.com/${SDE_MIRROR_ID}/sde-external-${SDE_VERSION}-${SDE_DATE}-lin.tar.xz" - SDE_SHA256="50b320cd226acef7a491f5b321fc1be3c3c7984f9e27a456e64894b5b0979dd3" - curl -fsSL -o /tmp/sde.tar.xz "$SDE_URL" - echo "$SDE_SHA256 /tmp/sde.tar.xz" | sha256sum -c - - mkdir /tmp/sde - tar -xf /tmp/sde.tar.xz -C /tmp/sde/ - sudo mv /tmp/sde/sde-external-${SDE_VERSION}-${SDE_DATE}-lin /opt/sde - echo "/opt/sde" >> "$GITHUB_PATH" - - - name: config - run: | - ./config --banner=Configured --strict-warnings no-shared enable-fips - - - name: build - run: make -j4 - - - name: show CPU and OpenSSL build info - run: | - cat /proc/cpuinfo | grep -m1 "model name" - sde64 -icx -- ./apps/openssl version -c - - - name: ml_dsa_internal_test (AVX512 via SDE) - run: sde64 -icx -- ./test/ml_dsa_internal_test - - - name: sha3_x4_internal_test (AVX512 via SDE) - run: sde64 -icx -- ./test/sha3_x4_internal_test - - - name: fipsinstall (FIPS KAT via SDE) - run: sde64 -icx -- ./apps/openssl fipsinstall -module ./providers/fips.so -out /tmp/fipsmodule.cnf -provider_name fips - - windows: - runs-on: windows-2022 - env: - VCVARS: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - - name: install nasm - if: github.repository == 'openssl/openssl' - run: | - $installer = "nasm-3.01-installer-x64.exe" - Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer - $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer - $actual = (Get-FileHash $installer -Algorithm SHA256).Hash - if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" } - Start-Process -FilePath ".\$installer" -ArgumentList '/S' -Wait - "C:\Program Files\NASM" | Out-File -FilePath "$env:GITHUB_PATH" -Append - - name: install nasm (forks) - if: github.repository != 'openssl/openssl' - run: | - $installer = "nasm-3.01-installer-x64.exe" - Invoke-WebRequest -Uri "https://www.nasm.us/pub/nasm/releasebuilds/3.01/win64/$installer" -OutFile $installer - Start-Process -FilePath ".\$installer" -ArgumentList '/S' -Wait - "C:\Program Files\NASM" | Out-File -FilePath "$env:GITHUB_PATH" -Append - - - name: install jom - if: github.repository == 'openssl/openssl' - run: | - mkdir C:\jom - Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe - $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe' - $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash - if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" } - "C:\jom" | Out-File -FilePath "$env:GITHUB_PATH" -Append - - name: install jom (forks) - if: github.repository != 'openssl/openssl' - run: | - mkdir C:\jom - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/jom/jom_1_1_7.zip" -OutFile C:\jom\jom.zip - Expand-Archive -Path C:\jom\jom.zip -DestinationPath C:\jom - "C:\jom" | Out-File -FilePath "$env:GITHUB_PATH" -Append - - - name: install Intel SDE - run: | - $url = "https://downloadmirror.intel.com/$env:SDE_MIRROR_ID/sde-external-$env:SDE_VERSION-$env:SDE_DATE-win.tar.xz" - $expected = "176F87C80EB42BB91B73E1428F4A0FD067DF322F901F9B4359B20B86B92C2BAE" - curl.exe -fsSL -o sde-win.tar.xz $url - $actual = (Get-FileHash sde-win.tar.xz -Algorithm SHA256).Hash - if ($actual -ne $expected) { throw "SDE SHA256 mismatch: got $actual" } - & "C:\Program Files\7-Zip\7z.exe" x sde-win.tar.xz -so | & "C:\Program Files\7-Zip\7z.exe" x -si -ttar -o"C:\sde" - $sdeRoot = "C:\sde\sde-external-$env:SDE_VERSION-$env:SDE_DATE-win" - if (-not (Test-Path "$sdeRoot\sde.exe")) { throw "sde.exe not found in $sdeRoot" } - "$sdeRoot" | Out-File -FilePath $env:GITHUB_PATH -Append - - - name: prepare build directory - run: mkdir _build - - - name: config - working-directory: _build - shell: cmd - run: | - call "%VCVARS%" - perl ..\Configure --banner=Configured --strict-warnings no-shared enable-fips no-makedepend - - - name: build - working-directory: _build - shell: cmd - run: | - call "%VCVARS%" - jom /j4 /S - - - name: show CPU and OpenSSL build info - working-directory: _build - run: sde -icx -- apps\openssl.exe version -c - - - name: ml_dsa_internal_test (AVX512 via SDE) - working-directory: _build - shell: cmd - run: sde -icx -- test\ml_dsa_internal_test.exe - - - name: sha3_x4_internal_test (AVX512 via SDE) - working-directory: _build - shell: cmd - run: sde -icx -- test\sha3_x4_internal_test.exe - - - name: fipsinstall (FIPS KAT via SDE) - working-directory: _build - shell: cmd - run: sde -icx -- apps\openssl.exe fipsinstall -module providers\fips.dll -out fipsmodule.cnf -provider_name fips diff --git a/.github/workflows/ci-doc-changes.yml b/.github/workflows/ci-doc-changes.yml deleted file mode 100644 index 08919fc323..0000000000 --- a/.github/workflows/ci-doc-changes.yml +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -name: Documentation and Installability CI - -on: [pull_request, push] - -permissions: - contents: read - -env: - OSSL_RUN_CI_TESTS: 1 - -jobs: - check_docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - name: config - run: ./config --strict-warnings --banner=Configured enable-fips && perl configdata.pm --dump - - name: make build_generated - run: make -s build_generated - - name: make doc-nits - run: make doc-nits - - name: make help - run: make help - - name: make md-nits - run: | - sudo gem install mdl - make md-nits - - # out-of-source-and-install checks multiple things at the same time: - # - That building, testing and installing works from an out-of-source - # build tree - # - That building, testing and installing works with a read-only source - # tree - out-of-readonly-source-and-install-ubuntu: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - path: ./source - persist-credentials: false - - name: checkout fuzz/corpora submodule - run: git submodule update --init --depth 1 fuzz/corpora - working-directory: ./source - - name: make source read-only - run: chmod -R a-w ./source - - name: create build and install directories - run: | - mkdir ./build - mkdir ./install - - name: config - run: | - ../source/config --banner=Configured enable-demos enable-h3demo enable-fips enable-lms enable-quic enable-acvp-tests --strict-warnings --prefix=$(cd ../install; pwd) - perl configdata.pm --dump - working-directory: ./build - - name: make - run: make -s -j4 - working-directory: ./build - - name: get cpu info - run: | - cat /proc/cpuinfo - ./util/opensslwrap.sh version -c - working-directory: ./build - - name: make test - run: ../source/.github/workflows/make-test - working-directory: ./build - - name: save artifacts - if: success() || failure() - uses: actions/upload-artifact@v5 - with: - name: "ci@out-of-readonly-source-and-install-ubuntu" - path: build/artifacts.tar.gz - - name: make install - run: make install - working-directory: ./build - - out-of-readonly-source-and-install-macos: - runs-on: macos-15 - steps: - - uses: actions/checkout@v6 - with: - path: ./source - persist-credentials: false - - name: checkout fuzz/corpora submodule - run: git submodule update --init --depth 1 fuzz/corpora - working-directory: ./source - - name: make source read-only - run: chmod -R a-w ./source - - name: create build and install directories - run: | - mkdir ./build - mkdir ./install - - name: config - run: | - ../source/config --banner=Configured enable-fips enable-lms enable-demos enable-h3demo enable-quic enable-acvp-tests --strict-warnings --prefix=$(cd ../install; pwd) - perl configdata.pm --dump - working-directory: ./build - - name: make - run: make -s -j4 - working-directory: ./build - - name: get cpu info - run: | - sysctl machdep.cpu - ./util/opensslwrap.sh version -c - working-directory: ./build - - name: make test - run: ../source/.github/workflows/make-test - working-directory: ./build - - name: save artifacts - if: success() || failure() - uses: actions/upload-artifact@v5 - with: - name: "ci@out-of-readonly-source-and-install-macos-15" - path: build/artifacts.tar.gz - - name: make install - run: make install - working-directory: ./build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a80ea66b29..8086c9207c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,25 +7,7 @@ name: GitHub CI -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' - push: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request, push] # for some reason, this does not work: # variables: @@ -63,6 +45,25 @@ jobs: - name: git diff run: git diff --exit-code + check_docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - name: config + run: ./config --strict-warnings --banner=Configured enable-fips && perl configdata.pm --dump + - name: make build_generated + run: make -s build_generated + - name: make doc-nits + run: make doc-nits + - name: make help + run: make help + - name: make md-nits + run: | + sudo gem install mdl + make md-nits + # This checks that we use ANSI C language syntax and semantics. # We are not as strict with libraries, but rather adapt to what's # expected to be available in a certain version of each platform. @@ -87,14 +88,12 @@ jobs: run: git submodule update --init --depth 1 fuzz/corpora - name: localegen run: sudo locale-gen tr_TR.UTF-8 - - name: cmocka - run: sudo apt-get -y install libcmocka-dev - name: fipsvendor # Make one fips build use a customized FIPS vendor run: echo "FIPS_VENDOR=CI" >> VERSION.dat - name: config # enable-quic is on by default, but we leave it here to check we're testing the explicit enable somewhere - run: CC=gcc ./config --strict-warnings --banner=Configured enable-demos enable-h3demo enable-ec_explicit_curves enable-sslkeylog enable-fips enable-quic enable-lms enable-unit-tests && perl configdata.pm --dump + run: CC=gcc ./config --strict-warnings --banner=Configured enable-demos enable-h3demo enable-ec_explicit_curves enable-sslkeylog enable-fips enable-quic enable-lms && perl configdata.pm --dump - name: make run: make -s -j4 - name: get cpu info @@ -461,40 +460,6 @@ jobs: path: artifacts.tar.gz if-no-files-found: ignore - fuzz_tests_mfail: - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - name: checkout fuzz/corpora submodule - run: git submodule update --init --depth 1 fuzz/corpora - - name: Adjust ASLR for sanitizer - run: sudo sysctl -w vm.mmap_rnd_bits=28 - - name: config - run: | - ./config --strict-warnings --banner=Configured --debug \ - -DPEDANTIC -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION \ - enable-asan enable-ec_explicit_curves enable-ubsan \ - enable-rc5 enable-md2 enable-ec_nistp_64_gcc_128 \ - enable-weak-ssl-ciphers enable-nextprotoneg - perl configdata.pm --dump - - name: make - run: make -s -j4 - - name: make test (fuzz with mfail) - env: - OSSL_FUZZ_TEST_BUDGET: 1200 - OSSL_FUZZ_TEST_JOBS: 4 - run: .github/workflows/make-test OPENSSL_TEST_RAND_ORDER=0 TESTS="test_fuzz*" - - name: save artifacts - if: success() || failure() - uses: actions/upload-artifact@v5 - with: - name: "ci@fuzz_tests_mfail" - path: artifacts.tar.gz - if-no-files-found: ignore - memory_sanitizer: runs-on: ubuntu-latest steps: @@ -664,6 +629,95 @@ jobs: name: "ci@legacy" path: artifacts.tar.gz + # out-of-source-and-install checks multiple things at the same time: + # - That building, testing and installing works from an out-of-source + # build tree + # - That building, testing and installing works with a read-only source + # tree + out-of-readonly-source-and-install-ubuntu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + path: ./source + persist-credentials: false + - name: checkout fuzz/corpora submodule + run: git submodule update --init --depth 1 fuzz/corpora + working-directory: ./source + - name: make source read-only + run: chmod -R a-w ./source + - name: create build and install directories + run: | + mkdir ./build + mkdir ./install + - name: config + run: | + ../source/config --banner=Configured enable-demos enable-h3demo enable-fips enable-lms enable-quic enable-acvp-tests --strict-warnings --prefix=$(cd ../install; pwd) + perl configdata.pm --dump + working-directory: ./build + - name: make + run: make -s -j4 + working-directory: ./build + - name: get cpu info + run: | + cat /proc/cpuinfo + ./util/opensslwrap.sh version -c + working-directory: ./build + - name: make test + run: ../source/.github/workflows/make-test + working-directory: ./build + - name: save artifacts + if: success() || failure() + uses: actions/upload-artifact@v5 + with: + name: "ci@out-of-readonly-source-and-install-ubuntu" + path: build/artifacts.tar.gz + - name: make install + run: make install + working-directory: ./build + + out-of-readonly-source-and-install-macos: + runs-on: macos-15 + steps: + - uses: actions/checkout@v6 + with: + path: ./source + persist-credentials: false + - name: checkout fuzz/corpora submodule + run: git submodule update --init --depth 1 fuzz/corpora + working-directory: ./source + - name: make source read-only + run: chmod -R a-w ./source + - name: create build and install directories + run: | + mkdir ./build + mkdir ./install + - name: config + run: | + ../source/config --banner=Configured enable-fips enable-lms enable-demos enable-h3demo enable-quic enable-acvp-tests --strict-warnings --prefix=$(cd ../install; pwd) + perl configdata.pm --dump + working-directory: ./build + - name: make + run: make -s -j4 + working-directory: ./build + - name: get cpu info + run: | + sysctl machdep.cpu + ./util/opensslwrap.sh version -c + working-directory: ./build + - name: make test + run: ../source/.github/workflows/make-test + working-directory: ./build + - name: save artifacts + if: success() || failure() + uses: actions/upload-artifact@v5 + with: + name: "ci@out-of-readonly-source-and-install-macos-15" + path: build/artifacts.tar.gz + - name: make install + run: make install + working-directory: ./build + external-tests-misc: runs-on: ubuntu-latest steps: @@ -675,6 +729,10 @@ jobs: run: | sudo apt-get update sudo apt-get -yq install bison gettext keyutils ldap-utils libldap2-dev libkeyutils-dev python3 python3-paste python3-pyrad slapd tcsh python3-virtualenv virtualenv python3-kdcproxy gdb libtls-dev wget gpg + - name: install cpanm and Test2::V0 for gost_engine testing + uses: perl-actions/install-with-cpanm@10d60f00b4073f484fc29d45bfbe2f776397ab3d # v1.7 + with: + install: Test2::V0 - name: setup hostname workaround run: sudo hostname localhost - name: config @@ -688,9 +746,8 @@ jobs: run: | cat /proc/cpuinfo ./util/opensslwrap.sh version -c - - name: test failure when selecting non-existing test case - run: | - ! make test TESTS="test_external_gost_engine" + - name: test external gost-engine + run: make test TESTS="test_external_gost_engine" - name: test external krb5 run: make test TESTS="test_external_krb5" - name: test external tlsfuzzer diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml index 34075a3566..4c873babc8 100644 --- a/.github/workflows/coveralls.yml +++ b/.github/workflows/coveralls.yml @@ -47,10 +47,10 @@ jobs: MATRIX=$(cat << EOF [{ "branch": "master", - "extra_config": "enable-fips enable-tfo enable-lms enable-crypto-mdebug enable-unit-tests" + "extra_config": "enable-fips enable-tfo enable-lms enable-crypto-mdebug enable-allocfail-tests" }, { "branch": "openssl-4.0", - "extra_config": "enable-fips enable-tfo enable-lms enable-crypto-mdebug" + "extra_config": "enable-fips enable-tfo enable-lms enable-crypto-mdebug enable-allocfail-tests" },{ "branch": "openssl-3.6", "extra_config": "no-afalgeng enable-fips enable-tfo enable-lms" @@ -93,7 +93,7 @@ jobs: run: | sudo apt-get update sudo apt-get -yq install lcov - sudo apt-get -yq install bison gettext keyutils ldap-utils libcmocka-dev libldap2-dev libkeyutils-dev python3 python3-paste python3-pyrad slapd tcsh python3-virtualenv virtualenv python3-kdcproxy + sudo apt-get -yq install bison gettext keyutils ldap-utils libldap2-dev libkeyutils-dev python3 python3-paste python3-pyrad slapd tcsh python3-virtualenv virtualenv python3-kdcproxy - name: install Test2::V0 for gost_engine testing uses: perl-actions/install-with-cpanm@10d60f00b4073f484fc29d45bfbe2f776397ab3d #v1.7 with: diff --git a/.github/workflows/cross-compiles.yml b/.github/workflows/cross-compiles.yml index d0f5ff8284..efc498edf1 100644 --- a/.github/workflows/cross-compiles.yml +++ b/.github/workflows/cross-compiles.yml @@ -7,35 +7,13 @@ name: Cross Compile -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' - push: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request, push] permissions: contents: read jobs: cross-compilation: - # Run the full test suite on push, and on pull requests labelled with - # 'extended tests'. Other pull requests only run the EVP tests. - env: - EXTENDED: ${{ github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'extended tests') }} strategy: fail-fast: false matrix: @@ -233,19 +211,19 @@ jobs: cat /proc/cpuinfo QEMU_LD_PREFIX=/usr/${{ matrix.platform.arch }} ./util/opensslwrap.sh version -c - name: make all tests - if: env.EXTENDED == 'true' && matrix.platform.tests == '' + if: github.event_name == 'push' && matrix.platform.tests == '' run: | .github/workflows/make-test \ TESTS="-test_afalg" \ QEMU_LD_PREFIX=/usr/${{ matrix.platform.arch }} - name: make some tests - if: env.EXTENDED == 'true' && matrix.platform.tests != 'none' && matrix.platform.tests != '' + if: github.event_name == 'push' && matrix.platform.tests != 'none' && matrix.platform.tests != '' run: | .github/workflows/make-test \ TESTS="${{ matrix.platform.tests }} -test_afalg" \ QEMU_LD_PREFIX=/usr/${{ matrix.platform.arch }} - name: make evp tests - if: env.EXTENDED != 'true' && matrix.platform.tests != 'none' + if: github.event_name == 'pull_request' && matrix.platform.tests != 'none' run: | .github/workflows/make-test \ TESTS="test_evp*" \ diff --git a/.github/workflows/fips-checksums.yml b/.github/workflows/fips-checksums.yml index 5fd96b3159..f82a604ab7 100644 --- a/.github/workflows/fips-checksums.yml +++ b/.github/workflows/fips-checksums.yml @@ -6,16 +6,7 @@ # https://www.openssl.org/source/license.html name: FIPS Check and ABIDIFF -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request] permissions: contents: read diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml new file mode 100644 index 0000000000..746da6e059 --- /dev/null +++ b/.github/workflows/make-release.yml @@ -0,0 +1,48 @@ +# Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +name: "Make release" + +on: + push: + tags: + - "openssl-*" + +permissions: {} + +jobs: + release: + runs-on: "releaser" + steps: + - name: "Checkout" + uses: "actions/checkout@v6" + with: + fetch-depth: 1 + ref: ${{ github.ref_name }} + github-server-url: "https://github.openssl.org/" + repository: "openssl/openssl" + token: ${{ secrets.GHE_TOKEN }} + path: ${{ github.ref_name }} + persist-credentials: false + - name: "Prepare assets" + env: + SIGNING_KEY_UID: ${{ vars.signing_key_uid }} + run: | + cd "$GITHUB_REF_NAME" + ./util/mktar.sh + mkdir -p assets && mv "$GITHUB_REF_NAME.tar.gz" assets/ && cd assets + openssl sha1 -r "$GITHUB_REF_NAME.tar.gz" > "$GITHUB_REF_NAME.tar.gz.sha1" + openssl sha256 -r "$GITHUB_REF_NAME.tar.gz" > "$GITHUB_REF_NAME.tar.gz.sha256" + gpg -u "$SIGNING_KEY_UID" -o "$GITHUB_REF_NAME.tar.gz.asc" -sba "$GITHUB_REF_NAME.tar.gz" + - name: "Create release" + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + run: | + VERSION=$(echo "$GITHUB_REF_NAME" | cut -d "-" -f 2-) + PRE_RELEASE=$([[ "$GITHUB_REF_NAME" =~ alpha|beta ]] && echo "-p" || echo "") + NOTES=$(curl -s "https://api.openssl.org/release-metadata/news/?version=$VERSION&capture_title=False") + gh release create "$GITHUB_REF_NAME" $PRE_RELEASE -t "OpenSSL $VERSION" -d --notes "$NOTES" -R "$GITHUB_REPOSITORY" "$GITHUB_REF_NAME/assets/"* diff --git a/.github/workflows/perl-minimal-checker.yml b/.github/workflows/perl-minimal-checker.yml index 2606add5fb..9ca4e9b509 100644 --- a/.github/workflows/perl-minimal-checker.yml +++ b/.github/workflows/perl-minimal-checker.yml @@ -7,25 +7,7 @@ # Jobs run per pull request submission name: Perl-minimal-checker CI -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' - push: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request, push] permissions: contents: read diff --git a/.github/workflows/prov-compat-label.yml b/.github/workflows/prov-compat-label.yml index 94334da8e5..cf2b44e169 100644 --- a/.github/workflows/prov-compat-label.yml +++ b/.github/workflows/prov-compat-label.yml @@ -10,16 +10,7 @@ name: Provider compatibility for PRs -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request] permissions: contents: read diff --git a/.github/workflows/riscv-more-cross-compiles.yml b/.github/workflows/riscv-more-cross-compiles.yml index 069495e0f6..cac662b8d3 100644 --- a/.github/workflows/riscv-more-cross-compiles.yml +++ b/.github/workflows/riscv-more-cross-compiles.yml @@ -10,14 +10,6 @@ name: Cross Compile for RISC-V Extensions on: pull_request: types: [opened, reopened, edited, synchronize] - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' push: schedule: - cron: '35 02 * * *' diff --git a/.github/workflows/run-checker-ci.yml b/.github/workflows/run-checker-ci.yml index 89186ff03c..70d105e3f2 100644 --- a/.github/workflows/run-checker-ci.yml +++ b/.github/workflows/run-checker-ci.yml @@ -7,25 +7,7 @@ # Jobs run per pull request submission name: Run-checker CI -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' - push: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request, push] permissions: contents: read diff --git a/.github/workflows/style-checks.yml b/.github/workflows/style-checks.yml index f4d251681d..b345ae5110 100644 --- a/.github/workflows/style-checks.yml +++ b/.github/workflows/style-checks.yml @@ -7,16 +7,7 @@ name: Coding style validation -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' +on: [pull_request] jobs: check-style: diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index eb8649f741..dd513c658b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -7,26 +7,7 @@ name: Windows GitHub CI -on: - pull_request: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' - push: - paths-ignore: - - 'doc/**' - - '*.md' - - '*.pod' - - 'README*' - - 'funding.json' - - 'LICENSE.txt' - - 'VERSION.dat' - +on: [pull_request, push] permissions: contents: read @@ -209,59 +190,6 @@ jobs: call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" nmake test VERBOSE_FAILURE=yes HARNESS_JOBS=4 - unit-tests: - runs-on: windows-2022 - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - name: checkout fuzz/corpora submodule - run: git submodule update --init --depth 1 fuzz/corpora - - name: install jom - if: github.repository == 'openssl/openssl' - run: | - mkdir C:\jom - Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe - $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe' - $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash - if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" } - "C:\jom" | Out-File -FilePath "$env:GITHUB_PATH" -Append - - name: install jom (forks) - if: github.repository != 'openssl/openssl' - run: | - mkdir C:\jom - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/jom/jom_1_1_7.zip" -OutFile C:\jom\jom.zip - Expand-Archive -Path C:\jom\jom.zip -DestinationPath C:\jom - "C:\jom" | Out-File -FilePath "$env:GITHUB_PATH" -Append - - name: install cmocka and detours via vcpkg - shell: pwsh - run: | - & "$env:VCPKG_INSTALLATION_ROOT\vcpkg.exe" install cmocka:x64-windows-static-md detours:x64-windows-static-md - "VCPKG_INST=$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows-static-md" | Out-File -FilePath $env:GITHUB_ENV -Append - - name: prepare the build directory - run: mkdir _build - - name: config - working-directory: _build - shell: cmd - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - perl ..\Configure VC-WIN64A --banner=Configured --strict-warnings no-makedepend no-asm enable-unit-tests ^ - --with-cmocka-include=%VCPKG_INST%\include --with-cmocka-lib=%VCPKG_INST%\lib ^ - --with-detours-include=%VCPKG_INST%\include --with-detours-lib=%VCPKG_INST%\lib - perl configdata.pm --dump - - name: build - working-directory: _build - shell: cmd - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - jom /j4 /S - - name: test - working-directory: _build - shell: cmd - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - jom test VERBOSE=1 TESTS=test_unit - minimal: runs-on: windows-2022 steps: diff --git a/CHANGES.md b/CHANGES.md index 8d507e4f32..3cdace8517 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,58 +31,6 @@ OpenSSL Releases ### Changes between 4.0 and 4.1 [xx XXX xxxx] - * Fixed TLS 1.3 external PSK connections being wrongly rejected when - the client sets a non-empty session ID context. - - *Viktor Dukhovni* - - * Fixed a TLS 1.3 server with no session ID context to accept external PSK - connections and to stop issuing unusable session tickets. - - *Viktor Dukhovni* - - * Added AVX512 optimized SHAKE x4 operations for ML-DSA on `x86_64`. - - *Marcel Cornu and Tomasz Kantecki* - - * EC key point format simplification. - - The point conversion form (compressed, uncompressed, or hybrid) - is now a single value on the `EC_GROUP` and round-trips - unchanged through import and export of `EC_KEY` objects. - - Freshly generated keys have their public point encoded in - uncompressed form. A `point-format` supplied at key generation - time via `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT` is - validated (an invalid value is rejected) but otherwise ignored - on the generated key. EC parameter generation continues to - honour the requested form on the group's generator; imported - keys keep their form. - - The `ec_point_formats` extension no longer affects TLS 1.2 - X.509 certificate selection or acceptance. OpenSSL now - accepts an EC certificate in any point form it can decode, - and sends any EC certificate it has regardless of point form. - TLS 1.3 disregards the extension entirely. - - The RFC 4492/8422 section 5.1.2 requirement that the peer's - point-format list contain "uncompressed" is now enforced on - both sides (previously client-only), and only when an ECC - TLS 1.2 ciphersuite is negotiated -- a missing "uncompressed" - is ignored under TLS 1.3 or with a non-ECC cipher. - - *Viktor Dukhovni* - - * Added unit tests setup activated via `enable-unit-tests` option. This works - only on platforms with ld `--wrap` support (Linux, BSD). - - *Jakub Zelenka* - - * Deprecated the `enable-unit-test` configure option and the - `SSL_test_functions()` function. Both will be removed in OpenSSL 5.0. - - *Jakub Zelenka* - * Added -testmode option for `s_time` app. *Jakub Zelenka* @@ -93,7 +41,7 @@ OpenSSL Releases *Adriano Sela Aviles* * SubjectPublicKeyInfo blobs whose AlgorithmIdentifier uses id-RSAES-OAEP - (`NID_rsaesOaep`, 1.2.840.113549.1.1.7) with a plain RSAPublicKey body + (NID_rsaesOaep, 1.2.840.113549.1.1.7) with a plain RSAPublicKey body are now decoded as RSA keys. This is required for interoperability with TPM 1.2 Endorsement Key certificates per TCG Credential Profiles V1.2 section 3.2.7. The OAEP AlgorithmIdentifier parameters are not @@ -116,17 +64,6 @@ OpenSSL Releases *Jakub Zelenka* - * Windows-on-Itanium (VC-WIN64I) support was dropped - the Itanium - architecture has been discontinued and the platform is no longer - supported or tested. - - *Bob Beck* - - * Windows CE support was dropped - Windows CE has been unsupported since - 2018 and does not have a modern C99 toolchain. - - *Bob Beck* - * Improved DTLS handshake robustness under UDP reordering by buffering and replaying early ChangeCipherSpec (CCS) records at the expected state. @@ -141,14 +78,6 @@ OpenSSL Releases *Bob Beck* - * `ASN1_STRING_set()` and `ASN1_STRING_length()` have been - deprecated. The replacement functions `ASN1_STRING_set_data()` or - `ASN1_STRING_set_string()`, and `ASN1_STRING_length_ex()` should be - used in their place. This prepares the ASN1_STRING type to support - modern size_t length values in the future. - - *Bob Beck* - * `EVP_CIPHER_CTX_get_num()` and `EVP_CIPHER_CTX_set_num()' have been deprecated. Refer to ossl-migration-guide(7) for more info. @@ -190,12 +119,6 @@ OpenSSL Releases *Bob Beck* - * Fixed X.509 verification of certificate chains that use DSA signatures - with SHA-384 or SHA-512 by registering `dsa_with_SHA384` and - `dsa_with_SHA512` in the signature-algorithm cross-reference table. - - *John Claus* - * Added AVX2 optimized ML-DSA NTT operations on `x86_64`. *Marcel Cornu and Tomasz Kantecki* @@ -271,11 +194,6 @@ OpenSSL Releases *Timo Keller* - * Added `EVP_KDF_CTX_get0_kdf()` and `EVP_KDF_CTX_get1_kdf()` functions - as a replacement for the now deprecated `EVP_KDF_CTX_kdf()`. - - *Leon Timmermans* - * Add `FIPS_mode()` as a convenience define to `EVP_default_properties_is_fips_enabled(NULL)`, which is shorthand to check whether the `fips=yes` property is currently enabled @@ -1350,9 +1268,7 @@ OpenSSL 4.0 *Tomáš Mráz* * Removed deprecated functions `ERR_get_state()`, `ERR_remove_state()` - and `ERR_remove_thread_state()`, as well as the `ERR_FLAG_MARK`, - `ERR_FLAG_CLEAR` and `ERR_NUM_ERRORS` macros. The `ERR_STATE` object is now - always opaque. + and `ERR_remove_thread_state()`. The `ERR_STATE` object is now always opaque. *Tomáš Mráz* @@ -4175,7 +4091,7 @@ breaking changes, and mappings for the large list of deprecated functions. * Fixed a bug in the function `OCSP_basic_verify` that verifies the signer certificate on an OCSP response. The bug caused the function in the case - where the (non-default) flag OCSP_NOCHECKS is used to return a positive + where the (non-default) flag OCSP_NOCHECKS is used to return a postivie response (meaning a successful verification) even in the case where the response signing certificate fails to verify. @@ -19973,7 +19889,7 @@ s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k The new configuration file reading functions are: NCONF_new, NCONF_free, NCONF_load, NCONF_load_fp, NCONF_load_bio, - NCONF_get_section, NCONF_get_string, NCONF_get_number + NCONF_get_section, NCONF_get_string, NCONF_get_numbre NCONF_default, NCONF_WIN32 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8101e47114..3813c1e23d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,37 +80,7 @@ guidelines: git push -f [ []] ``` - 2. Similarly, if a non-trivial portion of a contribution was created - using an AI tool, you must declare which agent and model were used. - This is done by adding `Assisted-by: {agent}:{model}` below the commit - message: - - ``` - One-line summary of change with AI-generated portions - - Assisted-by: Claude:claude-sonnet-4-6 - ``` - - Multiple Assisted-by trailers can be included if multiple tools were used: - - ``` - Assisted-by: Claude:claude-sonnet-4-6 - Assisted-by: ChatGPT:gpt-4o - Assisted-by: GitHub Copilot:gpt-4.1 - ``` - - You will need to have signed a v1.1 or later CLA in order to - include AI-generated content in your contribution. CLAs signed - after June 2026 will have the requisite clauses. - - Consult the [OpenSSL AI Code and Documentation Contribution - Policy] if an AI model assisted with the creation of your - contribution. - - [OpenSSL AI Code and Documentation Contribution - Policy]: - - 3. All source files should start with the following text (with + 2. All source files should start with the following text (with appropriate comment characters at the start of each line and the year(s) updated): @@ -123,14 +93,12 @@ guidelines: https://www.openssl.org/source/license.html ``` - 4. Patches should be as current as possible; expect to have to rebase + 3. Patches should be as current as possible; expect to have to rebase often. We do not accept merge commits, you will have to remove them (usually by rebasing) before it will be acceptable. - 5. Code provided should follow our [coding style](STYLE.md) and - [documentation policy](DOCUMENTATION.md) and compile without warnings when - using a --strict-warnings configuration. - + 4. Code provided should follow our [coding style] and [documentation policy] + and compile without warnings. Consistent formatting is enforced by using `clang-format` with configuration stored in [.clang-format](.clang-format). OpenSSL uses `WebKit` style. You can configure git pre-commit to automatically reformat your code with @@ -144,16 +112,19 @@ guidelines: Clean builds via GitHub Actions are required. They are started automatically whenever a PR is created or updated by committers. - 6. When at all possible, code contributions should include tests. These can + [coding style]: https://openssl-library.org/policies/technical/coding-style/ + [documentation policy]: https://openssl-library.org/policies/technical/documentation-policy/ + + 5. When at all possible, code contributions should include tests. These can either be added to an existing test, or completely new. Please see [test/README.md](test/README.md) for information on the test framework. - 7. New features or changed functionality must include + 6. New features or changed functionality must include documentation. Please look at the `.pod` files in `doc/man[1357]` for examples of our style. Run `make doc-nits` to make sure that your documentation changes are clean. - 8. For user visible changes (API changes, behaviour changes, ...), + 7. For user visible changes (API changes, behaviour changes, ...), consider adding a note in [CHANGES.md](CHANGES.md). This could be a summarising description of the change, and could explain the grander details. @@ -164,10 +135,10 @@ guidelines: with a specific release without having to sift through the higher noise ratio in git-log. - 9. Guidelines on how to integrate error output of new crypto library modules + 8. Guidelines on how to integrate error output of new crypto library modules can be found in [crypto/err/README.md](crypto/err/README.md). -10. Once your Pull Request gets to the stage of being reviewed fixup commits + 9. Once your Pull Request gets to the stage of being reviewed fixup commits should be used where possible. Fixup commits are squashed when the PR is finally merged. Fixup commits are done in the following way: @@ -190,11 +161,11 @@ guidelines: git log ``` -11. If a Pull Request addresses an [issue](https://github.com/openssl/openssl/issues/) +10. If a Pull Request addresses an [issue](https://github.com/openssl/openssl/issues/) the commit should include the line: ``` - Fixes: LINK + Fixes #XXXXX ``` - where LINK is the https link to the issue in github. + where XXXXX is the issue number. diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index 9c7261c3f2..a497bcce4f 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -61,6 +61,70 @@ sub vc_win32_info { return $vc_win32_info; } +my $vc_wince_info = {}; +sub vc_wince_info { + unless (%$vc_wince_info) { + # sanity check + $die->('%OSVERSION% is not defined') if (!defined(env('OSVERSION'))); + $die->('%PLATFORM% is not defined') if (!defined(env('PLATFORM'))); + $die->('%TARGETCPU% is not defined') if (!defined(env('TARGETCPU'))); + + # + # Idea behind this is to mimic flags set by eVC++ IDE... + # + my $wcevers = env('OSVERSION'); # WCENNN + my $wcevernum; + my $wceverdotnum; + if ($wcevers =~ /^WCE([1-9])([0-9]{2})$/) { + $wcevernum = "$1$2"; + $wceverdotnum = "$1.$2"; + } else { + $die->('%OSVERSION% value is insane'); + $wcevernum = "{unknown}"; + $wceverdotnum = "{unknown}"; + } + my $wcecdefs = "-D_WIN32_WCE=$wcevernum -DUNDER_CE=$wcevernum"; # -D_WIN32_WCE=NNN + my $wcelflag = "/subsystem:windowsce,$wceverdotnum"; # ...,N.NN + + my $wceplatf = env('PLATFORM'); + + $wceplatf =~ tr/a-z0-9 /A-Z0-9_/; + $wcecdefs .= " -DWCE_PLATFORM_$wceplatf"; + + my $wcetgt = env('TARGETCPU'); # just shorter name... + SWITCH: for($wcetgt) { + /^X86/ && do { $wcecdefs.=" -Dx86 -D_X86_ -D_i386_ -Di_386_"; + $wcelflag.=" /machine:X86"; last; }; + /^ARMV4[IT]/ && do { $wcecdefs.=" -DARM -D_ARM_ -D$wcetgt"; + $wcecdefs.=" -DTHUMB -D_THUMB_" if($wcetgt=~/T$/); + $wcecdefs.=" -QRarch4T -QRinterwork-return"; + $wcelflag.=" /machine:THUMB"; last; }; + /^ARM/ && do { $wcecdefs.=" -DARM -D_ARM_ -D$wcetgt"; + $wcelflag.=" /machine:ARM"; last; }; + /^MIPSIV/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000 -D$wcetgt"; + $wcecdefs.=" -D_MIPS64 -QMmips4 -QMn32"; + $wcelflag.=" /machine:MIPSFPU"; last; }; + /^MIPS16/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000 -D$wcetgt"; + $wcecdefs.=" -DMIPSII -QMmips16"; + $wcelflag.=" /machine:MIPS16"; last; }; + /^MIPSII/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000 -D$wcetgt"; + $wcecdefs.=" -QMmips2"; + $wcelflag.=" /machine:MIPS"; last; }; + /^R4[0-9]{3}/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000"; + $wcelflag.=" /machine:MIPS"; last; }; + /^SH[0-9]/ && do { $wcecdefs.=" -D$wcetgt -D_${wcetgt}_ -DSHx"; + $wcecdefs.=" -Qsh4" if ($wcetgt =~ /^SH4/); + $wcelflag.=" /machine:$wcetgt"; last; }; + { $wcecdefs.=" -D$wcetgt -D_${wcetgt}_"; + $wcelflag.=" /machine:$wcetgt"; last; }; + } + + $vc_wince_info = { cppflags => $wcecdefs, + lflags => $wcelflag }; + } + return $vc_wince_info; +} + # Helper functions for the VMS configs my $vms_info = {}; sub vms_info { @@ -906,6 +970,7 @@ my %targets = ( perlasm_scheme => 'void', }, "linux64-sparcv9" => { + # GCC 3.1 is a requirement inherit_from => [ "linux-generic64" ], cflags => add("-m64 -mcpu=ultrasparc"), cxxflags => add("-m64 -mcpu=ultrasparc"), @@ -1434,7 +1499,7 @@ my %targets = ( #### Visual C targets # -# Win64 target, WIN64A denotes AMD64 +# Win64 targets, WIN64I denotes IA-64/Itanium and WIN64A - AMD64 # # Note about /wd4090, disable warning C4090. This warning returns false # positives in some situations. Disabling it altogether masks both @@ -1542,6 +1607,17 @@ my %targets = ( }), bn_ops => add("SIXTY_FOUR_BIT"), }, + "VC-WIN64I" => { + inherit_from => [ "VC-WIN64-common" ], + AS => "ias", + ASFLAGS => "-d debug", + asoutflag => "-o ", + sys_id => "WIN64I", + uplink_arch => 'ia64', + asm_arch => 'ia64', + perlasm_scheme => "ias", + multilib => "-ia64", + }, "VC-WIN64A" => { inherit_from => [ "VC-WIN64-common" ], AS => sub { vc_win64a_info()->{AS} }, @@ -1569,6 +1645,53 @@ my %targets = ( # some installation path heuristics in windows-makefile.tmpl... build_scheme => add("VC-WOW", { separator => undef }), }, + "VC-CE" => { + inherit_from => [ "VC-common" ], + CFLAGS => add(picker(debug => "/Od", + release => "/O1i")), + CPPDEFINES => picker(debug => [ "DEBUG", "_DEBUG" ]), + LDFLAGS => add("/nologo /opt:ref"), + cflags => + combine('/GF /Gy', + sub { vc_wince_info()->{cflags}; }, + sub { `cl 2>&1` =~ /Version ([0-9]+)\./ && $1>=14 + ? ($disabled{shared} ? " /MT" : ($disabled{"static-vcruntime"} ? " /MD" : "")) + : " /MC"; }), + cppflags => sub { vc_wince_info()->{cppflags}; }, + lib_defines => add("NO_CHMOD", "OPENSSL_SMALL_FOOTPRINT"), + lib_cppflags => sub { vc_wince_info()->{cppflags}; }, + includes => + add(combine(sub { defined(env('WCECOMPAT')) + ? '$(WCECOMPAT)/include' : (); }, + sub { defined(env('PORTSDK_LIBPATH')) + ? '$(PORTSDK_LIBPATH)/../../include' + : (); })), + lflags => add(combine(sub { vc_wince_info()->{lflags}; }, + sub { defined(env('PORTSDK_LIBPATH')) + ? "/entry:mainCRTstartup" : (); })), + sys_id => "WINCE", + bn_ops => add("BN_LLONG"), + ex_libs => add(sub { + my @ex_libs = (); + push @ex_libs, 'ws2.lib' unless $disabled{sock}; + push @ex_libs, 'crypt32.lib'; + if (defined(env('WCECOMPAT'))) { + my $x = '$(WCECOMPAT)/lib'; + if (-f "$x/env('TARGETCPU')/wcecompatex.lib") { + $x .= '/$(TARGETCPU)/wcecompatex.lib'; + } else { + $x .= '/wcecompatex.lib'; + } + push @ex_libs, $x; + } + push @ex_libs, '$(PORTSDK_LIBPATH)/portlib.lib' + if (defined(env('PORTSDK_LIBPATH'))); + push @ex_libs, '/nodefaultlib coredll.lib corelibc.lib' + if (env('TARGETCPU') =~ /^X86|^ARMV4[IT]/); + return join(" ", @ex_libs); + }), + }, + #### MinGW "mingw-common" => { inherit_from => [ 'BASE_unix' ], @@ -1580,7 +1703,7 @@ my %targets = ( cppflags => combine("-DUNICODE -D_UNICODE -DWIN32_LEAN_AND_MEAN", threads("-D_MT")), lib_cppflags => "-DL_ENDIAN", - ex_libs => add("-lws2_32 -lgdi32 -lcrypt32 -lbcrypt"), + ex_libs => add("-lws2_32 -lgdi32 -lcrypt32"), thread_scheme => "winthreads", dso_scheme => "win32", shared_target => "mingw-shared", diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index 3f9d04b6d0..de345a5e8a 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -11,7 +11,6 @@ our $makedepcmd = platform->makedepcmd(); sub windowsdll { $config{target} =~ /^(?:Cygwin|mingw)/ } - sub run_on_windows { $^O =~ /^(?:cygwin|msys|MSWin32)/ } # Shared AIX support is special. We put libcrypto[64].so.ver into # libcrypto.a and use libcrypto_a.a as static one, unless using @@ -504,9 +503,6 @@ BIN_LDFLAGS={- join(' ', $target{bin_lflags} || (), '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) -CMOCKA_LIBS={- $config{cmocka_libs} // '' -} -DETOURS_LIBS={- $config{detours_libs} // '' -} - # CPPFLAGS_Q is used for one thing only: to build up buildinf.h CPPFLAGS_Q={- $cppflags1 =~ s|([\\"])|\\$1|g; $cppflags2 =~ s|([\\"])|\\$1|g; @@ -660,8 +656,8 @@ clean: libclean ## Clean the workspace, keep the configuration -o -path './python-ecdsa' \ -o -path './tlsfuzzer' \ -o -path './tlslite-ng' \ - -o -path './wycheproof' \) \ - -prune \ + -o -path './wycheproof' \ + -prune \) \ -o \! -type d \ \( -name '*{- platform->depext() -}' \ -o -name '*{- platform->objext() -}' \ @@ -1583,24 +1579,12 @@ EOF my $section = $1; my $name = uc basename($args{src}, ".$section"); my $pod = $gen0; - - if ($config{manpage_format} eq "mdoc") { - return <<"EOF"; -$args{src}: $pod - pod2mdoc -n $name -s $section\$(MANSUFFIX) \\ - -d \$(RELEASE_DATE) \\ - $pod >\$\@ -EOF - } elsif ($config{manpage_format} eq "roff") { - return <<"EOF"; + return <<"EOF"; $args{src}: $pod pod2man --name=$name --section=$section\$(MANSUFFIX) --center=OpenSSL \\ --date=\$(RELEASE_DATE) --release=\$(VERSION) \\ $pod >\$\@ EOF - } else { - die "Unhandled manpage format: $config{manpage_format}"; - } } elsif (platform->isdef($args{src})) { # # Linker script-ish generator @@ -1911,27 +1895,13 @@ $import: $full EOF } } - if (!run_on_windows()) { - $recipe .= <<"EOF"; + $recipe .= <<"EOF"; $full: $fulldeps \$(CC) \$(LIB_CFLAGS) $linkflags\$(LIB_LDFLAGS)$shared_soname$shared_imp \\ -o $full$shared_def \\ $fullobjs \\ $linklibs \$(LIB_EX_LIBS) EOF - } else { - $recipe .= <<"EOF"; -$full: $fulldeps - \$(file >\$@.lst, \\ - $fullobjs \\ - ) - \$(CC) \$(LIB_CFLAGS) $linkflags\$(LIB_LDFLAGS)$shared_soname$shared_imp \\ - -o $full$shared_def \\ - @\$@.lst \\ - $linklibs \$(LIB_EX_LIBS) - rm -f \$@.lst -EOF - } if (windowsdll()) { $recipe .= <<"EOF"; rm -f apps/$full @@ -2036,15 +2006,6 @@ EOF push @linkdirs, $d unless grep { $d eq $_ } @linkdirs; } } - my $wrapflags = ''; - if (defined $unified_info{wraps}->{$args{bin}}) { - $wrapflags = ' ' . join(' ', - map { "-Wl,--wrap=$_" } - @{$unified_info{wraps}->{$args{bin}}}); - } - my $utlibs = $unified_info{unit_test_libs}->{$args{bin}}; - $utlibs = $utlibs ne '' ? ' ' . $utlibs : '' if defined $utlibs; - $utlibs //= ''; my $linkflags = join("", map { $_." " } @linkdirs); my $linklibs = join("", map { $_." " } @linklibs); my $cmd = '$(CC)'; @@ -2062,10 +2023,10 @@ EOF return <<"EOF"; $bin: $deps rm -f $bin - \$\${LDCMD:-$cmd} $cmdflags $linkflags\$(BIN_LDFLAGS)$wrapflags \\ + \$\${LDCMD:-$cmd} $cmdflags $linkflags\$(BIN_LDFLAGS) \\ -o $bin \\ $objs \\ - $linklibs\$(BIN_EX_LIBS)$utlibs + $linklibs\$(BIN_EX_LIBS) EOF } sub in2script { diff --git a/Configurations/windows-makefile.tmpl b/Configurations/windows-makefile.tmpl index a7f2b6652b..16fed4670d 100644 --- a/Configurations/windows-makefile.tmpl +++ b/Configurations/windows-makefile.tmpl @@ -380,9 +380,6 @@ BIN_LDFLAGS={- join(' ', $target{bin_lflags} || (), '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) -CMOCKA_LIBS={- $config{cmocka_libs} // '' -} -DETOURS_LIBS={- $config{detours_libs} // '' -} - # CPPFLAGS_Q is used for one thing only: to build up buildinf.h CPPFLAGS_Q={- $cppflags1 =~ s|([\\"])|\\$1|g; $cppflags2 =~ s|([\\"])|\\$1|g; @@ -1004,14 +1001,11 @@ EOF my $ress = join($target{ld_resp_delim}, @ress); my $linklibs = join("", map { "$_$target{ld_resp_delim}" } @deps); my $deps = join(" ", @objs, @ress, @deps); - my $utlibs = $unified_info{unit_test_libs}->{$args{bin}}; - $utlibs = (defined $utlibs && $utlibs ne '') - ? "$utlibs$target{ld_resp_delim}" : ''; return <<"EOF"; $bin: $deps IF EXIST $bin.manifest DEL /F /Q $bin.manifest \$(LD) \$(LDFLAGS) \$(BIN_LDFLAGS) @<< -$objs$target{ld_resp_delim}\$(LDOUTFLAG)$bin$target{ldpostoutflag}$target{ld_resp_delim}$utlibs$linklibs\$(BIN_EX_LIBS)$target{ldresflag}$target{ldresflag}$ress +$objs$target{ld_resp_delim}\$(LDOUTFLAG)$bin$target{ldpostoutflag}$target{ld_resp_delim}$linklibs\$(BIN_EX_LIBS)$target{ldresflag}$target{ldresflag}$ress << IF EXIST $bin.manifest \\ \$(MT) \$(MTFLAGS) \$(MTINFLAG)$bin.manifest \$(MTOUTFLAG)$bin diff --git a/Configure b/Configure index 75f1f6b67b..918a7c7cc0 100755 --- a/Configure +++ b/Configure @@ -27,7 +27,7 @@ use OpenSSL::config; my $orig_death_handler = $SIG{__DIE__}; $SIG{__DIE__} = \&death_handler; -my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]thread-pool] [[no-]default-thread-pool] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] [--manpage-format={roff,mdoc}] [--help] os/compiler[:flags]\n"; +my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]thread-pool] [[no-]default-thread-pool] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] [--help] os/compiler[:flags]\n"; my $banner = <<"EOF"; @@ -295,7 +295,6 @@ my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl")); my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR'; -$config{manpage_format} = "roff"; $config{sourcedir} = abs2rel($srcdir, $blddir); $config{builddir} = abs2rel($blddir, $blddir); # echo -n 'holy hand grenade of antioch' | openssl sha256 @@ -578,7 +577,6 @@ my @disablables_features = ( "ubsan", "ui-console", "unit-test", - "unit-tests", "uplink", "weak-ssl-ciphers", "zlib-dynamic", @@ -656,7 +654,6 @@ our %disabled = ( # "what" => "comment" "trace" => "default", "ubsan" => "default", "unit-test" => "default", - "unit-tests" => "default", "weak-ssl-ciphers" => "default", "zlib" => "default", "zlib-dynamic" => "default", @@ -726,7 +723,7 @@ my @disable_cascades = ( "stdio" => [ "apps", "egd" ], "apps" => [ "tests" ], - "tests" => [ "external-tests", "unit-tests" ], + "tests" => [ "external-tests" ], "comp" => [ "zlib", "brotli", "zstd" ], "sm3" => [ "sm2" ], sub { !$disabled{"unit-test"} } => [ "heartbeats" ], @@ -1045,10 +1042,6 @@ while (@argvcopy) { $config{build_type} = "release"; } - elsif (/^--manpage-format=(mdoc|roff)$/) - { - $config{manpage_format}="$1"; - } elsif (/^--pgo$/) { $config{build_type} = "pgo"; @@ -1122,22 +1115,6 @@ while (@argvcopy) { $withargs{fuzzer_include}=$1; } - elsif (/^--with-cmocka-lib=(.*)$/) - { - $withargs{cmocka_lib}=$1; - } - elsif (/^--with-cmocka-include=(.*)$/) - { - $withargs{cmocka_include}=$1; - } - elsif (/^--with-detours-lib=(.*)$/) - { - $withargs{detours_lib}=$1; - } - elsif (/^--with-detours-include=(.*)$/) - { - $withargs{detours_include}=$1; - } elsif (/^--with-rand-seed=(.*)$/) { foreach my $x (split(m|,|, $1)) @@ -1694,13 +1671,8 @@ unless ($disabled{asan} || defined $detected_sanitizers{asan}) { $config{target} =~ /^VC-/ ? "/fsanitize=address" : "-fsanitize=address"; } -my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); - unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) { push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC"; - if ($predefined_C{__clang__}) { - push @{$config{cflags}}, "-fno-sanitize=function"; - } } unless ($disabled{msan} || defined $detected_sanitizers{msan}) { @@ -1780,6 +1752,7 @@ if ($target{sys_id} ne "") push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}"; } +my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); my %predefined_CXX = $config{CXX} ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX}) : (); @@ -1940,29 +1913,6 @@ unless ($disabled{winstore}) { push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls}); -# Keywords accepted in a build.info UNIT_TEST[] link set. -my @unit_test_keywords = qw(cmocka detours); - -unless ($disabled{"unit-tests"}) { - if ($target =~ /^linux/ || $target =~ /^BSD/) { - $config{cmocka_includes} = - $withargs{cmocka_include} ? [$withargs{cmocka_include}] : []; - $config{cmocka_libs} = $withargs{cmocka_lib} - ? "-L$withargs{cmocka_lib} -lcmocka" : "-lcmocka"; - } elsif ($target =~ /^VC-/) { - $config{cmocka_includes} = - $withargs{cmocka_include} ? [$withargs{cmocka_include}] : []; - $config{cmocka_libs} = $withargs{cmocka_lib} - ? "/LIBPATH:$withargs{cmocka_lib} cmocka.lib" : "cmocka.lib"; - $config{detours_includes} = - $withargs{detours_include} ? [$withargs{detours_include}] : []; - $config{detours_libs} = $withargs{detours_lib} - ? "/LIBPATH:$withargs{detours_lib} detours.lib" : "detours.lib"; - } else { - disable('no-unit-test-support', 'unit-tests'); - } -} - # Get the extra flags used when building shared libraries and modules. We # do this late because some of them depend on %disabled. @@ -2187,8 +2137,6 @@ if ($builder eq "unified") { my %includes = (); my %defines = (); my %depends = (); - my %unit_tests = (); - my %wraps = (); my %generate = (); my %imagedocs = (); my %htmldocs = (); @@ -2444,16 +2392,6 @@ if ($builder eq "unified") { \$attributes{depends}, $+{ATTRIBS}, tokenize($expand_variables->($+{VALUE}))) if !@skip || $skip[$#skip] > 0; }, - qr/^\s* UNIT_TEST ${index_re} \s* = \s* ${value_re} \s* $/x - => sub { $push_to->(\%unit_tests, $expand_variables->($+{INDEX}), - undef, undef, - tokenize($expand_variables->($+{VALUE}))) - if !@skip || $skip[$#skip] > 0; }, - qr/^\s* WRAP ${index_re} \s* = \s* ${value_re} \s* $/x - => sub { $push_to->(\%wraps, $expand_variables->($+{INDEX}), - undef, undef, - tokenize($expand_variables->($+{VALUE}))) - if !@skip || $skip[$#skip] > 0; }, qr/^\s* GENERATE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x => sub { $push_to->(\%generate, $expand_variables->($+{INDEX}), \$attributes{generate}, $+{ATTRIBS}, @@ -2740,27 +2678,6 @@ if ($builder eq "unified") { } } - foreach my $dest (keys %wraps) { - my $ddest = cleanfile($buildd, $dest, $blddir); - foreach my $fn (@{$wraps{$dest}}) { - push @{$unified_info{wraps}->{$ddest}}, $fn; - } - } - - foreach my $dest (keys %unit_tests) { - my $ddest = cleanfile($buildd, $dest, $blddir); - foreach my $kw (@{$unit_tests{$dest}}) { - die "***** Unknown keyword '$kw' in UNIT_TEST[$dest] at $sourced/$f\n" - unless grep { $_ eq $kw } @unit_test_keywords; - } - $unified_info{unit_tests}->{$ddest} = - [ @{$unit_tests{$dest}} ]; - } - # WRAP implies cmocka unless an explicit UNIT_TEST set was given - foreach my $dest (keys %{$unified_info{wraps} // {}}) { - $unified_info{unit_tests}->{$dest} //= [ "cmocka" ]; - } - foreach my $section (keys %imagedocs) { foreach (@{$imagedocs{$section}}) { my $imagedocs = cleanfile($buildd, $_, $blddir); @@ -3093,28 +3010,6 @@ EOF } } -# Attach cmocka (and, on Windows, Detours) include paths to unit tests, -# based on each test's UNIT_TEST[] link set. -if (!$disabled{"unit-tests"}) { - while (my ($dest, $libs) = each %{$unified_info{unit_tests} // {}}) { - my %want = map { $_ => 1 } @$libs; - push @{$unified_info{includes}->{$dest}}, @{$config{cmocka_includes}} - if $want{cmocka} && @{$config{cmocka_includes} // []}; - push @{$unified_info{includes}->{$dest}}, @{$config{detours_includes}} - if $want{detours} && @{$config{detours_includes} // []}; - } -} - -if (!$disabled{"unit-tests"}) { - foreach my $dest (sort keys %{$unified_info{unit_tests} // {}}) { - my %want = map { $_ => 1 } @{$unified_info{unit_tests}->{$dest}}; - my @resolved; - push @resolved, '$(CMOCKA_LIBS)' if $want{cmocka} && $config{cmocka_libs}; - push @resolved, '$(DETOURS_LIBS)' if $want{detours} && $config{detours_libs}; - $unified_info{unit_test_libs}->{$dest} = join(' ', @resolved); - } -} - # For the schemes that need it, we provide the old *_obj configs # from the *_asm_obj ones foreach (grep /_(asm|aux)_src$/, keys %target) { diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md deleted file mode 100644 index 05bbb8564c..0000000000 --- a/DOCUMENTATION.md +++ /dev/null @@ -1,194 +0,0 @@ -OpenSSL Documentation Policy -============================ - -This document describes the code documentation and commenting requirements -for the OpenSSL project. - -The project's documentation is about making the libraries and tools more -accessible to our users and making the code more maintainable. This policy -applies to new submissions; existing code does not uniformly conform to it -and will be brought up to standard gradually. - -Any non-trivial change to existing code must bring the affected code into -conformance with this policy as part of the same change. In particular, -renaming or relocating functions, changes to public APIs, and any change -that would render an existing POD page or in-source comment inaccurate -require the corresponding documentation to be updated. This includes -adding documentation that was previously absent where the change brings -the affected code within the scope of this policy. - -The form and style of code comments themselves -- comment markers, layout, -the use of `/**` and `/*-` blocks, doxygen markup, the structure of the -sample multi-line comment, and similar -- are described in -[STYLE.md](STYLE.md). This file describes what *must* be documented and -where; [STYLE.md](STYLE.md) describes how code comments look. - -Command line commands and arguments ------------------------------------ - -All new commands, as well as new or modified arguments to existing -commands, must be documented in the `doc/man1` directory. This -documentation is in POD format. - -Public symbols in the libraries -------------------------------- - -All new public symbols must be documented in a POD manual page in the -`doc/man3` directory. This includes types, macros, and functions. - -The allowed exceptions are: - -- guard macros preventing a header file being included twice -- new symbols generated automatically via `make update` (errors, objects, etc.) - -Each public function's declaration in its public header must carry a -doxygen comment block. The block's `@see` must include the function's -own manual page (`name(3)`) and may include additional manual pages -that a caller needs to use the function correctly. The doxygen block -is a navigation aid pointing to the canonical reference documentation -in the corresponding POD file; see [STYLE.md](STYLE.md) for the -doxygen form. - -Overviews, conventions, et al ------------------------------ - -Where additional user-facing information is required, it should be -included in the `doc/man7` section. This includes, but is not limited to: - -- algorithm descriptions and parameters -- architectural and subsystem overviews -- user guides and tutorials -- conventions and reference material (environment variables, glossary, - threading rules, file format conventions) - -Internal functions, structures, globals and macros --------------------------------------------------- - -Internal functions, structures, globals and macros are non-public -items declared in any header that is not part of the public API. -These include items declared in: - -- `include/internal/` (shared across subsystems); -- `include/crypto/` (cryptographic internals); -- per-directory local headers (for example, `crypto/asn1/asn1_local.h`) - shared between source files in a single subdirectory. - -These should all be documented at the declaration site -- that is, -in the header that declares them -- using a doxygen-style comment -block. For functions, this places the comment at the prototype, -where editor tooling (clangd and similar) can surface it to readers -at every call site. The comment should describe the purpose and, -for functions, the input and output arguments and the return value. -See [STYLE.md](STYLE.md) for the doxygen conventions used by OpenSSL. - -For *trivial* items, where their operation is obvious from their -implementation, the documentation requirement is not mandated. The -following are generally representative of trivial items, however it is -quite possible for any of these to be non-trivial in specific instances -and therefore require documentation: - -- `OSSL_DISPATCH` tables -- upref functions -- free functions -- simple getter/setter functions -- wrappers for other functions (a function that calls a more recent - `_ex` variant or a group of functions that call a common internal - routine) - -For structures, each of the fields should be commented stating its -purpose. Again, a *trivial* exception applies where the purpose is -obvious. Some representative examples: - -- `OSSL_LIB_CTX *ctx;` where there is only one library context referenced - in the structure. -- `struct *next;` in a linked list implementation. -- `CRYPTO_REF_COUNT refcnt;` - -File-local items ----------------- - -These are functions, structures, globals, and macros that are local -to a single C file: `static` functions, file-scope variables, -structures, and macros defined inside a `.c` file with no declaration -in any header. - -These should all be documented at the point of definition. Follow the -same rules and exceptions as for internal items above. In some cases -slightly more leniency with respect to *trivial* can be tolerated. - -Code comments -------------- - -The form, style, and content guidance for code comments are described in -[STYLE.md](STYLE.md). Comments are required at the points described in -the internal and static sections above, subject to the *trivial* -exception, and at the additional points described in -[STYLE.md](STYLE.md). - -Assembly code -------------- - -Assembly code should include a good description of the algorithm and -approach being used. This should be followed by a performance comparison -and then the assembly code itself. The assembly code should be well -commented, but it is not necessary to comment every line. A comment -describing each block of code suffices. - -For pure-assembly modules (`.s` files and the perlasm scripts that -generate them), comments use the native syntax of the assembler or -generator (typically `#`). Doxygen-style markup does not apply here; -the algorithm description, performance comparison, and per-block -comments described above are still required. - -For assembly that appears inline inside a C file (within an `asm()` -statement, for example), the surrounding C function is documented -with doxygen-style C comments as for any other C code; see -[STYLE.md](STYLE.md). Comments inside the `asm()` body itself use -plain C `/* */` comments. - -There are no *trivial* exceptions for assembly code. - -Configure options ------------------ - -New options added to the configuration scripts must be documented in the -[INSTALL.md](INSTALL.md) file. - -Changes and news ----------------- - -Significant modifications should be documented in the -[CHANGES.md](CHANGES.md) file. - -Very significant features and changes should be documented in the -[NEWS.md](NEWS.md) file. - -In both cases, the added note should be short and to the point, and -should be written for users of the library, focusing on impact rather -than implementation details. - -Automated sanity checking -------------------------- - -The `make doc-nits` command should be run before submitting a pull -request and any problems it locates must be addressed. - -Language --------- - -The language used for documentation shall be *British English*. - -In general the language, abbreviations, layout and formatting should also -correspond to the -[LDP](https://openssl-library.org/policies/general/glossary/#ldp) -guidelines. - -Common sense ------------- - -Comments and documentation are to improve readability and comprehension. -Where the code is obvious, there is no need to include a comment. -However, common sense applies: always err in favour of including more -comments than less or none. Code that you have just written that is -*obvious* will not necessarily be to someone else two years later. See -[STYLE.md](STYLE.md) for the form and content of code comments. diff --git a/INSTALL.md b/INSTALL.md index 5d132b49f0..b44e2705c0 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -169,11 +169,13 @@ issue the following commands to build OpenSSL. $ nmake test As mentioned in the [Choices](#choices) section, you need to pick one -of the Configure targets in the first command. +of the four Configure targets in the first command. Most likely you will be using the `VC-WIN64A`/`VC-WIN64A-HYBRIDCRT` target for 64bit Windows binaries (AMD64) or `VC-WIN32`/`VC-WIN32-HYBRIDCRT` for 32bit Windows binaries (X86). +The other two options are `VC-WIN64I` (Intel IA64, Itanium) and +`VC-CE` (Windows CE) are rather uncommon nowadays. Installing OpenSSL ------------------ @@ -426,22 +428,6 @@ The names of the libraries are: * brotlidec.lib * brotlienc.lib -### with-cmocka-include - - --with-cmocka-include=DIR - -The directory for the location of the cmocka include file. This option is only -necessary if [enable-unit-tests](#enable-unit-tests) is used and the include -file is not already on the system include path. - -### with-cmocka-lib - - --with-cmocka-lib=DIR - -The directory containing the cmocka library. This option is only necessary if -[enable-unit-tests](#enable-unit-tests) is used and the library is not already -on the system library path. - ### with-zlib-include --with-zlib-include=DIR @@ -832,12 +818,6 @@ external test suites are currently supported: See the file [test/README-external.md](test/README-external.md) for further details. -### enable-unit-tests - -Enable building and running unit tests. - -This works only on platforms supporting ld `--wrap` option like Linux and BSD. - ### no-filenames Don't compile in filename and line number information (e.g. for errors and @@ -1115,12 +1095,10 @@ The User Interface console method enables text based console prompts. ### enable-unit-test -Enable exposing SSL_test_functions for overwriting ssl_init_wbio_buffer. +Enable additional unit test APIs. This should not typically be used in production deployments. -This option is deprecated and will be removed in OpenSSL 5.0. - ### no-uplink Don't build support for UPLINK interface. @@ -1223,8 +1201,7 @@ Build without support for the specified algorithm. The `ripemd` algorithm is deprecated and if used is synonymous with `rmd160`. -Compiler-specific options -------------------------- +### Compiler-specific options -Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static @@ -1255,17 +1232,7 @@ encoding. Take note of the [Environment Variables](#environment-variables) documentation below and how these flags interact with those variables. -Miscellaneous options ---------------------- - -### --manpage-format - -Specify a specific output manpage format. The supported output types are mandoc -and *roff. The *roff output format is the default for legacy and portability -reasons. - -Environment Variables ---------------------- +### Environment Variables VAR=value @@ -1342,18 +1309,10 @@ If `CC` is set, it is advisable to also set `CXX` to ensure both the C and C++ compiler are in the same "family". This becomes relevant with `enable-external-tests` and `enable-buildtest-c++`. -Reconfigure ------------ +### Reconfigure -### Make targets - - `$ make reconf` - -or - - `$ make reconfigure` - -### Description + reconf + reconfigure Reconfigure from earlier data. @@ -1971,8 +1930,9 @@ on Cygwin, shared libraries are named `cygcrypto-1.1.dll` and `cygssl-1.1.dll` with import libraries `libcrypto.dll.a` and `libssl.dll.a`. On Windows build with MSVC or using MingW, shared libraries are named -`libcrypto-1_1.dll` and `libssl-1_1.dll` for 32-bit Windows, and -`libcrypto-1_1-x64.dll` and `libssl-1_1-x64.dll` for 64-bit x86_64 Windows. +`libcrypto-1_1.dll` and `libssl-1_1.dll` for 32-bit Windows, +`libcrypto-1_1-x64.dll` and `libssl-1_1-x64.dll` for 64-bit x86_64 Windows, +and `libcrypto-1_1-ia64.dll` and `libssl-1_1-ia64.dll` for IA64 Windows. With MSVC, the import libraries are named `libcrypto.lib` and `libssl.lib`, while with MingW, they are named `libcrypto.dll.a` and `libssl.dll.a`. diff --git a/NEWS.md b/NEWS.md index 239f195de0..278ec1309d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -31,8 +31,6 @@ OpenSSL 4.1 * API calls `CRYPTO_atomic_load_ptr`, `CRYPTO_atomic_store_ptr`, and `CRYPTO_atomic_cmp_exch_ptr` have been added. - * Fixed verification of DSA certificates signed with SHA-384 or SHA-512. - OpenSSL 4.0 ----------- diff --git a/README.md b/README.md index fcefc19923..28e2a5e51a 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The OpenSSL toolkit includes: basis of the TLS implementation, but can also be used independently. - **openssl** - the OpenSSL command line tool, a Swiss Army knife for cryptographic tasks, + the OpenSSL command line tool, a swiss army knife for cryptographic tasks, testing and analyzing. It can be used for - creation of key parameters - creation of X.509 certificates, CSRs and CRLs @@ -150,10 +150,11 @@ The manual pages for the master branch and all current stable releases are available online. - [OpenSSL master](https://docs.openssl.org/master/) -- [OpenSSL 4.0](https://docs.openssl.org/4.0/) - [OpenSSL 3.6](https://docs.openssl.org/3.6/) - [OpenSSL 3.5](https://docs.openssl.org/3.5/) - [OpenSSL 3.4](https://docs.openssl.org/3.4/) +- [OpenSSL 3.3](https://docs.openssl.org/3.3/) +- [OpenSSL 3.2](https://docs.openssl.org/3.2/) - [OpenSSL 3.0](https://docs.openssl.org/3.0/) Demos diff --git a/STYLE.md b/STYLE.md deleted file mode 100644 index 2bedc42a5a..0000000000 --- a/STYLE.md +++ /dev/null @@ -1,1133 +0,0 @@ -OpenSSL Style Guide -=================== - -Applicability -------------- - -New code in OpenSSL is expected to follow the conventions in this -guide. Existing code does not uniformly comply and is being brought -up to standard gradually; non-trivial changes to existing code -should bring the affected area into compliance. - -When bringing an area into compliance as part of a larger change, -do so in a separate commit -- typically one that lands first, so -that the substantive change then operates on already-compliant -code. Combining a compliance sweep with a behaviour change in one -commit makes the diff hard to review and hard to revert. - -Do not bring code into compliance as part of a bug fix. Make the -minimal change that fixes the bug. This holds for any bug fix, and -especially for one that may be backported to a stable release -branch -- and at the time of the fix you often cannot know whether -it will be. Mixing compliance changes into a fix complicates -backporting and makes the change larger than it needs to be. Leave -any compliance work for a separate change. - -The language is C99 (ISO/IEC 9899:1999). More modern C versions -are not yet supported on every platform OpenSSL targets and -should be avoided. - -Formatting ----------- - -OpenSSL follows the -[WebKit coding style for C code](https://webkit.org/code-style-guidelines/). -In cases where the WebKit guide gives different rules for C and C++, -OpenSSL uses the C variant. - -Whitespace, indentation, brace placement, line wrapping, alignment and -the other mechanical aspects of formatting are enforced by `clang-format` -using the [`.clang-format`](.clang-format) file at the top of this -repository. The configuration is the WebKit C style with a small set -of OpenSSL-specific customisations (notably the list of project -typedefs, the `STACK_OF` / `LHASH_OF` type macros, and the list of -statement-shaped macros). - -Run `clang-format` on your changes before submitting; the output of -`clang-format` is deemed correct. See -[CONTRIBUTING.md](CONTRIBUTING.md) for the tooling (`.pre-commit-config.yaml`, -the `util/reformat-patches.sh` helper, and editor integrations). - -In rare situations it may be necessary to disable `clang-format` on a -piece of code. This may be done with paired comments: - -```c -/* clang-format off */ -I am doing something nasty here. -Reviewers should be triggered. -/* clang-format on */ -``` - -This should be used sparingly, and should not be used if there is any -other way to do what you are doing. - -Multi-line comment blocks have an additional clang-format opt-out -via the `/**` and `/*-` markers; see [Comments](#comments). - -Naming ------- - -### Functions and variables - -A name describes what the identifier holds or what it does. -Match the name to its role: a variable holding an `X509 *` is -typically `cert`; one holding an `X509_STORE_CTX *` is typically -`ctx`; a function that counts the number of active users is -called `count_active_users()`, not `cntusr()`. Use whole words -when there is no established short form, and reuse the same -name across the codebase for the same concept rather than -inventing synonyms. - -Names use lowercase with underscores (snake_case). For public -functions, snake_case applies to the portion of the name after -the uppercase subsystem prefix (see below). Do not begin a -name with an underscore; identifiers starting with an -underscore are reserved by the C standard in various contexts -and can collide with toolchain or system identifiers. - -For variables, OpenSSL has well-established short forms that -are fine to use without further qualification: `ctx`, `ptr`, -`len`, `buf`, `cert`, `key`, `pkey`, `ret`, `tmp`, and similar. -Use these in preference to longer forms; do not coin a new -variant when one of these already covers the meaning. Use the -suffix `_count` for a number of items, `_len` for a byte length, -and `_size` for a size in bytes; do not invent variants like -`num_X`, `X_length`, or `X_bytes` when one of these already -applies. - -A variable that mirrors notation from a standard, RFC, paper, -or other authoritative specification being implemented may use -whatever name the spec uses (for example, `n`, `e`, `d` for RSA -parameters, or `salt` and `info` for HKDF). Document the spec -citation and which variables come from it in the function or -file doxygen comment; see [Doxygen comments](#doxygen-comments) -for the form. - -Outside spec-mirroring, single letters are appropriate only as -loop counters (`i`, `j`, `k`). - -For functions, OpenSSL names follow a `PREFIX_[OBJECT_]action()` -shape: an uppercase subsystem prefix; then, where the function -operates on a particular object or context, that object -- usually -the uppercase or mixed-case type name; then the action, in -lowercase with underscores. Where the prefix already identifies -the object, or the function is a general subsystem utility, there -is no separate object element. -Examples: `EVP_KDF_CTX_get0_kdf` (prefix `EVP`, object `KDF_CTX`, -action `get0_kdf`), `EVP_PKEY_sign`, `OSSL_CMP_validate_msg`, -`SSL_CTX_set_verify`; and, with no object element, `BIO_eof` and -`CRYPTO_malloc`. - -This shape is aspirational and describes the direction for new -code. Much of the existing API predates it and carries years of -naming baggage, so it does not uniformly conform. Do not rename -existing public functions to fit it -- that breaks the API. - -Public (API) functions use the uppercase subsystem prefix. -Internal functions use the lowercase `ossl_` prefix unless they -are static (i.e., local to the source file); static functions -need no prefix. - -Functions that return a pointer disclose ownership of the -returned value via a `0` or `1` suffix on the name: - -- `get0_X()` returns a non-owning pointer. -- `get1_X()` returns an owning pointer; the caller is the new - owner, of either a fresh allocation or an up-ref. - -The same convention applies in reverse for setters and -pushers that take a pointer: - -- `set0_X(obj, p)` and `push0_X(coll, p)` transfer ownership - of `p` to `obj` or `coll`. -- `set1_X(obj, p)` and `push1_X(coll, p)` leave ownership - with the caller; the callee stores a copy or up-ref. - -Use these forms rather than a bare `get_` / `set_` / `push_` -whenever a pointer crosses the API boundary. - -A function extended from an existing form takes an `_ex` -suffix (`_ex2` for a second extension, `_ex3` for a third, -and so on). See [Extending existing functions](#extending-existing-functions) -for when to add an extended form and how to handle the -parameter list. - -### Typedefs - -OpenSSL uses typedefs extensively. Struct typedefs are named in -`ALL_CAPS_WITH_UNDERSCORES`, with a subsystem prefix, and the -underlying struct tag is the lowercase form of the typedef name -suffixed `_st`: - -```c -typedef struct evp_pkey_st EVP_PKEY; -``` - -For more examples, look in ``. - -When a typedef'd enum is used (see [Structs and typedefs](#structs-and-typedefs) -below for the policy on enums), the enum type name is lowercase -and the values are uppercase. - -Function-pointer and callback typedefs use one of two -suffixes: - -- `_cb` for typedefs that are user-supplied callbacks - (`X509_STORE_CTX_verify_cb`, `pem_password_cb`). -- `_fn` for function pointers in an internal interface or - dispatch table (`OSSL_provider_init_fn`, - `X509_STORE_CTX_verify_fn`). - -When introducing a new type, consider that a bare or generic -name may collide with system or third-party headers; OpenSSL -has historically used unprefixed names like `X509` and these -now collide with Windows headers in places. Prefix new type -names (for example `EVP_PKEY`, `OSSL_PARAM`) to avoid this. - -### Macros and enum labels - -Macros and labels in enums should be named in -`ALL_CAPS_WITH_UNDERSCORES`. This convention helps distinguish -macros from functions and variables. - -```c -#define OPENSSL_MAGIC_FOO 0x12345 -``` - -Error reason codes follow a `SUBSYSTEM_R_REASON` pattern, -where `_R_` is the infix marking the macro as an error reason: -`X509_R_INVALID_TRUST`, `SSL_R_NO_SHARED_CIPHER`, -`ERR_R_MALLOC_FAILURE`. - -Feature-disable macros follow `OPENSSL_NO_` -- for -example, `OPENSSL_NO_SOCK` (no socket support), -`OPENSSL_NO_RSA` (no RSA), `OPENSSL_NO_DEPRECATED__` -(no APIs deprecated as of that version). When defined, the -corresponding feature's headers and implementations are -conditionally compiled out. - -Comments --------- - -This section describes the form and style of code comments. -[DOCUMENTATION.md](DOCUMENTATION.md) is the companion document that -describes the policy: when a comment is required, the *trivial* -exception, and the per-field commenting requirement on structures. - -Use the classic `/* ... */` comment markers. Do not use `// ...` -markers. - -Comments should describe *what* the code does and *why*. Do not -parrot the effect of each statement; well-written code is its own -description of *how*. As the complexity of the code increases, the -size and detail of comments should also increase. Err in favour of -more comments rather than fewer: code that is *obvious* to you -today will not necessarily be obvious to someone else two years -later. - -### Multi-line comment blocks - -The preferred style for long (multi-line) comments is: - -```c -/*- - * This is the preferred style for multi-line - * comments in the OpenSSL source code. - * Please use it consistently. - * - * Description: A column of asterisks on the left side, - * with beginning and ending almost-blank lines. - */ -``` - -Both `/*-` and `/**` are recognised by the `CommentPragmas` setting -in [`.clang-format`](.clang-format) and cause the block to be left -exactly as written. Use `/*-` for plain prose comments whose layout -you want to preserve, and `/**` for doxygen blocks (see below). - -### TODO and FIXME markers - -Use `/* TODO: */` to mark work that should be -done later. Use `/* FIXME: */` to mark a known -incorrectness, hack, or workaround that needs to be addressed. If -a marker is worth adding, the underlying work is worth tracking: -ensure a GitHub issue is opened for it and include the issue's -full URL in the marker (e.g., `/* TODO: -(https://github.com/openssl/openssl/issues/1234) */`). Use the URL -form because OpenSSL has issue trackers in multiple repositories. - -### Doxygen comments - -OpenSSL code uses doxygen-style comments on functions, data -structures, and macros to make the source easier to navigate and to -translate into reference documentation. The internal-function, -struct-field, and other in-source documentation requirements set out -in [DOCUMENTATION.md](DOCUMENTATION.md) must be satisfied with -doxygen-style comments using the conventions described below. - -Use the `@` form of doxygen markers (`@brief`, `@param`, `@returns`, -`@file`, `@def`, `@struct`, and so on). Do not use the `\` form -(`\brief`, `\param`, etc.). - -For the full set of recognised tags and their semantics, see the -Doxygen manual: the [commands list](https://www.doxygen.nl/manual/commands.html) -is the practical reference for what you can write inside a doxygen -block; the chapter on -[documenting the code](https://www.doxygen.nl/manual/docblocks.html) -explains the block forms and where comments attach. - -The following sample illustrates the convention: - -```c -/** - * @file doxysample.c - * This is a brief file description that you may add. - * Subsequent lines contain more detailed information about what you - * will find defined in this file. It is not currently required that - * you add a file description, but it is available if you like. - */ - -/** - * @def MAX(x, y) - * Document a macro that returns the maximum of two inputs. - * @param x integer input value - * @param y integer input value - * @returns the maximum of x and y - */ -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -/** - * @struct foo_st - * @brief Description of the foo_st struct. - * Optional more detailed description here. - */ -typedef struct foo_st { - int a; /**< Describe the a field here */ - char b; /**< Describe the b field here */ -} FOO; - -/** - * @brief Describe the function ossl_add briefly. - * Add a more detailed description here, like sums two inputs and - * returns the result. - * @param a input integer to add - * @param b input integer to add - * @returns the sum of a and b - */ -int ossl_add(int a, int b); -``` - -#### Spec-mirroring variables - -When a function uses variable names taken from a specification -(see [Functions and variables](#functions-and-variables) in the -Naming section), the doxygen block cites the spec and identifies -each spec-derived variable: - -```c -/** - * @brief Transmogrify Calvin into Hobbes per RFC 31337 section 1.2.3. - * - * Variable naming follows the spec: - * - Calvin: input to be transmogrified - * - Hobbes: transmogrified output (caller-allocated) - * - * @param Calvin pointer to the input bytes to transmogrify - * @param Calvin_len the number of bytes available at Calvin - * @param Hobbes pointer to the caller-allocated output buffer - * @param Hobbes_len the number of bytes available at Hobbes - * @returns 1 on success, 0 on failure - * @see https://www.example.org/rfc/rfc31337.html#section-1.2.3 - * @see https://calvinandhobbes.fandom.com/wiki/Transmogrifier - */ -int ossl_transmogrify(const uint8_t *Calvin, size_t Calvin_len, - uint8_t *Hobbes, size_t Hobbes_len); -``` - -#### Public functions: link the manual page - -Every public function declaration in a public header must carry a -doxygen block that includes an `@see` referencing the function's -manual page in the standard `name(3)` form. This in-source comment -is a navigation aid; the canonical reference documentation lives in -the POD file under `doc/man3/` (see [DOCUMENTATION.md](DOCUMENTATION.md)). - -The cross-reference is to the function name, not the POD file -name; the build emits a man-page entry per function name, so -`man X509_verify_cert` resolves regardless of which POD file -currently documents it. - -```c -/** - * @brief One-line summary of what the function does. - * @see X509_verify_cert(3) - */ -int X509_verify_cert(X509_STORE_CTX *ctx); -``` - -Additional `@see` entries may be added for any manual page a caller -needs in order to use the function correctly, such as pages -documenting argument types, the flag families that affect the -function's behaviour, or closely related functions. List them -comma-separated on a single `@see`, matching the form used in POD's -`SEE ALSO` section: - -```c -/** - * @brief One-line summary of what the function does. - * @see X509_verify_cert(3), X509_STORE_CTX_new(3), - * X509_VERIFY_PARAM_set_flags(3) - */ -int X509_verify_cert(X509_STORE_CTX *ctx); -``` - -The doxygen comment should not duplicate the POD content. Two -copies of "what this function does" inevitably diverge; the POD is -the source of truth. Keep the doxygen block to a short summary and -the `@see` references. - -Structs and typedefs --------------------- - -See [Typedefs](#typedefs) under Naming for naming conventions. - -Typedef'd enums are used much less often than struct typedefs; -consider not using a typedef for an enum at all. A typedef'd -enum hides the integer-ness of the type from the caller, which -makes the implementation-defined underlying type easier to -forget. - -Enum arguments to public functions are not permitted. C's `enum` -underlying type is implementation-defined, and adding values to -an enum can change its ABI; use `int` and document the allowed -values instead. - -OpenSSL has historically made all struct definitions public, which -caused problems with maintaining binary compatibility and adding -features. New structs are opaque and expose only pointers in the -API; the struct definition is placed in a local header file that -is not exported. Legacy structs that are still part of the public -ABI are exempt; do not add new public struct definitions. - -In practice, the opaque pattern is to forward-declare the typedef -in the public header (`typedef struct foo_st FOO;`, with no struct -body) and place the `struct foo_st { ... };` definition in a local -header that is not exported. Callers see only the pointer type. - -Bitfield layout is implementation-defined and varies across -compilers and ABIs. Where that layout is observable -- in structs -that are part of the public ABI or that mirror a wire or file -format -- avoid bitfields and use explicit shifts and masks on a -regular integer instead. - -Flexible array members (C99 trailing `[]`) are permitted and -preferred over the older `[1]` "struct hack" for variable-length -trailing data. Remember that `sizeof(struct)` does not include the -flexible member; allocate the trailing data explicitly when the -struct is created. - -C99 designated initializers (`{ .field = value }`) are encouraged -for struct initialisation, particularly where they make the field -assignments self-documenting. - -A trailing comma in an initializer list is a layout hint to -`clang-format`: with it the list is kept one element per line; -without it the formatter may pack the list onto fewer lines. -Most of the time you do not want a trailing comma; omit it -unless you specifically want to lock the one-per-line layout -(for example, in a multi-row table of values). - -Integers --------- - -Prefer explicitly-sized integers over generic C ones where the -size matters. To represent a byte use `uint8_t`, not -`unsigned char`; for a two-byte field, `uint16_t` rather than -`unsigned short`. - -Avoid `long` and `long long` specifically. `long` is 32 bits on -64-bit Windows and 64 bits on 64-bit Linux; using it for "at -least 32 bits" produces code that works inconsistently across -platforms. Use `int32_t`, `int64_t`, `size_t`, or another -`` type as appropriate. - -Sizes are `size_t`. When converting to or from `int` for legacy -reasons, check for overflow and underflow. - -Add an integer literal suffix when the literal participates in a -shift or appears in an expression involving a wider type -- -without a suffix the literal is `int`. Use `U` for unsigned -semantics (`1U << 31`) and the `UINT8_C` through `UINT64_C` -macros from `` for explicit widths (`UINT32_C(1) << 31`, -`UINT64_C(1) << 63`). Avoid `UL` and `ULL`, for the same reason -as `long` / `long long`: their widths vary by platform. - -Bit shifts should be performed on unsigned operands. -Left-shifting a signed value is undefined behaviour when the -operand is negative or when the result reaches the sign bit; -right-shifting a signed negative value is implementation-defined. -Combined with the literal-suffix rule above, shifts of constants -typically take the form `UINT32_C(1) << n` or `(uint32_t)x << n`. - -In structs that are retained across the lifetime of a connection, -new integer fields whose value range is known should use a smaller -integer type (`uint8_t`, `uint16_t`) where doing so is -straightforward. This reduces per-connection memory in server -processes. Do not make code significantly more complex to achieve -it, and continue to bounds-check at the struct boundary. - -This narrowing should not propagate to local variables or function -parameters; those use the conventional integer types so callers -are not forced to deal with narrow types. - -Do not retroactively narrow existing integer fields in legacy -structs; this risks ABI breakage. - -When doing arithmetic, account for overflow. - -Use `int` with `0` / `1` for boolean values, both in public API -and internal code. Do not introduce `` for new code; -the public API convention is `int`, and using `bool` internally -just to convert to `int` at the API boundary adds friction -without enough benefit. - -Except in platform-specific code, do not use `ssize_t`; MSVC lacks -it. Use `size_t` and signal errors out-of-band (see -[Return values in new code](#return-values-in-new-code)). - -Preprocessor directives ------------------------ - -Headers use traditional include guards in the `#if defined()` -form rather than `#pragma once`, which is non-standard: - -```c -#if !defined(OPENSSL_FOO_H) -#define OPENSSL_FOO_H - -/* ... header contents ... */ - -#endif /* defined(OPENSSL_FOO_H) */ -``` - -Prefer `#if defined(FOO)` and `#if !defined(FOO)` to `#ifdef` and -`#ifndef`. This allows logical operations when conditional -compilation is dependent on more than one variable, without -nesting multiple blocks. - -All `#endif` blocks must have a comment matching their `#if`: - -```c -#if defined(OPENSSL_LINUX) && (!defined(OPENSSL_NO_HOOBLA) || !defined(OPENSSL_BULA)) -... -#endif /* defined(OPENSSL_LINUX) && (!defined(OPENSSL_NO_HOOBLA) || !defined(OPENSSL_BULA)) */ -``` - -Minimise the footprint of conditional compilation in source -code: the more conditional code is concentrated and confined, -the easier the unconditional flow is to read. - -Concentrate conditional compilation rather than dispersing it. -Do not duplicate the same OS-dispatch ladder across the -codebase: - -```c -#if defined(OPENSSL_OS_FOO) || defined(OPENSSL_OS_BAR) - stuff the way foo or bar does it; -#elif defined(OPENSSL_OS_BLAH) || defined(OPENSSL_OS_WOOF) - stuff the way blah or woof does it; -#endif /* defined(OPENSSL_OS_FOO) || defined(OPENSSL_OS_BAR) */ -``` - -For OS-dependent code in particular, put the directives inside -a single function that wraps the OS-dependent work, so callers -see a clean interface. When the OS-dependent implementations -are large, put them in separate files (`stuff_foo.c`, -`stuff_blah.c`) implementing a common function and select the -appropriate file via the build process; this lets non-mainstream -platforms add an implementation file without patching shared -code. - -When a feature can be compiled out, prefer to provide a no-op -stub implementation of its functions in the disabled case -rather than wrapping every call site in `#if`. Callers then -invoke the functions unconditionally and the compiler discards -the stubs: - -```c -#if defined(OPENSSL_NO_FOO) -static ossl_inline int ossl_foo_init(void) { return 1; } -static ossl_inline void ossl_foo_cleanup(void) { } -#else -int ossl_foo_init(void); -void ossl_foo_cleanup(void); -#endif /* defined(OPENSSL_NO_FOO) */ -``` - -Macros and enums ----------------- - -**Just use a function, not a macro.** OpenSSL has historically -used macros heavily to avoid function-call overhead, but modern -compilers inline well; the trade-offs that justified that pattern -no longer apply. Where a macro is genuinely unavoidable, the -rules below apply. - -For the naming convention used for macros and enum labels, see the -[Macros and enum labels](#macros-and-enum-labels) subsection of -Naming above. - -Enums are preferred when defining several related constants. -Enum arguments to public functions are not permitted, because -C's `enum` underlying type is implementation-defined and adding -values can change ABI; see -[Structs and typedefs](#structs-and-typedefs) for the rule and -the canonical alternative (use `int` and document the allowed -values). - -Where the constants need a fixed underlying width (for ABI or -wire-format reasons), use `#define` or `static const` with an -explicit-width type from `` instead, since enum width -is implementation-defined. - -### Avoid complex macros - -Avoid complex or clever macros: they are hard to read, debug, and -maintain. Do not nest macros calling other macros. - -### Avoid function-like macros - -Prefer functions over function-like macros. Do not optimise for -function-call overhead without first measuring with a function -implementation; if the function is hot enough to need inlining, -mark it `ossl_inline` rather than converting it to a macro. - -### Macro parenthesisation - -Always parenthesise arguments in function-like macros to prevent -operator-precedence issues during expansion. Enclose the entire -macro definition in parentheses if it expands to an expression, so -the expansion evaluates correctly inside larger expressions. For -example: - -```c -#define BOB(blah) ((blah) + 42 - 23) -``` - -### Multi-statement macros - -Enclose multi-statement macros in a `do { } while (0)` block. Do -not include a semicolon at the end, and do not use bare braces -(which fail when followed by `else`). For example: - -```c -/* This is bad. */ -#define KERMIT(x) muppet((x)); frog((x)); green((x)) -if (something) - KERMIT(bob); -else /* This now breaks. */ - -/* This is also bad, because now you have to omit the semicolon. */ -#define KERMIT(x) { muppet((x)); frog((x)); green((x)) } -if (something) - KERMIT(bob) /* No semicolon. */ -else - -/* This works. */ -#define KERMIT(x) do { muppet((x)); frog((x)); green((x)) } while (0) -if (something) - KERMIT(bob); -else - -/* - * But just use a function -- now we know that x is an integer that - * has something to do with frogginess and we gain some type safety. - */ -static void kermit(int frogginess) -{ - muppet(frogginess); - frog(frogginess); - green(frogginess); -} -if (something) - kermit(bob); -else -``` - -### Do not include files as multi-line macros - -Do not put code in a file and include it inline: - -```c - ... - printf("Yolo\n"); -#include "./abagfullofcode.inc" - printf("That was fun\n"); - ... -``` - -Either make a function out of the code and call it, or put the code -in place. - -### Be careful with macro arguments that have side effects - -Be careful when writing a function-like macro that could be called -with arguments that have side effects. Because a macro may expand an -argument more than once, a side-effecting argument (`n++`, a function -call, a volatile access) can then be evaluated more than once, with -unexpected results: - -```c -#define SQUARE(x) ((x) * (x)) - -int n = 1; -int result = SQUARE(n++); /* expands to ((n++) * (n++)) -- evaluates twice */ -``` - -Where it can reasonably be avoided, prefer a form that expands each -argument exactly once -- a function, or an `ossl_inline` function -for a fixed type. If there is any doubt that your function-like -macro could be called with arguments that have side effects, treat -that as a sign to follow the advice in -[Avoid function-like macros](#avoid-function-like-macros) and make -it a real function. Some macros cannot avoid it: a type-generic macro -such as `MAX` must name each operand and so evaluates it more than -once. When that is unavoidable, say so at the definition and avoid -passing side-effecting expressions at the call site. - -### Avoid macros that depend on magic names - -Do not write macros that rely on a particular variable name being -in scope at the call site: - -```c -#define FOO(val) bar(index, (val)) /* requires `index' to exist */ -``` - -This is confusing to the reader and prone to breakage from -seemingly innocent changes. - -### Avoid macros that expand to l-values - -Do not write a macro that expands to something assignable: - -```c -#define FIELD(p) (((struct foo *)(p))->field) - -FIELD(x) = y; /* legal C, but the macro hides the assignment */ -``` - -Use an accessor function or expose the field directly through a -typed pointer. - -### Avoid macros that affect control flow - -Do not write macros that `return`, `goto`, `break`, or `continue` -out of their expansion. Such macros hide control flow from a -reader at the call site, who sees what looks like a function -call but which may exit the surrounding function or jump out of -a loop: - -```c -#define RETURN_IF_NULL(p) do { if ((p) == NULL) return -1; } while (0) - -int ossl_frobnicate(void *p) -{ - RETURN_IF_NULL(p); /* may return from ossl_frobnicate() -- not visible at the call site */ - /* ... */ -} -``` - -### Avoid `#` and `##` in new code - -The stringification (`#`) and token-pasting (`##`) operators are -forbidden in new code. Existing macros that use them (notably the -`DECLARE_*` and `IMPLEMENT_*` macro families) are not retroactively -changed; new code should achieve the same effect through -functions. - -### Use variadic macros sparingly - -Variadic macros (`__VA_ARGS__`) are permitted but should be used -sparingly: prefer a function or a small set of helper functions -where possible. They are harder to reason about and debug than -functions, and the rules around zero variadic arguments and -`__VA_ARGS__` forwarding are subtle. - -Functions ---------- - -A function should do one thing and be short enough that a -reader can hold its behaviour in their head while reading it. -Length follows from complexity, not the other way around: a -long but flat function (for example, a single switch dispatching -to many cases) is fine; a short function with three levels of -nested control flow is not. - -When complexity grows, factor out helpers with descriptive -names. A large number of local variables is a signal that this -factoring is overdue; consider splitting before reaching for a -comment to explain the variables. Performance-critical helpers -can be marked `inline`; see -[Avoid function-like macros](#avoid-function-like-macros) for -why this is preferable to a macro. - -In function prototypes, include parameter names alongside their -types. C does not require this, but it carries useful information -for the reader; the name in the prototype should match the name -in the definition. - -### Functions with no arguments - -A function that takes no arguments must declare so explicitly -with `void` in its parameter list: `int f(void);`, not -`int f();`. The latter declares the parameter list as -unspecified and prevents the compiler from checking calls. - -### Internal linkage - -Functions that are local to a single source file are declared -`static`. Static functions need no `ossl_` prefix (see -[Naming](#functions-and-variables) above) and do not appear in -the symbol table of the resulting object file. - -### Parameter ordering - -In OpenSSL's API style, a context parameter (an `SSL_CTX *`, -`EVP_PKEY_CTX *`, `OSSL_LIB_CTX *`, or similar) is the first -parameter. The order of the remaining parameters is at the -function's discretion but should be consistent with similar -functions in the same subsystem. - -### `const`-correctness - -Pointer parameters that are not modified by the function should -be declared `const`; likewise, pointer return values that the -caller must not modify should be declared `const`. The -return-side rule pairs with the `get0_X()` ownership convention: -a non-owning pointer is typically a read-only view, while an -owning pointer returned by `get1_X()` is non-`const` because the -caller controls it. The `const` qualifier documents the contract, -allows callers to pass or receive `const`-qualified data without -casts, and lets the compiler catch accidental modification. - -### Return values in legacy code - -Historically, functions in OpenSSL can return values of many different -kinds, and one of the most common is a value indicating whether the -function succeeded or failed. Usually this is: - -- `1`: success -- `0`: failure - -Other patterns appear in legacy code: - -- `-1` indicates a serious error (internal error or memory - allocation failure), and in some subsystems (BIO, SSL, etc.) - means "should retry" -- `>= 1` indicates success with the value carrying additional - information; `<= 0` indicates failure with the value indicating - the reason - -Functions that return a computed value (not a success/failure -indicator) are exempt. - -**Read the existing return-value contract carefully before -modifying legacy code.** OpenSSL's legacy return-value -conventions are not uniform -- a function may use values, -overloadings, or semantics outside the patterns above -- and -bugs have been introduced into OpenSSL when contributors -assumed a function followed a familiar pattern when it did not. -The contract is part of the API, not just a stylistic choice. - -### Return values in new code - -For new code, functions should return `int` with `1` on success -and `0` on error. Do not overload the return value to both -signal success/failure and output an integer. For example: - -```c -/** - * @brief ossl_snuffle_thingamabob snuffles a thingamabob from bytes of input. - * If a valid thingamabob is snuffled, the result is stored in - * *out_thingamabob. On failure a snuffling error code is stored - * in *out_err. - * @param input pointer to the bytes to snuffle - * @param input_len the number of bytes available to snuffle from input - * @param out_err pointer to an integer to store an error code - * @param out_thingamabob pointer to a thingamabob to store the output - * @returns 1 if a thingamabob was snuffled and stored, 0 otherwise. - */ -int ossl_snuffle_thingamabob(const uint8_t *input, size_t input_len, - int *out_err, thingamabob *out_thingamabob); -``` - -If a function outputs a single pointer and no other values, -return the pointer directly, with `NULL` on error. - -### Checking function arguments - -A public function must verify that its arguments are sensible -and return its documented failure value if they are not. -Typical checks include: - -- non-optional pointer arguments are not NULL; -- numeric arguments are within their expected ranges. - -Public-API callers are outside the OpenSSL development envelope. -The contract cannot be enforced through code review, so a NULL -non-optional pointer or an out-of-range integer is a possibility -that must be handled defensively at the boundary. Failing with a -documented error code on the error stack is preferable to a -SIGSEGV in the calling application's process. - -For NULL pointer arguments, the canonical pattern is: - -```c -if (arg == NULL) { - ERR_raise(ERR_LIB_, ERR_R_PASSED_NULL_PARAMETER); - return 0; -} -``` - -Use the function's documented failure value in place of `0` -where it differs (`NULL` for pointer-returning functions, `-1` -for functions that may return `-1`, and so on). - -Internal functions must not repeat these checks. Their callers -are us; the contract is enforceable in code review, and a NULL -or out-of-range argument is a programmer error of the same -character as the impossibilities discussed under -[Assertions](#assertions). A runtime check at an internal call -site is dead on any correct execution, and the untested branch -is itself attack surface. Use `assert()` instead where you want -to document an internal invariant. - -### Extending existing functions - -When an existing public function needs additional parameters, -keep the original and add a new function with the same name plus -an `_ex` suffix (`RAND_bytes_ex` extends `RAND_bytes`). Further -extensions use `_ex2`, `_ex3`, and so on. - -The extended function preserves the existing parameters in their -existing order. New parameters may be inserted at any position -(they do not have to be at the end); parameters that are no -longer needed may be removed. - -### Centralised exiting of functions - -When a function exits from multiple locations and some common -work (such as cleanup) has to be done at every exit, use `goto` -to a single exit label. Return directly when there is no cleanup -to do. The rationale: - -- a single exit point is easier to read and follow; -- it reduces excessive control structures and nesting; -- it avoids errors caused by failing to update multiple exit - points when the code changes; -- it lets the compiler avoid emitting redundant cleanup code. - -For example: - -```c -int ossl_do_thing(const uint8_t *in, size_t in_len) -{ - int ret = 0; - uint8_t *buf = OPENSSL_malloc(in_len); - - if (buf == NULL) - return 0; - - if (!ossl_step1(in, in_len, buf)) - goto out; - if (!ossl_step2(buf, in_len)) - goto out; - - ret = 1; -out: - OPENSSL_free(buf); - return ret; -} -``` - -Error reporting ---------------- - -OpenSSL surfaces errors through a per-thread error stack; see -`ERR_raise(3)` for the calls and `include/openssl/err.h` for the -available reason codes. This section describes the conventions -for using them. - -Raise at the leaf. The function that detects the failure pushes -the error; intermediate wrappers that propagate the failure -value must not re-raise. Re-raising on each frame floods the -stack with duplicates and obscures the originating condition. - -Use the `ERR_LIB_` corresponding to the function's -home directory (`ERR_LIB_X509` in code under `crypto/x509/`, and -so on). Use a cross-library reason (`ERR_R_PASSED_NULL_PARAMETER`, -`ERR_R_MALLOC_FAILURE`, `ERR_R_INTERNAL_ERROR`, and others) for -portable failure modes; use a `SUBSYSTEM_R_REASON` -(`X509_R_INVALID_TRUST`, etc.) for domain-specific ones. - -Do not call `ERR_clear_error` at function entry; the error stack -belongs to the caller, who may have pushed errors before -invoking you that they intend to inspect. - -Use `ERR_set_mark` / `ERR_pop_to_mark` to suppress error-stack -pollution from operations expected to fail sometimes (a -speculative parse, a capability probe), leaving earlier errors -intact. - -Allocating memory ------------------ - -Use the `OPENSSL_malloc` family for general allocation; see -`OPENSSL_malloc(3)` for the full set of calls. Do not mix these -with the C standard library's `malloc()` / `free()` family; -allocations made with one set must be released with the matching -set, and OpenSSL can be built with custom allocator hooks that -the C library does not know about. - -For arrays, use `OPENSSL_malloc_array()` and -`OPENSSL_realloc_array()`, which take the element size and -element count separately and check for integer overflow. - -Memory holding sensitive material (key bytes, plaintext, -internal state of cryptographic primitives) must be cleansed -before release. `OPENSSL_clear_free()` combines cleansing and -freeing; `OPENSSL_cleanse()` wipes without freeing. For -long-lived sensitive data, use the `OPENSSL_secure_malloc()` -family (`OPENSSL_secure_malloc(3)`), which allocates from a -separate non-pageable secure heap, and release with -`OPENSSL_secure_clear_free()`. - -An API that owns internal state requires both an initialisation -function to set it up and a completion function to release it. -This is the standard constructor/destructor pair for opaque -types; see [Structs and typedefs](#structs-and-typedefs). - -Processor-specific code ------------------------ - -The only reason for processor-specific code in OpenSSL is -performance. Every processor-specific path must have a -platform-neutral pure-C implementation as a fallback, because -not every target architecture or build configuration enables -the processor-specific path. OpenSSL selects between -implementations at runtime via the CPU-capability detection in -`OPENSSL_cpuid_setup` and the `OPENSSL_*` capability flags; -processor-specific code must integrate with this dispatch. - -Cryptographic primitives operating on secret data must execute -in time independent of those secrets. Avoid secret-dependent -branches, secret-indexed memory accesses, and variable-time -arithmetic (such as variable-time multiplication or division) -on words derived from secrets. Hand-coded asm is sometimes used -specifically to force a particular sequence of constant-time -operations that a compiler might otherwise rewrite. - -Short processor-specific operations are typically written as -inline assembly. Use a `static inline` function when the asm -constraints permit it. When the asm requires a compile-time -constant operand (an `i` constraint), use a statement-expression -macro instead, because a function parameter does not satisfy the -immediate-constant constraint. When `asm()` has side effects the -compiler cannot see, mark it `volatile`; do not mark `volatile` -unnecessarily as that limits optimisation. - -When writing a single inline assembly statement containing -multiple instructions, put each instruction on a separate line -in a separate quoted string, and end each string except the -last with `\n\t` to properly indent the next instruction in the -assembly output: - -```c -asm("magic %reg1, #42\n\t" - "more_magic %reg2, %reg3" - : /* outputs */ : /* inputs */ : /* clobbers */); -``` - -Large, non-trivial assembly functions go in pure assembly -modules, with corresponding C prototypes. The preferred way to -generate these is *perlasm*: a Perl script that generates a -`.s` file. Perlasm allows symbolic names for variables -(registers and stack-allocated locals) that are independent of -the specific assembler, and supports multiple ABIs and -assemblers from a single source by adhering to its coding -rules. See `crypto/perlasm/x86_64-xlate.pl` for an example. - -Compiler intrinsics are permitted but used sparingly. They are -appropriate for self-contained SIMD acceleration where the -intrinsic vocabulary is well-supported across our target -compilers and the code does not need to span multiple ABIs -- -`crypto/evp/enc_b64_avx2.c` (AVX2 base64) is an example. -Intrinsics are not appropriate for cryptographic primitives -where constant-time execution is required (the compiler may -reorder, branch, or otherwise alter the timing), or where an -existing perlasm implementation already covers the multi-ABI -case. - -Assertions ----------- - -Assertions check programmer errors -- invariants, preconditions, and -postconditions that must hold in any correctly-functioning build. -They are not for runtime conditions such as allocation failure, I/O -errors, or malformed input from callers; those are errors the -surrounding code must handle and propagate. - -OpenSSL provides three assertion forms, which differ in their -behaviour depending on whether `NDEBUG` is defined (release) or not -(debug): - -| Form | Failure (debug) | Failure (release) | Success | -|---|---|---|---| -| `assert(e)` | abort | `e` not evaluated | no effect | -| `ossl_assert(e)` | abort | returns 0 | returns 1 | -| `OPENSSL_assert(e)` | abort | abort | no effect | - -Choosing between these forms is a trade-off, not a default. Each -form pays a cost somewhere: - -- `OPENSSL_assert()` terminates the host process when an invariant - fails, which is hostile to applications that link against - OpenSSL. -- `ossl_assert()` returns failure in release builds so the host - process survives, but the caller must then handle a failure for - a condition that, by definition, cannot occur in correct code. - That handling code is dead on any correct execution and cannot - be exercised by ordinary tests; untested branches accumulate - their own bugs and become part of the attack surface. -- `assert()` is silently dropped in release builds, so an invariant - violation in production passes through to downstream code that - may then operate on inconsistent state. - -Use `ossl_assert()` when the surrounding function already returns -success/failure and the recovery path collapses naturally into the -function's existing error path: push an internal error and return -the function's failure value. The recovery code is then colocated -with tested error handling and is not a structurally new branch: - -```c -if (!ossl_assert(invariant_holds)) { - ERR_raise(ERR_LIB_..., ERR_R_INTERNAL_ERROR); - return 0; -} -``` - -Use `assert()` for impossible cases in internal code -- typically -`switch` defaults, unreachable branches in helpers, and invariants -local to a function whose contract makes the violation strictly -impossible. The release-build behaviour ("do nothing") is the -right choice here, because the alternative is untested recovery -code for a case that cannot occur, and that code is itself a -hazard. The assertion expression must be free of side effects, -because `assert()` does not evaluate it in release builds. - -Use `OPENSSL_assert()` only when continued execution would be more -dangerous than termination -- typically when global library state -is irrecoverably corrupted -- or in applications, test programs, -and fuzzers where termination on a failed check is desired. -`OPENSSL_assert()` aborts in all builds, including production. diff --git a/apps/asn1parse.c b/apps/asn1parse.c index b8449762fe..ed5ebd076f 100644 --- a/apps/asn1parse.c +++ b/apps/asn1parse.c @@ -82,8 +82,7 @@ int asn1parse_main(int argc, char **argv) const unsigned char *ctmpbuf; int indent = 0, noout = 0, dump = 0, informat = FORMAT_PEM; int offset = 0, ret = 1, i, j; - long num; - size_t tmplen; + long num, tmplen; const unsigned char *tmpbuf; unsigned int length = 0; OPTION_CHOICE o; @@ -242,12 +241,12 @@ int asn1parse_main(int argc, char **argv) if (sk_OPENSSL_STRING_num(osk)) { tmpbuf = str; - tmplen = (size_t)num; + tmplen = num; for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) { ASN1_TYPE *atmp; int typ; j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0); - if (j <= 0 || (size_t)j >= tmplen) { + if (j <= 0 || j >= tmplen) { BIO_printf(bio_err, "'%s' is out of range\n", sk_OPENSSL_STRING_value(osk, i)); continue; @@ -256,7 +255,7 @@ int asn1parse_main(int argc, char **argv) tmplen -= j; atmp = at; ctmpbuf = tmpbuf; - at = d2i_ASN1_TYPE(NULL, &ctmpbuf, (long)tmplen); + at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen); ASN1_TYPE_free(atmp); if (!at) { BIO_puts(bio_err, "Error parsing structure\n"); @@ -273,16 +272,11 @@ int asn1parse_main(int argc, char **argv) } /* hmm... this is a little evil but it works */ tmpbuf = ASN1_STRING_get0_data(at->value.asn1_string); - tmplen = ASN1_STRING_length_ex(at->value.asn1_string); - if (tmplen > INT_MAX) { - BIO_puts(bio_err, "ASN.1 string length exceeds INT_MAX\n"); - ERR_print_errors(bio_err); - goto end; - } + tmplen = ASN1_STRING_length(at->value.asn1_string); } /* XXX casts away const */ str = (unsigned char *)tmpbuf; - num = (int)tmplen; + num = tmplen; } if (offset < 0 || offset >= num) { diff --git a/apps/ca.c b/apps/ca.c index 8f98bc9a6a..c0a58f4d16 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1077,8 +1077,8 @@ end_of_options: X509 *xi = sk_X509_value(cert_sk, i); const ASN1_INTEGER *serialNumber = X509_get0_serialNumber(xi); const unsigned char *psn = ASN1_STRING_get0_data(serialNumber); - const size_t snl = ASN1_STRING_length_ex(serialNumber); - const size_t filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem"); + const int snl = ASN1_STRING_length(serialNumber); + const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem"); char *n = new_cert + outdirlen; if (outdirlen + filen_len > PATH_MAX) { @@ -1089,7 +1089,7 @@ end_of_options: if (snl > 0) { static const char HEX_DIGITS[] = "0123456789ABCDEF"; - for (j = 0; (size_t)j < snl; j++, psn++) { + for (j = 0; j < snl; j++, psn++) { *n++ = HEX_DIGITS[*psn >> 4]; *n++ = HEX_DIGITS[*psn & 0x0F]; } @@ -1523,10 +1523,8 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, goto end; } if (type != V_ASN1_BMPSTRING && type != V_ASN1_UTF8STRING) { - size_t tmp = ASN1_STRING_length_ex(str); - if (tmp > INT_MAX) - goto end; - j = ASN1_PRINTABLE_type(ASN1_STRING_get0_data(str), (int)tmp); + j = ASN1_PRINTABLE_type(ASN1_STRING_get0_data(str), + ASN1_STRING_length(str)); if ((j == V_ASN1_T61STRING && type != V_ASN1_T61STRING) || (j == V_ASN1_IA5STRING && type == V_ASN1_PRINTABLESTRING)) { BIO_puts(bio_err, @@ -1903,9 +1901,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, /* We now just add it to the database as DB_TYPE_VAL('V') */ row[DB_type] = OPENSSL_strdup("V"); tm = X509_get0_notAfter(ret); - row[DB_exp_date] = app_malloc(ASN1_STRING_length_ex(tm) + 1, "row expdate"); - memcpy(row[DB_exp_date], ASN1_STRING_get0_data(tm), ASN1_STRING_length_ex(tm)); - row[DB_exp_date][ASN1_STRING_length_ex(tm)] = '\0'; + row[DB_exp_date] = app_malloc(ASN1_STRING_length(tm) + 1, "row expdate"); + memcpy(row[DB_exp_date], ASN1_STRING_get0_data(tm), ASN1_STRING_length(tm)); + row[DB_exp_date][ASN1_STRING_length(tm)] = '\0'; row[DB_rev_date] = NULL; row[DB_file] = OPENSSL_strdup("unknown"); if ((row[DB_type] == NULL) || (row[DB_file] == NULL) @@ -2139,9 +2137,9 @@ static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, /* We now just add it to the database as DB_TYPE_REV('V') */ row[DB_type] = OPENSSL_strdup("V"); tm = X509_get0_notAfter(x509); - row[DB_exp_date] = app_malloc(ASN1_STRING_length_ex(tm) + 1, "row exp_data"); - memcpy(row[DB_exp_date], ASN1_STRING_get0_data(tm), ASN1_STRING_length_ex(tm)); - row[DB_exp_date][ASN1_STRING_length_ex(tm)] = '\0'; + row[DB_exp_date] = app_malloc(ASN1_STRING_length(tm) + 1, "row exp_data"); + memcpy(row[DB_exp_date], ASN1_STRING_get0_data(tm), ASN1_STRING_length(tm)); + row[DB_exp_date][ASN1_STRING_length(tm)] = '\0'; row[DB_rev_date] = NULL; row[DB_file] = OPENSSL_strdup("unknown"); @@ -2352,7 +2350,7 @@ static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg) const char *reason = NULL, *other = NULL; ASN1_OBJECT *otmp; ASN1_UTCTIME *revtm = NULL; - size_t i; + int i; switch (rev_type) { case REV_NONE: @@ -2409,12 +2407,12 @@ static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg) if (!revtm) return NULL; - i = ASN1_STRING_length_ex(revtm) + 1; + i = ASN1_STRING_length(revtm) + 1; if (reason) - i += strlen(reason) + 1; + i += (int)(strlen(reason) + 1); if (other) - i += strlen(other) + 1; + i += (int)(strlen(other) + 1); str = app_malloc(i, "revocation reason"); OPENSSL_strlcpy(str, (const char *)ASN1_STRING_get0_data(revtm), i); @@ -2494,7 +2492,7 @@ static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str) { char buf[25], *pbuf; const char *p; - size_t j; + int j; j = i2a_ASN1_OBJECT(bio_err, obj); pbuf = buf; @@ -2516,7 +2514,7 @@ static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str) BIO_printf(bio_err, "ASN.1 %2d:'", ASN1_STRING_type(str)); p = (const char *)ASN1_STRING_get0_data(str); - for (j = ASN1_STRING_length_ex(str); j > 0; j--) { + for (j = ASN1_STRING_length(str); j > 0; j--) { if ((*p >= ' ') && (*p <= '~')) BIO_printf(bio_err, "%c", *p); else if (*p & 0x80) diff --git a/apps/cmp.c b/apps/cmp.c index abe6de5cb9..a0770dcb97 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -2140,7 +2140,7 @@ static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name) return 0; if ((utf8string = ASN1_UTF8STRING_new()) == NULL) goto err; - if (!ASN1_STRING_set_string(utf8string, name)) { + if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) { ASN1_STRING_free(utf8string); goto err; } @@ -2215,7 +2215,7 @@ static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) else *end++ = '\0'; if ((text = ASN1_UTF8STRING_new()) == NULL - || !ASN1_STRING_set_string(text, ptr)) + || !ASN1_STRING_set(text, ptr, -1)) goto oom; ptr = end; ASN1_TYPE_set(type, V_ASN1_UTF8STRING, text); diff --git a/apps/cms.c b/apps/cms.c index 5e32ab55af..46f9b3b11e 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -1580,15 +1580,13 @@ static void receipt_request_print(CMS_ContentInfo *cms) ERR_print_errors(bio_err); } else { const char *id; - size_t idlen; + int idlen; CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst, &rlist, &rto); BIO_puts(bio_err, " Signed Content ID:\n"); - idlen = ASN1_STRING_length_ex(scid); - if (idlen > INT_MAX) - idlen = INT_MAX; + idlen = ASN1_STRING_length(scid); id = (const char *)ASN1_STRING_get0_data(scid); - BIO_dump_indent(bio_err, id, (int)idlen, 4); + BIO_dump_indent(bio_err, id, idlen, 4); BIO_puts(bio_err, " Receipts From"); if (rlist != NULL) { BIO_puts(bio_err, " List:\n"); diff --git a/apps/ec.c b/apps/ec.c index 8ed452a153..588b488ac1 100644 --- a/apps/ec.c +++ b/apps/ec.c @@ -54,7 +54,7 @@ const OPTIONS ec_options[] = { { "check", OPT_CHECK, '-', "check key consistency" }, { "", OPT_CIPHER, '-', "Any supported cipher" }, { "param_enc", OPT_PARAM_ENC, 's', - "Selects between named_curve and explicit EC parameter encoding" }, + "Specifies the way the ec parameters are encoded" }, { "conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form " }, OPT_SECTION("Output"), diff --git a/apps/ecparam.c b/apps/ecparam.c index aece2cb81d..cbb2ec8d50 100644 --- a/apps/ecparam.c +++ b/apps/ecparam.c @@ -57,7 +57,7 @@ const OPTIONS ecparam_options[] = { { "text", OPT_TEXT, '-', "Print the ec parameters in text form" }, { "noout", OPT_NOOUT, '-', "Do not print the ec parameter" }, { "param_enc", OPT_PARAM_ENC, 's', - "Selects between named_curve and explicit EC parameter encoding" }, + "Specifies the way the ec parameters are encoded" }, OPT_SECTION("Parameter"), { "check", OPT_CHECK, '-', "Validate the ec parameters" }, diff --git a/apps/lib/apps.c b/apps/lib/apps.c index b44e4b2bef..b2756b3b1d 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -40,7 +40,6 @@ #include #include #include -#include #include "s_apps.h" #include "apps.h" @@ -606,46 +605,20 @@ EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin, int suppress_decode_errors) { EVP_PKEY *params = NULL; - OSSL_DECODER_CTX *dctx = NULL; - BIO *file_bio = BIO_new_file(uri, "rb"); - OSSL_LIB_CTX *libctx = app_get0_libctx(); - const char *propq = app_get0_propq(); if (desc == NULL) desc = "key parameters"; - /* - * Use the store lookup path for anything that is not DER/ASN1 format - * Or if we are unable to opens the uri as a file. - */ - if (format != FORMAT_ASN1 || file_bio == NULL) { - (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, - suppress_decode_errors, - NULL, NULL, ¶ms, NULL, NULL, NULL, NULL, NULL); - if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) { - ERR_print_errors(bio_err); - BIO_printf(bio_err, - "Unable to load %s from %s (unexpected parameters type)\n", - desc, uri); - EVP_PKEY_free(params); - params = NULL; - } - } else { - dctx = OSSL_DECODER_CTX_new_for_pkey(¶ms, NULL, NULL, keytype, - OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, - libctx, propq); - if (dctx == NULL) { - ERR_print_errors(bio_err); - BIO_printf(bio_err, "Unable to allocate decoder context\n"); - } else { - if (!OSSL_DECODER_from_bio(dctx, file_bio)) { - ERR_print_errors(bio_err); - BIO_printf(bio_err, "Unable to decode file %s\n", uri); - } - } + (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, + suppress_decode_errors, + NULL, NULL, ¶ms, NULL, NULL, NULL, NULL, NULL); + if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, + "Unable to load %s from %s (unexpected parameters type)\n", + desc, uri); + EVP_PKEY_free(params); + params = NULL; } - - BIO_free(file_bio); - OSSL_DECODER_CTX_free(dctx); return params; } @@ -1876,18 +1849,11 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) goto err; #ifndef OPENSSL_NO_POSIX_IO - if (BIO_get_fp(in, &dbfp) > 0 && dbfp != NULL) { - if (fstat(fileno(dbfp), &dbst) == -1) { - ERR_raise_data(ERR_LIB_SYS, errno, - "calling fstat(%s)", dbfile); - goto err; - } - } else { - if (stat(dbfile, &dbst) == -1) { - ERR_raise_data(ERR_LIB_SYS, errno, - "calling stat(%s)", dbfile); - goto err; - } + BIO_get_fp(in, &dbfp); + if (fstat(fileno(dbfp), &dbst) == -1) { + ERR_raise_data(ERR_LIB_SYS, errno, + "calling fstat(%s)", dbfile); + goto err; } #endif @@ -2833,7 +2799,7 @@ static const char *get_dp_url(DIST_POINT *dp) for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { gen = sk_GENERAL_NAME_value(gens, i); uri = GENERAL_NAME_get0_value(gen, >ype); - if (gtype == GEN_URI && ASN1_STRING_length_ex(uri) > 6) { + if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { const char *uptr = (const char *)ASN1_STRING_get0_data(uri); if (IS_HTTP(uptr)) /* can/should not use HTTPS here */ @@ -3151,10 +3117,14 @@ static int WIN32_rename(const char *from, const char *to) if (tfrom == NULL) goto err; tto = tfrom + flen; +#if !defined(_WIN32_WCE) || _WIN32_WCE >= 101 if (!MultiByteToWideChar(CP_ACP, 0, from, (int)flen, (WCHAR *)tfrom, (int)flen)) +#endif for (i = 0; i < flen; i++) tfrom[i] = (TCHAR)from[i]; +#if !defined(_WIN32_WCE) || _WIN32_WCE >= 101 if (!MultiByteToWideChar(CP_ACP, 0, to, (int)tlen, (WCHAR *)tto, (int)tlen)) +#endif for (i = 0; i < tlen; i++) tto[i] = (TCHAR)to[i]; } @@ -3722,7 +3692,7 @@ int has_stdin_waiting(void) int corrupt_signature(ASN1_STRING *signature) { const unsigned char *valid = ASN1_STRING_get0_data(signature); - size_t length = ASN1_STRING_length_ex(signature); + int length = ASN1_STRING_length(signature); unsigned char *s = OPENSSL_memdup(valid, length); if (s == NULL) @@ -3730,7 +3700,7 @@ int corrupt_signature(ASN1_STRING *signature) s[length - 1] ^= 0x1; - ASN1_STRING_set0(signature, s, (int)length); + ASN1_STRING_set0(signature, s, length); return 1; } diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index 825a2b6709..43cf6af314 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -345,7 +345,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, STACK_OF(ASN1_UTF8STRING) *strs; ASN1_UTF8STRING *str; const char *data; - size_t len; + int len; if (OBJ_obj2nid(obj) == NID_id_it_certProfile) { if (!OSSL_CMP_ITAV_get0_certProfile(itav, &strs)) @@ -360,7 +360,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } - if (((len = ASN1_STRING_length_ex(str)) != sizeof("profile1") - 1) + if (((len = ASN1_STRING_length(str)) != (int)sizeof("profile1") - 1) || memcmp(data, "profile1", len) != 0) { ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); return NULL; diff --git a/apps/lib/opt.c b/apps/lib/opt.c index d139346cc2..9c6041230b 100644 --- a/apps/lib/opt.c +++ b/apps/lib/opt.c @@ -1236,7 +1236,9 @@ int opt_isdir(const char *name) if (len_0 > MAX_PATH) return -1; +#if !defined(_WIN32_WCE) || _WIN32_WCE >= 101 if (!MultiByteToWideChar(CP_ACP, 0, name, (int)len_0, tempname, MAX_PATH)) +#endif for (i = 0; i < len_0; i++) tempname[i] = (WCHAR)name[i]; diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c index f83ffd7236..d4dcf12a07 100644 --- a/apps/lib/s_cb.c +++ b/apps/lib/s_cb.c @@ -576,7 +576,6 @@ static STRINT_PAIR ssl_versions[] = { { "TLS 1.2", TLS1_2_VERSION }, { "TLS 1.3", TLS1_3_VERSION }, { "DTLS 1.0", DTLS1_VERSION }, - { "DTLS 1.2", DTLS1_2_VERSION }, { "DTLS 1.0 (bad)", DTLS1_BAD_VER }, { NULL } }; @@ -654,10 +653,7 @@ void msg_cb(int write_p, int version, int content_type, const void *buf, const char *str_version, *str_content_type = "", *str_details1 = "", *str_details2 = ""; const unsigned char *bp = buf; - if (version == TLS1_VERSION || version == TLS1_1_VERSION - || version == TLS1_2_VERSION || version == TLS1_3_VERSION - || version == DTLS1_VERSION || version == DTLS1_2_VERSION - || version == DTLS1_BAD_VER) { + if (version == TLS1_VERSION || version == TLS1_1_VERSION || version == TLS1_2_VERSION || version == TLS1_3_VERSION || version == DTLS1_VERSION || version == DTLS1_BAD_VER) { str_version = lookup(version, ssl_versions, "???"); switch (content_type) { case SSL3_RT_CHANGE_CIPHER_SPEC: @@ -779,8 +775,8 @@ static const STRINT_PAIR tlsext_types[] = { { NULL } }; +/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */ static STRINT_PAIR signature_tls13_scheme_list[] = { - /* RFC 8446 4.2.3 */ { "rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */ }, { "ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */ }, /* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */ @@ -799,59 +795,9 @@ static STRINT_PAIR signature_tls13_scheme_list[] = { { "rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */ }, { "rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */ }, { "rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */ }, - - /* RFC 8734 */ - { "ecdsa_brainpoolP256r1tls13_sha256", 0x81a }, - { "ecdsa_brainpoolP256r1tls13_sha384", 0x81b }, - { "ecdsa_brainpoolP256r1tls13_sha512", 0x81c }, - - /* RFC 8998 */ - { "sm2sig_sm3", 0x0708 /* TLSEXT_SIGALG_sm2sig_sm3 */ }, - - /* RFC 9367 */ - { "gostr34102012_256a", 0x709 }, - { "gostr34102012_256b", 0x70a }, - { "gostr34102012_256c", 0x70b }, - { "gostr34102012_256d", 0x70c }, - { "gostr34102012_512a", 0x70d }, - { "gostr34102012_512b", 0x70e }, - { "gostr34102012_512c", 0x70f }, - - /* RFC 9963 */ - { "rsa_pkcs1_sha256_legacy", 0x0420 }, - { "rsa_pkcs1_sha384_legacy", 0x0520 }, - { "rsa_pkcs1_sha512_legacy", 0x0620 }, - - /* IBS (https://datatracker.ietf.org/doc/html/draft-wang-tls-raw-public-key-with-ibc-02) */ - { "eccsi_sha256", 0x0704 }, - { "iso_ibs1", 0x0705 }, - { "iso_ibs2", 0x0706 }, - { "iso_chinese_ibs", 0x0707 }, - - /* ML-DSA (https://datatracker.ietf.org/doc/html/draft-ietf-tls-mldsa-00) */ - { "mldsa44", 0x0904 }, - { "mldsa65", 0x0905 }, - { "mldsa87", 0x0906 }, - - /* SLH-DSA (https://datatracker.ietf.org/doc/html/draft-reddy-tls-slhdsa-01) */ - { "slhdsa_sha2_128s", 0x0911 }, - { "slhdsa_sha2_128f", 0x0912 }, - { "slhdsa_sha2_192s", 0x0913 }, - { "slhdsa_sha2_192f", 0x0914 }, - { "slhdsa_sha2_256s", 0x0915 }, - { "slhdsa_sha2_256f", 0x0916 }, - { "slhdsa_shake_128s", 0x0917 }, - { "slhdsa_shake_128f", 0x0918 }, - { "slhdsa_shake_192s", 0x0919 }, - { "slhdsa_shake_192f", 0x091a }, - { "slhdsa_shake_256s", 0x091b }, - { "slhdsa_shake_256f", 0x091c }, - - /* GOST (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */ { "gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */ }, { "gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */ }, { "gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */ }, - { NULL } }; @@ -1528,7 +1474,10 @@ static STRINT_PAIR callback_types[] = { { "Signature Algorithm mask", SSL_SECOP_SIGALG_MASK }, { "Certificate chain EE key", SSL_SECOP_EE_KEY }, { "Certificate chain CA key", SSL_SECOP_CA_KEY }, + { "Peer Chain EE key", SSL_SECOP_PEER_EE_KEY }, + { "Peer Chain CA key", SSL_SECOP_PEER_CA_KEY }, { "Certificate chain CA digest", SSL_SECOP_CA_MD }, + { "Peer chain CA digest", SSL_SECOP_PEER_CA_MD }, { "SSL compression", SSL_SECOP_COMPRESSION }, { "Session ticket", SSL_SECOP_TICKET }, { NULL } @@ -1562,6 +1511,7 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, show_nm = 0; break; case SSL_SECOP_CA_MD: + case SSL_SECOP_PEER_CA_MD: cert_md = 1; break; case SSL_SECOP_SIGALG_SUPPORTED: diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c index e60d7f0a1b..faceb05d01 100644 --- a/apps/lib/vms_term_sock.c +++ b/apps/lib/vms_term_sock.c @@ -495,7 +495,7 @@ static int CreateSocketPair(int SocketFamily, SocketPair[0] = SockDesc2; SocketPair[1] = socket_fd(TcpDeviceChan); - return 0; + return (0); } /*----------------------------------------------------------------------------*/ diff --git a/apps/ocsp.c b/apps/ocsp.c index 59d33e90f2..2293185daf 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -74,7 +74,7 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp); static char *prog; -#ifndef OPENSSL_NO_POSIX_IO +#ifdef HTTP_DAEMON static int index_changed(CA_DB *); #endif @@ -680,7 +680,7 @@ int ocsp_main(int argc, char **argv) redo_accept: if (acbio != NULL) { -#ifndef OPENSSL_NO_POSIX_IO +#ifdef HTTP_DAEMON if (index_changed(rdb)) { CA_DB *newrdb = load_index(ridx_filename, NULL); @@ -926,7 +926,7 @@ end: return ret; } -#ifndef OPENSSL_NO_POSIX_IO +#ifdef HTTP_DAEMON static int index_changed(CA_DB *rdb) { @@ -937,11 +937,7 @@ static int index_changed(CA_DB *rdb) || rdb->dbst.st_ctime != sb.st_ctime || rdb->dbst.st_ino != sb.st_ino || rdb->dbst.st_dev != sb.st_dev) { -#ifdef HTTP_DAEMON syslog(LOG_INFO, "index file changed, reloading"); -#else - BIO_printf(bio_err, "%s: index file changed, reloading\n", prog); -#endif return 1; } } diff --git a/apps/pkcs12.c b/apps/pkcs12.c index e37aefc7a3..f817999562 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -833,7 +833,7 @@ int pkcs12_main(int argc, char **argv) ASN1_INTEGER_get(pbkdf2_param->iter)); BIO_printf(bio_err, "Key length: %ld, Salt length: %d\n", ASN1_INTEGER_get(pbkdf2_param->keylength), - (int)ASN1_STRING_length_ex(pbkdf2_param->salt->value.octet_string)); + ASN1_STRING_length(pbkdf2_param->salt->value.octet_string)); if (pbkdf2_param->prf == NULL) { prfnid = NID_hmacWithSHA1; } else { @@ -847,8 +847,8 @@ int pkcs12_main(int argc, char **argv) BIO_printf(bio_err, ", Iteration %ld\n", tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L); BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n", - tmac != NULL ? (long)ASN1_STRING_length_ex(tmac) : 0L, - tsalt != NULL ? (long)ASN1_STRING_length_ex(tsalt) : 0L); + tmac != NULL ? ASN1_STRING_length(tmac) : 0L, + tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L); } } @@ -1231,7 +1231,7 @@ static int alg_print(const X509_ALGOR *alg) } BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, " "Block size(r): %ld, Parallelism(p): %ld", - (int)ASN1_STRING_length_ex(kdf->salt), + ASN1_STRING_length(kdf->salt), ASN1_INTEGER_get(kdf->costParameter), ASN1_INTEGER_get(kdf->blockSize), ASN1_INTEGER_get(kdf->parallelizationParameter)); @@ -1282,25 +1282,25 @@ void print_attribute(BIO *out, const ASN1_TYPE *av) switch (av->type) { case V_ASN1_BMPSTRING: value = OPENSSL_uni2asc(ASN1_STRING_get0_data(av->value.bmpstring), - (int)ASN1_STRING_length_ex(av->value.bmpstring)); + ASN1_STRING_length(av->value.bmpstring)); BIO_printf(out, "%s\n", value); OPENSSL_free(value); break; case V_ASN1_UTF8STRING: - BIO_printf(out, "%.*s\n", (int)ASN1_STRING_length_ex(av->value.utf8string), + BIO_printf(out, "%.*s\n", ASN1_STRING_length(av->value.utf8string), ASN1_STRING_get0_data(av->value.utf8string)); break; case V_ASN1_OCTET_STRING: hex_print(out, ASN1_STRING_get0_data(av->value.octet_string), - (int)ASN1_STRING_length_ex(av->value.octet_string)); + ASN1_STRING_length(av->value.octet_string)); BIO_puts(out, "\n"); break; case V_ASN1_BIT_STRING: hex_print(out, ASN1_STRING_get0_data(av->value.bit_string), - (int)ASN1_STRING_length_ex(av->value.bit_string)); + ASN1_STRING_length(av->value.bit_string)); BIO_puts(out, "\n"); break; diff --git a/apps/pkey.c b/apps/pkey.c index 868e411820..48b091c86d 100644 --- a/apps/pkey.c +++ b/apps/pkey.c @@ -72,7 +72,7 @@ const OPTIONS pkey_options[] = { { "ec_conv_form", OPT_EC_CONV_FORM, 's', "Specifies the EC point conversion form in the encoding" }, { "ec_param_enc", OPT_EC_PARAM_ENC, 's', - "Selects between named_curve and explicit EC parameter encoding" }, + "Specifies the way the EC parameters are encoded" }, { NULL } }; diff --git a/apps/rand.c b/apps/rand.c index 3b1647d9b1..7aec7b6e17 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -23,7 +23,6 @@ typedef enum OPTION_choice { OPT_OUT, OPT_BASE64, OPT_HEX, - OPT_NO_NEWLINE, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -38,7 +37,6 @@ const OPTIONS rand_options[] = { { "out", OPT_OUT, '>', "Output file" }, { "base64", OPT_BASE64, '-', "Base64 encode output" }, { "hex", OPT_HEX, '-', "Hex encode output" }, - { "n", OPT_NO_NEWLINE, '-', "Do not output the trailing newline" }, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -53,7 +51,7 @@ int rand_main(int argc, char **argv) BIO *out = NULL; char *outfile = NULL, *prog; OPTION_CHOICE o; - int format = FORMAT_BINARY, r, i, ret = 1, newline = 1; + int format = FORMAT_BINARY, r, i, ret = 1; size_t buflen = (1 << 16); /* max rand chunk size is 2^16 bytes */ long num = -1; uint64_t scaled_num = 0; @@ -84,9 +82,6 @@ int rand_main(int argc, char **argv) case OPT_HEX: format = FORMAT_TEXT; break; - case OPT_NO_NEWLINE: - newline = 0; - break; case OPT_PROV_CASES: if (!opt_provider(o)) goto end; @@ -213,7 +208,7 @@ int rand_main(int argc, char **argv) } scaled_num -= chunk; } - if (newline && format == FORMAT_TEXT) + if (format == FORMAT_TEXT) BIO_puts(out, "\n"); if (BIO_flush(out) <= 0) goto end; diff --git a/apps/req.c b/apps/req.c index 83ac38ef86..695fd049dd 100644 --- a/apps/req.c +++ b/apps/req.c @@ -1254,21 +1254,25 @@ static int prompt_info(X509_REQ *req, if (!join(buf, sizeof(buf), type, "_value", "Name")) goto err; + ; value = app_conf_try_string(req_conf, attr_sect, buf); if (!join(buf, sizeof(buf), type, "_min", "Name")) goto err; + ; if (!app_conf_try_number(req_conf, attr_sect, buf, &n_min)) n_min = -1; if (!join(buf, sizeof(buf), type, "_max", "Name")) goto err; + ; if (!app_conf_try_number(req_conf, attr_sect, buf, &n_max)) n_max = -1; if (!add_attribute_object(req, v->value, def, value, nid, n_min, n_max, chtype)) goto err; + ; } } } else { diff --git a/apps/s_client.c b/apps/s_client.c index 65aff3eb42..2d1f61a179 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -3049,7 +3049,6 @@ re_start: ASN1_TYPE *atyp = NULL; BIO *ldapbio = BIO_new(BIO_s_mem()); CONF *cnf = NCONF_new(NULL); - size_t ssl_request_len; if (ldapbio == NULL || cnf == NULL) { BIO_free(ldapbio); @@ -3082,18 +3081,11 @@ re_start: BIO_puts(bio_err, "ASN1_generate_nconf failed\n"); goto end; } - ssl_request_len = ASN1_STRING_length_ex(atyp->value.sequence); - if (ssl_request_len > INT_MAX) { - NCONF_free(cnf); - ASN1_TYPE_free(atyp); - BIO_puts(bio_err, "generated NCONF size is too large\n"); - goto end; - } NCONF_free(cnf); /* Send SSLRequest packet */ BIO_write(sbio, ASN1_STRING_get0_data(atyp->value.sequence), - (int)ssl_request_len); + ASN1_STRING_length(atyp->value.sequence)); (void)BIO_flush(sbio); ASN1_TYPE_free(atyp); @@ -3528,32 +3520,29 @@ shut: print_stuff(bio_c_out, con, full_log); do_ssl_shutdown(con); - /* The following half-close/drain workaround is TCP-specific. */ - if (!isdtls && !isquic) { - /* - * If we ended with an alert being sent, but still with data in the - * network buffer to be read, then calling BIO_closesocket() will - * result in a TCP-RST being sent. On some platforms (notably - * Windows) then this will result in the peer immediately abandoning - * the connection including any buffered alert data before it has - * had a chance to be read. Shutting down the sending side first, - * and then closing the socket sends TCP-FIN first followed by - * TCP-RST. This seems to allow the peer to read the alert data. - */ - shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ - /* - * We just said we have nothing else to say, but it doesn't mean that - * the other side has nothing. It's even recommended to consume incoming - * data. [In testing context this ensures that alerts are passed on...] - */ - timeout.tv_sec = 0; - timeout.tv_usec = 500000; /* some extreme round-trip */ - do { - FD_ZERO(&readfds); - openssl_fdset(sock, &readfds); - } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 - && BIO_read(sbio, sbuf, BUFSIZZ) > 0); - } + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean that + * the other side has nothing. It's even recommended to consume incoming + * data. [In testing context this ensures that alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(sock, &readfds); + } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 + && BIO_read(sbio, sbuf, BUFSIZZ) > 0); BIO_closesocket(SSL_get_fd(con)); end: diff --git a/apps/s_server.c b/apps/s_server.c index 4d99e5442b..43b212df7a 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -462,7 +462,7 @@ typedef struct tlsextctx_st { static unsigned int ech_print_cb(SSL *s, const char *str) { if (str != NULL) - BIO_printf(bio_s_out, "ECH Server callback printing:\n%s\n", str); + BIO_printf(bio_s_out, "ECH Server callback printing: \n%s\n", str); return 1; } @@ -4020,7 +4020,6 @@ static int www_body(int s, int stype, int prot, unsigned char *context) if (rpk_files != NULL && !rpk_enable(con)) { BIO_puts(bio_err, "Error enabling client RPK verification\n"); - SSL_free(con); goto err; } @@ -4544,7 +4543,6 @@ static int rev_body(int s, int stype, int prot, unsigned char *context) if (rpk_files != NULL && !rpk_enable(con)) { BIO_puts(bio_err, "Error enabling client RPK verification\n"); ERR_print_errors(bio_err); - SSL_free(con); goto err; } diff --git a/apps/speed.c b/apps/speed.c index b1732744d3..aa10d32bd5 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -2945,7 +2945,7 @@ int speed_main(int argc, char **argv) &outlen, loopargs[k].buf, lengths[testnum])) { BIO_puts(bio_err, - "\nFailed to encrypt the data\n"); + "\nFailed to to encrypt the data\n"); dofail(); exit(1); } @@ -4633,7 +4633,7 @@ static int do_multi(int multi, int size_num) for (n = 0; n < multi; ++n) { while (wait(&status) == -1) if (errno != EINTR) { - BIO_printf(bio_err, "Waiting for child failed with 0x%x\n", + BIO_printf(bio_err, "Waitng for child failed with 0x%x\n", errno); return 1; } diff --git a/apps/spkac.c b/apps/spkac.c index 27b2392bb9..bcf5626277 100644 --- a/apps/spkac.c +++ b/apps/spkac.c @@ -155,8 +155,8 @@ int spkac_main(int argc, char **argv) if (spki == NULL) goto end; if (challenge != NULL - && !ASN1_STRING_set_string(spki->spkac->challenge, - challenge)) + && !ASN1_STRING_set(spki->spkac->challenge, + challenge, (int)strlen(challenge))) goto end; if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) { BIO_puts(bio_err, "Error setting public key\n"); diff --git a/apps/ts.c b/apps/ts.c index 2049eb9331..aaec526154 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -583,7 +583,7 @@ static ASN1_INTEGER *create_nonce(int bits) if ((nonce = ASN1_INTEGER_new()) == NULL) goto err; - if (!ASN1_STRING_set_data(nonce, buf, len)) + if (!ASN1_STRING_set(nonce, buf, len)) goto err; ret = nonce; diff --git a/crypto/LPdir_win.c b/crypto/LPdir_win.c index 425a7962d0..bc5cec35d9 100644 --- a/crypto/LPdir_win.c +++ b/crypto/LPdir_win.c @@ -36,13 +36,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include -#include "internal/e_os.h" #include "internal/numbers.h" #ifndef LPDIR_H #include "LPdir.h" #endif +/* + * We're most likely overcautious here, but let's reserve for broken WinCE + * headers and explicitly opt for UNICODE call. Keep in mind that our WinCE + * builds are compiled with -DUNICODE [as well as -D_UNICODE]. + */ +#if defined(LP_SYS_WINCE) && !defined(FindFirstFile) +#define FindFirstFile FindFirstFileW +#endif +#if defined(LP_SYS_WINCE) && !defined(FindNextFile) +#define FindNextFile FindNextFileW +#endif + #ifndef NAME_MAX #define NAME_MAX 255 #endif diff --git a/crypto/LPdir_wince.c b/crypto/LPdir_wince.c new file mode 100644 index 0000000000..e4c883dcef --- /dev/null +++ b/crypto/LPdir_wince.c @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LP_SYS_WINCE +/* + * We might want to define LP_MULTIBYTE_AVAILABLE here. It's currently under + * investigation what the exact conditions would be + */ +/* clang-format off */ +#include "LPdir_win.c" +/* clang-format on */ diff --git a/crypto/armcap.c b/crypto/armcap.c index f4f6b0d7f9..cdb8336b13 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -19,7 +19,7 @@ #endif #include "internal/cryptlib.h" #ifdef _WIN32 -#include "internal/e_os.h" +#include #else #include #endif @@ -69,7 +69,7 @@ uint32_t OPENSSL_rdtsc(void) /* First determine if getauxval() is available (OSSL_IMPLEMENT_GETAUXVAL) */ -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 void OPENSSL_cpuid_setup(void) __attribute__((constructor)); #endif @@ -415,52 +415,15 @@ void OPENSSL_cpuid_setup(void) if (OPENSSL_armcap_P & ARMV8_CPUID) OPENSSL_arm_midr = _armv8_cpuid_probe(); - if ((OPENSSL_armcap_P & ARMV7_NEON) - && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1))) + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1)) && (OPENSSL_armcap_P & ARMV7_NEON)) { OPENSSL_armv8_rsa_neonized = 1; - - if ((OPENSSL_armcap_P & ARMV8_SHA3) - && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_COBALT_100) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) - || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) + } + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_COBALT_100) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE) && (OPENSSL_armcap_P & ARMV8_SHA3)) OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3; - - if ((OPENSSL_armcap_P & ARMV8_SHA3) - && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) - || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS)) && (OPENSSL_armcap_P & ARMV8_SHA3)) OPENSSL_armcap_P |= ARMV8_UNROLL12_EOR3; - - if ((OPENSSL_armcap_P & ARMV8_SHA3) - && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS)) && (OPENSSL_armcap_P & ARMV8_SHA3)) OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING; - if (OPENSSL_armcap_P & ARMV9_SVE2) { uint64_t vl_bytes = _armv8_sve_get_vl_bytes(); diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c index fdefb80e26..914ff98400 100644 --- a/crypto/asn1/a_bitstr.c +++ b/crypto/asn1/a_bitstr.c @@ -18,7 +18,7 @@ #ifndef OPENSSL_NO_DEPRECATED_4_1 int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) { - return ossl_asn1_string_set_internal(x, d, len, /*add_nul_byte=*/0); + return ASN1_STRING_set(x, d, len); } #endif @@ -263,9 +263,8 @@ int ASN1_BIT_STRING_set1(ASN1_BIT_STRING *abs, const uint8_t *data, size_t lengt if (length > 0 && (data[length - 1] & ((1 << unused_bits) - 1)) != 0) return 0; - if (!ossl_asn1_string_set_internal(abs, data, (int)length, /*add_nul_byte=*/0)) + if (!ASN1_STRING_set(abs, data, (int)length)) return 0; - abs->type = V_ASN1_BIT_STRING; ossl_asn1_bit_string_set_unused_bits(abs, unused_bits); diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index 41491b92a1..8f9e267689 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -141,20 +141,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) i = BIO_read(in, &(b->data[len]), (int)want); if (i <= 0) { - /* - * A read error (i < 0), an EOF in the middle of an object - * (diff != 0, some bytes already buffered), or an EOF while - * still inside an indefinite-length constructed value awaiting - * its end-of-contents octets (eos != 0) all mean the input is - * truncated. Only a clean EOF at a top-level object boundary - * (i == 0, diff == 0, eos == 0) is the normal end of input: - * fail without queuing an error so that callers looping over - * concatenated DER values (e.g. the libcrypto d2i_*_bio() - * consumers in CPython's ssl module) terminate cleanly instead - * of seeing a spurious ASN1_R_NOT_ENOUGH_DATA. - */ - if (i < 0 || diff != 0 || eos != 0) - ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c index 10db6b6a3c..3b10ee99e5 100644 --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c @@ -316,7 +316,7 @@ ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, } else ret = *a; - if (ASN1_STRING_set_data(ret, NULL, r) == 0) { + if (r > INT_MAX || ASN1_STRING_set(ret, NULL, (int)r) == 0) { ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } @@ -371,7 +371,7 @@ static int asn1_string_set_int64(ASN1_STRING *a, int64_t r, int itype) off = asn1_put_uint64(tbuf, r); a->type &= ~V_ASN1_NEG; } - return ASN1_STRING_set_data(a, tbuf + off, (sizeof(tbuf) - off)); + return ASN1_STRING_set(a, tbuf + off, (int)(sizeof(tbuf) - off)); } static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a, @@ -399,7 +399,7 @@ static int asn1_string_set_uint64(ASN1_STRING *a, uint64_t r, int itype) a->type = itype; off = asn1_put_uint64(tbuf, r); - return ASN1_STRING_set_data(a, tbuf + off, (sizeof(tbuf) - off)); + return ASN1_STRING_set(a, tbuf + off, (int)(sizeof(tbuf) - off)); } /* @@ -503,7 +503,7 @@ static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai, if (len == 0) len = 1; - if (ASN1_STRING_set_data(ret, NULL, len) == 0) { + if (ASN1_STRING_set(ret, NULL, len) == 0) { ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index e70fe92db5..236082ec39 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -69,9 +69,6 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, if (len < 0) { ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT); return -1; - } else if (len >= INT_MAX) { - ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG); - return -1; } /* First do a string check and work out the number of characters */ @@ -171,7 +168,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, } /* If both the same type just copy across */ if (inform == outform) { - if (!ASN1_STRING_set_data(dest, in, len)) { + if (!ASN1_STRING_set(dest, in, len)) { if (free_out) { ASN1_STRING_free(dest); *out = NULL; @@ -308,7 +305,7 @@ static int out_utf8(uint32_t value, void *arg) return len; } outlen = arg; - if (*outlen >= INT_MAX - len) { + if (*outlen > INT_MAX - len) { ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG); return -1; } diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c index 99df7539a1..4efb8ec517 100644 --- a/crypto/asn1/a_octet.c +++ b/crypto/asn1/a_octet.c @@ -25,11 +25,5 @@ int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len) { - if (len < -1) { - ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); - return 0; - } - if (len == -1) - return ASN1_STRING_set_string(x, (const char *)d); - return ASN1_STRING_set_data(x, d, len); + return ASN1_STRING_set(x, d, len); } diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 4315355632..e488c87f5b 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -12,7 +12,6 @@ #include "internal/cryptlib.h" #include "internal/sizes.h" #include "internal/unicode.h" -#include "internal/safe_math.h" #include "crypto/asn1.h" #include #include @@ -32,8 +31,6 @@ #define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_2254 | ASN1_STRFLGS_ESC_QUOTE | ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB) -OSSL_SAFE_MATH_SIGNED(int, int) - /* * Three IO functions for sending data to memory, a BIO and a FILE * pointer. @@ -145,10 +142,6 @@ static int do_buf(const unsigned char *buf, int buflen, const unsigned char *p, *q; uint32_t c; - if (buflen < 0) - return -1; - if (buflen == 0) - return 0; p = buf; q = buf + buflen; outlen = 0; @@ -243,10 +236,6 @@ static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, unsigned char *p, *q; char hextmp[2]; - if (buflen < 0) - return -1; - if (buflen == 0) - return 0; if (arg) { p = buf; q = buf + buflen; @@ -441,7 +430,6 @@ static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, char objtmp[80]; const char *objbuf; int outlen, len; - int err = 0; char *sep_dn, *sep_mv, *sep_eq; int sep_dn_len, sep_mv_len, sep_eq_len; if (indent < 0) @@ -505,20 +493,14 @@ static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, if (prev == X509_NAME_ENTRY_set(ent)) { if (!io_ch(arg, sep_mv, sep_mv_len)) return -1; - outlen = safe_add_int(outlen, sep_mv_len, &err); - if (err != 0) - return -1; + outlen += sep_mv_len; } else { if (!io_ch(arg, sep_dn, sep_dn_len)) return -1; - outlen = safe_add_int(outlen, sep_dn_len, &err); - if (err != 0) - return -1; + outlen += sep_dn_len; if (!do_indent(io_ch, arg, indent)) return -1; - outlen = safe_add_int(outlen, indent, &err); - if (err != 0) - return -1; + outlen += indent; } } prev = X509_NAME_ENTRY_set(ent); @@ -549,18 +531,11 @@ static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { if (!do_indent(io_ch, arg, fld_len - objlen)) return -1; - outlen = safe_add_int(outlen, fld_len - objlen, &err); - if (err != 0) - return -1; + outlen += fld_len - objlen; } if (!io_ch(arg, sep_eq, sep_eq_len)) return -1; - outlen = safe_add_int(outlen, objlen, &err); - if (err != 0) - return -1; - outlen = safe_add_int(outlen, sep_eq_len, &err); - if (err != 0) - return -1; + outlen += objlen + sep_eq_len; } /* * If the field name is unknown then fix up the DER dump flag. We @@ -575,9 +550,7 @@ static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, len = do_print_ex(io_ch, arg, flags | orflags, val); if (len < 0) return -1; - outlen = safe_add_int(outlen, len, &err); - if (err != 0) - return -1; + outlen += len; } return outlen; } diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 341bd5142d..56366fe531 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -271,7 +271,7 @@ ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type) if (tmps == NULL) return NULL; - if (!ASN1_STRING_set_data(tmps, NULL, len)) + if (!ASN1_STRING_set(tmps, NULL, len)) goto err; tmps->type = type; diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c index 6fbf581b49..35abf85ca4 100644 --- a/crypto/asn1/asn1_gen.c +++ b/crypto/asn1/asn1_gen.c @@ -651,7 +651,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } - if (!ASN1_STRING_set_string(atmp->value.asn1_string, str)) { + if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } @@ -706,7 +706,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) atmp->value.asn1_string->length = rdlen; atmp->value.asn1_string->type = utype; } else if (format == ASN1_GEN_FORMAT_ASCII) { - if (!ASN1_STRING_set_string(atmp->value.asn1_string, str)) { + if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 4b9e720bad..99903564e2 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -265,8 +265,7 @@ int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) if (str == NULL) return 0; dst->type = str->type; - if (!ossl_asn1_string_set_internal(dst, str->data, str->length, - /*add_nul_byte=*/0)) + if (!ASN1_STRING_set(dst, str->data, str->length)) return 0; /* Copy flags but preserve embed value */ dst->flags &= ASN1_STRING_FLAG_EMBED; @@ -290,18 +289,12 @@ ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) return ret; } -int ossl_asn1_string_set_internal(ASN1_STRING *str, const uint8_t *data, - int len_in, int add_nul_byte) +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in) { - size_t len, alloc_len; + unsigned char *c; + const char *data = _data; + size_t len; -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - /* - * Force no NUL byte for callers that are requesting it - * 0 length object data will be NULL - */ - add_nul_byte = 0; -#endif if (len_in < -1) { ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); return 0; @@ -309,17 +302,16 @@ int ossl_asn1_string_set_internal(ASN1_STRING *str, const uint8_t *data, if (len_in == -1) { if (data == NULL) return 0; - len = strlen((const char *)data); + len = strlen(data); } else { len = (size_t)len_in; } /* - * Add one to the length to allow for adding an a '\0' terminator - * "even though this isn't strictly necessary". + * Verify that the length fits within an integer for assignment to + * str->length below. The additional 1 is subtracted to allow for the + * '\0' terminator even though this isn't strictly necessary. */ - alloc_len = add_nul_byte ? len + 1 : len; - - if (alloc_len > INT_MAX) { + if (len > INT_MAX - 1) { ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } @@ -330,47 +322,39 @@ int ossl_asn1_string_set_internal(ASN1_STRING *str, const uint8_t *data, str->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED; } - /* Ensure copying a 0 length data field is defined. */ - if (alloc_len == 0) { - OPENSSL_free(str->data); - str->data = NULL; - str->length = 0; - return 1; - } - - if ((size_t)str->length != alloc_len) { - uint8_t *c; - c = OPENSSL_realloc(str->length == 0 ? NULL : str->data, alloc_len); - if (c == NULL) + if ((size_t)str->length <= len || str->data == NULL) { + c = str->data; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* No NUL terminator in fuzzing builds */ + str->data = OPENSSL_realloc(c, len != 0 ? len : 1); +#else + str->data = OPENSSL_realloc(c, len + 1); +#endif + if (str->data == NULL) { + str->data = c; return 0; - str->data = c; - } - /* length never includes the added \0 byte */ - str->length = (int)len; - - if (data != NULL && str->data != NULL) { - memcpy(str->data, data, len); - if (add_nul_byte) { - /* - * Add a '\0' terminator. This should not be necessary - but we add it as - * a safety precaution - */ - str->data[len] = '\0'; } } + str->length = (int)len; + if (data != NULL) { + memcpy(str->data, data, len); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Set the unused byte to something non NUL and printable. */ + if (len == 0) + str->data[len] = '~'; +#else + /* + * Add a NUL terminator. This should not be necessary - but we add it as + * a safety precaution + */ + str->data[len] = '\0'; +#endif + } ossl_asn1_bit_string_clear_unused_bits(str); return 1; } -#ifndef OPENSSL_NO_DEPRECATED_4_1 -int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in) -{ - return ossl_asn1_string_set_internal(str, (const uint8_t *)_data, len_in, - /*add_nul_byte=*/1); -} -#endif - void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) { if (!(str->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) { @@ -381,26 +365,6 @@ void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) str->length = len; } -int ASN1_STRING_set_data(ASN1_STRING *str, const uint8_t *data, size_t len_in) -{ - if (str->type == V_ASN1_BIT_STRING) { - ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT); - return 0; - } - /* This will go away once ASN1_STRING can size_t internally */ - if (len_in > INT_MAX) { - ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); - return 0; - } - return ossl_asn1_string_set_internal(str, data, (int)len_in, /*add_nul_byte=*/0); -} - -int ASN1_STRING_set_string(ASN1_STRING *str, const char *c_string) -{ - return ASN1_STRING_set_data(str, (const uint8_t *)c_string, - strlen(c_string)); -} - ASN1_STRING *ASN1_STRING_new(void) { return ASN1_STRING_type_new(V_ASN1_OCTET_STRING); @@ -505,17 +469,10 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) } } -#ifndef OPENSSL_NO_DEPRECATED_4_1 int ASN1_STRING_length(const ASN1_STRING *x) { return x->length; } -#endif - -size_t ASN1_STRING_length_ex(const ASN1_STRING *x) -{ - return (size_t)x->length; -} #ifndef OPENSSL_NO_DEPRECATED_3_0 void ASN1_STRING_length_set(ASN1_STRING *x, int len) @@ -552,7 +509,7 @@ char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, current = sk_ASN1_UTF8STRING_value(text, i); if (i > 0) length += sep_len; - length += ASN1_STRING_length_ex(current); + length += ASN1_STRING_length(current); if (max_len != 0 && length > max_len) return NULL; } @@ -562,7 +519,7 @@ char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, p = result; for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { current = sk_ASN1_UTF8STRING_value(text, i); - length = ASN1_STRING_length_ex(current); + length = ASN1_STRING_length(current); if (i > 0 && sep_len > 0) { strncpy(p, sep, sep_len + 1); /* using + 1 to silence gcc warning */ p += sep_len; diff --git a/crypto/asn1/asn1_local.h b/crypto/asn1/asn1_local.h index 6f3ee7983c..46d7aca7a2 100644 --- a/crypto/asn1/asn1_local.h +++ b/crypto/asn1/asn1_local.h @@ -12,7 +12,6 @@ #if !defined(OSSL_LIBCRYPTO_ASN1_ASN1_LOCAL_H) #define OSSL_LIBCRYPTO_ASN1_ASN1_LOCAL_H -#include #include "crypto/asn1.h" typedef const ASN1_VALUE const_ASN1_VALUE; @@ -100,9 +99,5 @@ int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it, OSSL_LIB_CTX *libctx, const char *propq); int ossl_asn1_time_time_t_to_tm(const time_t *time, struct tm *out_tm); int ossl_asn1_time_tm_to_time_t(const struct tm *tm, time_t *out); -int ossl_asn1_call_aux_cb(const ASN1_AUX *aux, int operation, - const ASN1_VALUE **in, const ASN1_ITEM *it, void *exarg); -int ossl_asn1_string_set_internal(ASN1_STRING *str, const uint8_t *data, - int len_in, int add_nul_byte); #endif /* !defined(OSSL_LIBCRYPTO_ASN1_ASN1_LOCAL_H) */ diff --git a/crypto/asn1/evp_asn1.c b/crypto/asn1/evp_asn1.c index 2f081e56d3..2d50dc657b 100644 --- a/crypto/asn1/evp_asn1.c +++ b/crypto/asn1/evp_asn1.c @@ -34,7 +34,6 @@ int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len) int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len) { int ret, num; - size_t tmp; const unsigned char *p; if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) { @@ -42,13 +41,7 @@ int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_l return -1; } p = ASN1_STRING_get0_data(a->value.octet_string); - tmp = ASN1_STRING_length_ex(a->value.octet_string); - if (tmp > INT_MAX) { - ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); - return -1; - } - ret = (int)tmp; - + ret = ASN1_STRING_length(a->value.octet_string); if (ret < max_len) num = ret; else @@ -76,19 +69,11 @@ static ossl_inline void asn1_type_init_oct(ASN1_OCTET_STRING *oct, static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum, long *num, unsigned char *data, int max_len) { - int ret, n; - size_t tmp; + int ret = ASN1_STRING_length(oct), n; if (num != NULL) *num = anum; - tmp = ASN1_STRING_length_ex(oct); - - if (tmp > INT_MAX) - tmp = INT_MAX; - - ret = (int)tmp; - if (max_len > ret) n = ret; else diff --git a/crypto/asn1/p5_scrypt.c b/crypto/asn1/p5_scrypt.c index 9e1b537b9f..64980a1a68 100644 --- a/crypto/asn1/p5_scrypt.c +++ b/crypto/asn1/p5_scrypt.c @@ -173,7 +173,7 @@ static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, int saltlen, saltlen = PKCS5_DEFAULT_PBE2_SALT_LEN; /* This will either copy salt or grow the buffer */ - if (ASN1_STRING_set_data(sparam->salt, salt, saltlen) == 0) { + if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) { ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c index 77f03e82ef..143f503dea 100644 --- a/crypto/asn1/p8_pkey.c +++ b/crypto/asn1/p8_pkey.c @@ -72,13 +72,11 @@ int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8) { - if (ASN1_STRING_length_ex(p8->pkey) > INT_MAX) - return 0; if (ppkalg) *ppkalg = p8->pkeyalg->algorithm; if (pk) { *pk = ASN1_STRING_get0_data(p8->pkey); - *ppklen = (int)ASN1_STRING_length_ex(p8->pkey); + *ppklen = ASN1_STRING_length(p8->pkey); } if (pa) *pa = p8->pkeyalg; diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 911eb42be7..197fd24105 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -983,7 +983,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, ASN1_STRING_set0(stmp, (unsigned char *)cont /* UGLY CAST! */, ilen); *free_cont = 0; } else { - if (!ASN1_STRING_set_data(stmp, cont, len)) { + if (!ASN1_STRING_set(stmp, cont, ilen)) { ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); ASN1_STRING_free(stmp); *pval = NULL; diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index e489e29a0c..834d087ebc 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -85,10 +85,16 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, int i, seqcontlen, seqlen, ndef = 1; const ASN1_EXTERN_FUNCS *ef; const ASN1_AUX *aux = it->funcs; + ASN1_aux_const_cb *asn1_cb = NULL; if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL) return 0; + if (aux != NULL) { + asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb + : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */ + } + switch (it->itype) { case ASN1_ITYPE_PRIMITIVE: @@ -117,7 +123,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE); return -1; } - if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_PRE, pval, it, NULL)) + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) return 0; i = ossl_asn1_get_choice_selector_const(pval, it); if ((i >= 0) && (i < it->tcount)) { @@ -128,7 +134,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); } /* Fixme: error condition if selector out of range */ - if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_POST, pval, it, NULL)) + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) return 0; break; @@ -160,7 +166,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) | V_ASN1_UNIVERSAL; } - if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_PRE, pval, it, NULL)) + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) return 0; /* First work out sequence content length */ for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { @@ -194,7 +200,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, } if (ndef == 2) ASN1_put_eoc(out); - if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_POST, pval, it, NULL)) + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) return 0; return seqlen; diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c index 72922c6530..080b5623e4 100644 --- a/crypto/asn1/tasn_prn.c +++ b/crypto/asn1/tasn_prn.c @@ -138,12 +138,15 @@ static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, const ASN1_EXTERN_FUNCS *ef; const ASN1_VALUE **tmpfld; const ASN1_AUX *aux = it->funcs; + ASN1_aux_const_cb *asn1_cb = NULL; ASN1_PRINT_ARG parg; int i; if (aux != NULL) { parg.out = out; parg.indent = indent; parg.pctx = pctx; + asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb + : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */ } if (((it->itype != ASN1_ITYPE_PRIMITIVE) @@ -217,11 +220,13 @@ static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, } } - i = ossl_asn1_call_aux_cb(aux, ASN1_OP_PRINT_PRE, fld, it, &parg); - if (i == 0) - return 0; - if (i == 2) - return 1; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg); + if (i == 0) + return 0; + if (i == 2) + return 1; + } /* Print each field entry */ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { @@ -239,9 +244,11 @@ static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, return 0; } - i = ossl_asn1_call_aux_cb(aux, ASN1_OP_PRINT_POST, fld, it, &parg); - if (i == 0) - return 0; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg); + if (i == 0) + return 0; + } break; default: diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c index a4ab762960..5e82a10fbd 100644 --- a/crypto/asn1/tasn_utl.c +++ b/crypto/asn1/tasn_utl.c @@ -288,19 +288,3 @@ err: ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); return NULL; } - -int ossl_asn1_call_aux_cb(const ASN1_AUX *aux, int operation, - const ASN1_VALUE **in, const ASN1_ITEM *it, void *exarg) -{ - if (aux == NULL) - return 1; - - if ((aux->flags & ASN1_AFLG_CONST_CB) != 0) { - if (aux->asn1_const_cb != NULL) - return aux->asn1_const_cb(operation, in, it, exarg); - } else if (aux->asn1_cb != NULL) { - return aux->asn1_cb(operation, (ASN1_VALUE **)in, it, exarg); - } - - return 1; -} diff --git a/crypto/asn1/x_long.c b/crypto/asn1/x_long.c index 4dc9dc6c6b..19f44f7b68 100644 --- a/crypto/asn1/x_long.c +++ b/crypto/asn1/x_long.c @@ -8,8 +8,8 @@ */ #include -#include "internal/cryptlib.h" #include +#include "crypto/cryptlib.h" #define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b)) @@ -56,31 +56,6 @@ static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) memcpy(pval, &it->size, COPY_SIZE(*pval, it->size)); } -/* - * Originally BN_num_bits_word was called to perform this operation, but - * trouble is that there is no guarantee that sizeof(long) equals to - * sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide - * as long, but also double or half... - */ -static int num_bits_ulong(unsigned long value) -{ - size_t i; - unsigned long ret = 0; - - /* - * It is argued that *on average* constant counter loop performs - * not worse [if not better] than one with conditional break or - * mask-n-table-lookup-style, because of branch misprediction - * penalties. - */ - for (i = 0; i < sizeof(value) * 8; i++) { - ret += (value != 0); - value >>= 1; - } - - return (int)ret; -} - static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it) { @@ -103,7 +78,7 @@ static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, sign = 0; utmp = ltmp; } - clen = num_bits_ulong(utmp); + clen = (int)ossl_num_bits(utmp); /* If MSB of leading octet set we need to pad */ if (!(clen & 0x7)) pad = 1; diff --git a/crypto/async/arch/async_win.c b/crypto/async/arch/async_win.c index 2ca4ed6a93..849da5c3c4 100644 --- a/crypto/async/arch/async_win.c +++ b/crypto/async/arch/async_win.c @@ -12,7 +12,7 @@ #ifdef ASYNC_WIN -#include "internal/e_os.h" +#include #include "internal/cryptlib.h" int ASYNC_is_capable(void) diff --git a/crypto/async/async_local.h b/crypto/async/async_local.h index f10a6745f8..e1d1113464 100644 --- a/crypto/async/async_local.h +++ b/crypto/async/async_local.h @@ -21,7 +21,6 @@ #include #include -#include typedef struct async_ctx_st async_ctx; typedef struct async_pool_st async_pool; @@ -30,6 +29,7 @@ typedef struct async_pool_st async_pool; #define ASYNC_WIN #define ASYNC_ARCH +#include #include "internal/cryptlib.h" typedef struct async_fibre_st { diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index 6066cc0d8c..b7d4bc549e 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -116,22 +116,24 @@ BIO *BIO_new(const BIO_METHOD *method) return BIO_new_ex(NULL, method); } -static int BIO_free_int(BIO *a, int *ret) +int BIO_free(BIO *a) { + int ret; if (a == NULL) return 0; - if (CRYPTO_DOWN_REF(&a->references, ret) <= 0) + if (CRYPTO_DOWN_REF(&a->references, &ret) <= 0) return 0; - REF_PRINT_COUNT("BIO", *ret, a); - if (*ret > 0) + REF_PRINT_COUNT("BIO", ret, a); + if (ret > 0) return 1; - REF_ASSERT_ISNT(*ret < 0); + REF_ASSERT_ISNT(ret < 0); if (HAS_CALLBACK(a)) { - if ((int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL) <= 0) + ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); + if (ret <= 0) return 0; } @@ -147,13 +149,6 @@ static int BIO_free_int(BIO *a, int *ret) return 1; } -int BIO_free(BIO *b) -{ - int ref; - - return BIO_free_int(b, &ref); -} - void BIO_set_data(BIO *a, void *ptr) { a->ptr = ptr; @@ -193,7 +188,7 @@ int BIO_up_ref(BIO *a) { int i; - if (!CRYPTO_UP_REF(&a->references, &i)) + if (CRYPTO_UP_REF(&a->references, &i) <= 0) return 0; REF_PRINT_COUNT("BIO", i, a); @@ -879,11 +874,11 @@ void BIO_free_all(BIO *bio) while (bio != NULL) { b = bio; + CRYPTO_GET_REF(&b->references, &ref); bio = bio->next_bio; - ref = 0; - BIO_free_int(b, &ref); - /* Since ref count > 0, don't free anyone else. */ - if (ref > 0) + BIO_free(b); + /* Since ref count > 1, don't free anyone else. */ + if (ref > 1) break; } } diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h index 87227e4f8f..36f72f5df1 100644 --- a/crypto/bio/bio_local.h +++ b/crypto/bio/bio_local.h @@ -74,7 +74,6 @@ struct bio_addrinfo_st { #include "internal/cryptlib.h" #include "internal/bio.h" #include "internal/refcount.h" -#include "internal/time.h" typedef struct bio_f_buffer_ctx_struct { /*- @@ -123,87 +122,6 @@ struct bio_st { }; #ifndef OPENSSL_NO_SOCK - -typedef struct bio_connect_st { - int state; - int connect_family; - int connect_sock_type; - char *param_hostname; - char *param_service; - int connect_mode; -#ifndef OPENSSL_NO_KTLS - unsigned char record_type; -#endif - int tfo_first; - - BIO_ADDRINFO *addr_first; - const BIO_ADDRINFO *addr_iter; - /* - * int socket; this will be kept in bio->num so that it is compatible - * with the bss_sock bio - */ - /* - * called when the connection is initially made callback(BIO,state,ret); - * The callback should return 'ret'. state is for compatibility with the - * ssl info_callback - */ - BIO_info_cb *info_callback; - /* - * Used when connect_sock_type is SOCK_DGRAM. Owned by us; we forward - * read/write(mmsg) calls to this if present. - */ - BIO *dgram_bio; -} BIO_CONNECT; - -typedef struct bio_accept_st { - int state; - int accept_family; - int bind_mode; /* Socket mode for BIO_listen */ - int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */ - char *param_addr; - char *param_serv; - - int accept_sock; - - BIO_ADDRINFO *addr_first; - const BIO_ADDRINFO *addr_iter; - BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */ - char *cache_accepting_name, *cache_accepting_serv; - BIO_ADDR cache_peer_addr; - char *cache_peer_name, *cache_peer_serv; - - BIO *bio_chain; -} BIO_ACCEPT; - -#ifndef OPENSSL_NO_DGRAM -typedef struct bio_dgram_data_st { - BIO_ADDR peer; - BIO_ADDR local_addr; - unsigned int connected; - unsigned int _errno; - unsigned int mtu; - OSSL_TIME next_timeout; - OSSL_TIME socket_timeout; - unsigned int peekmode; - char local_addr_enabled; -} bio_dgram_data; -#endif - -#define BIO_CONN_S_BEFORE 1 -#define BIO_CONN_S_GET_ADDR 2 -#define BIO_CONN_S_CREATE_SOCKET 3 -#define BIO_CONN_S_CONNECT 4 -#define BIO_CONN_S_OK 5 -#define BIO_CONN_S_BLOCKED_CONNECT 6 -#define BIO_CONN_S_CONNECT_ERROR 7 - -#define BIO_ACPT_S_BEFORE 1 -#define BIO_ACPT_S_GET_ADDR 2 -#define BIO_ACPT_S_CREATE_SOCKET 3 -#define BIO_ACPT_S_LISTEN 4 -#define BIO_ACPT_S_ACCEPT 5 -#define BIO_ACPT_S_OK 6 - #ifdef OPENSSL_SYS_VMS typedef unsigned int socklen_t; #endif diff --git a/crypto/bio/bio_print.c b/crypto/bio/bio_print.c index 5366587a2a..8b0c3481f0 100644 --- a/crypto/bio/bio_print.c +++ b/crypto/bio/bio_print.c @@ -111,7 +111,7 @@ int BIO_vprintf(BIO *bio, const char *format, va_list args) */ sz = vsnprintf(buf, sizeof(buf), format, args); if (sz >= 0) { - if ((size_t)sz >= sizeof(buf)) { + if ((size_t)sz > sizeof(buf)) { sz += 1; abuf = (char *)OPENSSL_malloc(sz); if (abuf == NULL) { diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c index c9cdba041a..1ba91c6592 100644 --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -15,6 +15,26 @@ #ifndef OPENSSL_NO_SOCK +typedef struct bio_accept_st { + int state; + int accept_family; + int bind_mode; /* Socket mode for BIO_listen */ + int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */ + char *param_addr; + char *param_serv; + + int accept_sock; + + BIO_ADDRINFO *addr_first; + const BIO_ADDRINFO *addr_iter; + BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */ + char *cache_accepting_name, *cache_accepting_serv; + BIO_ADDR cache_peer_addr; + char *cache_peer_name, *cache_peer_serv; + + BIO *bio_chain; +} BIO_ACCEPT; + static int acpt_write(BIO *h, const char *buf, int num); static int acpt_read(BIO *h, char *buf, int size); static int acpt_puts(BIO *h, const char *str); @@ -26,6 +46,13 @@ static void acpt_close_socket(BIO *data); static BIO_ACCEPT *BIO_ACCEPT_new(void); static void BIO_ACCEPT_free(BIO_ACCEPT *a); +#define ACPT_S_BEFORE 1 +#define ACPT_S_GET_ADDR 2 +#define ACPT_S_CREATE_SOCKET 3 +#define ACPT_S_LISTEN 4 +#define ACPT_S_ACCEPT 5 +#define ACPT_S_OK 6 + static const BIO_METHOD methods_acceptp = { BIO_TYPE_ACCEPT, "socket accept", @@ -56,7 +83,7 @@ static int acpt_new(BIO *bi) if ((ba = BIO_ACCEPT_new()) == NULL) return 0; bi->ptr = (char *)ba; - ba->state = BIO_ACPT_S_BEFORE; + ba->state = ACPT_S_BEFORE; bi->shutdown = 1; return 1; } @@ -125,7 +152,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) for (;;) { switch (c->state) { - case BIO_ACPT_S_BEFORE: + case ACPT_S_BEFORE: if (c->param_addr == NULL && c->param_serv == NULL) { ERR_raise_data(ERR_LIB_BIO, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED, @@ -147,10 +174,10 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) OPENSSL_free(c->cache_peer_serv); c->cache_peer_serv = NULL; - c->state = BIO_ACPT_S_GET_ADDR; + c->state = ACPT_S_GET_ADDR; break; - case BIO_ACPT_S_GET_ADDR: { + case ACPT_S_GET_ADDR: { int family = AF_UNSPEC; switch (c->accept_family) { case BIO_FAMILY_IPV6: @@ -186,10 +213,10 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) goto exit_loop; } c->addr_iter = c->addr_first; - c->state = BIO_ACPT_S_CREATE_SOCKET; + c->state = ACPT_S_CREATE_SOCKET; break; - case BIO_ACPT_S_CREATE_SOCKET: + case ACPT_S_CREATE_SOCKET: ERR_set_mark(); s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), BIO_ADDRINFO_socktype(c->addr_iter), @@ -211,11 +238,11 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) } c->accept_sock = s; b->num = s; - c->state = BIO_ACPT_S_LISTEN; + c->state = ACPT_S_LISTEN; s = -1; break; - case BIO_ACPT_S_LISTEN: { + case ACPT_S_LISTEN: { if (!BIO_listen(c->accept_sock, BIO_ADDRINFO_address(c->addr_iter), c->bind_mode)) { @@ -244,14 +271,14 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) OPENSSL_free(c->cache_accepting_serv); c->cache_accepting_name = BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1); c->cache_accepting_serv = BIO_ADDR_service_string(&c->cache_accepting_addr, 1); - c->state = BIO_ACPT_S_ACCEPT; + c->state = ACPT_S_ACCEPT; s = -1; ret = 1; goto end; - case BIO_ACPT_S_ACCEPT: + case ACPT_S_ACCEPT: if (b->next_bio != NULL) { - c->state = BIO_ACPT_S_OK; + c->state = ACPT_S_OK; break; } BIO_clear_retry_flags(b); @@ -307,14 +334,14 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) c->cache_peer_name = BIO_ADDR_hostname_string(&c->cache_peer_addr, 1); c->cache_peer_serv = BIO_ADDR_service_string(&c->cache_peer_addr, 1); - c->state = BIO_ACPT_S_OK; + c->state = ACPT_S_OK; bio = NULL; ret = 1; goto end; - case BIO_ACPT_S_OK: + case ACPT_S_OK: if (b->next_bio == NULL) { - c->state = BIO_ACPT_S_ACCEPT; + c->state = ACPT_S_ACCEPT; break; } ret = 1; @@ -385,7 +412,7 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) switch (cmd) { case BIO_CTRL_RESET: ret = 0; - data->state = BIO_ACPT_S_BEFORE; + data->state = ACPT_S_BEFORE; acpt_close_socket(b); BIO_ADDRINFO_free(data->addr_first); data->addr_first = NULL; @@ -447,7 +474,7 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_SET_FD: b->num = *((int *)ptr); data->accept_sock = b->num; - data->state = BIO_ACPT_S_ACCEPT; + data->state = ACPT_S_ACCEPT; b->shutdown = (int)num; b->init = 1; break; diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index c4355392e4..0e84e959d8 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -16,6 +16,37 @@ #ifndef OPENSSL_NO_SOCK +typedef struct bio_connect_st { + int state; + int connect_family; + int connect_sock_type; + char *param_hostname; + char *param_service; + int connect_mode; +#ifndef OPENSSL_NO_KTLS + unsigned char record_type; +#endif + int tfo_first; + + BIO_ADDRINFO *addr_first; + const BIO_ADDRINFO *addr_iter; + /* + * int socket; this will be kept in bio->num so that it is compatible + * with the bss_sock bio + */ + /* + * called when the connection is initially made callback(BIO,state,ret); + * The callback should return 'ret'. state is for compatibility with the + * ssl info_callback + */ + BIO_info_cb *info_callback; + /* + * Used when connect_sock_type is SOCK_DGRAM. Owned by us; we forward + * read/write(mmsg) calls to this if present. + */ + BIO *dgram_bio; +} BIO_CONNECT; + static int conn_write(BIO *h, const char *buf, int num); static int conn_read(BIO *h, char *buf, int size); static int conn_puts(BIO *h, const char *str); @@ -34,6 +65,14 @@ static void conn_close_socket(BIO *data); static BIO_CONNECT *BIO_CONNECT_new(void); static void BIO_CONNECT_free(BIO_CONNECT *a); +#define BIO_CONN_S_BEFORE 1 +#define BIO_CONN_S_GET_ADDR 2 +#define BIO_CONN_S_CREATE_SOCKET 3 +#define BIO_CONN_S_CONNECT 4 +#define BIO_CONN_S_OK 5 +#define BIO_CONN_S_BLOCKED_CONNECT 6 +#define BIO_CONN_S_CONNECT_ERROR 7 + static const BIO_METHOD methods_connectp = { BIO_TYPE_CONNECT, "socket connect", diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 1d98239511..0a1479e834 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -14,6 +14,7 @@ #include #include +#include "internal/time.h" #include "bio_local.h" #ifndef OPENSSL_NO_DGRAM @@ -212,7 +213,21 @@ static const BIO_METHOD methods_dgramp_sctp = { NULL, /* sendmmsg */ NULL, /* recvmmsg */ }; +#endif +typedef struct bio_dgram_data_st { + BIO_ADDR peer; + BIO_ADDR local_addr; + unsigned int connected; + unsigned int _errno; + unsigned int mtu; + OSSL_TIME next_timeout; + OSSL_TIME socket_timeout; + unsigned int peekmode; + char local_addr_enabled; +} bio_dgram_data; + +#ifndef OPENSSL_NO_SCTP typedef struct bio_dgram_sctp_save_message_st { BIO *bio; char *data; diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c index 7aed585342..11e96a23d7 100644 --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -332,13 +332,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) /* the ptr parameter is actually a FILE ** in this case. */ if (ptr != NULL) { fpp = (FILE **)ptr; - if (BIO_FLAGS_UPLINK_INTERNAL == 0 - || b->flags & BIO_FLAGS_UPLINK_INTERNAL) { - *fpp = (FILE *)b->ptr; - } else { /* avoid returning internal FILE * to the app */ - *fpp = NULL; - ret = 0; - } + *fpp = (FILE *)b->ptr; } break; case BIO_CTRL_GET_CLOSE: diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c index 2928ae5c41..74a5b6c5c5 100644 --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -22,7 +22,8 @@ #include "bio_local.h" #include "internal/cryptlib.h" -#if defined(OPENSSL_SYS_WIN32) +#if defined(OPENSSL_SYS_WINCE) +#elif defined(OPENSSL_SYS_WIN32) #elif defined(__wasi__) #define NO_SYSLOG #elif defined(OPENSSL_SYS_VMS) diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c index 03299a7b72..c25b06e770 100644 --- a/crypto/bn/asm/x86_64-gcc.c +++ b/crypto/bn/asm/x86_64-gcc.c @@ -8,7 +8,7 @@ */ #include "../bn_local.h" -#if !defined(__GNUC__) +#if !(defined(__GNUC__) && __GNUC__ >= 2) /* clang-format off */ # include "../bn_asm.c" /* kind of dirty hack for Sun Studio */ /* clang-format on */ @@ -261,7 +261,7 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, #else /* Simics 1.4<7 has buggy sbbq:-( */ #define BN_MASK2 0xffffffffffffffffL -BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) { BN_ULONG t1, t2; int c = 0; @@ -408,7 +408,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) #define sqr_add_c2(a, i, j, c0, c1, c2) \ mul_add_c2((a)[i], (a)[j], c0, c1, c2) -void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b) { BN_ULONG c1, c2, c3; @@ -511,7 +511,7 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) r[15] = c1; } -void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b) { BN_ULONG c1, c2, c3; diff --git a/crypto/bn/bn_add.c b/crypto/bn/bn_add.c index 24151d0e13..1784091b01 100644 --- a/crypto/bn/bn_add.c +++ b/crypto/bn/bn_add.c @@ -96,9 +96,7 @@ int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) if (bn_wexpand(r, max + 1) == NULL) return 0; - r->top = max; - if (max == 0) - goto end; + bn_set_top(r, max); ap = a->d; bp = b->d; @@ -116,9 +114,8 @@ int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) carry &= (t2 == 0); } *rp = carry; - r->top += (int)carry; + bn_set_top(r, r->top + (int)carry); -end: r->neg = 0; bn_check_top(r); return 1; @@ -146,9 +143,6 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) if (bn_wexpand(r, max) == NULL) return 0; - if (max == 0) - goto end; - ap = a->d; bp = b->d; rp = r->d; @@ -168,10 +162,8 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) while (max && *--rp == 0) max--; -end: - r->top = max; + bn_set_top(r, max); r->neg = 0; - bn_pollute(r); return 1; } diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c index e667702143..f7998658ac 100644 --- a/crypto/bn/bn_asm.c +++ b/crypto/bn/bn_asm.c @@ -622,7 +622,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, mul_add_c2((a)[i], (a)[j], c0, c1, c2) #endif /* !BN_LLONG */ -void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b) { BN_ULONG c1, c2, c3; @@ -725,7 +725,7 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) r[15] = c1; } -void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b) { BN_ULONG c1, c2, c3; @@ -1006,7 +1006,7 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) bn_sqr_normal(r, a, 8, t); } -void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b) { r[4] = bn_mul_words(&(r[0]), a, 4, b[0]); r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]); @@ -1014,7 +1014,7 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]); } -void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b) { r[8] = bn_mul_words(&(r[0]), a, 8, b[0]); r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]); diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c index 7722ed1e48..681b086b18 100644 --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -185,7 +185,7 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, } mask = (BN_ULONG)0 - ((rtop - ntop) >> (8 * sizeof(ntop) - 1)); /* always true, if (rtop >= ntop) n->top = r->top; */ - n->top = (int)((rtop & ~mask) | (ntop & mask)); + bn_set_top(n, (int)((rtop & ~mask) | (ntop & mask))); n->flags |= (BN_FLG_FIXED_TOP & ~mask); } ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx); diff --git a/crypto/bn/bn_conv.c b/crypto/bn/bn_conv.c index f295e5db9a..ff49ebca81 100644 --- a/crypto/bn/bn_conv.c +++ b/crypto/bn/bn_conv.c @@ -178,7 +178,7 @@ int BN_hex2bn(BIGNUM **bn, const char *a) } j -= BN_BYTES * 2; } - ret->top = h; + bn_set_top(ret, h); bn_correct_top(ret); *bn = ret; diff --git a/crypto/bn/bn_dh.c b/crypto/bn/bn_dh.c index 1630be9191..ee948095dd 100644 --- a/crypto/bn/bn_dh.c +++ b/crypto/bn/bn_dh.c @@ -1374,50 +1374,53 @@ static const BN_ULONG ffdhe8192_q[] = { #define make_dh_bn(x) \ extern const BIGNUM ossl_bignum_##x; \ const BIGNUM ossl_bignum_##x = { \ - (BN_ULONG *)x, \ - OSSL_NELEM(x), \ - OSSL_NELEM(x), \ - 0, BN_FLG_STATIC_DATA \ - }; + .d = (BN_ULONG *)x, \ + .top = OSSL_NELEM(x), \ + .dmax = OSSL_NELEM(x), \ + .flags = BN_FLG_STATIC_DATA, \ + } static const BN_ULONG value_2 = 2; const BIGNUM ossl_bignum_const_2 = { - (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)&value_2, + .top = 1, + .dmax = 1, + .flags = BN_FLG_STATIC_DATA, }; -make_dh_bn(dh1024_160_p) -make_dh_bn(dh1024_160_q) -make_dh_bn(dh1024_160_g) -make_dh_bn(dh2048_224_p) -make_dh_bn(dh2048_224_q) -make_dh_bn(dh2048_224_g) -make_dh_bn(dh2048_256_p) -make_dh_bn(dh2048_256_q) -make_dh_bn(dh2048_256_g) +make_dh_bn(dh1024_160_p); +make_dh_bn(dh1024_160_q); +make_dh_bn(dh1024_160_g); +make_dh_bn(dh2048_224_p); +make_dh_bn(dh2048_224_q); +make_dh_bn(dh2048_224_g); +make_dh_bn(dh2048_256_p); +make_dh_bn(dh2048_256_q); +make_dh_bn(dh2048_256_g); -make_dh_bn(ffdhe2048_p) -make_dh_bn(ffdhe2048_q) -make_dh_bn(ffdhe3072_p) -make_dh_bn(ffdhe3072_q) -make_dh_bn(ffdhe4096_p) -make_dh_bn(ffdhe4096_q) -make_dh_bn(ffdhe6144_p) -make_dh_bn(ffdhe6144_q) -make_dh_bn(ffdhe8192_p) -make_dh_bn(ffdhe8192_q) +make_dh_bn(ffdhe2048_p); +make_dh_bn(ffdhe2048_q); +make_dh_bn(ffdhe3072_p); +make_dh_bn(ffdhe3072_q); +make_dh_bn(ffdhe4096_p); +make_dh_bn(ffdhe4096_q); +make_dh_bn(ffdhe6144_p); +make_dh_bn(ffdhe6144_q); +make_dh_bn(ffdhe8192_p); +make_dh_bn(ffdhe8192_q); #ifndef FIPS_MODULE -make_dh_bn(modp_1536_p) -make_dh_bn(modp_1536_q) +make_dh_bn(modp_1536_p); +make_dh_bn(modp_1536_q); #endif -make_dh_bn(modp_2048_p) -make_dh_bn(modp_2048_q) -make_dh_bn(modp_3072_p) -make_dh_bn(modp_3072_q) -make_dh_bn(modp_4096_p) -make_dh_bn(modp_4096_q) -make_dh_bn(modp_6144_p) -make_dh_bn(modp_6144_q) -make_dh_bn(modp_8192_p) -make_dh_bn(modp_8192_q) +make_dh_bn(modp_2048_p); +make_dh_bn(modp_2048_q); +make_dh_bn(modp_3072_p); +make_dh_bn(modp_3072_q); +make_dh_bn(modp_4096_p); +make_dh_bn(modp_4096_q); +make_dh_bn(modp_6144_p); +make_dh_bn(modp_6144_q); +make_dh_bn(modp_8192_p); +make_dh_bn(modp_8192_q); diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c index a731b2d37d..0cec75bf94 100644 --- a/crypto/bn/bn_div.c +++ b/crypto/bn/bn_div.c @@ -61,7 +61,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_zero(dv); if (bn_wexpand(dv, 1) == NULL) goto end; - dv->top = 1; + bn_set_top(dv, 1); if (!BN_lshift(D, D, nm - nd)) goto end; @@ -160,7 +160,7 @@ static int bn_left_align(BIGNUM *num) #if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \ && !defined(PEDANTIC) && !defined(BN_DIV3W) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 #if defined(__i386) || defined(__i386__) /*- * There were two reasons for implementing this template: @@ -310,7 +310,9 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, if (bn_wexpand(snum, div_n + 1) == NULL) goto err; memset(&(snum->d[num_n]), 0, (div_n - num_n + 1) * sizeof(BN_ULONG)); - snum->top = num_n = div_n + 1; + num_n = div_n + 1; + bn_set_top(snum, num_n); + snum->flags |= BN_FLG_FIXED_TOP; } loop = num_n - div_n; @@ -330,13 +332,15 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, goto err; num_neg = num->neg; res->neg = (num_neg ^ divisor->neg); - res->top = loop; + bn_set_top(res, loop); res->flags |= BN_FLG_FIXED_TOP; resp = &(res->d[loop]); /* space for temp */ if (!bn_wexpand(tmp, (div_n + 1))) goto err; + tmp->top = div_n + 1; + tmp->flags |= BN_FLG_FIXED_TOP; for (i = 0; i < loop; i++, wnumtop--) { BN_ULONG q, l0; @@ -446,7 +450,7 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, } /* snum holds remainder, it's as wide as divisor */ snum->neg = num_neg; - snum->top = div_n; + bn_set_top(snum, div_n); snum->flags |= BN_FLG_FIXED_TOP; if (rm != NULL && bn_rshift_fixed_top(rm, snum, norm_shift) == 0) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index c3bd5e7b5d..65445a40e5 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -402,7 +402,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, r->d[0] = (0 - m->d[0]) & BN_MASK2; for (i = 1; i < j; i++) r->d[i] = (~m->d[i]) & BN_MASK2; - r->top = j; + bn_set_top(r, j); r->flags |= BN_FLG_FIXED_TOP; } else #endif @@ -468,7 +468,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, val[0]->d[0] = 1; /* borrow val[0] */ for (i = 1; i < j; i++) val[0]->d[i] = 0; - val[0]->top = j; + bn_set_top(val[0], j); + val[0]->flags |= BN_FLG_FIXED_TOP; if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx)) goto err; } else @@ -581,7 +582,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, } } - b->top = top; + bn_set_top(b, top); b->flags |= BN_FLG_FIXED_TOP; return 1; } @@ -612,7 +613,7 @@ int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, unsigned char *powerbufFree = NULL; int powerbufLen = 0; unsigned char *powerbuf = NULL; - BIGNUM tmp, am; + BIGNUM tmp = { .data = NULL }, am = { .data = NULL }; #if defined(SPARC_T4_MONT) unsigned int t4 = 0; #endif @@ -681,7 +682,7 @@ int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, goto err; RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, mont->n0[0]); - rr->top = 16; + bn_set_top(rr, 16); rr->neg = 0; bn_correct_top(rr); ret = 1; @@ -690,7 +691,7 @@ int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, if (NULL == bn_wexpand(rr, 8)) goto err; RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d); - rr->top = 8; + bn_set_top(rr, 8); rr->neg = 0; bn_correct_top(rr); ret = 1; @@ -1488,12 +1489,12 @@ int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1 mont2->RR.d, mont2->n0[0], mod_bits); - rr1->top = topn; + bn_set_top(rr1, topn); rr1->neg = 0; bn_correct_top(rr1); bn_check_top(rr1); - rr2->top = topn; + bn_set_top(rr2, topn); rr2->neg = 0; bn_correct_top(rr2); bn_check_top(rr2); diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c index 81a7fda5b3..5ad173337e 100644 --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -267,7 +267,7 @@ int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) r->d[i] = at->d[i]; } - r->top = at->top; + bn_set_top(r, at->top); bn_correct_top(r); return 1; @@ -305,7 +305,7 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]) for (j = 0; j < a->top; j++) { r->d[j] = a->d[j]; } - r->top = a->top; + bn_set_top(r, a->top); } z = r->d; @@ -419,7 +419,7 @@ int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, zlen = a->top + b->top + 4; if (!bn_wexpand(s, zlen)) goto err; - s->top = zlen; + bn_set_top(s, zlen); for (i = 0; i < zlen; i++) s->d[i] = 0; @@ -498,7 +498,7 @@ int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], s->d[2 * i] = SQR0(a->d[i]); } - s->top = 2 * a->top; + bn_set_top(s, 2 * a->top); bn_correct_top(s); if (!BN_GF2m_mod_arr(r, s, p)) goto err; @@ -618,20 +618,20 @@ static int BN_GF2m_mod_inv_vartime(BIGNUM *r, const BIGNUM *a, udp = u->d; for (i = u->top; i < top; i++) udp[i] = 0; - u->top = top; + bn_set_top(u, top); if (!bn_wexpand(b, top)) goto err; bdp = b->d; bdp[0] = 1; for (i = 1; i < top; i++) bdp[i] = 0; - b->top = top; + bn_set_top(b, top); if (!bn_wexpand(c, top)) goto err; cdp = c->d; for (i = 0; i < top; i++) cdp[i] = 0; - c->top = top; + bn_set_top(c, top); vdp = v->d; /* It pays off to "cache" *->d pointers, * because it allows optimizer to be more * aggressive. But we don't have to "cache" diff --git a/crypto/bn/bn_intern.c b/crypto/bn/bn_intern.c index f963d42b86..89e0b5a60a 100644 --- a/crypto/bn/bn_intern.c +++ b/crypto/bn/bn_intern.c @@ -174,7 +174,9 @@ void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size) * |const| qualifier omission is compensated by BN_FLG_STATIC_DATA * flag, which effectively means "read-only data". */ + a->data = NULL; a->d = (BN_ULONG *)words; + /* No need to call bn_set_top() in this case */ a->dmax = a->top = size; a->neg = 0; a->flags |= BN_FLG_STATIC_DATA; @@ -188,8 +190,10 @@ int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words) return 0; } + /* TODO(FIXNUM): In the future, we'll use an OSSL_FN function on a->data */ memcpy(a->d, words, sizeof(BN_ULONG) * num_words); - a->top = num_words; + + bn_set_top(a, num_words); bn_correct_top(a); return 1; } diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index a63e2b9154..e3ed1b29ea 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,11 +9,14 @@ #include #include +#include +#include +#include #include "internal/cryptlib.h" #include "internal/endian.h" -#include "bn_local.h" -#include #include "internal/constant_time.h" +#include "crypto/fn.h" +#include "bn_local.h" /* This stuff appears to be completely unused, so is deprecated */ #ifndef OPENSSL_NO_DEPRECATED_0_9_8 @@ -83,12 +86,24 @@ const BIGNUM *BN_value_one(void) { static const BN_ULONG data_one = 1L; static const BIGNUM const_one = { - (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)&data_one, + .top = 1, + .dmax = 1, + .flags = BN_FLG_STATIC_DATA, }; return &const_one; } +/* + * Old Visual Studio ARM compiler miscompiles BN_num_bits_word() + * https://mta.openssl.org/pipermail/openssl-users/2018-August/008465.html + */ +#if defined(_MSC_VER) && defined(_ARM_) && defined(_WIN32_WCE) \ + && _MSC_VER >= 1400 && _MSC_VER < 1501 +#define MS_BROKEN_BN_num_bits_word +#pragma optimize("", off) +#endif int BN_num_bits_word(BN_ULONG l) { BN_ULONG x, mask; @@ -133,6 +148,9 @@ int BN_num_bits_word(BN_ULONG l) return bits; } +#ifdef MS_BROKEN_BN_num_bits_word +#pragma optimize("", on) +#endif /* * This function still leaks `a->dmax`: it's caller's responsibility to @@ -187,7 +205,7 @@ int BN_num_bits(const BIGNUM *a) return ((i * BN_BITS2) + BN_num_bits_word(a->d[i])); } -static void bn_free_d(BIGNUM *a, int clear) +static void bn_free_d(BIGNUM *a, bool clear) { if (BN_get_flags(a, BN_FLG_SECURE)) OPENSSL_secure_clear_free(a->d, a->dmax * sizeof(a->d[0])); @@ -201,8 +219,12 @@ void BN_clear_free(BIGNUM *a) { if (a == NULL) return; - if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA)) - bn_free_d(a, 1); + if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) { + if (a->data != NULL) + OSSL_FN_clear_free(a->data); + else + bn_free_d(a, true); + } if (BN_get_flags(a, BN_FLG_MALLOCED)) { OPENSSL_cleanse(a, sizeof(*a)); OPENSSL_free(a); @@ -213,8 +235,12 @@ void BN_free(BIGNUM *a) { if (a == NULL) return; - if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) - bn_free_d(a, 0); + if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) { + if (a->data != NULL) + OSSL_FN_free(a->data); + else + bn_free_d(a, false); + } if (a->flags & BN_FLG_MALLOCED) OPENSSL_free(a); } @@ -249,11 +275,11 @@ BIGNUM *BN_secure_new(void) /* This is used by bn_expand2() */ /* The caller MUST check that words > b->dmax before calling this */ -static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) +static OSSL_FN *bn_expand_internal(const BIGNUM *b, int words) { - BN_ULONG *a = NULL; + OSSL_FN *a = NULL; - if (ossl_unlikely(words > (INT_MAX / (4 * BN_BITS2)))) { + if (ossl_unlikely(words > BN_MAX_WORDS)) { ERR_raise(ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG); return NULL; } @@ -262,15 +288,19 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) return NULL; } if (BN_get_flags(b, BN_FLG_SECURE)) - a = OPENSSL_secure_calloc(words, sizeof(*a)); + a = OSSL_FN_secure_new_limbs(words); else - a = OPENSSL_calloc(words, sizeof(*a)); + a = OSSL_FN_new_limbs(words); if (ossl_unlikely(a == NULL)) return NULL; assert(b->top <= words); - if (b->top > 0) - memcpy(a, b->d, sizeof(*a) * b->top); + if (b->top > 0) { + if (b->data != NULL) + ossl_fn_copy_internal(a, b->data, -1); + else if (b->d != NULL) + ossl_fn_copy_internal_limbs(a, b->d, b->top); + } return a; } @@ -286,19 +316,58 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) BIGNUM *bn_expand2(BIGNUM *b, int words) { if (ossl_likely(words > b->dmax)) { - BN_ULONG *a = bn_expand_internal(b, words); + OSSL_FN *a = bn_expand_internal(b, words); if (ossl_unlikely(!a)) return NULL; - if (b->d != NULL) - bn_free_d(b, 1); - b->d = a; - b->dmax = words; + if (b->data != NULL) + OSSL_FN_clear_free(b->data); + else if (b->d != NULL) + bn_free_d(b, true); + b->data = a; + /* TODO(FIXNUM) The following is TO BE REMOVED */ + b->d = b->data->d; + b->dmax = b->data->dsize; } return b; } +OSSL_FN *bn_acquire_ossl_fn(BIGNUM *b, int limbs) +{ + if (ossl_unlikely(b == NULL)) + return NULL; + + if (bn_wexpand(b, limbs) == NULL) + return NULL; + /* TODO(FIXNUM): should we add a flag bit for this in b->flags ? */ + return b->data; +} + +void bn_release(BIGNUM *b, int limbs) +{ + if (ossl_unlikely(b == NULL || b->data == NULL)) + return; + + int fixed_top = (b->flags & BN_FLG_FIXED_TOP) != 0; + + bn_set_top(b, limbs); + + /* Don't correct top if BN_FLG_FIXED_TOP was set */ + if (fixed_top) + return; + + bn_correct_top(b); +} + +OSSL_FN *bn_get_ossl_fn(const BIGNUM *bn) +{ + if (ossl_unlikely(bn == NULL)) + return NULL; + + return bn->data; +} + BIGNUM *BN_dup(const BIGNUM *a) { BIGNUM *t; @@ -331,11 +400,14 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) if (ossl_unlikely(bn_wexpand(a, bn_words) == NULL)) return NULL; - if (ossl_likely(b->top > 0)) - memcpy(a->d, b->d, sizeof(b->d[0]) * bn_words); - + if (ossl_likely(bn_words > 0)) { + if (b->data != NULL) + ossl_fn_copy_internal(a->data, b->data, bn_words); + else if (b->d != NULL) + ossl_fn_copy_internal_limbs(a->data, b->d, bn_words); + } a->neg = b->neg; - a->top = b->top; + bn_set_top(a, b->top); a->flags |= b->flags & BN_FLG_FIXED_TOP; bn_check_top(a); return a; @@ -347,6 +419,7 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) void BN_swap(BIGNUM *a, BIGNUM *b) { int flags_old_a, flags_old_b; + OSSL_FN *tmp_data; BN_ULONG *tmp_d; int tmp_top, tmp_dmax, tmp_neg; @@ -356,16 +429,19 @@ void BN_swap(BIGNUM *a, BIGNUM *b) flags_old_a = a->flags; flags_old_b = b->flags; + tmp_data = a->data; tmp_d = a->d; tmp_top = a->top; tmp_dmax = a->dmax; tmp_neg = a->neg; + a->data = b->data; a->d = b->d; a->top = b->top; a->dmax = b->dmax; a->neg = b->neg; + b->data = tmp_data; b->d = tmp_d; b->top = tmp_top; b->dmax = tmp_dmax; @@ -382,10 +458,12 @@ void BN_clear(BIGNUM *a) if (a == NULL) return; bn_check_top(a); - if (a->d != NULL) + if (a->data != NULL) + OSSL_FN_clear(a->data); + else if (a->d != NULL) OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax); a->neg = 0; - a->top = 0; + bn_set_top(a, 0); a->flags &= ~BN_FLG_FIXED_TOP; } @@ -402,11 +480,11 @@ BN_ULONG BN_get_word(const BIGNUM *a) int BN_set_word(BIGNUM *a, BN_ULONG w) { bn_check_top(a); - if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL) + if (bn_wexpand(a, 1) == NULL) return 0; a->neg = 0; a->d[0] = w; - a->top = (w ? 1 : 0); + bn_set_top(a, (w ? 1 : 0)); a->flags &= ~BN_FLG_FIXED_TOP; bn_check_top(a); return 1; @@ -488,7 +566,7 @@ static BIGNUM *bin2bn(const unsigned char *s, int len, BIGNUM *ret, } /* If it was all zeros, we're done */ if (len == 0) { - ret->top = 0; + bn_set_top(ret, 0); return ret; } n = ((len - 1) / BN_BYTES) + 1; /* Number of resulting bignum chunks */ @@ -496,7 +574,7 @@ static BIGNUM *bin2bn(const unsigned char *s, int len, BIGNUM *ret, BN_free(bn); return NULL; } - ret->top = n; + bn_set_top(ret, n); ret->neg = neg; for (i = 0; n-- > 0; i++) { BN_ULONG l = 0; /* Accumulator */ @@ -696,37 +774,19 @@ int BN_ucmp(const BIGNUM *a, const BIGNUM *b) int i; BN_ULONG t1, t2, *ap, *bp; - /* - * As it is a public API function, we should handle NULL parameters in - * some way. The function can’t return an error, so let’s define that NULL - * is less than any BIGNUM. - */ - if (!ossl_assert(a != NULL && b != NULL)) - return (b == NULL) - (a == NULL); - ap = a->d; bp = b->d; if (BN_get_flags(a, BN_FLG_CONSTTIME) - || BN_get_flags(b, BN_FLG_CONSTTIME)) { + && a->top == b->top) { int res = 0; - int min_top = a->top < b->top ? a->top : b->top; - for (i = 0; i < min_top; i++) { + for (i = 0; i < b->top; i++) { res = constant_time_select_int((int)constant_time_lt_bn(ap[i], bp[i]), -1, res); res = constant_time_select_int((int)constant_time_lt_bn(bp[i], ap[i]), 1, res); } - - for (i = min_top; i < a->top; ++i) - res = constant_time_select_int((int)constant_time_is_zero_bn(ap[i]), - res, 1); - - for (i = min_top; i < b->top; ++i) - res = constant_time_select_int((int)constant_time_is_zero_bn(bp[i]), - res, -1); - return res; } @@ -795,7 +855,7 @@ int BN_cmp(const BIGNUM *a, const BIGNUM *b) int BN_set_bit(BIGNUM *a, int n) { - int i, j, k; + int i, j; if (n < 0) return 0; @@ -805,9 +865,12 @@ int BN_set_bit(BIGNUM *a, int n) if (a->top <= i) { if (bn_wexpand(a, i + 1) == NULL) return 0; - for (k = a->top; k < i + 1; k++) - a->d[k] = 0; - a->top = i + 1; + /* + * If 'a' is actually expanded, we know that the expanded + * part of the 'd' array is zeroed during allocation, so + * no need to zero it again here. + */ + bn_set_top(a, i + 1); a->flags &= ~BN_FLG_FIXED_TOP; } @@ -860,9 +923,9 @@ int ossl_bn_mask_bits_fixed_top(BIGNUM *a, int n) if (w >= a->top) return 0; if (b == 0) - a->top = w; + bn_set_top(a, w); else { - a->top = w + 1; + bn_set_top(a, w + 1); a->d[w] &= ~(BN_MASK2 << b); } a->flags |= BN_FLG_FIXED_TOP; @@ -1029,7 +1092,7 @@ int BN_security_bits(int L, int N) void BN_zero_ex(BIGNUM *a) { a->neg = 0; - a->top = 0; + bn_set_top(a, 0); a->flags &= ~BN_FLG_FIXED_TOP; } @@ -1040,7 +1103,12 @@ int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w) int BN_is_zero(const BIGNUM *a) { - return a->top == 0; + if ((a->flags & BN_FLG_FIXED_TOP) == 0) + return a->top == 0; + for (size_t i = a->top; i-- > 0;) + if (a->d[i] != (BN_ULONG)0) + return 0; + return 1; } int BN_is_one(const BIGNUM *a) @@ -1087,6 +1155,7 @@ int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags) { + dest->data = b->data; dest->d = b->d; dest->top = b->top; dest->dmax = b->dmax; @@ -1170,6 +1239,11 @@ void bn_correct_top_consttime(BIGNUM *a) } mask = constant_time_eq_int(atop, 0); + /* + * We just went through the whole 'd' array to identify where + * any leading set of zeros are located, so there's no need to + * call bn_set_top() here. + */ a->top = atop; a->neg = constant_time_select_int(mask, 0, a->neg); a->flags &= ~BN_FLG_FIXED_TOP; @@ -1186,10 +1260,14 @@ void bn_correct_top(BIGNUM *a) if (*ftl != 0) break; } + /* + * We just verified that the BN_ULONGs between a->top and + * tmp_top are all zero, so there's no need to call + * bn_set_top() here. + */ a->top = tmp_top; } if (a->top == 0) a->neg = 0; a->flags &= ~BN_FLG_FIXED_TOP; - bn_pollute(a); } diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h index 4602cdcaba..d6813efed7 100644 --- a/crypto/bn/bn_local.h +++ b/crypto/bn/bn_local.h @@ -10,27 +10,24 @@ #ifndef OSSL_CRYPTO_BN_LOCAL_H #define OSSL_CRYPTO_BN_LOCAL_H +#include +#include + #include #include "internal/cryptlib.h" #include "internal/numbers.h" #include "crypto/bn.h" +#include "../fn/fn_local.h" + /* - * These preprocessor symbols control various aspects of the bignum headers - * and library code. They're not defined by any "normal" configuration, as - * they are intended for development and testing purposes. NB: defining - * them can be useful for debugging application code as well as openssl - * itself. BN_DEBUG - turn on various debugging alterations to the bignum - * code BN_RAND_DEBUG - uses random poisoning of unused words to trip up - * mismanagement of bignum internals. Enable BN_RAND_DEBUG is known to - * break some of the OpenSSL tests. + * BN_RAND_DEBUG was historically used to poison unused words in bignum data, + * for integrity debugging purposes. This isn't done any more, but enabling + * BN_RAND_DEBUG also defined BN_DEBUG, which we preserve for the moment. */ #if defined(BN_RAND_DEBUG) && !defined(BN_DEBUG) #define BN_DEBUG #endif -#if defined(BN_RAND_DEBUG) -#include -#endif /* * This should limit the stack usage due to alloca to about 4K. @@ -120,32 +117,65 @@ typedef unsigned long long BN_ULLONG; #define BN_DEC_FMT2 "%09u" #endif +#define BN_MAX_WORDS (INT_MAX / (4 * BN_BITS2)) + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); +BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int num); +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int num); + +struct bignum_st { + /* The number itself is a FIXNUM */ + OSSL_FN *data; + + /* Some of these flags are replicated in OSSL_FN, some are not */ + int flags; + + BN_ULONG *d; /* Pointer to |data->d| */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Copy of |data->dsize| */ + int neg; /* One if the number is negative */ +}; + /*- * Bignum consistency macros + * * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from * bignum data after direct manipulations on the data. There is also an * "internal" macro, bn_check_top(), for verifying that there are no leading - * zeroes. Unfortunately, some auditing is required due to the fact that - * bn_fix_top() has become an overabused duct-tape because bignum data is - * occasionally passed around in an inconsistent state. So the following - * changes have been made to sort this out; + * zeroes, and in case the BIGNUM has an integrated OSSL_FN, check the + * consistency of the integration, including that the unused part of the + * data is all zeros. + * + * Unfortunately, some auditing is required due to the fact that bn_fix_top() + * has become an overabused duck-tape because bignum data is occasionally + * passed around in an inconsistent state. So the following changes have been + * made to sort this out; + * * - bn_fix_top()s implementation has been moved to bn_correct_top() - * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and - * bn_check_top() is as before. - * - if BN_DEBUG *is* defined; - * - bn_check_top() tries to pollute unused words even if the bignum 'top' is - * consistent. (ed: only if BN_RAND_DEBUG is defined) + * - if BN_DEBUG isn't defined: + * - bn_check_top() does nothing. + * - bn_fix_top() maps to bn_correct_top() + * - if BN_DEBUG is defined: + * - bn_check_top() performs its consistency checks * - bn_fix_top() maps to bn_check_top() rather than "fixing" anything. + * * The idea is to have debug builds flag up inconsistent bignums when they - * occur. If that occurs in a bn_fix_top(), we examine the code in question; if - * the use of bn_fix_top() was appropriate (ie. it follows directly after code - * that manipulates the bignum) it is converted to bn_correct_top(), and if it - * was not appropriate, we convert it permanently to bn_check_top() and track - * down the cause of the bug. Eventually, no internal code should be using the - * bn_fix_top() macro. External applications and libraries should try this with - * their own code too, both in terms of building against the openssl headers - * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it - * defined. This not only improves external code, it provides more test + * occur. If that occurs in a bn_fix_top(), we examine the code in question; + * if the use of bn_fix_top() was appropriate (ie. it follows directly after + * code that manipulates the bignum) it is converted to bn_correct_top(), + * and if it was not appropriate, we convert it permanently to bn_check_top() + * and track down the cause of the bug. Eventually, no internal code should be + * using the bn_fix_top() macro. External applications and libraries should try + * this with their own code too, both in terms of building against the openssl + * headers with BN_DEBUG defined *and* linking with a version of OpenSSL built + * with it defined. This not only improves external code, it provides more test * coverage for openssl's own code. */ @@ -164,54 +194,49 @@ typedef unsigned long long BN_ULLONG; * all operations manipulating the bit in question in non-BN_DEBUG build. */ #define BN_FLG_FIXED_TOP 0x10000 -#ifdef BN_RAND_DEBUG -#define bn_pollute(a) \ - do { \ - const BIGNUM *_bnum1 = (a); \ - if (_bnum1->top < _bnum1->dmax) { \ - unsigned char _tmp_char; \ - /* We cast away const without the compiler knowing, any \ - * *genuinely* constant variables that aren't mutable \ - * wouldn't be constructed with top!=dmax. */ \ - BN_ULONG *_not_const; \ - memcpy(&_not_const, &_bnum1->d, sizeof(_not_const)); \ - (void)RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */ \ - memset(_not_const + _bnum1->top, _tmp_char, \ - sizeof(*_not_const) * (_bnum1->dmax - _bnum1->top)); \ - } \ - } while (0) -#else -#define bn_pollute(a) -#endif -#define bn_check_top(a) \ - do { \ - const BIGNUM *_bnum2 = (a); \ - if (_bnum2 != NULL) { \ - int _top = _bnum2->top; \ - if (_top == 0) { \ - assert(!_bnum2->neg); \ - } else if ((_bnum2->flags & BN_FLG_FIXED_TOP) == 0) { \ - assert(_bnum2->d[_top - 1] != 0); \ - } \ - bn_pollute(_bnum2); \ - } \ - } while (0) + +static ossl_inline bool bn_check_zero(BN_ULONG *words, int num_words) +{ + for (int i = 0; i < num_words; i++) + if (words[i] != 0) + return false; + return true; +} + +static ossl_inline void bn_check_top(const BIGNUM *bn) +{ + if (bn != NULL) { + /* BIGNUM <-> OSSL_FN compat checks */ + if (bn->data != NULL) { + /* TODO(FIXNUM): Assertion for the future */ + /* assert(_bnum2->d == NULL); */ + assert(bn->d == bn->data->d); + assert(bn->dmax == bn->data->dsize); + assert(bn_check_zero(&bn->d[bn->top], bn->dmax - bn->top)); + } + /* BIGNUM specific checks */ + if (bn->top == 0) { + assert(!bn->neg); + } else if ((bn->flags & BN_FLG_FIXED_TOP) == 0) { + assert(bn->d[bn->top - 1] != 0); + } + assert(bn->dmax >= 0 && bn->dmax <= BN_MAX_WORDS); + } +} #define bn_fix_top(a) bn_check_top(a) +static ossl_inline void bn_wcheck_size(const BIGNUM *bn, int words) +{ + assert(words <= bn->dmax); + assert(words >= bn->top); +} + #define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits + BN_BITS2 - 1)) / BN_BITS2) -#define bn_wcheck_size(bn, words) \ - do { \ - const BIGNUM *_bnum2 = (bn); \ - assert((words) <= (_bnum2)->dmax && (words) >= (_bnum2)->top); \ - /* avoid unused variable warning with NDEBUG */ \ - (void)(_bnum2); \ - } while (0) #else /* !BN_DEBUG */ #define BN_FLG_FIXED_TOP 0 -#define bn_pollute(a) #define bn_check_top(a) #define bn_fix_top(a) bn_correct_top(a) #define bn_check_size(bn, bits) @@ -219,29 +244,6 @@ typedef unsigned long long BN_ULLONG; #endif -BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, - BN_ULONG w); -BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); -void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); -BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); -BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - int num); -BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - int num); - -struct bignum_st { - BN_ULONG *d; /* - * Pointer to an array of 'BN_BITS2' bit - * chunks. These chunks are organised in - * a least significant chunk first order. - */ - int top; /* Index of last used d +1. */ - /* The next are internal book keeping for bn_expand. */ - int dmax; /* Size of the d array. */ - int neg; /* one if the number is negative */ - int flags; -}; - /* Used for montgomery multiplication */ struct bn_mont_ctx_st { BIGNUM RR; /* used to convert to montgomery form, @@ -380,7 +382,7 @@ struct bn_gencb_st { #if defined(__DECC) #include #define BN_UMULT_HIGH(a, b) (BN_ULONG)asm("umulh %a0,%a1,%v0", (a), (b)) -#elif defined(__GNUC__) +#elif defined(__GNUC__) && __GNUC__ >= 2 #define BN_UMULT_HIGH(a, b) ({ \ register BN_ULONG ret; \ asm ("umulh %1,%2,%0" \ @@ -389,7 +391,7 @@ struct bn_gencb_st { ret; }) #endif /* compiler */ #elif defined(_ARCH_PPC64) && defined(SIXTY_FOUR_BIT_LONG) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 #define BN_UMULT_HIGH(a, b) ({ \ register BN_ULONG ret; \ asm ("mulhdu %0,%1,%2" \ @@ -398,7 +400,7 @@ struct bn_gencb_st { ret; }) #endif /* compiler */ #elif (defined(__x86_64) || defined(__x86_64__)) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT)) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 #define BN_UMULT_HIGH(a, b) ({ \ register BN_ULONG ret,discard; \ asm ("mulq %3" \ @@ -422,7 +424,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, #define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high))) #endif #elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 #define BN_UMULT_HIGH(a, b) ({ \ register BN_ULONG ret; \ asm ("dmultu %1,%2" \ @@ -435,7 +437,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, : "r"(a), "r"(b)); #endif #elif defined(__aarch64__) && defined(SIXTY_FOUR_BIT_LONG) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 #define BN_UMULT_HIGH(a, b) ({ \ register BN_ULONG ret; \ asm ("umulh %0,%1,%2" \ @@ -643,21 +645,21 @@ void BN_RECP_CTX_init(BN_RECP_CTX *recp); void BN_MONT_CTX_init(BN_MONT_CTX *ctx); void bn_init(BIGNUM *a); -void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb); -void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); -void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b, int nb); +void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b); +void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b); void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp); void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a); void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a); int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n); int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); -void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, +void bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2, int dna, int dnb, BN_ULONG *t); -void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, +void bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n, int tna, int tnb, BN_ULONG *t); void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t); -void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n); -void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, +void bn_mul_low_normal(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n); +void bn_mul_low_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2, BN_ULONG *t); BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); @@ -667,6 +669,7 @@ void bn_correct_top_consttime(BIGNUM *a); BIGNUM *int_bn_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, int *noinv); +void bn_mul_truncated(BN_ULONG *r, int nr, const BN_ULONG *a, int na, const BN_ULONG *b, int nb); static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits) { @@ -682,4 +685,29 @@ static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits) int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx, int do_trial_division, BN_GENCB *cb); +/** + * Set top on a given BIGNUM. If it has an associated OSSL_FN (the 'data' + * field is non-NULL), and the new 'top' is less than the existing 'top', + * zeroise the space between them. + * + * @param[in] b The BIGNUM instance to zeroise + * @param[in] newtop The new 'top' + * @returns the new 'top' + * @pre b must not be NULL and newtop must be zero or positive + */ +static ossl_inline int bn_set_top(BIGNUM *b, int newtop) +{ + assert(b != NULL && newtop >= 0); + + if (b->data != NULL && newtop < b->top) { + BN_ULONG *start = &(b->d[newtop]); + size_t bytes = sizeof(BN_ULONG) * (b->top - newtop); + + memset(start, 0, bytes); + } + + b->top = newtop; + return b->top; +} + #endif diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c index 703072bbf2..6db2636d76 100644 --- a/crypto/bn/bn_mod.c +++ b/crypto/bn/bn_mod.c @@ -90,7 +90,7 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, rp[i] = (carry & tp[i]) | (~carry & rp[i]); ((volatile BN_ULONG *)tp)[i] = 0; } - r->top = (int)mtop; + bn_set_top(r, (int)mtop); r->flags |= BN_FLG_FIXED_TOP; r->neg = 0; @@ -176,7 +176,7 @@ int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, carry += (rp[i] < ta); } - r->top = (int)mtop; + bn_set_top(r, (int)mtop); r->flags |= BN_FLG_FIXED_TOP; r->neg = 0; diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 0bdfce3c48..aeaf399231 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -46,7 +46,7 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, return 0; if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { r->neg = a->neg ^ b->neg; - r->top = num; + bn_set_top(r, num); r->flags |= BN_FLG_FIXED_TOP; return 1; } @@ -94,7 +94,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) n = &(mont->N); nl = n->top; if (nl == 0) { - ret->top = 0; + bn_set_top(ret, 0); return 1; } @@ -112,7 +112,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) rp[i] &= v; } - r->top = max; + bn_set_top(r, max); r->flags |= BN_FLG_FIXED_TOP; n0 = mont->n0[0]; @@ -131,7 +131,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) if (bn_wexpand(ret, nl) == NULL) return 0; - ret->top = nl; + bn_set_top(ret, nl); ret->flags |= BN_FLG_FIXED_TOP; ret->neg = r->neg; @@ -325,7 +325,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) Ri->neg = 0; Ri->d[0] = BN_MASK2; Ri->d[1] = BN_MASK2; - Ri->top = 2; + bn_set_top(Ri, 2); } if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) goto err; diff --git a/crypto/bn/bn_mpi.c b/crypto/bn/bn_mpi.c index d2a86a3ead..17ffc6a476 100644 --- a/crypto/bn/bn_mpi.c +++ b/crypto/bn/bn_mpi.c @@ -65,7 +65,7 @@ BIGNUM *BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain) if (len == 0) { a->neg = 0; - a->top = 0; + bn_set_top(a, 0); return a; } d += 4; diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c index aefc335923..d887c23225 100644 --- a/crypto/bn/bn_mul.c +++ b/crypto/bn/bn_mul.c @@ -11,479 +11,6 @@ #include "internal/cryptlib.h" #include "bn_local.h" -#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS) -/* - * Here follows specialised variants of bn_add_words() and bn_sub_words(). - * They have the property performing operations on arrays of different sizes. - * The sizes of those arrays is expressed through cl, which is the common - * length ( basically, min(len(a),len(b)) ), and dl, which is the delta - * between the two lengths, calculated as len(a)-len(b). All lengths are the - * number of BN_ULONGs... For the operations that require a result array as - * parameter, it must have the length cl+abs(dl). These functions should - * probably end up in bn_asm.c as soon as there are assembler counterparts - * for the systems that use assembler files. - */ - -BN_ULONG bn_sub_part_words(BN_ULONG *r, - const BN_ULONG *a, const BN_ULONG *b, - int cl, int dl) -{ - BN_ULONG c, t; - - assert(cl >= 0); - c = bn_sub_words(r, a, b, cl); - - if (dl == 0) - return c; - - r += cl; - a += cl; - b += cl; - - if (dl < 0) { - for (;;) { - t = b[0]; - r[0] = (0 - t - c) & BN_MASK2; - if (t != 0) - c = 1; - if (++dl >= 0) - break; - - t = b[1]; - r[1] = (0 - t - c) & BN_MASK2; - if (t != 0) - c = 1; - if (++dl >= 0) - break; - - t = b[2]; - r[2] = (0 - t - c) & BN_MASK2; - if (t != 0) - c = 1; - if (++dl >= 0) - break; - - t = b[3]; - r[3] = (0 - t - c) & BN_MASK2; - if (t != 0) - c = 1; - if (++dl >= 0) - break; - - b += 4; - r += 4; - } - } else { - int save_dl = dl; - while (c) { - t = a[0]; - r[0] = (t - c) & BN_MASK2; - if (t != 0) - c = 0; - if (--dl <= 0) - break; - - t = a[1]; - r[1] = (t - c) & BN_MASK2; - if (t != 0) - c = 0; - if (--dl <= 0) - break; - - t = a[2]; - r[2] = (t - c) & BN_MASK2; - if (t != 0) - c = 0; - if (--dl <= 0) - break; - - t = a[3]; - r[3] = (t - c) & BN_MASK2; - if (t != 0) - c = 0; - if (--dl <= 0) - break; - - save_dl = dl; - a += 4; - r += 4; - } - if (dl > 0) { - if (save_dl > dl) { - switch (save_dl - dl) { - case 1: - r[1] = a[1]; - if (--dl <= 0) - break; - /* fall through */ - case 2: - r[2] = a[2]; - if (--dl <= 0) - break; - /* fall through */ - case 3: - r[3] = a[3]; - if (--dl <= 0) - break; - } - a += 4; - r += 4; - } - } - if (dl > 0) { - for (;;) { - r[0] = a[0]; - if (--dl <= 0) - break; - r[1] = a[1]; - if (--dl <= 0) - break; - r[2] = a[2]; - if (--dl <= 0) - break; - r[3] = a[3]; - if (--dl <= 0) - break; - - a += 4; - r += 4; - } - } - } - return c; -} -#endif - -#ifndef OPENSSL_SMALL_FOOTPRINT -/* - * Karatsuba recursive multiplication algorithm (cf. Knuth, The Art of - * Computer Programming, Vol. 2) - */ - -/*- - * r is 2*n2 words in size, - * a and b are both n2 words in size. - * n2 must be a power of 2. - * We multiply and return the result. - * t must be 2*n2 words in size - * We calculate - * a[0]*b[0] - * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) - * a[1]*b[1] - */ -/* dnX may not be positive, but n2/2+dnX has to be */ -void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, - int dna, int dnb, BN_ULONG *t) -{ - int n = n2 / 2, c1, c2; - int tna = n + dna, tnb = n + dnb; - unsigned int neg, zero; - BN_ULONG ln, lo, *p; - - /* - * Only call bn_mul_comba 8 if n2 == 8 and the two arrays are complete - * [steve] - */ - if (n2 == 8 && dna == 0 && dnb == 0) { - bn_mul_comba8(r, a, b); - return; - } - - /* Else do normal multiply */ - if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { - bn_mul_normal(r, a, n2 + dna, b, n2 + dnb); - if ((dna + dnb) < 0) - memset(&r[2 * n2 + dna + dnb], 0, - sizeof(BN_ULONG) * -(dna + dnb)); - return; - } - /* r=(a[0]-a[1])*(b[1]-b[0]) */ - c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); - c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); - zero = neg = 0; - switch (c1 * 3 + c2) { - case -4: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ - break; - case -3: - zero = 1; - break; - case -2: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ - neg = 1; - break; - case -1: - case 0: - case 1: - zero = 1; - break; - case 2: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ - neg = 1; - break; - case 3: - zero = 1; - break; - case 4: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); - break; - } - - if (n == 4 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba4 could take - * extra args to do this well */ - if (!zero) - bn_mul_comba4(&(t[n2]), t, &(t[n])); - else - memset(&t[n2], 0, sizeof(*t) * 8); - - bn_mul_comba4(r, a, b); - bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); - } else if (n == 8 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba8 could - * take extra args to do - * this well */ - if (!zero) - bn_mul_comba8(&(t[n2]), t, &(t[n])); - else - memset(&t[n2], 0, sizeof(*t) * 16); - - bn_mul_comba8(r, a, b); - bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); - } else { - p = &(t[n2 * 2]); - if (!zero) - bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); - else - memset(&t[n2], 0, sizeof(*t) * n2); - bn_mul_recursive(r, a, b, n, 0, 0, p); - bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p); - } - - /*- - * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign - * r[10] holds (a[0]*b[0]) - * r[32] holds (b[1]*b[1]) - */ - - c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); - - if (neg) { /* if t[32] is negative */ - c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); - } else { - /* Might have a carry */ - c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); - } - - /*- - * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) - * r[10] holds (a[0]*b[0]) - * r[32] holds (b[1]*b[1]) - * c1 holds the carry bits - */ - c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); - if (c1) { - p = &(r[n + n2]); - lo = *p; - ln = (lo + c1) & BN_MASK2; - *p = ln; - - /* - * The overflow will stop before we over write words we should not - * overwrite - */ - if (ln < (BN_ULONG)c1) { - do { - p++; - lo = *p; - ln = (lo + 1) & BN_MASK2; - *p = ln; - } while (ln == 0); - } - } -} - -/* - * n+tn is the word length t needs to be n*4 is size, as does r - */ -/* tnX may not be negative but less than n */ -void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, - int tna, int tnb, BN_ULONG *t) -{ - int i, j, n2 = n * 2; - int c1, c2, neg; - BN_ULONG ln, lo, *p; - - if (n < 8) { - bn_mul_normal(r, a, n + tna, b, n + tnb); - return; - } - - /* r=(a[0]-a[1])*(b[1]-b[0]) */ - c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); - c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); - neg = 0; - switch (c1 * 3 + c2) { - case -4: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ - break; - case -3: - case -2: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ - neg = 1; - break; - case -1: - case 0: - case 1: - case 2: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ - neg = 1; - break; - case 3: - case 4: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); - break; - } - /* - * The zero case isn't yet implemented here. The speedup would probably - * be negligible. - */ -#if 0 - if (n == 4) { - bn_mul_comba4(&(t[n2]), t, &(t[n])); - bn_mul_comba4(r, a, b); - bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn); - memset(&r[n2 + tn * 2], 0, sizeof(*r) * (n2 - tn * 2)); - } else -#endif - if (n == 8) { - bn_mul_comba8(&(t[n2]), t, &(t[n])); - bn_mul_comba8(r, a, b); - bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); - memset(&r[n2 + tna + tnb], 0, sizeof(*r) * (n2 - tna - tnb)); - } else { - p = &(t[n2 * 2]); - bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); - bn_mul_recursive(r, a, b, n, 0, 0, p); - i = n / 2; - /* - * If there is only a bottom half to the number, just do it - */ - if (tna > tnb) - j = tna - i; - else - j = tnb - i; - if (j == 0) { - bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), - i, tna - i, tnb - i, p); - memset(&r[n2 + i * 2], 0, sizeof(*r) * (n2 - i * 2)); - } else if (j > 0) { /* eg, n == 16, i == 8 and tn == 11 */ - bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), - i, tna - i, tnb - i, p); - memset(&(r[n2 + tna + tnb]), 0, - sizeof(BN_ULONG) * (n2 - tna - tnb)); - } else { /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ - - memset(&r[n2], 0, sizeof(*r) * n2); - if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL - && tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { - bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); - } else { - for (;;) { - i /= 2; - /* - * these simplified conditions work exclusively because - * difference between tna and tnb is 1 or 0 - */ - if (i < tna || i < tnb) { - bn_mul_part_recursive(&(r[n2]), - &(a[n]), &(b[n]), - i, tna - i, tnb - i, p); - break; - } else if (i == tna || i == tnb) { - bn_mul_recursive(&(r[n2]), - &(a[n]), &(b[n]), - i, tna - i, tnb - i, p); - break; - } - } - } - } - } - - /*- - * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign - * r[10] holds (a[0]*b[0]) - * r[32] holds (b[1]*b[1]) - */ - - c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); - - if (neg) { /* if t[32] is negative */ - c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); - } else { - /* Might have a carry */ - c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); - } - - /*- - * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) - * r[10] holds (a[0]*b[0]) - * r[32] holds (b[1]*b[1]) - * c1 holds the carry bits - */ - c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); - if (c1) { - p = &(r[n + n2]); - lo = *p; - ln = (lo + c1) & BN_MASK2; - *p = ln; - - /* - * The overflow will stop before we over write words we should not - * overwrite - */ - if (ln < (BN_ULONG)c1) { - do { - p++; - lo = *p; - ln = (lo + 1) & BN_MASK2; - *p = ln; - } while (ln == 0); - } - } -} - -/*- - * a and b must be the same size, which is n2. - * r needs to be n2 words and t needs to be n2*2 - */ -void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, - BN_ULONG *t) -{ - int n = n2 / 2; - - bn_mul_recursive(r, a, b, n, 0, 0, &(t[0])); - if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) { - bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2])); - bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); - bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2])); - bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); - } else { - bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n); - bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n); - bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); - bn_add_words(&(r[n]), &(r[n]), &(t[n]), n); - } -} -#endif /* OPENSSL_SMALL_FOOTPRINT */ - int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = bn_mul_fixed_top(r, a, b, ctx); @@ -501,8 +28,6 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) BIGNUM *rr; #if !defined(OPENSSL_SMALL_FOOTPRINT) int i; - BIGNUM *t = NULL; - int j = 0, k; #endif bn_check_top(a); @@ -533,7 +58,8 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) if (al == 4) { if (bn_wexpand(rr, 8) == NULL) goto err; - rr->top = 8; + rr->flags |= BN_FLG_FIXED_TOP; + bn_set_top(rr, 8); bn_mul_comba4(rr->d, a->d, b->d); goto end; } @@ -541,7 +67,8 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) if (al == 8) { if (bn_wexpand(rr, 16) == NULL) goto err; - rr->top = 16; + rr->flags |= BN_FLG_FIXED_TOP; + bn_set_top(rr, 16); bn_mul_comba8(rr->d, a->d, b->d); goto end; } @@ -549,6 +76,9 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) { if (i >= -1 && i <= 1) { + BIGNUM *t = NULL; + int j = 0, k; + /* * Find out the power of two lower or equal to the longest of the * two numbers @@ -568,26 +98,33 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) if (al > j || bl > j) { if (bn_wexpand(t, k * 4) == NULL) goto err; + t->top = k * 4; + t->flags |= BN_FLG_FIXED_TOP; if (bn_wexpand(rr, k * 4) == NULL) goto err; + bn_set_top(rr, k * 4); + rr->flags |= BN_FLG_FIXED_TOP; bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } else { /* al <= j || bl <= j */ - if (bn_wexpand(t, k * 2) == NULL) goto err; + t->top = k * 2; + t->flags |= BN_FLG_FIXED_TOP; if (bn_wexpand(rr, k * 2) == NULL) goto err; + bn_set_top(rr, k * 2); + rr->flags |= BN_FLG_FIXED_TOP; bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } - rr->top = top; + bn_set_top(rr, top); goto end; } } #endif /* OPENSSL_SMALL_FOOTPRINT */ if (bn_wexpand(rr, top) == NULL) goto err; - rr->top = top; + bn_set_top(rr, top); bn_mul_normal(rr->d, a->d, al, b->d, bl); #if !defined(OPENSSL_SMALL_FOOTPRINT) @@ -604,66 +141,3 @@ err: BN_CTX_end(ctx); return ret; } - -void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) -{ - BN_ULONG *rr; - - if (na < nb) { - int itmp; - BN_ULONG *ltmp; - - itmp = na; - na = nb; - nb = itmp; - ltmp = a; - a = b; - b = ltmp; - } - rr = &(r[na]); - if (nb <= 0) { - (void)bn_mul_words(r, a, na, 0); - return; - } else - rr[0] = bn_mul_words(r, a, na, b[0]); - - for (;;) { - if (--nb <= 0) - return; - rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); - if (--nb <= 0) - return; - rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); - if (--nb <= 0) - return; - rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); - if (--nb <= 0) - return; - rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); - rr += 4; - r += 4; - b += 4; - } -} - -void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) -{ - bn_mul_words(r, a, n, b[0]); - - for (;;) { - if (--n <= 0) - return; - bn_mul_add_words(&(r[1]), a, n, b[1]); - if (--n <= 0) - return; - bn_mul_add_words(&(r[2]), a, n, b[2]); - if (--n <= 0) - return; - bn_mul_add_words(&(r[3]), a, n, b[3]); - if (--n <= 0) - return; - bn_mul_add_words(&(r[4]), a, n, b[4]); - r += 4; - b += 4; - } -} diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c index b820ef7486..b7c99006d0 100644 --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -184,43 +184,38 @@ static const BN_ULONG _nist_p_521_sqr[] = { #endif static const BIGNUM ossl_bignum_nist_p_192 = { - (BN_ULONG *)_nist_p_192[0], - BN_NIST_192_TOP, - BN_NIST_192_TOP, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_192[0], + .top = BN_NIST_192_TOP, + .dmax = BN_NIST_192_TOP, + .flags = BN_FLG_STATIC_DATA, }; static const BIGNUM ossl_bignum_nist_p_224 = { - (BN_ULONG *)_nist_p_224[0], - BN_NIST_224_TOP, - BN_NIST_224_TOP, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_224[0], + .top = BN_NIST_224_TOP, + .dmax = BN_NIST_224_TOP, + .flags = BN_FLG_STATIC_DATA, }; static const BIGNUM ossl_bignum_nist_p_256 = { - (BN_ULONG *)_nist_p_256[0], - BN_NIST_256_TOP, - BN_NIST_256_TOP, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_256[0], + .top = BN_NIST_256_TOP, + .dmax = BN_NIST_256_TOP, + .flags = BN_FLG_STATIC_DATA, }; static const BIGNUM ossl_bignum_nist_p_384 = { - (BN_ULONG *)_nist_p_384[0], - BN_NIST_384_TOP, - BN_NIST_384_TOP, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_384[0], + .top = BN_NIST_384_TOP, + .dmax = BN_NIST_384_TOP, + .flags = BN_FLG_STATIC_DATA, }; static const BIGNUM ossl_bignum_nist_p_521 = { - (BN_ULONG *)_nist_p_521, - BN_NIST_521_TOP, - BN_NIST_521_TOP, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_521, + .top = BN_NIST_521_TOP, + .dmax = BN_NIST_521_TOP, + .flags = BN_FLG_STATIC_DATA, }; const BIGNUM *BN_get0_nist_prime_192(void) @@ -359,10 +354,10 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, } buf; BN_ULONG c_d[BN_NIST_192_TOP], *res; static const BIGNUM ossl_bignum_nist_p_192_sqr = { - (BN_ULONG *)_nist_p_192_sqr, - OSSL_NELEM(_nist_p_192_sqr), - OSSL_NELEM(_nist_p_192_sqr), - 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_192_sqr, + .top = OSSL_NELEM(_nist_p_192_sqr), + .dmax = OSSL_NELEM(_nist_p_192_sqr), + .flags = BN_FLG_STATIC_DATA, }; field = &ossl_bignum_nist_p_192; /* just to make sure */ @@ -462,7 +457,7 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, ? r_d : c_d; nist_cp_bn(r_d, res, BN_NIST_192_TOP); - r->top = BN_NIST_192_TOP; + bn_set_top(r, BN_NIST_192_TOP); bn_correct_top(r); return 1; @@ -495,10 +490,10 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_ULONG c_d[BN_NIST_224_TOP], *res; bn_addsub_f adjust; static const BIGNUM ossl_bignum_nist_p_224_sqr = { - (BN_ULONG *)_nist_p_224_sqr, - OSSL_NELEM(_nist_p_224_sqr), - OSSL_NELEM(_nist_p_224_sqr), - 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_224_sqr, + .top = OSSL_NELEM(_nist_p_224_sqr), + .dmax = OSSL_NELEM(_nist_p_224_sqr), + .flags = BN_FLG_STATIC_DATA, }; field = &ossl_bignum_nist_p_224; /* just to make sure */ @@ -630,7 +625,7 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, ? r_d : c_d; nist_cp_bn(r_d, res, BN_NIST_224_TOP); - r->top = BN_NIST_224_TOP; + bn_set_top(r, BN_NIST_224_TOP); bn_correct_top(r); return 1; @@ -661,10 +656,10 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_ULONG c_d[BN_NIST_256_TOP], *res; bn_addsub_f adjust; static const BIGNUM ossl_bignum_nist_p_256_sqr = { - (BN_ULONG *)_nist_p_256_sqr, - OSSL_NELEM(_nist_p_256_sqr), - OSSL_NELEM(_nist_p_256_sqr), - 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_256_sqr, + .top = OSSL_NELEM(_nist_p_256_sqr), + .dmax = OSSL_NELEM(_nist_p_256_sqr), + .flags = BN_FLG_STATIC_DATA, }; field = &ossl_bignum_nist_p_256; /* just to make sure */ @@ -859,7 +854,7 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, ? r_d : c_d; nist_cp_bn(r_d, res, BN_NIST_256_TOP); - r->top = BN_NIST_256_TOP; + bn_set_top(r, BN_NIST_256_TOP); bn_correct_top(r); return 1; @@ -894,10 +889,10 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_ULONG c_d[BN_NIST_384_TOP], *res; bn_addsub_f adjust; static const BIGNUM ossl_bignum_nist_p_384_sqr = { - (BN_ULONG *)_nist_p_384_sqr, - OSSL_NELEM(_nist_p_384_sqr), - OSSL_NELEM(_nist_p_384_sqr), - 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_384_sqr, + .top = OSSL_NELEM(_nist_p_384_sqr), + .dmax = OSSL_NELEM(_nist_p_384_sqr), + .flags = BN_FLG_STATIC_DATA, }; field = &ossl_bignum_nist_p_384; /* just to make sure */ @@ -1126,7 +1121,7 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, ? r_d : c_d; nist_cp_bn(r_d, res, BN_NIST_384_TOP); - r->top = BN_NIST_384_TOP; + bn_set_top(r, BN_NIST_384_TOP); bn_correct_top(r); return 1; @@ -1142,10 +1137,10 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, int top = a->top, i; BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res; static const BIGNUM ossl_bignum_nist_p_521_sqr = { - (BN_ULONG *)_nist_p_521_sqr, - OSSL_NELEM(_nist_p_521_sqr), - OSSL_NELEM(_nist_p_521_sqr), - 0, BN_FLG_STATIC_DATA + .d = (BN_ULONG *)_nist_p_521_sqr, + .top = OSSL_NELEM(_nist_p_521_sqr), + .dmax = OSSL_NELEM(_nist_p_521_sqr), + .flags = BN_FLG_STATIC_DATA, }; field = &ossl_bignum_nist_p_521; /* just to make sure */ @@ -1197,7 +1192,7 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, ? r_d : t_d; nist_cp_bn(r_d, res, BN_NIST_521_TOP); - r->top = BN_NIST_521_TOP; + bn_set_top(r, BN_NIST_521_TOP); bn_correct_top(r); return 1; diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c index 33a9fc8d67..d626956e3d 100644 --- a/crypto/bn/bn_prime.c +++ b/crypto/bn/bn_prime.c @@ -55,11 +55,10 @@ static const BN_ULONG small_prime_factors[] = { #define BN_SMALL_PRIME_FACTORS_TOP OSSL_NELEM(small_prime_factors) static const BIGNUM _bignum_small_prime_factors = { - (BN_ULONG *)small_prime_factors, - BN_SMALL_PRIME_FACTORS_TOP, - BN_SMALL_PRIME_FACTORS_TOP, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)small_prime_factors, + .top = BN_SMALL_PRIME_FACTORS_TOP, + .dmax = BN_SMALL_PRIME_FACTORS_TOP, + .flags = BN_FLG_STATIC_DATA, }; const BIGNUM *ossl_bn_get0_small_factors(void) diff --git a/crypto/bn/bn_rsa_fips186_5.c b/crypto/bn/bn_rsa_fips186_5.c index 635f013f73..ee80bb3a5a 100644 --- a/crypto/bn/bn_rsa_fips186_5.c +++ b/crypto/bn/bn_rsa_fips186_5.c @@ -41,11 +41,10 @@ static const BN_ULONG inv_sqrt_2_val[] = { }; const BIGNUM ossl_bn_inv_sqrt_2 = { - (BN_ULONG *)inv_sqrt_2_val, - OSSL_NELEM(inv_sqrt_2_val), - OSSL_NELEM(inv_sqrt_2_val), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)inv_sqrt_2_val, + .top = OSSL_NELEM(inv_sqrt_2_val), + .dmax = OSSL_NELEM(inv_sqrt_2_val), + .flags = BN_FLG_STATIC_DATA, }; /* diff --git a/crypto/bn/bn_s390x.c b/crypto/bn/bn_s390x.c index 4e7aba35f6..ef96161ced 100644 --- a/crypto/bn/bn_s390x.c +++ b/crypto/bn/bn_s390x.c @@ -20,20 +20,16 @@ #include #include -/* - * Returns 1 for success, 0 for failure, and -1 to tell the caller to use the - * SW-fallback. - */ static int s390x_mod_exp_hw(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m) { struct ica_rsa_modexpo me; unsigned char *buffer; size_t size; - int res = -1; + int res = 0; if (OPENSSL_s390xcex == -1 || OPENSSL_s390xcex_nodev) - return -1; + return 0; size = BN_num_bytes(m); buffer = OPENSSL_calloc(size, 4); if (buffer == NULL) @@ -46,15 +42,11 @@ static int s390x_mod_exp_hw(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, me.n_modulus = buffer + 3 * size; if (BN_bn2binpad(a, me.inputdata, size) == -1 || BN_bn2binpad(p, me.b_key, size) == -1 - || BN_bn2binpad(m, me.n_modulus, size) == -1) { - res = 0; + || BN_bn2binpad(m, me.n_modulus, size) == -1) goto dealloc; - } if (ioctl(OPENSSL_s390xcex, ICARSAMODEXPO, &me) != -1) { if (BN_bin2bn(me.outputdata, size, r) != NULL) res = 1; - else - res = 0; } else if (errno == EBADF || errno == ENOTTY) { /* * In this cases, someone (e.g. a sandbox) closed the fd. @@ -79,34 +71,27 @@ dealloc: int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { - int rc; - - rc = s390x_mod_exp_hw(r, a, p, m); - if (rc < 0) - return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); - return rc; + if (s390x_mod_exp_hw(r, a, p, m) == 1) + return 1; + return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); } -/* - * Returns 1 for success, 0 for failure, and -1 to tell the caller to use the - * SW-fallback. - */ int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q, const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp) { struct ica_rsa_modexpo_crt crt; unsigned char *buffer, *part; size_t size, plen, qlen; - int res = -1; + int res = 0; if (OPENSSL_s390xcex == -1 || OPENSSL_s390xcex_nodev) - return -1; + return 0; /*- * Hardware-accelerated CRT can only deal with p>q. Fall back to * software in the (hopefully rare) other cases. */ if (BN_ucmp(p, q) != 1) - return -1; + return 0; plen = BN_num_bytes(p); qlen = BN_num_bytes(q); size = (plen > qlen ? plen : qlen); @@ -134,15 +119,11 @@ int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q, || BN_bn2binpad(q, crt.nq_prime, size) == -1 || BN_bn2binpad(dmp, crt.bp_key, size + 8) == -1 || BN_bn2binpad(dmq, crt.bq_key, size) == -1 - || BN_bn2binpad(iqmp, crt.u_mult_inv, size + 8) == -1) { - res = 0; + || BN_bn2binpad(iqmp, crt.u_mult_inv, size + 8) == -1) goto dealloc; - } if (ioctl(OPENSSL_s390xcex, ICARSACRT, &crt) != -1) { if (BN_bin2bn(crt.outputdata, crt.outputdatalength, r) != NULL) res = 1; - else - res = 0; } else if (errno == EBADF || errno == ENOTTY) { /* * In this cases, someone (e.g. a sandbox) closed the fd. diff --git a/crypto/bn/bn_shift.c b/crypto/bn/bn_shift.c index 1ba635096e..2e6f7c7401 100644 --- a/crypto/bn/bn_shift.c +++ b/crypto/bn/bn_shift.c @@ -23,7 +23,7 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a) r->neg = a->neg; if (bn_wexpand(r, a->top + 1) == NULL) return 0; - r->top = a->top; + bn_set_top(r, a->top); } else { if (bn_wexpand(r, a->top + 1) == NULL) return 0; @@ -37,7 +37,7 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a) c = t >> (BN_BITS2 - 1); } *rp = c; - r->top += (int)c; + bn_set_top(r, r->top + (int)c); bn_check_top(r); return 1; } @@ -62,11 +62,10 @@ int BN_rshift1(BIGNUM *r, const BIGNUM *a) r->neg = a->neg; } rp = r->d; - r->top = i; t = ap[--i]; rp[i] = t >> 1; c = t << (BN_BITS2 - 1); - r->top -= (t == 1); + bn_set_top(r, i + (t > 1)); while (i > 0) { t = ap[--i]; rp[i] = ((t >> 1) & BN_MASK2) | c; @@ -141,7 +140,7 @@ int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n) memset(r->d, 0, sizeof(*t) * nw); r->neg = a->neg; - r->top = a->top + nw + 1; + bn_set_top(r, a->top + nw + 1); r->flags |= BN_FLG_FIXED_TOP; return 1; @@ -209,7 +208,7 @@ int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n) t[i] = l >> rb; r->neg = a->neg; - r->top = top; + bn_set_top(r, top); r->flags |= BN_FLG_FIXED_TOP; return 1; diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c index 807577bae5..1eb9e4c9ab 100644 --- a/crypto/bn/bn_sqr.c +++ b/crypto/bn/bn_sqr.c @@ -34,7 +34,7 @@ int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) al = a->top; if (al <= 0) { - r->top = 0; + bn_set_top(r, 0); r->neg = 0; return 1; } @@ -91,8 +91,12 @@ int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) #endif } + /* Ensure that tmp won't cause any trouble */ + tmp->top = tmp->dmax; + tmp->flags |= BN_FLG_FIXED_TOP; + rr->neg = 0; - rr->top = max; + bn_set_top(rr, max); rr->flags |= BN_FLG_FIXED_TOP; if (r != rr && BN_copy(r, rr) == NULL) goto err; @@ -100,7 +104,6 @@ int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) ret = 1; err: bn_check_top(rr); - bn_check_top(tmp); BN_CTX_end(ctx); return ret; } diff --git a/crypto/bn/bn_srp.c b/crypto/bn/bn_srp.c index 1cc30a56dd..1e7b38b619 100644 --- a/crypto/bn/bn_srp.c +++ b/crypto/bn/bn_srp.c @@ -49,11 +49,10 @@ static const BN_ULONG bn_group_1024_value[] = { }; const BIGNUM ossl_bn_group_1024 = { - (BN_ULONG *)bn_group_1024_value, - OSSL_NELEM(bn_group_1024_value), - OSSL_NELEM(bn_group_1024_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_1024_value, + .top = OSSL_NELEM(bn_group_1024_value), + .dmax = OSSL_NELEM(bn_group_1024_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_group_1536_value[] = { @@ -84,11 +83,10 @@ static const BN_ULONG bn_group_1536_value[] = { }; const BIGNUM ossl_bn_group_1536 = { - (BN_ULONG *)bn_group_1536_value, - OSSL_NELEM(bn_group_1536_value), - OSSL_NELEM(bn_group_1536_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_1536_value, + .top = OSSL_NELEM(bn_group_1536_value), + .dmax = OSSL_NELEM(bn_group_1536_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_group_2048_value[] = { @@ -127,11 +125,10 @@ static const BN_ULONG bn_group_2048_value[] = { }; const BIGNUM ossl_bn_group_2048 = { - (BN_ULONG *)bn_group_2048_value, - OSSL_NELEM(bn_group_2048_value), - OSSL_NELEM(bn_group_2048_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_2048_value, + .top = OSSL_NELEM(bn_group_2048_value), + .dmax = OSSL_NELEM(bn_group_2048_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_group_3072_value[] = { @@ -186,11 +183,10 @@ static const BN_ULONG bn_group_3072_value[] = { }; const BIGNUM ossl_bn_group_3072 = { - (BN_ULONG *)bn_group_3072_value, - OSSL_NELEM(bn_group_3072_value), - OSSL_NELEM(bn_group_3072_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_3072_value, + .top = OSSL_NELEM(bn_group_3072_value), + .dmax = OSSL_NELEM(bn_group_3072_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_group_4096_value[] = { @@ -261,11 +257,10 @@ static const BN_ULONG bn_group_4096_value[] = { }; const BIGNUM ossl_bn_group_4096 = { - (BN_ULONG *)bn_group_4096_value, - OSSL_NELEM(bn_group_4096_value), - OSSL_NELEM(bn_group_4096_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_4096_value, + .top = OSSL_NELEM(bn_group_4096_value), + .dmax = OSSL_NELEM(bn_group_4096_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_group_6144_value[] = { @@ -368,11 +363,10 @@ static const BN_ULONG bn_group_6144_value[] = { }; const BIGNUM ossl_bn_group_6144 = { - (BN_ULONG *)bn_group_6144_value, - OSSL_NELEM(bn_group_6144_value), - OSSL_NELEM(bn_group_6144_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_6144_value, + .top = OSSL_NELEM(bn_group_6144_value), + .dmax = OSSL_NELEM(bn_group_6144_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_group_8192_value[] = { @@ -507,39 +501,35 @@ static const BN_ULONG bn_group_8192_value[] = { }; const BIGNUM ossl_bn_group_8192 = { - (BN_ULONG *)bn_group_8192_value, - OSSL_NELEM(bn_group_8192_value), - OSSL_NELEM(bn_group_8192_value), - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_group_8192_value, + .top = OSSL_NELEM(bn_group_8192_value), + .dmax = OSSL_NELEM(bn_group_8192_value), + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_generator_19_value[] = { 19 }; const BIGNUM ossl_bn_generator_19 = { - (BN_ULONG *)bn_generator_19_value, - 1, - 1, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_generator_19_value, + .top = 1, + .dmax = 1, + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_generator_5_value[] = { 5 }; const BIGNUM ossl_bn_generator_5 = { - (BN_ULONG *)bn_generator_5_value, - 1, - 1, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_generator_5_value, + .top = 1, + .dmax = 1, + .flags = BN_FLG_STATIC_DATA, }; static const BN_ULONG bn_generator_2_value[] = { 2 }; const BIGNUM ossl_bn_generator_2 = { - (BN_ULONG *)bn_generator_2_value, - 1, - 1, - 0, - BN_FLG_STATIC_DATA + .d = (BN_ULONG *)bn_generator_2_value, + .top = 1, + .dmax = 1, + .flags = BN_FLG_STATIC_DATA, }; #endif diff --git a/crypto/bn/bnw_mul.c b/crypto/bn/bnw_mul.c new file mode 100644 index 0000000000..d2f44d8608 --- /dev/null +++ b/crypto/bn/bnw_mul.c @@ -0,0 +1,407 @@ +/* + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bn_local.h" + +#ifndef OPENSSL_SMALL_FOOTPRINT +/* + * Karatsuba recursive multiplication algorithm (cf. Knuth, The Art of + * Computer Programming, Vol. 2) + */ + +/*- + * r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +/* dnX may not be positive, but n2/2+dnX has to be */ +void bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2, + int dna, int dnb, BN_ULONG *t) +{ + int n = n2 / 2, c1, c2; + int tna = n + dna, tnb = n + dnb; + unsigned int neg, zero; + BN_ULONG ln, lo, *p; + + /* + * Only call bn_mul_comba 8 if n2 == 8 and the two arrays are complete + * [steve] + */ + if (n2 == 8 && dna == 0 && dnb == 0) { + bn_mul_comba8(r, a, b); + return; + } + + /* Else do normal multiply */ + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(r, a, n2 + dna, b, n2 + dnb); + if ((dna + dnb) < 0) + memset(&r[2 * n2 + dna + dnb], 0, + sizeof(BN_ULONG) * -(dna + dnb)); + return; + } + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); + c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); + zero = neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + break; + case -3: + zero = 1; + break; + case -2: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + zero = 1; + break; + case 2: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + neg = 1; + break; + case 3: + zero = 1; + break; + case 4: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); + break; + } + + if (n == 4 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba4 could take + * extra args to do this well */ + if (!zero) + bn_mul_comba4(&(t[n2]), t, &(t[n])); + else + memset(&t[n2], 0, sizeof(*t) * 8); + + bn_mul_comba4(r, a, b); + bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); + } else if (n == 8 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba8 could + * take extra args to do + * this well */ + if (!zero) + bn_mul_comba8(&(t[n2]), t, &(t[n])); + else + memset(&t[n2], 0, sizeof(*t) * 16); + + bn_mul_comba8(r, a, b); + bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); + } else { + p = &(t[n2 * 2]); + if (!zero) + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + else + memset(&t[n2], 0, sizeof(*t) * n2); + bn_mul_recursive(r, a, b, n, 0, 0, p); + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p); + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* + * The overflow will stop before we over write words we should not + * overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +/* + * n+tn is the word length t needs to be n*4 is size, as does r + */ +/* tnX may not be negative but less than n */ +void bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n, int tna, int tnb, BN_ULONG *t) +{ + int i, j, n2 = n * 2; + int c1, c2, neg; + BN_ULONG ln, lo, *p; + + if (n < 8) { + bn_mul_normal(r, a, n + tna, b, n + tnb); + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); + c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); + neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + break; + case -3: + case -2: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + case 2: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + neg = 1; + break; + case 3: + case 4: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); + break; + } + /* + * The zero case isn't yet implemented here. The speedup would probably + * be negligible. + */ +#if 0 + if (n == 4) { + bn_mul_comba4(&(t[n2]), t, &(t[n])); + bn_mul_comba4(r, a, b); + bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn); + memset(&r[n2 + tn * 2], 0, sizeof(*r) * (n2 - tn * 2)); + } else +#endif + if (n == 8) { + bn_mul_comba8(&(t[n2]), t, &(t[n])); + bn_mul_comba8(r, a, b); + bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); + memset(&r[n2 + tna + tnb], 0, sizeof(*r) * (n2 - tna - tnb)); + } else { + p = &(t[n2 * 2]); + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + bn_mul_recursive(r, a, b, n, 0, 0, p); + i = n / 2; + /* + * If there is only a bottom half to the number, just do it + */ + if (tna > tnb) + j = tna - i; + else + j = tnb - i; + if (j == 0) { + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + memset(&r[n2 + i * 2], 0, sizeof(*r) * (n2 - i * 2)); + } else if (j > 0) { /* eg, n == 16, i == 8 and tn == 11 */ + bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + memset(&(r[n2 + tna + tnb]), 0, + sizeof(BN_ULONG) * (n2 - tna - tnb)); + } else { /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + + memset(&r[n2], 0, sizeof(*r) * n2); + if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL + && tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); + } else { + for (;;) { + i /= 2; + /* + * these simplified conditions work exclusively because + * difference between tna and tnb is 1 or 0 + */ + if (i < tna || i < tnb) { + bn_mul_part_recursive(&(r[n2]), + &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + break; + } else if (i == tna || i == tnb) { + bn_mul_recursive(&(r[n2]), + &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + break; + } + } + } + } + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* + * The overflow will stop before we over write words we should not + * overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +/*- + * a and b must be the same size, which is n2. + * r needs to be n2 words and t needs to be n2*2 + */ +void bn_mul_low_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n2, BN_ULONG *t) +{ + int n = n2 / 2; + + bn_mul_recursive(r, a, b, n, 0, 0, &(t[0])); + if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) { + bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2])); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2])); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + } else { + bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n); + bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + bn_add_words(&(r[n]), &(r[n]), &(t[n]), n); + } +} +#endif /* OPENSSL_SMALL_FOOTPRINT */ + +/* + * This function doesn't zero out the rest of r in case of nr>na+nb; + * it's the calling function's responsibility to do so. + */ +void bn_mul_truncated(BN_ULONG *r, int nr, const BN_ULONG *a, int na, + const BN_ULONG *b, int nb) +{ + BN_ULONG tmp, *carryp = NULL; + int n; /* Number of words to use in the current iteration */ + + if (na < nb) { + int itmp; + const BN_ULONG *ltmp; + + itmp = na; + na = nb; + nb = itmp; + ltmp = a; + a = b; + b = ltmp; + } + n = (na < nr) ? na : nr; + if (nb <= 0) { + (void)bn_mul_words(r, a, n, 0); + return; + } else { + carryp = (na < nr) ? &r[na] : &tmp; + *carryp = bn_mul_words(r, a, n, b[0]); + } + + for (int i = 1; i < nb && i < nr; i++) { + int rspace = nr - i; + n = (na < rspace) ? na : rspace; + carryp = (na < rspace) ? &r[i + na] : &tmp; + *carryp = bn_mul_add_words(&(r[i]), a, n, b[i]); + } +} + +void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b, + int nb) +{ + bn_mul_truncated(r, na + nb, a, na, b, nb); +} + +void bn_mul_low_normal(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) +{ + bn_mul_words(r, a, n, b[0]); + + for (;;) { + if (--n <= 0) + return; + bn_mul_add_words(&(r[1]), a, n, b[1]); + if (--n <= 0) + return; + bn_mul_add_words(&(r[2]), a, n, b[2]); + if (--n <= 0) + return; + bn_mul_add_words(&(r[3]), a, n, b[3]); + if (--n <= 0) + return; + bn_mul_add_words(&(r[4]), a, n, b[4]); + r += 4; + b += 4; + } +} diff --git a/crypto/bn/bnw_sub.c b/crypto/bn/bnw_sub.c new file mode 100644 index 0000000000..f989878ce0 --- /dev/null +++ b/crypto/bn/bnw_sub.c @@ -0,0 +1,155 @@ +/* + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bn_local.h" + +#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS) +/* + * Here follows specialised variants of bn_add_words() and bn_sub_words(). + * They have the property performing operations on arrays of different sizes. + * The sizes of those arrays is expressed through cl, which is the common + * length ( basically, min(len(a),len(b)) ), and dl, which is the delta + * between the two lengths, calculated as len(a)-len(b). All lengths are the + * number of BN_ULONGs... For the operations that require a result array as + * parameter, it must have the length cl+abs(dl). + * + * These functions should probably end up in bn_asm.c as soon as there are + * assembler counterparts for the systems that use assembler files. + */ + +BN_ULONG bn_sub_part_words(BN_ULONG *r, + const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl) +{ + BN_ULONG c, t; + + assert(cl >= 0); + c = bn_sub_words(r, a, b, cl); + + if (dl == 0) + return c; + + r += cl; + a += cl; + b += cl; + + if (dl < 0) { + for (;;) { + t = b[0]; + r[0] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + t = b[1]; + r[1] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + t = b[2]; + r[2] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + t = b[3]; + r[3] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + b += 4; + r += 4; + } + } else { + int save_dl = dl; + while (c) { + t = a[0]; + r[0] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + t = a[1]; + r[1] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + t = a[2]; + r[2] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + t = a[3]; + r[3] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + save_dl = dl; + a += 4; + r += 4; + } + if (dl > 0) { + if (save_dl > dl) { + switch (save_dl - dl) { + case 1: + r[1] = a[1]; + if (--dl <= 0) + break; + /* fall through */ + case 2: + r[2] = a[2]; + if (--dl <= 0) + break; + /* fall through */ + case 3: + r[3] = a[3]; + if (--dl <= 0) + break; + } + a += 4; + r += 4; + } + } + if (dl > 0) { + for (;;) { + r[0] = a[0]; + if (--dl <= 0) + break; + r[1] = a[1]; + if (--dl <= 0) + break; + r[2] = a[2]; + if (--dl <= 0) + break; + r[3] = a[3]; + if (--dl <= 0) + break; + + a += 4; + r += 4; + } + } + } + return c; +} +#endif diff --git a/crypto/bn/build.info b/crypto/bn/build.info index 01e98e4544..10680e1100 100644 --- a/crypto/bn/build.info +++ b/crypto/bn/build.info @@ -105,11 +105,18 @@ IF[{- !$disabled{asm} -}] ENDIF ENDIF -$COMMON=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \ +$COMMON_BN=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \ bn_mod.c bn_conv.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \ bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_sqr.c \ bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \ bn_intern.c bn_dh.c bn_rsa_fips186_5.c bn_const.c +# bnw_*.c is a growing collection of files with routines that operate on +# BN_ULONG only. They were helper routines dispersed in bn_*.c, and are +# often routines that don't have an assembler implementation, and therefore +# didn't fit into bn_asm.c. +$COMMON_BNW=bnw_sub.c bnw_mul.c +$COMMON=$COMMON_BN $COMMON_BNW + SOURCE[../../libcrypto]=$COMMON $BNASM bn_print.c bn_err.c bn_srp.c DEFINE[../../libcrypto]=$BNDEF IF[{- !$disabled{'deprecated-0.9.8'} -}] diff --git a/crypto/build.info b/crypto/build.info index 4e9068407c..68ecd2db27 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -4,7 +4,7 @@ SUBDIRS=objects buffer bio stack lhash hashtable rand evp asn1 pem x509 conf \ txt_db pkcs7 pkcs12 ui kdf store property \ md2 md4 md5 sha mdc2 ml_kem hmac ripemd whrlpool poly1305 \ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \ - seed sm4 chacha modes bn ec rsa dsa dh sm2 dso \ + seed sm4 chacha modes fn bn ec rsa dsa dh sm2 dso \ err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \ ffc hpke thread lms ml_dsa slh_dsa @@ -16,6 +16,7 @@ IF[{- !$disabled{uplink} -}] $UPLINKSRC_common=../ms/uplink.c $UPLINKSRC_x86=$UPLINKSRC_common uplink-x86.S $UPLINKSRC_x86_64=$UPLINKSRC_common uplink-x86_64.s + $UPLINKSRC_ia64=$UPLINKSRC_common uplink-ia64.s IF[$UPLINKSRC_{- $target{uplink_arch} -}] $UPLINKSRC=$UPLINKSRC_{- $target{uplink_arch} -} @@ -98,7 +99,8 @@ $UTIL_COMMON=\ threads_pthread.c threads_win.c threads_none.c threads_common.c \ initthread.c context.c sparse_array.c asn1_dsa.c packet.c \ param_build.c param_build_set.c der_writer.c threads_lib.c \ - params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c + params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c \ + int.c SOURCE[../libcrypto]=$UTIL_COMMON \ mem.c mem_sec.c \ @@ -117,6 +119,7 @@ GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" " GENERATE[uplink-x86.S]=../ms/uplink-x86.pl GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl +GENERATE[uplink-ia64.s]=../ms/uplink-ia64.pl GENERATE[x86cpuid.S]=x86cpuid.pl DEPEND[x86cpuid.s]=perlasm/x86asm.pl diff --git a/crypto/chacha/chacha_enc.c b/crypto/chacha/chacha_enc.c index c7c36b9c54..e9a4d3263a 100644 --- a/crypto/chacha/chacha_enc.c +++ b/crypto/chacha/chacha_enc.c @@ -24,7 +24,7 @@ typedef union { #define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) #ifndef PEDANTIC -#if defined(__GNUC__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) #if defined(__riscv_zbb) || defined(__riscv_zbkb) #if __riscv_xlen == 64 #undef ROTATE diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index ac892f62bd..e664a6ae22 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -819,7 +819,7 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs, int only_self_issued); STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store); int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk, - const char *text, size_t len); + const char *text, int len); int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt, const ASN1_OCTET_STRING *src); int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt, diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index abea670ce9..fec747458d 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -824,13 +824,13 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si, goto err; msg->body->value.error->errorDetails = ft; if (lib != NULL && *lib != '\0' - && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, lib, strlen(lib))) + && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, lib, -1)) goto err; if (reason != NULL && *reason != '\0' - && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, reason, strlen(reason))) + && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, reason, -1)) goto err; if (details != NULL - && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details, strlen(details))) + && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details, -1)) goto err; } diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c index c0dba8392d..b0f52e9f36 100644 --- a/crypto/cmp/cmp_protect.c +++ b/crypto/cmp/cmp_protect.c @@ -73,11 +73,7 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, pbm_str = (ASN1_STRING *)ppval; pbm_str_uc = ASN1_STRING_get0_data(pbm_str); - if (ASN1_STRING_length_ex(pbm_str) > INT_MAX) { - ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID); - goto end; - } - pbm = d2i_OSSL_CRMF_PBMPARAMETER(NULL, &pbm_str_uc, (long)ASN1_STRING_length_ex(pbm_str)); + pbm = d2i_OSSL_CRMF_PBMPARAMETER(NULL, &pbm_str_uc, ASN1_STRING_length(pbm_str)); if (pbm == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID); goto end; @@ -85,7 +81,7 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, if (!OSSL_CRMF_pbm_new(ctx->libctx, ctx->propq, pbm, prot_part_der, prot_part_der_len, - ASN1_STRING_get0_data(ctx->secretValue), ASN1_STRING_length_ex(ctx->secretValue), + ASN1_STRING_get0_data(ctx->secretValue), ASN1_STRING_length(ctx->secretValue), &protection, &sig_len)) goto end; @@ -206,7 +202,7 @@ static X509_ALGOR *pbmac_algor(const OSSL_CMP_CTX *ctx) goto err; if ((pbm_der_len = i2d_OSSL_CRMF_PBMPARAMETER(pbm, &pbm_der)) < 0) goto err; - if (!ASN1_STRING_set_data(pbm_str, pbm_der, pbm_der_len)) + if (!ASN1_STRING_set(pbm_str, pbm_der, pbm_der_len)) goto err; alg = ossl_X509_ALGOR_from_nid(NID_id_PasswordBasedMAC, V_ASN1_SEQUENCE, pbm_str); diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c index 063bbe808c..40e1ee671e 100644 --- a/crypto/cmp/cmp_status.c +++ b/crypto/cmp/cmp_status.c @@ -214,7 +214,7 @@ static char *snprint_PKIStatusInfo_parts(int status, int fail_info, for (i = 0; i < n_status_strings; i++) { text = sk_ASN1_UTF8STRING_value(status_strings, i); printed_chars = BIO_snprintf(write_ptr, bufsize, "\"%.*s\"%s", - (int)ASN1_STRING_length_ex(text), + ASN1_STRING_length(text), ASN1_STRING_get0_data(text), i < n_status_strings - 1 ? ", " : ""); ADVANCE_BUFFER; @@ -275,7 +275,7 @@ OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info, if (text != NULL) { if ((utf8_text = ASN1_UTF8STRING_new()) == NULL - || !ASN1_STRING_set_string(utf8_text, text)) + || !ASN1_STRING_set(utf8_text, text, -1)) goto err; if ((si->statusString = sk_ASN1_UTF8STRING_new_null()) == NULL) goto err; diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c index f3a0c86d53..5c710addf2 100644 --- a/crypto/cmp/cmp_util.c +++ b/crypto/cmp/cmp_util.c @@ -219,7 +219,7 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs, } int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk, - const char *text, size_t len) + const char *text, int len) { ASN1_UTF8STRING *utf8string; @@ -227,7 +227,7 @@ int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk, return 0; if ((utf8string = ASN1_UTF8STRING_new()) == NULL) return 0; - if (!ASN1_STRING_set_data(utf8string, (const uint8_t *)text, len)) + if (!ASN1_STRING_set(utf8string, text, len)) goto err; if (!sk_ASN1_UTF8STRING_push(sk, utf8string)) goto err; diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index 96b125e930..63a26de742 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -306,9 +306,9 @@ ASN1_NDEF_SEQUENCE(CMS_AuthEnvelopedData) = { ASN1_IMP_OPT(CMS_AuthEnvelopedData, originatorInfo, CMS_OriginatorInfo, 0), ASN1_SET_OF(CMS_AuthEnvelopedData, recipientInfos, CMS_RecipientInfo), ASN1_SIMPLE(CMS_AuthEnvelopedData, authEncryptedContentInfo, CMS_EncryptedContentInfo), - ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, authAttrs, X509_ATTRIBUTE, 1), + ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, authAttrs, X509_ALGOR, 2), ASN1_SIMPLE(CMS_AuthEnvelopedData, mac, ASN1_OCTET_STRING), - ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, unauthAttrs, X509_ATTRIBUTE, 2) + ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, unauthAttrs, X509_ALGOR, 3) } ASN1_NDEF_SEQUENCE_END(CMS_AuthEnvelopedData) ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = { diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c index e307460e44..2e1dd78f5e 100644 --- a/crypto/cms/cms_dd.c +++ b/crypto/cms/cms_dd.c @@ -92,7 +92,7 @@ int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, else r = 1; } else { - if (!ASN1_STRING_set_data(dd->digest, md, mdlen)) + if (!ASN1_STRING_set(dd->digest, md, mdlen)) goto err; r = 1; } diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c index 03cef7455a..a3ae620dea 100644 --- a/crypto/cms/cms_dh.c +++ b/crypto/cms/cms_dh.c @@ -29,7 +29,7 @@ static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, BIGNUM *bnpub = NULL; const unsigned char *p; unsigned char *buf = NULL; - size_t plen; + int plen; X509_ALGOR_get0(&aoid, &atype, &aval, alg); if (OBJ_obj2nid(aoid) != NID_dhpublicnumber) @@ -43,33 +43,29 @@ static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, goto err; /* Get public key */ - plen = ASN1_STRING_length_ex(pubkey); - if (plen > INT_MAX) - goto err; + plen = ASN1_STRING_length(pubkey); p = ASN1_STRING_get0_data(pubkey); if (p == NULL || plen == 0) goto err; - if ((public_key = d2i_ASN1_INTEGER(NULL, &p, (int)plen)) == NULL) + if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL) goto err; /* * Pad to full p parameter size as that is checked by * EVP_PKEY_set1_encoded_public_key() */ plen = EVP_PKEY_get_size(pk); - if (plen > INT_MAX) - goto err; if ((bnpub = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) goto err; if ((buf = OPENSSL_malloc(plen)) == NULL) goto err; - if (BN_bn2binpad(bnpub, buf, (int)plen) < 0) + if (BN_bn2binpad(bnpub, buf, plen) < 0) goto err; pkpeer = EVP_PKEY_new(); if (pkpeer == NULL || !EVP_PKEY_copy_parameters(pkpeer, pk) - || EVP_PKEY_set1_encoded_public_key(pkpeer, buf, (int)plen) <= 0) + || EVP_PKEY_set1_encoded_public_key(pkpeer, buf, plen) <= 0) goto err; if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) @@ -89,9 +85,8 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) ASN1_OCTET_STRING *ukm; const unsigned char *p; unsigned char *dukm = NULL; - size_t dukmlen = 0; - int keylen; - size_t plen; + int dukmlen = 0; + int keylen, plen; EVP_CIPHER *kekcipher = NULL; EVP_CIPHER_CTX *kekctx; const ASN1_OBJECT *aoid; @@ -121,10 +116,8 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) goto err; p = ASN1_STRING_get0_data(parameter); - plen = ASN1_STRING_length_ex(parameter); - if (plen > INT_MAX) - goto err; - kekalg = d2i_X509_ALGOR(NULL, &p, (int)plen); + plen = ASN1_STRING_length(parameter); + kekalg = d2i_X509_ALGOR(NULL, &p, plen); if (kekalg == NULL) goto err; kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); @@ -153,15 +146,13 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) goto err; if (ukm != NULL) { - dukmlen = ASN1_STRING_length_ex(ukm); - if (dukmlen > INT_MAX) - goto err; - dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), (int)dukmlen); + dukmlen = ASN1_STRING_length(ukm); + dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen); if (dukm == NULL) goto err; } - if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, (int)dukmlen) <= 0) + if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0) goto err; dukm = NULL; @@ -215,7 +206,7 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) ASN1_OCTET_STRING *ukm; unsigned char *penc = NULL, *dukm = NULL; int penclen; - size_t dukmlen = 0; + int dukmlen = 0; int rv = 0; int kdf_type, wrap_nid; const EVP_MD *kdf_md; @@ -307,15 +298,13 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) goto err; if (ukm != NULL) { - dukmlen = ASN1_STRING_length_ex(ukm); - if (dukmlen > INT_MAX) - goto err; + dukmlen = ASN1_STRING_length(ukm); dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen); if (dukm == NULL) goto err; } - if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, (int)dukmlen) <= 0) + if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0) goto err; dukm = NULL; diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c index 98ab266779..8a8fe3f912 100644 --- a/crypto/cms/cms_ec.c +++ b/crypto/cms/cms_ec.c @@ -79,7 +79,7 @@ static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, int rv = 0; EVP_PKEY *pkpeer = NULL; const unsigned char *p; - size_t plen; + int plen; X509_ALGOR_get0(&aoid, &atype, &aval, alg); if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) @@ -106,14 +106,12 @@ static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, goto err; } /* We have parameters now set public key */ - plen = ASN1_STRING_length_ex(pubkey); - if (plen > INT_MAX) - goto err; + plen = ASN1_STRING_length(pubkey); p = ASN1_STRING_get0_data(pubkey); if (p == NULL || plen == 0) goto err; - if (EVP_PKEY_set1_encoded_public_key(pkpeer, p, (int)plen) <= 0) + if (EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen) <= 0) goto err; if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) @@ -165,8 +163,7 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) ASN1_OCTET_STRING *ukm; const unsigned char *p; unsigned char *der = NULL; - int keylen, plen_i; - size_t plen; + int plen, keylen; EVP_CIPHER *kekcipher = NULL; EVP_CIPHER_CTX *kekctx; const ASN1_OBJECT *aoid = NULL; @@ -189,10 +186,8 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) return 0; p = ASN1_STRING_get0_data(parameter); - plen = ASN1_STRING_length_ex(parameter); - if (plen > INT_MAX) - goto err; - kekalg = d2i_X509_ALGOR(NULL, &p, (int)plen); + plen = ASN1_STRING_length(parameter); + kekalg = d2i_X509_ALGOR(NULL, &p, plen); if (kekalg == NULL) goto err; kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); @@ -211,12 +206,12 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) goto err; - plen_i = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); + plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); - if (plen_i <= 0) + if (plen <= 0) goto err; - if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen_i) <= 0) + if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) goto err; der = NULL; diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index c29e2019ee..e702703758 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -278,17 +278,12 @@ BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data, CMS_ContentInfo *ci; BIO *bio = NULL; int res = 0; - size_t secret_len = 0; if (env == NULL) { ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_NULL_PARAMETER); return NULL; } - if (secret != NULL - && (secret_len = ASN1_STRING_length_ex(secret)) > INT_MAX) - return NULL; - if ((ci = CMS_ContentInfo_new_ex(libctx, propq)) == NULL || (bio = BIO_new(BIO_s_mem())) == NULL) goto end; @@ -296,7 +291,7 @@ BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data, ci->d.envelopedData = env; if (secret != NULL && CMS_decrypt_set1_password(ci, (unsigned char *)ASN1_STRING_get0_data(secret), - (int)secret_len) + ASN1_STRING_length(secret)) != 1) goto end; res = CMS_decrypt(ci, secret == NULL ? pkey : NULL, @@ -1241,35 +1236,6 @@ BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) return cms_EnvelopedData_Decryption_init_bio(cms); } -/* The DER encoding of authAttrs, with the universal SET OF tag, is the AAD */ -static int cms_AuthEnvelopedData_set_aad(BIO *b, - STACK_OF(X509_ATTRIBUTE) *authAttrs) -{ - EVP_CIPHER_CTX *ctx; - unsigned char *aad = NULL; - int aadlen, outl, ok = 0; - const ASN1_ITEM *item; - - if (!BIO_get_cipher_ctx(b, &ctx)) - return 0; - item = EVP_CIPHER_CTX_is_encrypting(ctx) - ? ASN1_ITEM_rptr(CMS_Attributes_AadEncrypt) - : ASN1_ITEM_rptr(CMS_Attributes_AadDecrypt); - aadlen = ASN1_item_i2d((ASN1_VALUE *)authAttrs, &aad, item); - if (aadlen <= 0 || aad == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); - goto err; - } - if (EVP_CipherUpdate(ctx, NULL, &outl, aad, aadlen) <= 0) { - ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE); - goto err; - } - ok = 1; -err: - OPENSSL_free(aad); - return ok; -} - BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms) { CMS_EncryptedContentInfo *ec; @@ -1286,16 +1252,9 @@ BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms) ec->taglen = aenv->mac->length; } ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms), 1); - if (ret == NULL) - return NULL; - /* authAttrs, if present, are the AEAD associated data */ - if (aenv->authAttrs != NULL - && !cms_AuthEnvelopedData_set_aad(ret, aenv->authAttrs)) - goto err; - - /* If no cipher end of processing */ - if (ec->cipher == NULL) + /* If error or no cipher end of processing */ + if (ret == NULL || ec->cipher == NULL) return ret; /* Now encrypt content key according to each RecipientInfo type */ diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c index bfe0ccbf3d..cafb827394 100644 --- a/crypto/cms/cms_ess.c +++ b/crypto/cms/cms_ess.c @@ -131,7 +131,7 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex( if (id) ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen); else { - if (!ASN1_STRING_set_data(rr->signedContentIdentifier, NULL, 32)) { + if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32)) { ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/cms/cms_kemri.c b/crypto/cms/cms_kemri.c index 3284ebc23a..1d867c0db1 100644 --- a/crypto/cms/cms_kemri.c +++ b/crypto/cms/cms_kemri.c @@ -388,7 +388,7 @@ int ossl_cms_RecipientInfo_kemri_decrypt(const CMS_ContentInfo *cms, goto err; kem_ct = ASN1_STRING_get0_data(kemri->kemct); - kem_ct_len = ASN1_STRING_length_ex(kemri->kemct); + kem_ct_len = ASN1_STRING_length(kemri->kemct); if (EVP_PKEY_decapsulate(kemri->pctx, NULL, &kem_secret_len, kem_ct, kem_ct_len) <= 0) return 0; diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index bfb0ca729b..5e0ac3907f 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -401,9 +401,6 @@ DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo) DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) DECLARE_ASN1_ITEM(CMS_Attributes_Sign) DECLARE_ASN1_ITEM(CMS_Attributes_Verify) -/* The authAttrs AAD encoding matches the signed-attributes one */ -#define CMS_Attributes_AadEncrypt_it CMS_Attributes_Sign_it -#define CMS_Attributes_AadDecrypt_it CMS_Attributes_Verify_it DECLARE_ASN1_ITEM(CMS_RecipientInfo) DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo) DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber) diff --git a/crypto/cms/cms_rsa.c b/crypto/cms/cms_rsa.c index 1b351f6cd1..fc7fc6c284 100644 --- a/crypto/cms/cms_rsa.c +++ b/crypto/cms/cms_rsa.c @@ -43,7 +43,7 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri) int nid; int rv = -1; const unsigned char *label = NULL; - size_t labellen = 0; + int labellen = 0; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_OAEP_PARAMS *oaep; const ASN1_OBJECT *aoid; @@ -90,9 +90,7 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri) } label = ASN1_STRING_get0_data(parameter); - labellen = ASN1_STRING_length_ex(parameter); - if (labellen > INT_MAX) - goto err; + labellen = ASN1_STRING_length(parameter); } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) @@ -107,7 +105,7 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri) if (dup_label == NULL) goto err; - if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, dup_label, (int)labellen) <= 0) { + if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, dup_label, labellen) <= 0) { OPENSSL_free(dup_label); goto err; } diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 352f75a45c..6466aacec1 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -304,7 +304,7 @@ static int ossl_cms_add1_signing_cert(CMS_SignerInfo *si, p = pp; i2d_ESS_SIGNING_CERT(sc, &p); - if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set_data(seq, pp, len)) { + if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) { ASN1_STRING_free(seq); OPENSSL_free(pp); return 0; @@ -329,7 +329,7 @@ static int ossl_cms_add1_signing_cert_v2(CMS_SignerInfo *si, p = pp; i2d_ESS_SIGNING_CERT_V2(sc, &p); - if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set_data(seq, pp, len)) { + if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) { ASN1_STRING_free(seq); OPENSSL_free(pp); return 0; diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 044cb2326f..659c033482 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -36,7 +36,6 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) unsigned char buf[4096]; int r = 0, i; BIO *tmpout; - BIO *aeadbuf = NULL; tmpout = cms_get_text_bio(out, flags); @@ -45,33 +44,6 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) goto err; } - /* - * For AEAD content (AuthEnvelopedData) the integrity tag is only verified - * once all the ciphertext has been processed, by the - * BIO_get_cipher_status() call below. RFC 5083 requires that the plaintext - * is not released to the caller until that verification succeeds, so - * buffer it in memory and only forward it to the output BIO once the tag - * has been checked. When CMS_TEXT is set tmpout is already a memory BIO - * that is flushed only on success, so the extra buffering is not needed. - */ - if (tmpout == out && BIO_method_type(in) == BIO_TYPE_CIPHER) { - EVP_CIPHER_CTX *ctx = NULL; - - if (BIO_get_cipher_ctx(in, &ctx) > 0 && ctx != NULL - && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx)) - & EVP_CIPH_FLAG_AEAD_CIPHER) - != 0) { - aeadbuf = BIO_new(BIO_s_mem()); - if (aeadbuf == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_BIO_LIB); - goto err; - } - /* Return 0 (EOF) rather than a retryable -1 once drained. */ - BIO_set_mem_eof_return(aeadbuf, 0); - tmpout = aeadbuf; - } - } - /* Read all content through chain to process digest, decrypt etc */ for (;;) { i = BIO_read(in, buf, sizeof(buf)); @@ -94,17 +66,6 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR); goto err; } - } else if (aeadbuf != NULL) { - /* Forward the AEAD BIO to out BIO as the tag has been verified. */ - for (;;) { - i = BIO_read(aeadbuf, buf, sizeof(buf)); - if (i < 0) - goto err; - if (i == 0) - break; - if (BIO_write(out, buf, i) != i) - goto err; - } } r = 1; diff --git a/crypto/comp/c_brotli.c b/crypto/comp/c_brotli.c index 9c99e066b7..d262ec6a4e 100644 --- a/crypto/comp/c_brotli.c +++ b/crypto/comp/c_brotli.c @@ -13,7 +13,6 @@ #include #include #include -#include "internal/e_os.h" #include "internal/comp.h" #include #include "crypto/cryptlib.h" @@ -47,6 +46,10 @@ static void brotli_free(void *opaque, void *address) * work. Therefore, all BROTLI routines are loaded at run time * and we do not link to a .LIB file when BROTLI_SHARED is set. */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +#include +#endif + #ifdef BROTLI_SHARED #include "internal/dso.h" diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c index 4af4e30b64..c90c7b090d 100644 --- a/crypto/comp/c_zlib.c +++ b/crypto/comp/c_zlib.c @@ -11,7 +11,6 @@ #include #include #include -#include "internal/e_os.h" #include "internal/comp.h" #include #include "crypto/cryptlib.h" @@ -65,6 +64,10 @@ static COMP_METHOD zlib_stateful_method = { * work. Therefore, all ZLIB routines are loaded at run time * and we do not link to a .LIB file when ZLIB_SHARED is set. */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +#include +#endif /* !(OPENSSL_SYS_WINDOWS || \ + * OPENSSL_SYS_WIN32) */ #ifdef ZLIB_SHARED #include "internal/dso.h" diff --git a/crypto/comp/c_zstd.c b/crypto/comp/c_zstd.c index c5c6cd6eef..a9c881f8f9 100644 --- a/crypto/comp/c_zstd.c +++ b/crypto/comp/c_zstd.c @@ -16,7 +16,6 @@ #include #include #include -#include "internal/e_os.h" #include "internal/comp.h" #include #include "crypto/cryptlib.h" @@ -63,6 +62,16 @@ static ZSTD_customMem zstd_mem_funcs = { }; #endif +/* + * When OpenSSL is built on Windows, we do not want to require that + * the LIBZSTD.DLL be available in order for the OpenSSL DLLs to + * work. Therefore, all ZSTD routines are loaded at run time + * and we do not link to a .LIB file when ZSTD_SHARED is set. + */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +#include +#endif + #ifdef ZSTD_SHARED #include "internal/dso.h" diff --git a/crypto/context.c b/crypto/context.c index 66d7e42955..3596c0e068 100644 --- a/crypto/context.c +++ b/crypto/context.c @@ -255,6 +255,12 @@ err: static void context_deinit_objs(OSSL_LIB_CTX *ctx) { + /* P2. We want evp_method_store to be cleaned up before the provider store */ + if (ctx->evp_method_store != NULL) { + ossl_method_store_free(ctx->evp_method_store); + ctx->evp_method_store = NULL; + } + /* P2. */ if (ctx->drbg != NULL) { ossl_rand_ctx_free(ctx->drbg); @@ -272,14 +278,14 @@ static void context_deinit_objs(OSSL_LIB_CTX *ctx) * P2. We want decoder_store/decoder_cache to be cleaned up before the * provider store */ - if (ctx->decoder_cache != NULL) { - ossl_decoder_cache_free(ctx->decoder_cache); - ctx->decoder_cache = NULL; - } if (ctx->decoder_store != NULL) { ossl_method_store_free(ctx->decoder_store); ctx->decoder_store = NULL; } + if (ctx->decoder_cache != NULL) { + ossl_decoder_cache_free(ctx->decoder_cache); + ctx->decoder_cache = NULL; + } /* P2. We want encoder_store to be cleaned up before the provider store */ if (ctx->encoder_store != NULL) { @@ -300,12 +306,6 @@ static void context_deinit_objs(OSSL_LIB_CTX *ctx) ctx->provider_store = NULL; } - /* P2. We want evp_method_store to be cleaned up before the provider store */ - if (ctx->evp_method_store != NULL) { - ossl_method_store_free(ctx->evp_method_store); - ctx->evp_method_store = NULL; - } - /* Default priority. */ if (ctx->property_string_data != NULL) { ossl_property_string_data_free(ctx->property_string_data); diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c index 3d09b384aa..3293f70372 100644 --- a/crypto/core_fetch.c +++ b/crypto/core_fetch.c @@ -107,7 +107,7 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider, struct construct_data_st *data = cbdata; void *method = NULL; - if ((method = data->mcm->construct(algo, provider, data->mcm_data, no_store)) + if ((method = data->mcm->construct(algo, provider, data->mcm_data)) == NULL) return; diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 07b244cb35..7624574103 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -15,6 +15,13 @@ #if defined(_WIN32) && !defined(OPENSSL_SYS_UEFI) #include #include +#ifdef __WATCOMC__ +#if defined(_UNICODE) || defined(__UNICODE__) +#define _vsntprintf _vsnwprintf +#else +#define _vsntprintf _vsnprintf +#endif +#endif #ifdef _MSC_VER #define alloca _alloca #endif @@ -103,6 +110,8 @@ void OPENSSL_showfatal(const char *fmta, ...) /* * First check if it's a console application, in which case the * error message would be printed to standard error. + * Windows CE does not have a concept of a console application, + * so we need to guard the check. */ #ifdef STD_ERROR_HANDLE HANDLE h; @@ -251,7 +260,9 @@ void OPENSSL_die(const char *message, const char *file, int line) /* * Win32 abort() customarily shows a dialog, but we just did that... */ +#if !defined(_WIN32_WCE) raise(SIGABRT); +#endif _exit(3); #endif } diff --git a/crypto/ct/ct_oct.c b/crypto/ct/ct_oct.c index 4f5fd8d027..b8bef582a9 100644 --- a/crypto/ct/ct_oct.c +++ b/crypto/ct/ct_oct.c @@ -381,7 +381,7 @@ STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, return NULL; p = ASN1_STRING_get0_data(oct); - if ((sk = o2i_SCT_LIST(a, &p, ASN1_STRING_length_ex(oct))) != NULL) + if ((sk = o2i_SCT_LIST(a, &p, ASN1_STRING_length(oct))) != NULL) *pp += len; ASN1_OCTET_STRING_free(oct); diff --git a/crypto/ctype.c b/crypto/ctype.c index 75192b11f4..686fe64165 100644 --- a/crypto/ctype.c +++ b/crypto/ctype.c @@ -226,7 +226,7 @@ static const unsigned short ctype_char_map[128] = { #ifdef CHARSET_EBCDIC int ossl_toascii(int c) { - if (c < -128 || c >= 256 || c == EOF) + if (c < -128 || c > 256 || c == EOF) return c; /* * Adjust negatively signed characters. @@ -241,7 +241,7 @@ int ossl_toascii(int c) int ossl_fromascii(int c) { - if (c < -128 || c >= 256 || c == EOF) + if (c < -128 || c > 256 || c == EOF) return c; if (c < 0) c += 256; diff --git a/crypto/des/des_local.h b/crypto/des/des_local.h index fa368c359c..0fee059ec4 100644 --- a/crypto/des/des_local.h +++ b/crypto/des/des_local.h @@ -32,7 +32,7 @@ #define ROTATE(a, n) (_lrotr(a, n)) #elif defined(__ICC) #define ROTATE(a, n) (_rotr(a, n)) -#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) +#elif defined(__GNUC__) && __GNUC__ >= 2 && !defined(__STRICT_ANSI__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) #if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) #define ROTATE(a, n) ({ \ register unsigned int ret; \ diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 1934c71080..27ca94d1a6 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -142,7 +142,7 @@ int DH_up_ref(DH *r) { int i; - if (!CRYPTO_UP_REF(&r->references, &i)) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; REF_PRINT_COUNT("DH", i, r); diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 5936b84098..834d271346 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -215,7 +215,7 @@ int DSA_up_ref(DSA *r) { int i; - if (!CRYPTO_UP_REF(&r->references, &i)) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; REF_PRINT_COUNT("DSA", i, r); diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 1366bea66d..6f51e4d35a 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -93,7 +93,7 @@ int DSO_up_ref(DSO *dso) return 0; } - if (!CRYPTO_UP_REF(&dso->references, &i)) + if (CRYPTO_UP_REF(&dso->references, &i) <= 0) return 0; REF_PRINT_COUNT("DSO", i, dso); diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c index 6ac6727fda..78cc649324 100644 --- a/crypto/dso/dso_win32.c +++ b/crypto/dso/dso_win32.c @@ -12,6 +12,49 @@ #if defined(DSO_WIN32) +#ifdef _WIN32_WCE +#if _WIN32_WCE < 300 +static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName) +{ + WCHAR lpProcNameW[64]; + int i; + + for (i = 0; lpProcName[i] && i < 64; i++) + lpProcNameW[i] = (WCHAR)lpProcName[i]; + if (i == 64) + return NULL; + lpProcNameW[i] = 0; + + return GetProcAddressW(hModule, lpProcNameW); +} +#endif +#undef GetProcAddress +#define GetProcAddress GetProcAddressA + +static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName) +{ + WCHAR *fnamw; + size_t len_0 = strlen(lpLibFileName) + 1, i; + +#ifdef _MSC_VER + fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR)); +#else + fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); +#endif + if (fnamw == NULL) { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } +#if defined(_WIN32_WCE) && _WIN32_WCE >= 101 + if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0)) +#endif + for (i = 0; i < len_0; i++) + fnamw[i] = (WCHAR)lpLibFileName[i]; + + return LoadLibraryW(fnamw); +} +#endif + #define GETPROCADDRESS(h, name, type) ((type)(void (*)(void))GetProcAddress((h), (name))) /* Part of the hack in "win32_load" ... */ @@ -429,10 +472,14 @@ static const char *openssl_strnchr(const char *string, int c, size_t len) } #include +#ifdef _WIN32_WCE +#define DLLNAME "TOOLHELP.DLL" +#else #ifdef MODULEENTRY32 #undef MODULEENTRY32 /* unmask the ASCII version! */ #endif #define DLLNAME "KERNEL32.DLL" +#endif typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD); typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE); @@ -535,7 +582,11 @@ static void *win32_globallookup(const char *name) return NULL; } /* We take the rest for granted... */ +#ifdef _WIN32_WCE + close_snap = GETPROCADDRESS(dll, "CloseToolhelp32Snapshot", CLOSETOOLHELP32SNAPSHOT); +#else close_snap = (CLOSETOOLHELP32SNAPSHOT)CloseHandle; +#endif module_first = GETPROCADDRESS(dll, "Module32First", MODULE32); module_next = GETPROCADDRESS(dll, "Module32Next", MODULE32); diff --git a/crypto/ec/asm/ecp_sm2p256-riscv64.pl b/crypto/ec/asm/ecp_sm2p256-riscv64.pl index 40938e75c0..2a17e124dc 100644 --- a/crypto/ec/asm/ecp_sm2p256-riscv64.pl +++ b/crypto/ec/asm/ecp_sm2p256-riscv64.pl @@ -366,7 +366,7 @@ $code.=<<___; .type .Lord_div_2,\@object .Lord_div_2: .dword 0xa9ddfa049ceaa092,0xb901efb590e30295,0xffffffffffffffff,0x7fffffff7fffffff -.previous + // void bn_rshift1(BN_ULONG *a); .globl bn_rshift1 diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c index 53c8bff5ed..c6886763ab 100644 --- a/crypto/ec/curve25519.c +++ b/crypto/ec/curve25519.c @@ -236,13 +236,6 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32], fe64_sub(tmp1, x2, z2); fe64_add(x2, x2, z2); fe64_add(z2, x3, z3); - /* The original copy in x25519_scalar_mult_generic uses argument order - * fe_mul(z3, tmp0, x2), with the input arguments swapped. - * - * The assembly implementation of fe64_mul used here runs faster in - * parallel with its nearby instructions when an earlier-computable - * input (like tmp0) is passed as the 2nd input because it consumes - * the 2nd input at a faster rate than the 1st input. */ fe64_mul(z3, x2, tmp0); fe64_mul(z2, z2, tmp1); fe64_sqr(tmp0, tmp1); diff --git a/crypto/ec/curve448/curve448.c b/crypto/ec/curve448/curve448.c index 29edb317f1..1a31f86355 100644 --- a/crypto/ec/curve448/curve448.c +++ b/crypto/ec/curve448/curve448.c @@ -502,7 +502,7 @@ struct smvt_control { int power, addend; }; -#if defined(__GNUC__) +#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) #define NUMTRAILINGZEROS __builtin_ctz #else #define NUMTRAILINGZEROS numtrailingzeros diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c index 1c375413ab..8615b19dfc 100644 --- a/crypto/ec/curve448/eddsa.c +++ b/crypto/ec/curve448/eddsa.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -94,7 +94,6 @@ static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx, * * pubkey (out): The public key. * privkey (in): The private key. - * propq (in): The property query used to fetch SHAKE256. */ static c448_error_t c448_ed448_derive_public_key( @@ -156,7 +155,6 @@ c448_ed448_derive_public_key( * you want to sign. * context (in): A "context" for this signature of up to 255 bytes. * context_len (in): Length of the context. - * propq (in): The property query used to fetch SHAKE256. * * For Ed25519, it is unsafe to use the same key for both prehashed and * non-prehashed messages, at least without some very careful protocol-level @@ -294,7 +292,6 @@ c448_ed448_pubkey_verify(const uint8_t *pub, size_t pub_len) * want to verify. * context (in): A "context" for this signature of up to 255 bytes. * context_len (in): Length of the context. - * propq (in): The property query used to fetch SHAKE256. * * For Ed25519, it is unsafe to use the same key for both prehashed and * non-prehashed messages, at least without some very careful protocol-level diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index 835f759935..b839e9d2a2 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -966,10 +966,9 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) if (priv_key->privateKey) { ASN1_OCTET_STRING *pkey = priv_key->privateKey; - size_t pkey_len = ASN1_STRING_length_ex(pkey); - if (pkey_len > INT_MAX) - goto err; - if (EC_KEY_oct2priv(ret, ASN1_STRING_get0_data(pkey), (int)pkey_len) == 0) + if (EC_KEY_oct2priv(ret, ASN1_STRING_get0_data(pkey), + ASN1_STRING_length(pkey)) + == 0) goto err; } else { ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); @@ -988,13 +987,11 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) if (priv_key->publicKey) { const unsigned char *pub_oct; - size_t pub_oct_len; + int pub_oct_len; pub_oct = ASN1_STRING_get0_data(priv_key->publicKey); - pub_oct_len = ASN1_STRING_length_ex(priv_key->publicKey); - if (pub_oct_len > INT_MAX) - goto err; - if (!EC_KEY_oct2key(ret, pub_oct, (int)pub_oct_len, NULL)) { + pub_oct_len = ASN1_STRING_length(priv_key->publicKey); + if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) { ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1066,7 +1063,7 @@ int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out) goto err; } - publen = EC_KEY_key2buf(a, EC_KEY_get_conv_form(a), &pub, NULL); + publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL); if (publen == 0 || publen > INT_MAX) { ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); @@ -1087,7 +1084,7 @@ err: OPENSSL_clear_free(priv, privlen); OPENSSL_free(pub); EC_PRIVATEKEY_free(priv_key); - return ok ? ret : 0; + return (ok ? ret : 0); } int i2d_ECParameters(const EC_KEY *a, unsigned char **out) @@ -1167,7 +1164,7 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) } buf_len = EC_POINT_point2oct(a->group, a->pub_key, - EC_KEY_get_conv_form(a), NULL, 0, NULL); + a->conv_form, NULL, 0, NULL); if (buf_len > INT_MAX) { ERR_raise(ERR_LIB_EC, ERR_R_PASSED_INVALID_ARGUMENT); @@ -1182,7 +1179,7 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) return 0; new_buffer = 1; } - if (!EC_POINT_point2oct(a->group, a->pub_key, EC_KEY_get_conv_form(a), + if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, *out, buf_len, NULL)) { ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); if (new_buffer) { diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c index 764ab7558b..0d1de52dbb 100644 --- a/crypto/ec/ec_backend.c +++ b/crypto/ec/ec_backend.c @@ -655,6 +655,7 @@ EC_KEY *ossl_ec_key_dup(const EC_KEY *src, int selection) /* copy the rest */ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) { ret->enc_flag = src->enc_flag; + ret->conv_form = src->conv_form; } ret->version = src->version; diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 4a84933bb6..8deaa3b930 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -146,6 +146,7 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) /* copy the rest */ dest->enc_flag = src->enc_flag; + dest->conv_form = src->conv_form; dest->version = src->version; dest->flags = src->flags; #ifndef FIPS_MODULE @@ -175,7 +176,7 @@ int EC_KEY_up_ref(EC_KEY *r) { int i; - if (!CRYPTO_UP_REF(&r->references, &i)) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; REF_PRINT_COUNT("EC_KEY", i, r); @@ -213,6 +214,56 @@ int ossl_ec_key_gen(EC_KEY *eckey) return ret; } +/* + * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1 + * Perform a KAT by duplicating the public key generation. + * + * NOTE: This issue requires a background understanding, provided in a separate + * document; the current IG 10.3.A AC1 is insufficient regarding the PCT for + * the key agreement scenario. + * + * Currently IG 10.3.A requires PCT in the mode of use prior to use of the + * key pair, citing the PCT defined in the associated standard. For key + * agreement, the only PCT defined in SP 800-56A is that of Section 5.6.2.4: + * the comparison of the original public key to a newly calculated public key. + */ +static int ecdsa_keygen_knownanswer_test(EC_KEY *eckey, BN_CTX *ctx, + OSSL_CALLBACK *cb, void *cbarg) +{ + int len, ret = 0; + OSSL_SELF_TEST *st = NULL; + unsigned char bytes[512] = { 0 }; + EC_POINT *pub_key2 = NULL; + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + return 0; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT_KAT, + OSSL_SELF_TEST_DESC_PCT_ECDSA); + + if ((pub_key2 = EC_POINT_new(eckey->group)) == NULL) + goto err; + + /* pub_key = priv_key * G (where G is a point on the curve) */ + if (!EC_POINT_mul(eckey->group, pub_key2, eckey->priv_key, NULL, NULL, ctx)) + goto err; + + if (BN_num_bytes(pub_key2->X) > (int)sizeof(bytes)) + goto err; + len = BN_bn2bin(pub_key2->X, bytes); + if (OSSL_SELF_TEST_oncorrupt_byte(st, bytes) + && BN_bin2bn(bytes, len, pub_key2->X) == NULL) + goto err; + ret = !EC_POINT_cmp(eckey->group, eckey->pub_key, pub_key2, ctx); + +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + EC_POINT_free(pub_key2); + return ret; +} + /* * ECC Key generation. * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates" @@ -309,7 +360,8 @@ static int ec_generate_key(EC_KEY *eckey, int pairwise_test) void *cbarg = NULL; OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg); - ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg); + ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg) + && ecdsa_keygen_knownanswer_test(eckey, ctx, cb, cbarg); } err: /* Step (9): If there is an error return an invalid keypair. */ @@ -831,13 +883,12 @@ void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) { - return key->group != NULL - ? EC_GROUP_get_point_conversion_form(key->group) - : POINT_CONVERSION_UNCOMPRESSED; + return key->conv_form; } void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) { + key->conv_form = cform; if (key->group != NULL) EC_GROUP_set_point_conversion_form(key->group, cform); } @@ -908,10 +959,8 @@ int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, * EC_POINT_oct2point() has already performed sanity checking of * the buffer so we know it is valid. */ - if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { - EC_GROUP_set_point_conversion_form(key->group, - (point_conversion_form_t)(buf[0] & ~0x01)); - } + if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) + key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01); return 1; } diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c index b27a40519d..b98bdd578e 100644 --- a/crypto/ec/ec_kmeth.c +++ b/crypto/ec/ec_kmeth.c @@ -90,6 +90,7 @@ EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq) ret->meth = EC_KEY_get_default_method(); ret->version = 1; + ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; /* No ex_data inside the FIPS provider */ #ifndef FIPS_MODULE diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h index 0be3c5529e..16adfbb92f 100644 --- a/crypto/ec/ec_local.h +++ b/crypto/ec/ec_local.h @@ -301,6 +301,7 @@ struct ec_key_st { EC_POINT *pub_key; BIGNUM *priv_key; unsigned int enc_flag; + point_conversion_form_t conv_form; CRYPTO_REF_COUNT references; int flags; #ifndef FIPS_MODULE diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index f5c6ac7893..4771789151 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -72,8 +72,8 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre) { int i; - if (pre == NULL || !CRYPTO_UP_REF(&pre->references, &i)) - return NULL; + if (pre != NULL) + CRYPTO_UP_REF(&pre->references, &i); return pre; } diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c index 1a0952083c..7183131622 100644 --- a/crypto/ec/ecp_nistp224.c +++ b/crypto/ec/ecp_nistp224.c @@ -1234,8 +1234,8 @@ static NISTP224_PRE_COMP *nistp224_pre_comp_new(void) NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *p) { int i; - if (p == NULL || !CRYPTO_UP_REF(&p->references, &i)) - return NULL; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i); return p; } diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c index fba197a8c7..e247e51c9c 100644 --- a/crypto/ec/ecp_nistp256.c +++ b/crypto/ec/ecp_nistp256.c @@ -1852,8 +1852,8 @@ static NISTP256_PRE_COMP *nistp256_pre_comp_new(void) NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *p) { int i; - if (p == NULL || !CRYPTO_UP_REF(&p->references, &i)) - return NULL; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i); return p; } diff --git a/crypto/ec/ecp_nistp384.c b/crypto/ec/ecp_nistp384.c index 3d212dcc15..e03bda2178 100644 --- a/crypto/ec/ecp_nistp384.c +++ b/crypto/ec/ecp_nistp384.c @@ -1576,8 +1576,8 @@ NISTP384_PRE_COMP *ossl_ec_nistp384_pre_comp_dup(NISTP384_PRE_COMP *p) { int i; - if (p == NULL || !CRYPTO_UP_REF(&p->references, &i)) - return NULL; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i); return p; } diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c index f7315f136c..7ea8d00c14 100644 --- a/crypto/ec/ecp_nistp521.c +++ b/crypto/ec/ecp_nistp521.c @@ -1667,8 +1667,8 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *p) { int i; - if (p == NULL || !CRYPTO_UP_REF(&p->references, &i)) - return NULL; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i); return p; } diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c index df467b948f..301f90188a 100644 --- a/crypto/ec/ecp_nistz256.c +++ b/crypto/ec/ecp_nistz256.c @@ -1208,8 +1208,8 @@ static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group) NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *p) { int i; - if (p == NULL || !CRYPTO_UP_REF(&p->references, &i)) - return NULL; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i); return p; } diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c index d95e8bb084..710ad31a66 100644 --- a/crypto/ec/ecx_backend.c +++ b/crypto/ec/ecx_backend.c @@ -230,19 +230,15 @@ ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, const X509_ALGOR *palg; if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) - goto err; + return 0; oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); if (oct == NULL) { p = NULL; plen = 0; } else { - size_t tmp; p = ASN1_STRING_get0_data(oct); - tmp = ASN1_STRING_length_ex(oct); - if (tmp > INT_MAX) - goto err; - plen = (int)tmp; + plen = ASN1_STRING_length(oct); } /* @@ -251,7 +247,6 @@ ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, */ ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE, libctx, propq); -err: ASN1_OCTET_STRING_free(oct); return ecx; } diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c index 036e308e8b..4d8c945755 100644 --- a/crypto/ec/ecx_key.c +++ b/crypto/ec/ecx_key.c @@ -92,7 +92,7 @@ int ossl_ecx_key_up_ref(ECX_KEY *key) { int i; - if (!CRYPTO_UP_REF(&key->references, &i)) + if (CRYPTO_UP_REF(&key->references, &i) <= 0) return 0; REF_PRINT_COUNT("ECX_KEY", i, key); diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c index 632d20c996..4d460af1c2 100644 --- a/crypto/encode_decode/decoder_meth.c +++ b/crypto/encode_decode/decoder_meth.c @@ -26,7 +26,39 @@ static void ossl_decoder_free(void *data) { - OSSL_DECODER *decoder = (OSSL_DECODER *)data; + OSSL_DECODER_free(data); +} + +static int ossl_decoder_up_ref(void *data) +{ + return OSSL_DECODER_up_ref(data); +} + +/* Simple method structure constructor and destructor */ +static OSSL_DECODER *ossl_decoder_new(void) +{ + OSSL_DECODER *decoder = NULL; + + if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&decoder->base.refcnt, 1)) { + OSSL_DECODER_free(decoder); + return NULL; + } + + return decoder; +} + +int OSSL_DECODER_up_ref(OSSL_DECODER *decoder) +{ + int ref = 0; + + CRYPTO_UP_REF(&decoder->base.refcnt, &ref); + return 1; +} + +void OSSL_DECODER_free(OSSL_DECODER *decoder) +{ int ref = 0; if (decoder == NULL) @@ -42,58 +74,6 @@ static void ossl_decoder_free(void *data) OPENSSL_free(decoder); } -static int ossl_decoder_up_ref(void *data) -{ - OSSL_DECODER *decoder = (OSSL_DECODER *)data; - int ref = 0; - - return CRYPTO_UP_REF(&decoder->base.refcnt, &ref); -} - -/* Simple method structure constructor and destructor */ -static OSSL_DECODER *ossl_decoder_new(void) -{ - OSSL_DECODER *decoder = NULL; - - if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL) - return NULL; - if (!CRYPTO_NEW_REF(&decoder->base.refcnt, 1)) { - ossl_decoder_free(decoder); - return NULL; - } - - return decoder; -} - -int OSSL_DECODER_up_ref(OSSL_DECODER *decoder) -{ -#ifdef OPENSSL_NO_CACHED_FETCH - return ossl_decoder_up_ref(decoder); -#else - /* - * DECODERS do something weird. They manually build methods rather than - * attempt to fetch them from the method store or construct them through - * the ossl_generic_fetch mechanism. As such they don't make use of the refcounting - * that we rely on in the method store, and so we always need to refcount them here - * We can identify them based on the fact that they never have a registered nid (i.e. - * its always zero) - */ - if (decoder->base.id == 0 || decoder->base.no_store != 0) - return ossl_decoder_up_ref(decoder); - return 1; -#endif -} - -void OSSL_DECODER_free(OSSL_DECODER *decoder) -{ -#ifdef OPENSSL_NO_CACHED_FETCH - ossl_decoder_free(decoder); -#else - if (decoder != NULL && (decoder->base.id == 0 || decoder->base.no_store != 0)) - ossl_decoder_free(decoder); -#endif -} - /* Data to be passed through ossl_method_construct() */ struct decoder_data_st { OSSL_LIB_CTX *libctx; @@ -227,7 +207,7 @@ static int put_decoder_in_store(void *store, void *method, /* Create and populate a decoder method */ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { OSSL_DECODER *decoder = NULL; const OSSL_DISPATCH *fns = algodef->implementation; @@ -236,16 +216,15 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, if ((decoder = ossl_decoder_new()) == NULL) return NULL; decoder->base.id = id; - decoder->base.no_store = no_store; if ((decoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - ossl_decoder_free(decoder); + OSSL_DECODER_free(decoder); return NULL; } decoder->base.algodef = algodef; if ((decoder->base.parsed_propdef = ossl_parse_property(libctx, algodef->property_definition)) == NULL) { - ossl_decoder_free(decoder); + OSSL_DECODER_free(decoder); return NULL; } @@ -297,13 +276,13 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, if (!((decoder->newctx == NULL && decoder->freectx == NULL) || (decoder->newctx != NULL && decoder->freectx != NULL)) || decoder->decode == NULL) { - ossl_decoder_free(decoder); + OSSL_DECODER_free(decoder); ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); return NULL; } if (prov != NULL && !ossl_provider_up_ref(prov)) { - ossl_decoder_free(decoder); + OSSL_DECODER_free(decoder); return NULL; } @@ -317,7 +296,7 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, * then call ossl_decoder_from_algorithm() with that identity number. */ static void *construct_decoder(const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, void *data, int no_store) + OSSL_PROVIDER *prov, void *data) { /* * This function is only called if get_decoder_from_store() returned @@ -333,7 +312,7 @@ static void *construct_decoder(const OSSL_ALGORITHM *algodef, void *method = NULL; if (id != 0) - method = ossl_decoder_from_algorithm(id, algodef, prov, no_store); + method = ossl_decoder_from_algorithm(id, algodef, prov); /* * Flag to indicate that there was actual construction errors. This @@ -349,7 +328,17 @@ static void *construct_decoder(const OSSL_ALGORITHM *algodef, /* Intermediary function to avoid ugly casts, used below */ static void destruct_decoder(void *method, void *data) { - ossl_decoder_free(method); + OSSL_DECODER_free(method); +} + +static int up_ref_decoder(void *method) +{ + return OSSL_DECODER_up_ref(method); +} + +static void free_decoder(void *method) +{ + OSSL_DECODER_free(method); } /* Fetching support. Can fetch by numeric identity or by name */ @@ -405,22 +394,9 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, */ if (id == 0 && name != NULL) id = ossl_namemap_name2num(namemap, name); - if (id != 0 && methdata->tmp_store == NULL) { + if (id != 0) ossl_method_store_cache_set(store, prov, id, propq, method, - ossl_decoder_up_ref, ossl_decoder_free); - } else { - /* - * Like with EVP methods, if the provider requests no caching we need - * to take an extra refcount here so that the tmp_stored decoder - * lives beyond the freeing of that tmp_store - */ -#ifndef OPENSSL_NO_CACHED_FETCH - if (!OSSL_DECODER_up_ref((OSSL_DECODER *)method)) { - ossl_decoder_free(method); - method = NULL; - } -#endif - } + up_ref_decoder, free_decoder); } /* diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h index 6ebbe1c513..789212746b 100644 --- a/crypto/encode_decode/encoder_local.h +++ b/crypto/encode_decode/encoder_local.h @@ -24,7 +24,6 @@ struct ossl_endecode_base_st { OSSL_PROVIDER *prov; int id; - int no_store; char *name; const OSSL_ALGORITHM *algodef; OSSL_PROPERTY_LIST *parsed_propdef; diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c index cb167004ab..74ba83fc3d 100644 --- a/crypto/encode_decode/encoder_meth.c +++ b/crypto/encode_decode/encoder_meth.c @@ -27,28 +27,12 @@ static void ossl_encoder_free(void *data) { - OSSL_ENCODER *encoder = (OSSL_ENCODER *)data; - int ref = 0; - - if (encoder == NULL) - return; - - CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref); - if (ref > 0) - return; - OPENSSL_free(encoder->base.name); - ossl_property_free(encoder->base.parsed_propdef); - ossl_provider_free(encoder->base.prov); - CRYPTO_FREE_REF(&encoder->base.refcnt); - OPENSSL_free(encoder); + OSSL_ENCODER_free(data); } static int ossl_encoder_up_ref(void *data) { - OSSL_ENCODER *encoder = (OSSL_ENCODER *)data; - int ref = 0; - - return CRYPTO_UP_REF(&encoder->base.refcnt, &ref); + return OSSL_ENCODER_up_ref(data); } /* Simple method structure constructor and destructor */ @@ -68,23 +52,27 @@ static OSSL_ENCODER *ossl_encoder_new(void) int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder) { -#ifdef OPENSSL_NO_CACHED_FETCH - return ossl_encoder_up_ref(encoder); -#else - if (encoder->base.no_store != 0) - return ossl_encoder_up_ref(encoder); + int ref = 0; + + CRYPTO_UP_REF(&encoder->base.refcnt, &ref); return 1; -#endif } void OSSL_ENCODER_free(OSSL_ENCODER *encoder) { -#ifdef OPENSSL_NO_CACHED_FETCH - ossl_encoder_free(encoder); -#else - if (encoder != NULL && (encoder->base.no_store != 0)) - ossl_encoder_free(encoder); -#endif + int ref = 0; + + if (encoder == NULL) + return; + + CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref); + if (ref > 0) + return; + OPENSSL_free(encoder->base.name); + ossl_property_free(encoder->base.parsed_propdef); + ossl_provider_free(encoder->base.prov); + CRYPTO_FREE_REF(&encoder->base.refcnt); + OPENSSL_free(encoder); } /* Data to be passed through ossl_method_construct() */ @@ -220,7 +208,7 @@ static int put_encoder_in_store(void *store, void *method, /* Create and populate a encoder method */ static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { OSSL_ENCODER *encoder = NULL; const OSSL_DISPATCH *fns = algodef->implementation; @@ -229,16 +217,15 @@ static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, if ((encoder = ossl_encoder_new()) == NULL) return NULL; encoder->base.id = id; - encoder->base.no_store = no_store; if ((encoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - ossl_encoder_free(encoder); + OSSL_ENCODER_free(encoder); return NULL; } encoder->base.algodef = algodef; if ((encoder->base.parsed_propdef = ossl_parse_property(libctx, algodef->property_definition)) == NULL) { - ossl_encoder_free(encoder); + OSSL_ENCODER_free(encoder); return NULL; } @@ -296,13 +283,13 @@ static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, || (encoder->import_object != NULL && encoder->free_object != NULL) || (encoder->import_object == NULL && encoder->free_object == NULL)) || encoder->encode == NULL) { - ossl_encoder_free(encoder); + OSSL_ENCODER_free(encoder); ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); return NULL; } if (prov != NULL && !ossl_provider_up_ref(prov)) { - ossl_encoder_free(encoder); + OSSL_ENCODER_free(encoder); return NULL; } @@ -316,7 +303,7 @@ static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, * then call encoder_from_algorithm() with that identity number. */ static void *construct_encoder(const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, void *data, int no_store) + OSSL_PROVIDER *prov, void *data) { /* * This function is only called if get_encoder_from_store() returned @@ -332,7 +319,7 @@ static void *construct_encoder(const OSSL_ALGORITHM *algodef, void *method = NULL; if (id != 0) - method = encoder_from_algorithm(id, algodef, prov, no_store); + method = encoder_from_algorithm(id, algodef, prov); /* * Flag to indicate that there was actual construction errors. This @@ -348,7 +335,17 @@ static void *construct_encoder(const OSSL_ALGORITHM *algodef, /* Intermediary function to avoid ugly casts, used below */ static void destruct_encoder(void *method, void *data) { - ossl_encoder_free(method); + OSSL_ENCODER_free(method); +} + +static int up_ref_encoder(void *method) +{ + return OSSL_ENCODER_up_ref(method); +} + +static void free_encoder(void *method) +{ + OSSL_ENCODER_free(method); } /* Fetching support. Can fetch by numeric identity or by name */ @@ -404,19 +401,8 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, */ if (id == 0) id = ossl_namemap_name2num(namemap, name); - if (id != 0 && methdata->tmp_store == NULL) { - ossl_method_store_cache_set(store, prov, id, propq, method, - ossl_encoder_up_ref, ossl_encoder_free); - } else { - /* - * Like with EVP methods, if the provider requests no caching we need - * to take an extra refcount here so that the tmp_stored encoder - * lives beyond the freeing of that tmp_store - */ -#ifndef OPENSSL_NO_CACHED_FETCH - OSSL_ENCODER_up_ref((OSSL_ENCODER *)method); -#endif - } + ossl_method_store_cache_set(store, prov, id, propq, method, + up_ref_encoder, free_encoder); } /* diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index 7761410f2d..e614f4229d 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -13,6 +13,7 @@ #include "crypto/cryptoerr.h" #include "crypto/asn1err.h" #include "crypto/bnerr.h" +#include "crypto/fnerr.h" #include "crypto/ecerr.h" #include "crypto/buffererr.h" #include "crypto/bioerr.h" @@ -51,6 +52,7 @@ int ossl_err_load_crypto_strings(void) #ifndef OPENSSL_NO_ERR || ossl_err_load_ERR_strings() == 0 /* include error strings for SYSerr */ || ossl_err_load_BN_strings() == 0 + || ossl_err_load_OSSL_FN_strings() == 0 || ossl_err_load_RSA_strings() == 0 #ifndef OPENSSL_NO_DH || ossl_err_load_DH_strings() == 0 diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index 91aa11d1a6..ca1fae106f 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -43,6 +43,7 @@ L PROV include/openssl/proverr.h providers/common/provider_err.c L OSSL_ENCODER include/openssl/encodererr.h crypto/encode_decode/encoder_err.c include/crypto/encodererr.h L OSSL_DECODER include/openssl/decodererr.h crypto/encode_decode/decoder_err.c include/crypto/decodererr.h L HTTP include/openssl/httperr.h crypto/http/http_err.c include/crypto/httperr.h +L OSSL_FN NONE crypto/fn/fn_err.c include/crypto/fnerr.h # SSL/TLS alerts R SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE 1010 diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 8b6c912977..95d968db1f 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -888,6 +888,13 @@ OSSL_ENCODER_R_ENCODER_NOT_FOUND:101:encoder not found OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query OSSL_ENCODER_R_MISSING_GET_PARAMS:102:missing get params OSSL_ENCODER_R_UNKNOWN_PARAMETER_NAME:104:unknown parameter name +OSSL_FN_R_DIV_BY_ZERO:101:div by zero +OSSL_FN_R_INPUT_NOT_REDUCED:103:input not reduced +OSSL_FN_R_BITS_TOO_SMALL:105:bits too small +OSSL_FN_R_INVALID_RANGE:106:invalid range +OSSL_FN_R_INVALID_SHIFT:102:invalid shift +OSSL_FN_R_RESULT_ARG_TOO_SMALL:100:result arg too small +OSSL_FN_R_TOO_MANY_ITERATIONS:107:too many iterations OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac @@ -1106,7 +1113,6 @@ PROV_R_INVALID_THREAD_POOL_SIZE:234:invalid thread pool size PROV_R_INVALID_UKM_LENGTH:200:invalid ukm length PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest PROV_R_IN_ERROR_STATE:192:in error state -PROV_R_KEY_IMMUTABLE_ONCE_SET:266:key immutable once set PROV_R_KEY_SETUP_FAILED:101:key setup failed PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small PROV_R_LENGTH_TOO_LARGE:202:length too large @@ -1645,24 +1651,25 @@ SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE:1113:\ SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE:1111:tlsv1 certificate unobtainable SSL_R_TLSV1_UNRECOGNIZED_NAME:1112:tlsv1 unrecognized name SSL_R_TLSV1_UNSUPPORTED_EXTENSION:1110:tlsv1 unsupported extension -SSL_R_TLS_ALERT_BAD_CERTIFICATE:1042:tls alert bad certificate -SSL_R_TLS_ALERT_BAD_RECORD_MAC:1020:tls alert bad record mac -SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED:1045:tls alert certificate expired -SSL_R_TLS_ALERT_CERTIFICATE_REVOKED:1044:tls alert certificate revoked -SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN:1046:tls alert certificate unknown -SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE:1030:tls alert decompression failure -SSL_R_TLS_ALERT_HANDSHAKE_FAILURE:1040:tls alert handshake failure -SSL_R_TLS_ALERT_ILLEGAL_PARAMETER:1047:tls alert illegal parameter -SSL_R_TLS_ALERT_NO_CERTIFICATE:1041:tls alert no certificate -SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE:1010:tls alert unexpected message -SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE:1043:tls alert unsupported certificate +SSL_R_TLS_ALERT_BAD_CERTIFICATE:1042:ssl/tls alert bad certificate +SSL_R_TLS_ALERT_BAD_RECORD_MAC:1020:ssl/tls alert bad record mac +SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED:1045:ssl/tls alert certificate expired +SSL_R_TLS_ALERT_CERTIFICATE_REVOKED:1044:ssl/tls alert certificate revoked +SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN:1046:ssl/tls alert certificate unknown +SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE:1030:ssl/tls alert decompression failure +SSL_R_TLS_ALERT_HANDSHAKE_FAILURE:1040:ssl/tls alert handshake failure +SSL_R_TLS_ALERT_ILLEGAL_PARAMETER:1047:ssl/tls alert illegal parameter +SSL_R_TLS_ALERT_NO_CERTIFICATE:1041:ssl/tls alert no certificate +SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE:1010:ssl/tls alert unexpected message +SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE:1043:\ + ssl/tls alert unsupported certificate SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH:232:\ - tls ext invalid max fragment length -SSL_R_TLS_EXT_INVALID_SERVERNAME:319:tls ext invalid servername -SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE:320:tls ext invalid servername type + ssl3 ext invalid max fragment length +SSL_R_TLS_EXT_INVALID_SERVERNAME:319:ssl3 ext invalid servername +SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE:320:ssl3 ext invalid servername type SSL_R_TLS_ILLEGAL_EXPORTER_LABEL:367:tls illegal exporter label SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST:157:tls invalid ecpointformat list -SSL_R_TLS_SESSION_ID_TOO_LONG:300:tls session id too long +SSL_R_TLS_SESSION_ID_TOO_LONG:300:ssl3 session id too long SSL_R_TOO_MANY_KEY_UPDATES:132:too many key updates SSL_R_TOO_MANY_WARN_ALERTS:409:too many warn alerts SSL_R_TOO_MUCH_EARLY_DATA:164:too much early data diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c index ec643bec9e..e31e601c63 100644 --- a/crypto/evp/asymcipher.c +++ b/crypto/evp/asymcipher.c @@ -19,26 +19,12 @@ static void evp_asym_cipher_free(void *data) { - EVP_ASYM_CIPHER *cipher = (EVP_ASYM_CIPHER *)data; - int i; - - if (cipher == NULL) - return; - CRYPTO_DOWN_REF(&cipher->refcnt, &i); - if (i > 0) - return; - OPENSSL_free(cipher->type_name); - ossl_provider_free(cipher->prov); - CRYPTO_FREE_REF(&cipher->refcnt); - OPENSSL_free(cipher); + EVP_ASYM_CIPHER_free(data); } static int evp_asym_cipher_up_ref(void *data) { - EVP_ASYM_CIPHER *cipher = (EVP_ASYM_CIPHER *)data; - int ref = 0; - - return CRYPTO_UP_REF(&cipher->refcnt, &ref); + return EVP_ASYM_CIPHER_up_ref(data); } static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, @@ -341,7 +327,7 @@ static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov) static void *evp_asym_cipher_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_ASYM_CIPHER *cipher = NULL; @@ -354,7 +340,6 @@ static void *evp_asym_cipher_from_algorithm(int name_id, } cipher->name_id = name_id; - cipher->no_store = no_store; if ((cipher->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) goto err; cipher->description = algodef->algorithm_description; @@ -453,29 +438,31 @@ static void *evp_asym_cipher_from_algorithm(int name_id, return cipher; err: - evp_asym_cipher_free(cipher); + EVP_ASYM_CIPHER_free(cipher); return NULL; } void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_asym_cipher_free(cipher); -#else - if (cipher != NULL && (cipher->no_store != 0)) - evp_asym_cipher_free(cipher); -#endif + int i; + + if (cipher == NULL) + return; + CRYPTO_DOWN_REF(&cipher->refcnt, &i); + if (i > 0) + return; + OPENSSL_free(cipher->type_name); + ossl_provider_free(cipher->prov); + CRYPTO_FREE_REF(&cipher->refcnt); + OPENSSL_free(cipher); } int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_asym_cipher_up_ref(cipher); -#else - if (cipher->no_store != 0) - return evp_asym_cipher_up_ref(cipher); + int ref = 0; + + CRYPTO_UP_REF(&cipher->refcnt, &ref); return 1; -#endif } OSSL_PROVIDER *EVP_ASYM_CIPHER_get0_provider(const EVP_ASYM_CIPHER *cipher) diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index db7121f0a4..b6c01daeee 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -23,8 +23,6 @@ #include -static void evp_md_free(void *m); - void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force, int keep_fetched) { if (ctx->algctx != NULL) { @@ -494,8 +492,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) return 0; } - if (out->digest == in->digest && in->digest->copyctx != NULL - && out->algctx != NULL && in->algctx != NULL) { + if (out->digest == in->digest && in->digest->copyctx != NULL) { in->digest->copyctx(out->algctx, in->algctx); @@ -832,7 +829,7 @@ static int evp_md_cache_constants(EVP_MD *md) static void *evp_md_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_MD *md = NULL; @@ -844,9 +841,6 @@ static void *evp_md_from_algorithm(int name_id, return NULL; } - if (no_store != 0) - md->flags |= EVP_MD_FLAG_NO_STORE; - #ifndef FIPS_MODULE md->type = NID_undef; if (!evp_names_do_all(prov, name_id, set_legacy_nid, &md->type) @@ -971,36 +965,18 @@ static void *evp_md_from_algorithm(int name_id, return md; err: - evp_md_free(md); + EVP_MD_free(md); return NULL; } -static int evp_md_up_ref(void *m) +static int evp_md_up_ref(void *md) { - EVP_MD *md = (EVP_MD *)m; - int ref = 0; - - if (md->origin == EVP_ORIG_DYNAMIC) - return CRYPTO_UP_REF(&md->refcnt, &ref); - return 1; + return EVP_MD_up_ref(md); } -static void evp_md_free(void *m) +static void evp_md_free(void *md) { - EVP_MD *md = (EVP_MD *)m; - int i; - - if (md == NULL || md->origin != EVP_ORIG_DYNAMIC) - return; - - CRYPTO_DOWN_REF(&md->refcnt, &i); - if (i > 0) - return; - - OPENSSL_free(md->type_name); - ossl_provider_free(md->prov); - CRYPTO_FREE_REF(&md->refcnt); - OPENSSL_free(md); + EVP_MD_free(md); } EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, @@ -1014,24 +990,28 @@ EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, int EVP_MD_up_ref(EVP_MD *md) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_md_up_ref(md); -#else - if (md->flags & EVP_MD_FLAG_NO_STORE) - return evp_md_up_ref(md); + int ref = 0; + + if (md->origin == EVP_ORIG_DYNAMIC) + CRYPTO_UP_REF(&md->refcnt, &ref); return 1; -#endif } void EVP_MD_free(EVP_MD *md) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_md_free(md); -#else - if (md != NULL && (md->flags & EVP_MD_FLAG_NO_STORE)) - evp_md_free(md); - return; -#endif + int i; + + if (md == NULL || md->origin != EVP_ORIG_DYNAMIC) + return; + + CRYPTO_DOWN_REF(&md->refcnt, &i); + if (i > 0) + return; + + OPENSSL_free(md->type_name); + ossl_provider_free(md->prov); + CRYPTO_FREE_REF(&md->refcnt); + OPENSSL_free(md); } void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx, diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c index 78dbe45ce4..628f89bbdc 100644 --- a/crypto/evp/e_chacha20_poly1305.c +++ b/crypto/evp/e_chacha20_poly1305.c @@ -41,7 +41,7 @@ static const EVP_CIPHER chacha20_poly1305 = { const EVP_CIPHER *EVP_chacha20_poly1305(void) { - return &chacha20_poly1305; + return (&chacha20_poly1305); } #endif #else diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index a5c513db0d..a23846fdf1 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -1340,33 +1340,9 @@ static void set_legacy_nid(const char *name, void *vlegacy_nid) } #endif -static int evp_cipher_up_ref(void *c) -{ - EVP_CIPHER *cipher = (EVP_CIPHER *)c; - int ref = 0; - - if (cipher->origin == EVP_ORIG_DYNAMIC) - return CRYPTO_UP_REF(&cipher->refcnt, &ref); - return 1; -} - -static void evp_cipher_free(void *c) -{ - EVP_CIPHER *cipher = (EVP_CIPHER *)c; - int i; - - if (cipher == NULL || cipher->origin != EVP_ORIG_DYNAMIC) - return; - - CRYPTO_DOWN_REF(&cipher->refcnt, &i); - if (i > 0) - return; - evp_cipher_free_int(cipher); -} - static void *evp_cipher_from_algorithm(const int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_CIPHER *cipher = NULL; @@ -1377,9 +1353,6 @@ static void *evp_cipher_from_algorithm(const int name_id, return NULL; } - if (no_store != 0) - cipher->flags |= EVP_CIPH_FLAG_NO_STORE; - #ifndef FIPS_MODULE cipher->nid = NID_undef; if (!evp_names_do_all(prov, name_id, set_legacy_nid, &cipher->nid) @@ -1538,10 +1511,20 @@ static void *evp_cipher_from_algorithm(const int name_id, return cipher; err: - evp_cipher_free(cipher); + EVP_CIPHER_free(cipher); return NULL; } +static int evp_cipher_up_ref(void *cipher) +{ + return EVP_CIPHER_up_ref(cipher); +} + +static void evp_cipher_free(void *cipher) +{ + EVP_CIPHER_free(cipher); +} + EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties) { @@ -1574,13 +1557,11 @@ int EVP_CIPHER_can_pipeline(const EVP_CIPHER *cipher, int enc) int EVP_CIPHER_up_ref(EVP_CIPHER *cipher) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_cipher_up_ref(cipher); -#else - if (cipher->flags & EVP_CIPH_FLAG_NO_STORE) - return evp_cipher_up_ref(cipher); + int ref = 0; + + if (cipher->origin == EVP_ORIG_DYNAMIC) + CRYPTO_UP_REF(&cipher->refcnt, &ref); return 1; -#endif } void evp_cipher_free_int(EVP_CIPHER *cipher) @@ -1593,12 +1574,15 @@ void evp_cipher_free_int(EVP_CIPHER *cipher) void EVP_CIPHER_free(EVP_CIPHER *cipher) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_cipher_free(cipher); -#else - if (cipher != NULL && (cipher->flags & EVP_CIPH_FLAG_NO_STORE)) - evp_cipher_free(cipher); -#endif + int i; + + if (cipher == NULL || cipher->origin != EVP_ORIG_DYNAMIC) + return; + + CRYPTO_DOWN_REF(&cipher->refcnt, &i); + if (i > 0) + return; + evp_cipher_free_int(cipher); } void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx, diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 15204628db..a446f976df 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "internal/cryptlib.h" #include "internal/thread_once.h" #include "internal/property.h" @@ -37,7 +36,7 @@ struct evp_method_data_st { unsigned int flag_construct_error_occurred : 1; void *(*method_from_algorithm)(int name_id, const OSSL_ALGORITHM *, - OSSL_PROVIDER *, int); + OSSL_PROVIDER *); int (*refcnt_up_method)(void *method); void (*destruct_method)(void *method); }; @@ -209,7 +208,7 @@ static int put_evp_method_in_store(void *store, void *method, * This function is responsible to getting an identity number for it. */ static void *construct_evp_method(const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, void *data, int no_store) + OSSL_PROVIDER *prov, void *data) { /* * This function is only called if get_evp_method_from_store() returned @@ -228,7 +227,7 @@ static void *construct_evp_method(const OSSL_ALGORITHM *algodef, if (name_id == 0) return NULL; - method = methdata->method_from_algorithm(name_id, algodef, prov, no_store); + method = methdata->method_from_algorithm(name_id, algodef, prov); /* * Flag to indicate that there was actual construction errors. This @@ -254,7 +253,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, const char *name, ossl_unused const char *properties, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)) { @@ -352,9 +351,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, if (name_id == 0) { ERR_raise_data(ERR_LIB_EVP, ERR_R_FETCH_FAILED, "Algorithm %s cannot be found", name != NULL ? name : ""); -#ifdef OPENSSL_NO_CACHED_FETCH free_method(method); -#endif method = NULL; } else { meth_id = evp_method_id(name_id, operation_id); @@ -364,70 +361,9 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, * cached end up in ->tmp_store when provider asks not * to cache the result (see ossl_method_construct_reserve_store()) */ - if (meth_id != 0 && methdata->tmp_store == NULL) { + if (meth_id != 0 && methdata->tmp_store == NULL) ossl_method_store_cache_set(store, prov, meth_id, propq, method, up_ref_method, free_method); - } else { -#ifndef OPENSSL_NO_CACHED_FETCH - /* - * There is a corner case we need to handle here. IF: - * 1) we are fetching an algorithm and plan to return it to the caller - * 2) The provider we fetched from requested no_cache - * Then we are in a situation in which this method that was constructed - * only lives in the tmp_store, and has a reference count of 1. - * On return from this function, that tmp_store is going to be deallocated, - * Which will drop the methods ref count to 0 and free it, after which the - * method will be returned to the called, as an already freed object. - * - * That's bad. We need to grab an extra ref count on the method before returning - * so that the requestor via EVP_*_fetch has ownership. - * - * BUT we only want to do this in the event that the algorithm is uncached. - * Unfortunately, we don't know that here, because it was the provider that - * made that request. However, each algorithm type does store that information - * so we have a path forward. Based on the operation id, call the appropriate - * up_ref method. That implementation knows how to query its algorithm type and - * decide if a reference needs to be taken here - */ - switch (operation_id) { - case OSSL_OP_DIGEST: - EVP_MD_up_ref((EVP_MD *)method); - break; - case OSSL_OP_CIPHER: - EVP_CIPHER_up_ref((EVP_CIPHER *)method); - break; - case OSSL_OP_MAC: - EVP_MAC_up_ref((EVP_MAC *)method); - break; - case OSSL_OP_KDF: - EVP_KDF_up_ref((EVP_KDF *)method); - break; - case OSSL_OP_RAND: - EVP_RAND_up_ref((EVP_RAND *)method); - break; - case OSSL_OP_KEYMGMT: - EVP_KEYMGMT_up_ref((EVP_KEYMGMT *)method); - break; - case OSSL_OP_KEYEXCH: - EVP_KEYEXCH_up_ref((EVP_KEYEXCH *)method); - break; - case OSSL_OP_SIGNATURE: - EVP_SIGNATURE_up_ref((EVP_SIGNATURE *)method); - break; - case OSSL_OP_ASYM_CIPHER: - EVP_ASYM_CIPHER_up_ref((EVP_ASYM_CIPHER *)method); - break; - case OSSL_OP_KEM: - EVP_KEM_up_ref((EVP_KEM *)method); - break; - case OSSL_OP_SKEYMGMT: - EVP_SKEYMGMT_up_ref((EVP_SKEYMGMT *)method); - break; - default: - break; - } -#endif - } } } @@ -462,7 +398,7 @@ void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id, const char *name, const char *properties, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)) { @@ -488,7 +424,7 @@ void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, const char *name, const char *properties, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)) { @@ -702,7 +638,7 @@ void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id, void *user_arg, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)) { diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 644772bf37..076efb30d1 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -310,7 +310,6 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher) size_t blksz = 0; size_t keylen = 0; unsigned int mode = 0; - int no_store = cipher->flags & EVP_CIPH_FLAG_NO_STORE; OSSL_PARAM params[11]; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, &blksz); @@ -333,7 +332,7 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher) cipher->block_size = (int)blksz; cipher->iv_len = (int)ivlen; cipher->key_len = (int)keylen; - cipher->flags = mode | no_store; + cipher->flags = mode; if (aead) cipher->flags |= EVP_CIPH_FLAG_AEAD_CIPHER; if (custom_iv) diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 1f41cfe644..d4a72b7527 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -102,7 +102,6 @@ struct evp_keymgmt_st { int id; /* libcrypto internal */ int name_id; - int no_store; /* NID for the legacy alg if there is one */ int legacy_alg; char *type_name; @@ -149,7 +148,6 @@ struct evp_keymgmt_st { struct evp_keyexch_st { int name_id; - int no_store; char *type_name; const char *description; OSSL_PROVIDER *prov; @@ -170,7 +168,6 @@ struct evp_keyexch_st { struct evp_signature_st { int name_id; - int no_store; char *type_name; const char *description; OSSL_PROVIDER *prov; @@ -214,7 +211,6 @@ struct evp_signature_st { struct evp_skeymgmt_st { int name_id; - int no_store; char *type_name; const char *description; OSSL_PROVIDER *prov; @@ -238,7 +234,6 @@ struct evp_skeymgmt_st { struct evp_asym_cipher_st { int name_id; - int no_store; char *type_name; const char *description; OSSL_PROVIDER *prov; @@ -259,7 +254,6 @@ struct evp_asym_cipher_st { struct evp_kem_st { int name_id; - int no_store; char *type_name; const char *description; OSSL_PROVIDER *prov; @@ -311,14 +305,14 @@ void *evp_generic_fetch(OSSL_LIB_CTX *ctx, int operation_id, const char *name, const char *properties, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)); void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, const char *name, const char *properties, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)); void evp_generic_do_all_prefetched(OSSL_LIB_CTX *libctx, int operation_id, @@ -329,7 +323,7 @@ void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id, void *user_arg, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store), + OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)); diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c index a0041719b5..623b87135a 100644 --- a/crypto/evp/evp_rand.c +++ b/crypto/evp/evp_rand.c @@ -24,7 +24,6 @@ struct evp_rand_st { OSSL_PROVIDER *prov; int name_id; - int no_store; char *type_name; const char *description; CRYPTO_REF_COUNT refcnt; @@ -117,7 +116,7 @@ static void evp_rand_unlock(EVP_RAND_CTX *rand) static void *evp_rand_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_RAND *rand = NULL; @@ -131,7 +130,6 @@ static void *evp_rand_from_algorithm(int name_id, return NULL; } rand->name_id = name_id; - rand->no_store = no_store; if ((rand->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { evp_rand_free(rand); return NULL; @@ -291,23 +289,12 @@ EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, int EVP_RAND_up_ref(EVP_RAND *rand) { -#ifdef OPENSSL_NO_CACHED_FETCH return evp_rand_up_ref(rand); -#else - if (rand->no_store != 0) - return evp_rand_up_ref(rand); - return 1; -#endif } void EVP_RAND_free(EVP_RAND *rand) { -#ifdef OPENSSL_NO_CACHED_FETCH evp_rand_free(rand); -#else - if (rand != NULL && (rand->no_store != 0)) - evp_rand_free(rand); -#endif } int evp_rand_get_number(const EVP_RAND *rand) diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index 8718726076..849bc21514 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -21,26 +21,12 @@ static void evp_keyexch_free(void *data) { - EVP_KEYEXCH *exchange = (EVP_KEYEXCH *)data; - int i; - - if (exchange == NULL) - return; - CRYPTO_DOWN_REF(&exchange->refcnt, &i); - if (i > 0) - return; - OPENSSL_free(exchange->type_name); - ossl_provider_free(exchange->prov); - CRYPTO_FREE_REF(&exchange->refcnt); - OPENSSL_free(exchange); + EVP_KEYEXCH_free(data); } static int evp_keyexch_up_ref(void *data) { - EVP_KEYEXCH *exchange = (EVP_KEYEXCH *)data; - int ref = 0; - - return CRYPTO_UP_REF(&exchange->refcnt, &ref); + return EVP_KEYEXCH_up_ref(data); } static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov) @@ -63,7 +49,7 @@ static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov) static void *evp_keyexch_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_KEYEXCH *exchange = NULL; @@ -75,7 +61,6 @@ static void *evp_keyexch_from_algorithm(int name_id, } exchange->name_id = name_id; - exchange->no_store = no_store; if ((exchange->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) goto err; exchange->description = algodef->algorithm_description; @@ -169,29 +154,31 @@ static void *evp_keyexch_from_algorithm(int name_id, return exchange; err: - evp_keyexch_free(exchange); + EVP_KEYEXCH_free(exchange); return NULL; } void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_keyexch_free(exchange); -#else - if (exchange != NULL && (exchange->no_store != 0)) - evp_keyexch_free(exchange); -#endif + int i; + + if (exchange == NULL) + return; + CRYPTO_DOWN_REF(&exchange->refcnt, &i); + if (i > 0) + return; + OPENSSL_free(exchange->type_name); + ossl_provider_free(exchange->prov); + CRYPTO_FREE_REF(&exchange->refcnt); + OPENSSL_free(exchange); } int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_keyexch_up_ref(exchange); -#else - if (exchange->no_store != 0) - return evp_keyexch_up_ref(exchange); + int ref = 0; + + CRYPTO_UP_REF(&exchange->refcnt, &ref); return 1; -#endif } OSSL_PROVIDER *EVP_KEYEXCH_get0_provider(const EVP_KEYEXCH *exchange) diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c index 67351044fb..4c98942992 100644 --- a/crypto/evp/kdf_lib.c +++ b/crypto/evp/kdf_lib.c @@ -104,25 +104,11 @@ const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf) return kdf->prov; } -const EVP_KDF *EVP_KDF_CTX_get0_kdf(const EVP_KDF_CTX *ctx) +const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx) { return ctx->meth; } -#if !defined(OPENSSL_NO_DEPRECATED_4_1) -const EVP_KDF *EVP_KDF_CTX_kdf(const EVP_KDF_CTX *ctx) -{ - return EVP_KDF_CTX_get0_kdf(ctx); -} -#endif /* !OPENSSL_NO_DEPRECATED_4_1 */ - -EVP_KDF *EVP_KDF_CTX_get1_kdf(const EVP_KDF_CTX *ctx) -{ - if (!EVP_KDF_up_ref(ctx->meth)) - return NULL; - return ctx->meth; -} - void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx) { if (ctx == NULL) diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c index c6df2971db..31680ee664 100644 --- a/crypto/evp/kdf_meth.c +++ b/crypto/evp/kdf_meth.c @@ -22,7 +22,8 @@ static int evp_kdf_up_ref(void *vkdf) EVP_KDF *kdf = (EVP_KDF *)vkdf; int ref = 0; - return CRYPTO_UP_REF(&kdf->refcnt, &ref); + CRYPTO_UP_REF(&kdf->refcnt, &ref); + return 1; } static void evp_kdf_free(void *vkdf) @@ -56,7 +57,7 @@ static void *evp_kdf_new(void) static void *evp_kdf_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_KDF *kdf = NULL; @@ -67,8 +68,6 @@ static void *evp_kdf_from_algorithm(int name_id, return NULL; } kdf->name_id = name_id; - kdf->no_store = no_store; - if ((kdf->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) goto err; @@ -177,23 +176,12 @@ EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, int EVP_KDF_up_ref(EVP_KDF *kdf) { -#ifdef OPENSSL_NO_CACHED_FETCH return evp_kdf_up_ref(kdf); -#else - if (kdf->no_store != 0) - return evp_kdf_up_ref(kdf); - return 1; -#endif } void EVP_KDF_free(EVP_KDF *kdf) { -#ifdef OPENSSL_NO_CACHED_FETCH evp_kdf_free(kdf); -#else - if (kdf != NULL && (kdf->no_store != 0)) - evp_kdf_free(kdf); -#endif } const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf) diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c index 8ae968d5a5..92db961892 100644 --- a/crypto/evp/kem.c +++ b/crypto/evp/kem.c @@ -19,27 +19,12 @@ static void evp_kem_free(void *data) { - EVP_KEM *kem = (EVP_KEM *)data; - int i; - - if (kem == NULL) - return; - - CRYPTO_DOWN_REF(&kem->refcnt, &i); - if (i > 0) - return; - OPENSSL_free(kem->type_name); - ossl_provider_free(kem->prov); - CRYPTO_FREE_REF(&kem->refcnt); - OPENSSL_free(kem); + EVP_KEM_free(data); } static int evp_kem_up_ref(void *data) { - EVP_KEM *kem = (EVP_KEM *)data; - int ref = 0; - - return CRYPTO_UP_REF(&kem->refcnt, &ref); + return EVP_KEM_up_ref(data); } static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, @@ -316,7 +301,7 @@ static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov) } static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_KEM *kem = NULL; @@ -329,8 +314,6 @@ static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, } kem->name_id = name_id; - kem->no_store = no_store; - if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) goto err; kem->description = algodef->algorithm_description; @@ -443,29 +426,32 @@ static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, return kem; err: - evp_kem_free(kem); + EVP_KEM_free(kem); return NULL; } void EVP_KEM_free(EVP_KEM *kem) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_kem_free(kem); -#else - if (kem != NULL && (kem->no_store != 0)) - evp_kem_free(kem); -#endif + int i; + + if (kem == NULL) + return; + + CRYPTO_DOWN_REF(&kem->refcnt, &i); + if (i > 0) + return; + OPENSSL_free(kem->type_name); + ossl_provider_free(kem->prov); + CRYPTO_FREE_REF(&kem->refcnt); + OPENSSL_free(kem); } int EVP_KEM_up_ref(EVP_KEM *kem) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_kem_up_ref(kem); -#else - if (kem->no_store != 0) - return evp_kem_up_ref(kem); + int ref = 0; + + CRYPTO_UP_REF(&kem->refcnt, &ref); return 1; -#endif } OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem) diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index 9cf4ef5e4f..e7f00d091f 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -19,27 +19,12 @@ static void evp_keymgmt_free(void *data) { - EVP_KEYMGMT *keymgmt = (EVP_KEYMGMT *)data; - int ref = 0; - - if (keymgmt == NULL) - return; - - CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref); - if (ref > 0) - return; - OPENSSL_free(keymgmt->type_name); - ossl_provider_free(keymgmt->prov); - CRYPTO_FREE_REF(&keymgmt->refcnt); - OPENSSL_free(keymgmt); + EVP_KEYMGMT_free(data); } static int evp_keymgmt_up_ref(void *data) { - EVP_KEYMGMT *keymgmt = (EVP_KEYMGMT *)data; - int ref = 0; - - return CRYPTO_UP_REF(&keymgmt->refcnt, &ref); + return EVP_KEYMGMT_up_ref(data); } static void *keymgmt_new(void) @@ -49,7 +34,7 @@ static void *keymgmt_new(void) if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL) return NULL; if (!CRYPTO_NEW_REF(&keymgmt->refcnt, 1)) { - OPENSSL_free(keymgmt); + EVP_KEYMGMT_free(keymgmt); return NULL; } return keymgmt; @@ -77,7 +62,7 @@ static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt) static void *keymgmt_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_KEYMGMT *keymgmt = NULL; @@ -91,10 +76,8 @@ static void *keymgmt_from_algorithm(int name_id, return NULL; keymgmt->name_id = name_id; - keymgmt->no_store = no_store; - if ((keymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - evp_keymgmt_free(keymgmt); + EVP_KEYMGMT_free(keymgmt); return NULL; } keymgmt->description = algodef->algorithm_description; @@ -270,13 +253,13 @@ static void *keymgmt_from_algorithm(int name_id, || (keymgmt->gen != NULL && (keymgmt->gen_init == NULL || keymgmt->gen_cleanup == NULL))) { - evp_keymgmt_free(keymgmt); + EVP_KEYMGMT_free(keymgmt); ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); return NULL; } keymgmt->prov = prov; if (prov != NULL && !ossl_provider_up_ref(prov)) { - evp_keymgmt_free(keymgmt); + EVP_KEYMGMT_free(keymgmt); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); return NULL; } @@ -310,23 +293,26 @@ EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_keymgmt_up_ref(keymgmt); -#else - if (keymgmt->no_store != 0) - return evp_keymgmt_up_ref(keymgmt); + int ref = 0; + + CRYPTO_UP_REF(&keymgmt->refcnt, &ref); return 1; -#endif } void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_keymgmt_free(keymgmt); -#else - if (keymgmt != NULL && (keymgmt->no_store != 0)) - evp_keymgmt_free(keymgmt); -#endif + int ref = 0; + + if (keymgmt == NULL) + return; + + CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref); + if (ref > 0) + return; + OPENSSL_free(keymgmt->type_name); + ossl_provider_free(keymgmt->prov); + CRYPTO_FREE_REF(&keymgmt->refcnt); + OPENSSL_free(keymgmt); } const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt) diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c index 2a6fb0abe5..ba47e95870 100644 --- a/crypto/evp/mac_meth.c +++ b/crypto/evp/mac_meth.c @@ -21,7 +21,8 @@ static int evp_mac_up_ref(void *vmac) EVP_MAC *mac = vmac; int ref = 0; - return CRYPTO_UP_REF(&mac->refcnt, &ref); + CRYPTO_UP_REF(&mac->refcnt, &ref); + return 1; } static void evp_mac_free(void *vmac) @@ -55,7 +56,7 @@ static void *evp_mac_new(void) static void *evp_mac_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_MAC *mac = NULL; @@ -66,7 +67,6 @@ static void *evp_mac_from_algorithm(int name_id, goto err; } mac->name_id = name_id; - mac->no_store = no_store; if ((mac->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) goto err; @@ -182,23 +182,12 @@ EVP_MAC *EVP_MAC_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, int EVP_MAC_up_ref(EVP_MAC *mac) { -#ifdef OPENSSL_NO_CACHED_FETCH return evp_mac_up_ref(mac); -#else - if (mac->no_store != 0) - return evp_mac_up_ref(mac); - return 1; -#endif } void EVP_MAC_free(EVP_MAC *mac) { -#ifdef OPENSSL_NO_CACHED_FETCH evp_mac_free(mac); -#else - if (mac != NULL && (mac->no_store != 0)) - evp_mac_free(mac); -#endif } const OSSL_PROVIDER *EVP_MAC_get0_provider(const EVP_MAC *mac) diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index f13390b54e..fcf64ed004 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1630,7 +1630,7 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey) { int i; - if (!CRYPTO_UP_REF(&pkey->references, &i)) + if (CRYPTO_UP_REF(&pkey->references, &i) <= 0) return 0; REF_PRINT_COUNT("EVP_PKEY", i, pkey); @@ -2405,10 +2405,13 @@ int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey) /* Might work through the legacy route */ const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); - if (ec != NULL) - return EC_KEY_get_conv_form(ec); -#endif + if (ec == NULL) + return 0; + + return EC_KEY_get_conv_form(ec); +#else return 0; +#endif } if (!EVP_PKEY_get_utf8_string_param(pkey, diff --git a/crypto/evp/s_lib.c b/crypto/evp/s_lib.c index 3f76136324..5594dc81c5 100644 --- a/crypto/evp/s_lib.c +++ b/crypto/evp/s_lib.c @@ -196,7 +196,7 @@ int EVP_SKEY_up_ref(EVP_SKEY *skey) { int i; - if (!CRYPTO_UP_REF(&skey->references, &i)) + if (CRYPTO_UP_REF(&skey->references, &i) <= 0) return 0; REF_PRINT_COUNT("EVP_SKEY", i, skey); diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 6c6aad7e92..3737bc6ba4 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -22,26 +22,12 @@ static void evp_signature_free(void *data) { - EVP_SIGNATURE *signature = (EVP_SIGNATURE *)data; - int i; - - if (signature == NULL) - return; - CRYPTO_DOWN_REF(&signature->refcnt, &i); - if (i > 0) - return; - OPENSSL_free(signature->type_name); - ossl_provider_free(signature->prov); - CRYPTO_FREE_REF(&signature->refcnt); - OPENSSL_free(signature); + EVP_SIGNATURE_free(data); } static int evp_signature_up_ref(void *data) { - EVP_SIGNATURE *signature = (EVP_SIGNATURE *)data; - int ref = 0; - - return CRYPTO_UP_REF(&signature->refcnt, &ref); + return EVP_SIGNATURE_up_ref(data); } static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov) @@ -65,7 +51,7 @@ static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov) static void *evp_signature_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_SIGNATURE *signature = NULL; @@ -84,7 +70,6 @@ static void *evp_signature_from_algorithm(int name_id, } signature->name_id = name_id; - signature->no_store = no_store; if ((signature->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) goto err; signature->description = algodef->algorithm_description; @@ -463,29 +448,31 @@ static void *evp_signature_from_algorithm(int name_id, return signature; err: - evp_signature_free(signature); + EVP_SIGNATURE_free(signature); return NULL; } void EVP_SIGNATURE_free(EVP_SIGNATURE *signature) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_signature_free(signature); -#else - if (signature != NULL && (signature->no_store != 0)) - evp_signature_free(signature); -#endif + int i; + + if (signature == NULL) + return; + CRYPTO_DOWN_REF(&signature->refcnt, &i); + if (i > 0) + return; + OPENSSL_free(signature->type_name); + ossl_provider_free(signature->prov); + CRYPTO_FREE_REF(&signature->refcnt); + OPENSSL_free(signature); } int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_signature_up_ref(signature); -#else - if (signature->no_store != 0) - return evp_signature_up_ref(signature); + int ref = 0; + + CRYPTO_UP_REF(&signature->refcnt, &ref); return 1; -#endif } OSSL_PROVIDER *EVP_SIGNATURE_get0_provider(const EVP_SIGNATURE *signature) diff --git a/crypto/evp/skeymgmt_meth.c b/crypto/evp/skeymgmt_meth.c index dbc14c0e0d..75c4fef675 100644 --- a/crypto/evp/skeymgmt_meth.c +++ b/crypto/evp/skeymgmt_meth.c @@ -17,8 +17,6 @@ #include "crypto/evp.h" #include "evp_local.h" -static void evp_skeymgmt_free(void *s); - void *evp_skeymgmt_generate(const EVP_SKEYMGMT *skeymgmt, const OSSL_PARAM params[]) { void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); @@ -47,6 +45,16 @@ void evp_skeymgmt_freedata(const EVP_SKEYMGMT *skeymgmt, void *keydata) skeymgmt->free(keydata); } +static int evp_skeymgmt_up_ref(void *skeymgmt) +{ + return EVP_SKEYMGMT_up_ref(skeymgmt); +} + +static void evp_skeymgmt_free(void *skeymgmt) +{ + EVP_SKEYMGMT_free(skeymgmt); +} + static void *skeymgmt_new(void) { EVP_SKEYMGMT *skeymgmt = NULL; @@ -54,7 +62,7 @@ static void *skeymgmt_new(void) if ((skeymgmt = OPENSSL_zalloc(sizeof(*skeymgmt))) == NULL) return NULL; if (!CRYPTO_NEW_REF(&skeymgmt->refcnt, 1)) { - evp_skeymgmt_free(skeymgmt); + EVP_SKEYMGMT_free(skeymgmt); return NULL; } return skeymgmt; @@ -62,7 +70,7 @@ static void *skeymgmt_new(void) static void *skeymgmt_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { const OSSL_DISPATCH *fns = algodef->implementation; EVP_SKEYMGMT *skeymgmt = NULL; @@ -71,9 +79,8 @@ static void *skeymgmt_from_algorithm(int name_id, return NULL; skeymgmt->name_id = name_id; - skeymgmt->no_store = no_store; if ((skeymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - evp_skeymgmt_free(skeymgmt); + EVP_SKEYMGMT_free(skeymgmt); return NULL; } skeymgmt->description = algodef->algorithm_description; @@ -115,13 +122,13 @@ static void *skeymgmt_from_algorithm(int name_id, if (skeymgmt->free == NULL || skeymgmt->import == NULL || skeymgmt->export == NULL) { - evp_skeymgmt_free(skeymgmt); + EVP_SKEYMGMT_free(skeymgmt); ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); return NULL; } if (!ossl_provider_up_ref(prov)) { - evp_skeymgmt_free(skeymgmt); + EVP_SKEYMGMT_free(skeymgmt); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); return NULL; } @@ -130,31 +137,6 @@ static void *skeymgmt_from_algorithm(int name_id, return skeymgmt; } -static int evp_skeymgmt_up_ref(void *s) -{ - EVP_SKEYMGMT *skeymgmt = (EVP_SKEYMGMT *)s; - int ref = 0; - - return CRYPTO_UP_REF(&skeymgmt->refcnt, &ref); -} - -static void evp_skeymgmt_free(void *s) -{ - EVP_SKEYMGMT *skeymgmt = (EVP_SKEYMGMT *)s; - int ref = 0; - - if (skeymgmt == NULL) - return; - - CRYPTO_DOWN_REF(&skeymgmt->refcnt, &ref); - if (ref > 0) - return; - OPENSSL_free(skeymgmt->type_name); - ossl_provider_free(skeymgmt->prov); - CRYPTO_FREE_REF(&skeymgmt->refcnt); - OPENSSL_free(skeymgmt); -} - EVP_SKEYMGMT *evp_skeymgmt_fetch_from_prov(OSSL_PROVIDER *prov, const char *name, const char *properties) @@ -178,23 +160,26 @@ EVP_SKEYMGMT *EVP_SKEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, int EVP_SKEYMGMT_up_ref(EVP_SKEYMGMT *skeymgmt) { -#ifdef OPENSSL_NO_CACHED_FETCH - return evp_skeymgmt_up_ref(skeymgmt); -#else - if (skeymgmt->no_store != 0) - return evp_skeymgmt_up_ref(skeymgmt); + int ref = 0; + + CRYPTO_UP_REF(&skeymgmt->refcnt, &ref); return 1; -#endif } void EVP_SKEYMGMT_free(EVP_SKEYMGMT *skeymgmt) { -#ifdef OPENSSL_NO_CACHED_FETCH - evp_skeymgmt_free(skeymgmt); -#else - if (skeymgmt != NULL && (skeymgmt->no_store != 0)) - evp_skeymgmt_free(skeymgmt); -#endif + int ref = 0; + + if (skeymgmt == NULL) + return; + + CRYPTO_DOWN_REF(&skeymgmt->refcnt, &ref); + if (ref > 0) + return; + OPENSSL_free(skeymgmt->type_name); + ossl_provider_free(skeymgmt->prov); + CRYPTO_FREE_REF(&skeymgmt->refcnt); + OPENSSL_free(skeymgmt); } const OSSL_PROVIDER *EVP_SKEYMGMT_get0_provider(const EVP_SKEYMGMT *skeymgmt) diff --git a/crypto/fn/build.info b/crypto/fn/build.info new file mode 100644 index 0000000000..cee3d11f66 --- /dev/null +++ b/crypto/fn/build.info @@ -0,0 +1,9 @@ +$LIBCRYPTO=../../libcrypto +$LIBFIPS=../../providers/libfips.a +LIBS=$LIBCRYPTO + +$COMMON=fn_err.c fn_lib.c fn_ctx.c fn_intern.c fn_addsub.c fn_shift.c fn_mul.c \ + fn_sqr.c fn_div.c fn_rand.c fn_mod.c + +SOURCE[$LIBCRYPTO]=$COMMON +SOURCE[$LIBFIPS]=$COMMON diff --git a/crypto/fn/fn_addsub.c b/crypto/fn/fn_addsub.c new file mode 100644 index 0000000000..ee1c2b2aa1 --- /dev/null +++ b/crypto/fn/fn_addsub.c @@ -0,0 +1,343 @@ +/* + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "crypto/fnerr.h" +#include "../bn/bn_local.h" /* For using the low level bignum functions */ +#include "fn_local.h" + +/* + * ossl_fn_add_words and ossl_fn_sub_words perform fixed-width unsigned + * addition and subtraction of multi-limb integers. + * + * The carry or borrow is always propagated through every limb of both + * operands (and through any extra result limbs when rl exceeds the operand + * sizes). The operation is effectively performed at the precision of the + * wider operand, then truncated to rl limbs — analogous to performing an + * unsigned operation in the wider of the operand types and then casting + * the result to a narrower type. + * + * The returned carry (addition) or borrow (subtraction) is the true + * overflow / borrow out of the most significant processed limb: + * + * - When rl <= max(al, bl), it is the carry / borrow out of max(al, bl) + * limbs. Note that this does NOT indicate whether the result fits in + * rl limbs; non-zero high limbs may have been truncated without + * generating a carry. If the caller needs the exact magnitude, rl + * must be at least max(al, bl). + * + * - For addition, when rl > max(al, bl), the carry is absorbed into the + * result (written to r[max(al,bl)], higher limbs zeroed) and the + * function returns 0. + * + * - For subtraction, when rl > max(al, bl), the borrow is propagated + * through all remaining result limbs (two's complement sign extension) + * and the function returns the borrow out of rl limbs. + */ + +/* unsigned addition of a and b, returns carry if there is one past the result size */ +OSSL_FN_ULONG ossl_fn_add_words(OSSL_FN_ULONG *r, size_t rl, + const OSSL_FN_ULONG *a, size_t al, + const OSSL_FN_ULONG *b, size_t bl) +{ + /* + * Addition is commutative, so we switch 'a' and 'b' around to + * ensure that 'a' is physically the largest, so a maximum of + * work is done with 'bn_add_words' + */ + if (al < bl) { + const OSSL_FN_ULONG *tmp; + size_t tmpl; + + tmp = a; + tmpl = al; + a = b; + al = bl; + b = tmp; + bl = tmpl; + } + + /* + * Four stages. + * + * For each stage, |stage_limbs| is used to hold the number + * of limbs being treated in that stage, |i| is used as an + * index into the arrays, and |carry| is used to transport + * the carry from one stage to the other. + * + * Note: |stage_limbs| is passed cast to 'int' when calling + * bn_add_words(). This is fine because the maximum size of + * any OSSL_FN_ULONG is BN_MAX_WORDS, which is small enough. + * Should that change some day, there's trouble ahead. + */ + size_t stage_limbs; + OSSL_FN_ULONG carry; + size_t i; + + /* + * Stage 1: calculate the least min(rl,bl) limbs + * + * This uses bn_add_words, with what performance benefits that gives. + */ + + stage_limbs = (bl > rl) ? rl : bl; + carry = bn_add_words(r, a, b, (int)stage_limbs); + + /* Record the array position past what bn_add_words calculated */ + i = stage_limbs; + + /* + * Stage 2: calculate min(rl,bl) to bl limbs + * + * Because this loop only engages when rl < bl, it cannot affect r. + * The only purpose of this loop is to propagate carry in this particular + * scenario. + */ + + stage_limbs = bl - stage_limbs; + + for (size_t dif = stage_limbs; dif > 0; dif--, i++) { + OSSL_FN_ULONG t1, t2; + + t1 = (a[i] + carry) & OSSL_FN_MASK; + carry = (t1 < carry); + t2 = (b[i] + t1) & OSSL_FN_MASK; + carry |= (t2 < t1); + } + + assert(i == bl); + + /* + * Stage 3: calculate bl to al limbs + * + * Note: at any time, the end of r may be reached. This is solved + * with a temporary pointer that's set appropriately inside the loop. + */ + + stage_limbs = al - bl; + + for (size_t dif = stage_limbs; dif > 0; dif--, i++) { + OSSL_FN_ULONG tmp = 0; + OSSL_FN_ULONG *rp = (i < rl) ? &r[i] : &tmp; + OSSL_FN_ULONG t1; + + t1 = (a[i] + carry) & OSSL_FN_MASK; + carry = (t1 < carry); + + *rp = t1; + } + + assert(i == al); + + /* If |r| is exhausted, there's nothing more to do */ + if (i >= rl) + return carry; + + /* + * Stage 4: calculate a final carry, for when rl > al + * + * This is relatively simple, compare to earlier loops. + */ + + stage_limbs = rl - al; + + for (size_t dif = stage_limbs; dif > 0; dif--, i++) { + r[i] = carry; + carry = 0; + } + + return carry; +} + +int OSSL_FN_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b) +{ + (void)ossl_fn_add_words(r->d, r->dsize, a->d, a->dsize, b->d, b->dsize); + return 1; +} + +/*- + * Adds the single-limb word |w| to |a| in place, propagating the carry + * through |a|'s limbs and truncating any carry out past a->dsize (OSSL_FN is + * fixed-size, so a carry past the last limb is discarded rather than grown + * into). The degenerate w == 0 case is a no-op. + * + * Not constant-time: the carry-propagation loop stops early once the carry + * is exhausted, so the number of limbs touched depends on the operand's + * value. + */ +int OSSL_FN_add_word(OSSL_FN *a, OSSL_FN_ULONG w) +{ + size_t i; + size_t dsize = (size_t)a->dsize; + + if (w == 0) + return 1; + + for (i = 0; i < dsize && w != 0; i++) { + OSSL_FN_ULONG l = (a->d[i] + w) & OSSL_FN_MASK; + + a->d[i] = l; + w = (w > l); + } + /* Any remaining carry out past dsize is truncated. */ + return 1; +} + +/* unsigned subtraction of b from a, returns borrow if there is one past the result size */ +OSSL_FN_ULONG ossl_fn_sub_words(OSSL_FN_ULONG *r, size_t rl, + const OSSL_FN_ULONG *a, size_t al, + const OSSL_FN_ULONG *b, size_t bl) +{ + size_t max = (al >= bl) ? al : bl; + size_t min = (al <= bl) ? al : bl; + + /* + * Four stages. + * + * For each stage, |stage_limbs| is used to hold the number + * of limbs being treated in that stage, |i| is used as an + * index into the arrays, and |borrow| is used to transport + * the borrow from one stage to the other. + * + * Note: |stage_limbs| is passed cast to 'int' when calling + * bn_sub_words(). This is fine because the maximum size of + * any OSSL_FN_ULONG is BN_MAX_WORDS, which is small enough. + * Should that change some day, there's trouble ahead. + */ + size_t stage_limbs; + OSSL_FN_ULONG borrow; + size_t i; + + /* + * Stage 1: calculate the least min(rl,al,bl) limbs + * + * This uses bn_sub_words, with what performance benefits that gives. + */ + + stage_limbs = (min > rl) ? rl : min; + borrow = bn_sub_words(r, a, b, (int)stage_limbs); + + /* Record the array position past what bn_sub_words calculated */ + i = stage_limbs; + + /* + * Stage 2: calculate the min(rl,al,bl) to min(al,bl) limbs + * + * Because this loop only engages when rl < min(al,bl), it cannot affect r. + * The only purpose of this loop is to propagate borrow in this particular + * scenario. + */ + + stage_limbs = min - stage_limbs; + + for (size_t dif = stage_limbs; dif > 0; dif--, i++) { + OSSL_FN_ULONG t1, t2; + + t1 = a[i]; + t2 = (t1 - borrow) & OSSL_FN_MASK; + borrow = (t2 > t1); + t1 = b[i]; + t1 = (t2 - t1) & OSSL_FN_MASK; + borrow |= (t1 > t2); + } + + assert(i == min); + + /* + * Stage 3: calculate the min(al,bl) to max(al,bl) limbs + * + * Note: at any time, the end of r may be reached. This is solved + * with a temporary pointer that's set appropriately inside the loop. + */ + + const OSSL_FN_ULONG *maxp = (al >= bl) ? a : b; + const OSSL_FN_ULONG s2_mask1 = (al >= bl) ? OSSL_FN_MASK : 0; + const OSSL_FN_ULONG s2_mask2 = ~s2_mask1; + + stage_limbs = max - min; + + /* calculate the result of borrowing from more significant limbs */ + for (size_t dif = stage_limbs; dif > 0; dif--, i++) { + OSSL_FN_ULONG tmp = 0; + OSSL_FN_ULONG *rp = (i < rl) ? &r[i] : &tmp; + OSSL_FN_ULONG t1, t2; + + t1 = maxp[i] & s2_mask1; + t2 = (t1 - borrow) & OSSL_FN_MASK; + borrow = (t2 > t1); + t1 = maxp[i] & s2_mask2; + t1 = (t2 - t1) & OSSL_FN_MASK; + borrow |= (t1 > t2); + + *rp = t1; + } + + assert(i == max); + + /* If |r| is exhausted, there's nothing more to do */ + if (i >= rl) + return borrow; + + /* + * Stage 4: calculate a final borrow, for when rl > max + * + * This is relatively simple, compare to earlier loops. + */ + + stage_limbs = rl - max; + + /* Finally, fill in the rest of the result array by borrowing from zeros */ + for (size_t dif = stage_limbs; dif > 0; dif--, i++) { + OSSL_FN_ULONG t1 = (0 - borrow) & OSSL_FN_MASK; + + borrow = (t1 > 0); + + r[i] = t1; + } + + return borrow; +} + +int OSSL_FN_sub(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b) +{ + (void)ossl_fn_sub_words(r->d, r->dsize, a->d, a->dsize, b->d, b->dsize); + return 1; +} + +/*- + * Subtracts the single-limb word |w| from |a| in place, propagating the + * borrow through |a|'s limbs. If the borrow runs past a->dsize (i.e. the + * unsigned value of |a| is less than |w|), the result is the 2's-complement + * wrap-around truncated to dsize, per OSSL_FN's fixed-size unsigned + * semantics: there is no sign to record, so the wrapped value is kept. The + * degenerate w == 0 case is a no-op. + * + * Not constant-time: the borrow-propagation loop returns early once the + * borrow is repaid, so the number of limbs touched depends on the operand's + * value. + */ +int OSSL_FN_sub_word(OSSL_FN *a, OSSL_FN_ULONG w) +{ + size_t i; + size_t dsize = (size_t)a->dsize; + + if (w == 0) + return 1; + + for (i = 0; i < dsize; i++) { + if (a->d[i] >= w) { + a->d[i] -= w; + return 1; /* borrow repaid */ + } + a->d[i] = (a->d[i] - w) & OSSL_FN_MASK; + w = 1; + } + /* Borrow out past dsize is truncated (2's complement). */ + return 1; +} diff --git a/crypto/fn/fn_ctx.c b/crypto/fn/fn_ctx.c new file mode 100644 index 0000000000..fc510e03fd --- /dev/null +++ b/crypto/fn/fn_ctx.c @@ -0,0 +1,253 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/safe_math.h" +#include "crypto/fn.h" +#include "fn_local.h" + +OSSL_SAFE_MATH_ADDU(size_t, size_t, OSSL_SAFE_MATH_MAXU(size_t)) +OSSL_SAFE_MATH_MULU(size_t, size_t, OSSL_SAFE_MATH_MAXU(size_t)) + +/* + * An OSSL_FN_CTX is a large pre-allocated chunk of memory that can be used + * to quickly allocate OSSL_FN instances. The organization of memory is as + * a fairly typical arena, where OSSL_FN instances are "stacked" one after + * the other. + * + * However, there is also the concept of frames, which are arenas within an + * arena. This allows easily passing an OSSL_FN_CTX to a function, and for + * that function to allocate such a frame for itself, and easily deallocate + * it when it's done. + */ + +size_t OSSL_FN_CTX_size(size_t max_n_frames, size_t max_n_numbers, + size_t max_n_limbs) +{ + int err = 0; + size_t frames, numbers, limbs, total; + + /* + * A context always needs at least one frame, since every use of an + * OSSL_FN_CTX calls OSSL_FN_CTX_start(), which carves out a frame. + */ + if (max_n_frames == 0) + return 0; + /* + * Number-header and limb budgets must both be present or both absent. + * OSSL_FN_CTX_get_limbs() allocates an OSSL_FN header and its limbs + * together, so a context with one budget but not the other can never + * produce a usable number. + */ + if ((max_n_numbers == 0) != (max_n_limbs == 0)) + return 0; + + frames = safe_mul_size_t(max_n_frames, + sizeof(struct ossl_fn_ctx_frame_st), &err); + numbers = safe_mul_size_t(max_n_numbers, sizeof(OSSL_FN), &err); + limbs = safe_mul_size_t(max_n_limbs, OSSL_FN_BYTES, &err); + total = safe_add_size_t(frames, numbers, &err); + total = safe_add_size_t(total, limbs, &err); + + return err == 0 ? total : 0; +} + +OSSL_FN_CTX *OSSL_FN_CTX_new(OSSL_LIB_CTX *libctx, size_t max_n_frames, + size_t max_n_numbers, size_t max_n_limbs) +{ + return OSSL_FN_CTX_new_size(libctx, + OSSL_FN_CTX_size(max_n_frames, max_n_numbers, max_n_limbs)); +} + +OSSL_FN_CTX *OSSL_FN_CTX_new_size(OSSL_LIB_CTX *libctx, size_t size) +{ + size_t total_size; + OSSL_FN_CTX *ctx; + + int err = 0; + + /* + * A size of 0 is the error return of OSSL_FN_CTX_size() (and the + * per-operation ctx-size helpers). Treat it as an error here too, so a + * caller does not get back a context with a zero-size arena that it + * would then hand to an operation expecting usable scratch space. + */ + if (size == 0) + return NULL; + + total_size = safe_add_size_t(sizeof(*ctx), size, &err); + if (err != 0) + return NULL; + + ctx = OPENSSL_zalloc(total_size); + + if (ctx != NULL) + ctx->msize = size; + + return ctx; +} + +OSSL_FN_CTX *OSSL_FN_CTX_secure_new(OSSL_LIB_CTX *libctx, size_t max_n_frames, + size_t max_n_numbers, size_t max_n_limbs) +{ + return OSSL_FN_CTX_secure_new_size(libctx, + OSSL_FN_CTX_size(max_n_frames, max_n_numbers, max_n_limbs)); +} + +OSSL_FN_CTX *OSSL_FN_CTX_secure_new_size(OSSL_LIB_CTX *libctx, size_t size) +{ + size_t total_size; + OSSL_FN_CTX *ctx; + + int err = 0; + + /* As in OSSL_FN_CTX_new_size(), a size of 0 is an error. */ + if (size == 0) + return NULL; + + total_size = safe_add_size_t(sizeof(*ctx), size, &err); + if (err != 0) + return NULL; + + ctx = OPENSSL_secure_zalloc(total_size); + + if (ctx != NULL) { + ctx->msize = size; + ctx->is_securely_allocated = 1; + } + + return ctx; +} + +void OSSL_FN_CTX_peak_usage(const OSSL_FN_CTX *ctx, size_t *peak_n_frames, + size_t *peak_n_numbers, size_t *peak_n_limbs) +{ + if (ctx == NULL) { + if (peak_n_frames != NULL) + *peak_n_frames = 0; + if (peak_n_numbers != NULL) + *peak_n_numbers = 0; + if (peak_n_limbs != NULL) + *peak_n_limbs = 0; + return; + } + if (peak_n_frames != NULL) + *peak_n_frames = ctx->peak_n_frames; + if (peak_n_numbers != NULL) + *peak_n_numbers = ctx->peak_n_numbers; + if (peak_n_limbs != NULL) + *peak_n_limbs = ctx->peak_n_limbs; +} + +void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx) +{ + if (ctx == NULL) + return; + + assert(ctx->last_frame == NULL); + + if (ctx->is_securely_allocated) + OPENSSL_secure_free(ctx); + else + OPENSSL_free(ctx); +} + +const void *OSSL_FN_CTX_start(OSSL_FN_CTX *ctx) +{ + if (!ossl_assert(ctx != NULL)) + return NULL; + + struct ossl_fn_ctx_frame_st *last_frame = ctx->last_frame; + size_t used = (last_frame == NULL) ? 0 : last_frame->free_memory - ctx->memory; + + if (ctx->msize - used < sizeof(struct ossl_fn_ctx_frame_st)) + return NULL; + + if (ctx->last_frame == NULL) + ctx->last_frame = (struct ossl_fn_ctx_frame_st *)ctx->memory; + else + ctx->last_frame = (struct ossl_fn_ctx_frame_st *)last_frame->free_memory; + + struct ossl_fn_ctx_frame_st *frame = ctx->last_frame; + frame->arena = ctx; + frame->previous_frame = last_frame; + frame->free_memory = frame->memory; + frame->msize = ctx->msize - used - sizeof(*frame); + frame->n_numbers = 0; + frame->n_limbs = 0; + + ctx->n_frames++; + if (ctx->n_frames > ctx->peak_n_frames) + ctx->peak_n_frames = ctx->n_frames; + + return ctx->last_frame; +} + +int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx, const void *token) +{ + if (!ossl_assert(ctx != NULL) || !ossl_assert(ctx->last_frame != NULL)) + return 0; + + struct ossl_fn_ctx_frame_st *last_frame = ctx->last_frame; + + if (last_frame != token) + return 0; + + ctx->n_numbers -= last_frame->n_numbers; + ctx->n_limbs -= last_frame->n_limbs; + ctx->n_frames--; + ctx->last_frame = last_frame->previous_frame; + + return 1; +} + +OSSL_FN *OSSL_FN_CTX_get_limbs(OSSL_FN_CTX *ctx, size_t limbs) +{ + if (!ossl_assert(ctx != NULL)) + return NULL; + + struct ossl_fn_ctx_frame_st *frame = ctx->last_frame; + + if (!ossl_assert(frame != NULL)) + return NULL; + + size_t totalsize = ossl_fn_totalsize(limbs); + size_t used = frame->free_memory - frame->memory; + if (totalsize == 0 || frame->msize - used < totalsize) + return NULL; + + OSSL_FN *fn = (OSSL_FN *)frame->free_memory; + frame->free_memory += totalsize; + frame->n_numbers++; + frame->n_limbs += limbs; + + ctx->n_numbers++; + ctx->n_limbs += limbs; + if (ctx->n_numbers > ctx->peak_n_numbers) + ctx->peak_n_numbers = ctx->n_numbers; + if (ctx->n_limbs > ctx->peak_n_limbs) + ctx->peak_n_limbs = ctx->n_limbs; + + memset(fn, 0, totalsize); + fn->dsize = (int)limbs; + fn->is_securely_allocated = ctx->is_securely_allocated; + + return fn; +} + +OSSL_FN *OSSL_FN_CTX_get_bytes(OSSL_FN_CTX *ctx, size_t bytes) +{ + return OSSL_FN_CTX_get_limbs(ctx, ossl_fn_bytes_to_limbs(bytes)); +} + +OSSL_FN *OSSL_FN_CTX_get_bits(OSSL_FN_CTX *ctx, size_t bits) +{ + return OSSL_FN_CTX_get_bytes(ctx, ossl_fn_bits_to_bytes(bits)); +} diff --git a/crypto/fn/fn_div.c b/crypto/fn/fn_div.c new file mode 100644 index 0000000000..9e0f67d20d --- /dev/null +++ b/crypto/fn/fn_div.c @@ -0,0 +1,395 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/safe_math.h" +#include "crypto/cryptlib.h" +#include "crypto/fnerr.h" +#include "../bn/bn_local.h" /* For using the low level bignum functions */ +#include "fn_local.h" + +OSSL_SAFE_MATH_ADDU(size_t, size_t, OSSL_SAFE_MATH_MAXU(size_t)) + +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \ + && !defined(PEDANTIC) && !defined(BN_DIV3W) +#if defined(__GNUC__) && __GNUC__ >= 2 +#if defined(__i386) || defined(__i386__) +/*- + * There were two reasons for implementing this template: + * - GNU C generates a call to a function (__udivdi3 to be exact) + * in reply to ((((BN_ULLONG)n0)< */ +#endif /* __GNUC__ */ +#endif /* OPENSSL_NO_ASM */ + +/* + * Copy src to dst and align it to the left using lshift. + * lshift is assumed to be less than OSSL_FN_BITS. + */ +static inline void copy_align_left(OSSL_FN *dst, const OSSL_FN *src, OSSL_FN_ULONG lshift) +{ + OSSL_FN_ULONG rshift = OSSL_FN_BITS - lshift; + OSSL_FN_ULONG rmask; + OSSL_FN_ULONG m; + const OSSL_FN_ULONG *s = src->d; + size_t sl = src->dsize; + OSSL_FN_ULONG *d = dst->d; + size_t dl = dst->dsize; + size_t l = (dl < sl) ? dl : sl; + size_t i; + + rshift %= OSSL_FN_BITS; + + /* rmask = 0 - (rshift != 0) */ + rmask = (OSSL_FN_ULONG)0 - rshift; + rmask |= rmask >> 8; + + /* src and dst may be the same, that's why this loop is made this way */ + for (i = 0, m = 0; i < l; i++) { + OSSL_FN_ULONG tmp = s[i]; + d[i] = ((tmp << lshift) | m) & OSSL_FN_MASK; + m = (tmp >> rshift) & rmask; + } + + for (; i < dl; i++) { + d[i] = m; + m = 0; + } +} + +/* + * Copy src to dst and align it to the right using rshift. + * rshift is assumed to be less than OSSL_FN_BITS. + */ +static inline void copy_align_right(OSSL_FN *dst, const OSSL_FN *src, OSSL_FN_ULONG rshift) +{ + OSSL_FN_ULONG lshift = OSSL_FN_BITS - rshift; + OSSL_FN_ULONG lmask; + const OSSL_FN_ULONG *s = src->d; + size_t sl = src->dsize; + OSSL_FN_ULONG *d = dst->d; + size_t dl = dst->dsize; + size_t i; + size_t l = (dl < sl) ? dl : sl; + + lshift %= OSSL_FN_BITS; + + /* lmask = 0 - (lshift != 0) */ + lmask = (OSSL_FN_ULONG)0 - lshift; + lmask |= lmask >> 8; + + /* Just to be safe */ + for (i = dl; i-- > l;) + d[i] = 0; + + /* + * m is a set of bits passed to the next limb down when shifting, + * and needs proper bootstrapping: if the source is larger than the + * destination, we must consider one source limb beyond the destination + * size. If not, m is simply starts with zero. + */ + OSSL_FN_ULONG m = (dl < sl) ? (s[dl] << lshift) & lmask : 0; + + /* src and dst may be the same, that's why this loop is made this way */ + for (i = l; i-- > 0;) { + OSSL_FN_ULONG tmp = s[i]; + d[i] = m | ((tmp >> rshift) & OSSL_FN_MASK); + m = (tmp << lshift) & lmask; + } +} + +static inline OSSL_FN_ULONG div_words(OSSL_FN_ULONG *wnumtop, OSSL_FN_ULONG *wnum, + OSSL_FN_ULONG d1, OSSL_FN_ULONG d0) +{ +#if defined(BN_DIV3W) + return bn_div_3_words(wnumtop, d1, d0); +#else + OSSL_FN_ULONG n0 = wnumtop[0], n1 = wnumtop[-1], quo = 0, rem = 0; + + if (n0 == d0) + quo = OSSL_FN_MASK; + else { /* n0 < d0 */ + OSSL_FN_ULONG n2 = (wnumtop == wnum) ? 0 : wnumtop[-2]; +#ifdef BN_LLONG + BN_ULLONG t2; + +#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) + quo = (OSSL_FN_ULONG)(((((BN_ULLONG)n0) << OSSL_FN_BITS) | n1) / d0); +#else + quo = bn_div_words(n0, n1, d0); +#endif + +#ifndef REMAINDER_IS_ALREADY_CALCULATED + /* + * rem doesn't have to be BN_ULLONG. The least we + * know it's less that d0, isn't it? + */ + rem = (n1 - quo * d0) & BN_MASK2; +#endif + t2 = (BN_ULLONG)d1 * quo; + + for (;;) { + if (t2 <= ((((BN_ULLONG)rem) << OSSL_FN_BITS) | n2)) + break; + quo--; + rem += d0; + if (rem < d0) + break; /* don't let rem overflow */ + t2 -= d1; + } +#else /* !BN_LLONG */ + OSSL_FN_ULONG t2l, t2h; + + quo = bn_div_words(n0, n1, d0); +#ifndef REMAINDER_IS_ALREADY_CALCULATED + rem = (n1 - quo * d0) & OSSL_FN_MASK; +#endif + +#if defined(BN_UMULT_LOHI) + BN_UMULT_LOHI(t2l, t2h, d1, quo); +#elif defined(BN_UMULT_HIGH) + t2l = d1 * quo; + t2h = BN_UMULT_HIGH(d1, quo); +#else + { + OSSL_FN_ULONG ql, qh; + t2l = LBITS(d1); + t2h = HBITS(d1); + ql = LBITS(quo); + qh = HBITS(quo); + mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */ + } +#endif + + for (;;) { + if ((t2h < rem) || ((t2h == rem) && (t2l <= n2))) + break; + quo--; + rem += d0; + if (rem < d0) + break; /* don't let rem overflow */ + if (t2l < d1) + t2h--; + t2l -= d1; + } +#endif /* !BN_LLONG */ + } + + return quo; +#endif /* !BN_DIV3W */ +} + +size_t OSSL_FN_div_ctx_size(const OSSL_FN *q, const OSSL_FN *r, + const OSSL_FN *n, const OSSL_FN *d) +{ + if ((q == NULL && r == NULL) || n == NULL || d == NULL) + return 0; + + size_t nl = n->dsize; + size_t dl = d->dsize; + size_t snuml, tmp; + int err = 0; + + snuml = safe_add_size_t(nl > dl ? nl : dl, 1, &err); + tmp = safe_add_size_t(dl, 1, &err); + + size_t max_ql = nl == 0 ? 1 : nl; + size_t ql = (q == NULL || (size_t)q->dsize < max_ql) ? max_ql : 0; + size_t max_n_numbers = 3 + (ql != 0); + size_t max_n_limbs; + + max_n_limbs = safe_add_size_t(snuml, dl, &err); + max_n_limbs = safe_add_size_t(max_n_limbs, tmp, &err); + max_n_limbs = safe_add_size_t(max_n_limbs, ql, &err); + + return err == 0 ? OSSL_FN_CTX_size(1, max_n_numbers, max_n_limbs) : 0; +} + +/* Trivia: this function implements Knuth's algorithm D */ +int OSSL_FN_div(OSSL_FN *q, OSSL_FN *r, const OSSL_FN *n, const OSSL_FN *d, OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + if (token == NULL) + return 0; + + size_t nl = n->dsize; + size_t dl = d->dsize; + size_t ql = (q == NULL) ? 0 : q->dsize; + + /* + * We need to figure out the significant size of |d|, to avoid division by + * zero if the highest limb(s) are zero. + * + * This doesn't quite give a sense that division can be constant time. + * However, in the use cases where constant time is interesting (cryptosystems), + * it can be argued that the denominator would have a constant enough size + * within each cryptosystem (and size therein), so it's assumed that time + * will be constant because of that. + */ + while (dl > 0 && d->d[dl - 1] == 0) + dl--; + + if (dl == 0) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_DIV_BY_ZERO); + goto err; + } + + /* + * Because some assembler language instructions have those requirements, + * the denominator need to be shifted "left" so the top bit is always 1. + * To ensure that we still get correct results, the numerator will have + * to be shifted left as many bits. The resulting quotient will end up + * correct, but the remainder will have to be shifted "right" before the + * end of this function. + */ + OSSL_FN_ULONG norm_shift = OSSL_FN_BITS - BN_num_bits_word(d->d[dl - 1]); + + /* + * Store a copy the numerator in snum, padded with extra zeros if nl <= dl + * eventually, this will contain the remainder. Because it may be shifted + * up to almost a full limb to the left (worst case scenario), an extra limb + * need to be allocated. + */ + size_t snuml = ((nl <= dl) ? dl : nl) + 1; + OSSL_FN *snum = OSSL_FN_CTX_get_limbs(ctx, snuml); + if (!ossl_assert(snuml <= INT_MAX && snum != NULL)) + goto err; + copy_align_left(snum, n, norm_shift); + + /* + * Store a copy of the denominator in sdiv, shifted left so that its top bit + * is always 1. This is necessary to avoid gnarly arithmetic exceptions when + * the denominator's highest limb is a very small number. + */ + size_t sdivl = dl; + OSSL_FN *sdiv = OSSL_FN_CTX_get_limbs(ctx, sdivl); + if (!ossl_assert(sdivl <= INT_MAX && sdiv != NULL)) + goto err; + copy_align_left(sdiv, d, norm_shift); + + /* + * The number of times we will iterate to perform division, i.e. + * how often we will "shift" the divisor "window" over the numerator. + * This also determines the size of the result. + * + * For the math oriented: + * + * snuml - sdivl = ((nl <= dl) ? dl : nl) + 1 - dl + * => snuml - sdivl = ((nl <= dl) ? 0 : nl - dl) + 1 + * => snuml - sdivl = (nl <= dl) ? 1 : nl - dl + 1 + */ + size_t loop = snuml - sdivl; + + /* + * Set up the quotient. It will be stored directly in |q| if it has + * enough space, otherwise temporary storage is allocated. + */ + OSSL_FN *res = (ql < loop) ? OSSL_FN_CTX_get_limbs(ctx, loop) : q; + if (!ossl_assert(res != NULL)) + goto err; + + /* Position of the next quotient limb to be calculated, plus one */ + OSSL_FN_ULONG *resp = &(res->d[loop]); + + /* Intermediary storage */ + OSSL_FN *tmp = OSSL_FN_CTX_get_limbs(ctx, sdivl + 1); + if (!ossl_assert(tmp != NULL)) + goto err; + + /* Set up the "window" position in snum. */ + OSSL_FN_ULONG *wnum = &(snum->d[loop]); + OSSL_FN_ULONG *wnumtop = &(snum->d[snuml - 1]); + + /* Get the top 2 words of the denominator */ + OSSL_FN_ULONG d0 = sdiv->d[sdivl - 1]; + OSSL_FN_ULONG d1 = (sdivl == 1) ? 0 : sdiv->d[sdivl - 2]; + + size_t i; + + /* If res is larger than the expected result, zero the limbs above */ + for (i = res->dsize; i > loop;) + res->d[--i] = 0; + for (i = 0; i < loop; i++, wnumtop--) { + OSSL_FN_ULONG quo, l0; + /* + * the first part of the loop uses the top two words of snum and sdiv + * to calculate a OSSL_FN_ULONG quo such that | wnum - d * q | < d + */ + quo = div_words(wnumtop, wnum, d1, d0); + + l0 = bn_mul_words(tmp->d, sdiv->d, (int)sdivl, quo); + tmp->d[sdivl] = l0; + wnum--; + + /* + * ignore top values of the bignums just sub the two OSSL_FN_ULONG + * arrays with bn_sub_words + */ + l0 = bn_sub_words(wnum, wnum, tmp->d, (int)sdivl + 1); + quo -= l0; + + /* + * Note: As we have considered only the leading two OSSL_FN_ULONGs + * in the calculation of q, d * q might be greater than wnum + * (but then (q-1) * d is less than or equal to wnum) + */ + size_t j; + for (l0 = 0 - l0, j = 0; j < sdivl; j++) + tmp->d[j] = sdiv->d[j] & l0; + l0 = bn_add_words(wnum, wnum, tmp->d, (int)sdivl); + (*wnumtop) += l0; + assert((*wnumtop) == 0); + + /* store part of the result */ + *--resp = quo; + } + /* snum holds remainder, it's as wide as divisor */ + if (r != NULL) + copy_align_right(r, snum, norm_shift); + /* res holds the quotient for a total of loop limbs, and is separate from q if ql < loop */ + if (q != NULL && q != res && OSSL_FN_copy_truncate(q, res) == 0) + goto err; + + OSSL_FN_CTX_end(ctx, token); + return 1; +err: + OSSL_FN_CTX_end(ctx, token); + return 0; +} diff --git a/crypto/fn/fn_err.c b/crypto/fn/fn_err.c new file mode 100644 index 0000000000..69c137feac --- /dev/null +++ b/crypto/fn/fn_err.c @@ -0,0 +1,42 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "crypto/fnerr.h" + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA OSSL_FN_str_reasons[] = { + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_DIV_BY_ZERO), "div by zero" }, + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_INVALID_RANGE), + "invalid range" }, + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_INPUT_NOT_REDUCED), + "input not reduced" }, + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_INVALID_SHIFT), + "invalid shift" }, + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_RESULT_ARG_TOO_SMALL), + "result arg too small" }, + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_BITS_TOO_SMALL), + "bits too small" }, + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_TOO_MANY_ITERATIONS), + "too many iterations" }, + { 0, NULL } +}; + +#endif + +int ossl_err_load_OSSL_FN_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_reason_error_string(OSSL_FN_str_reasons[0].error) == NULL) + ERR_load_strings_const(OSSL_FN_str_reasons); +#endif + return 1; +} diff --git a/crypto/fn/fn_intern.c b/crypto/fn/fn_intern.c new file mode 100644 index 0000000000..6113ccd215 --- /dev/null +++ b/crypto/fn/fn_intern.c @@ -0,0 +1,56 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "crypto/fn_intern.h" +#include "crypto/fnerr.h" +#include "fn_local.h" +#include + +int ossl_fn_set_words(OSSL_FN *f, const OSSL_FN_ULONG *words, size_t limbs) +{ + if (ossl_unlikely(f == NULL)) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if ((size_t)f->dsize < limbs) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL); + return 0; + } + + memcpy(f->d, words, sizeof(OSSL_FN_ULONG) * limbs); + memset(f->d + limbs, 0, sizeof(OSSL_FN_ULONG) * (f->dsize - limbs)); + return 1; +} + +const OSSL_FN_ULONG *ossl_fn_get_words(const OSSL_FN *f) +{ + if (ossl_unlikely(f == NULL)) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + return f->d; +} + +size_t ossl_fn_get_dsize(const OSSL_FN *f) +{ + return f->dsize; +} + +bool ossl_fn_is_dynamically_allocated(const OSSL_FN *f) +{ + return f->is_dynamically_allocated; +} + +bool ossl_fn_is_securely_allocated(const OSSL_FN *f) +{ + return f->is_securely_allocated; +} diff --git a/crypto/fn/fn_lib.c b/crypto/fn/fn_lib.c new file mode 100644 index 0000000000..08b78f6c02 --- /dev/null +++ b/crypto/fn/fn_lib.c @@ -0,0 +1,346 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/common.h" +#include "crypto/fnerr.h" +#include "fn_local.h" +#include "internal/constant_time.h" + +static OSSL_FN *ossl_fn_new_internal(size_t limbs, bool securely) +{ + /* Total size of the whole OSSL_FN, in bytes */ + size_t totalsize = ossl_fn_totalsize(limbs); + if (totalsize == 0) + return NULL; + + OSSL_FN *ret = NULL; + + if (securely) + ret = OPENSSL_secure_zalloc(totalsize); + else + ret = OPENSSL_zalloc(totalsize); + + if (ret != NULL) { + ret->dsize = (int)limbs; + ret->is_dynamically_allocated = 1; + ret->is_securely_allocated = securely; + } + return ret; +} + +static void ossl_fn_free_internal(OSSL_FN *f, bool clear) +{ + if (f == NULL) + return; + + size_t limbssize = f->dsize * sizeof(OSSL_FN_ULONG); + size_t totalsize = limbssize + sizeof(OSSL_FN); + + if (f->is_dynamically_allocated) { + if (f->is_securely_allocated) + OPENSSL_secure_clear_free(f, totalsize); + else if (clear) + OPENSSL_clear_free(f, totalsize); + else + OPENSSL_free(f); + } else if (clear) { + OPENSSL_cleanse(f->d, limbssize); + } +} + +OSSL_FN *OSSL_FN_new_limbs(size_t size) +{ + return ossl_fn_new_internal(size, false); +} + +OSSL_FN *OSSL_FN_secure_new_limbs(size_t size) +{ + return ossl_fn_new_internal(size, true); +} + +OSSL_FN *OSSL_FN_new_bytes(size_t size) +{ + return OSSL_FN_new_limbs(ossl_fn_bytes_to_limbs(size)); +} + +OSSL_FN *OSSL_FN_secure_new_bytes(size_t size) +{ + return OSSL_FN_secure_new_limbs(ossl_fn_bytes_to_limbs(size)); +} + +OSSL_FN *OSSL_FN_new_bits(size_t size) +{ + return OSSL_FN_new_bytes(ossl_fn_bits_to_bytes(size)); +} + +OSSL_FN *OSSL_FN_secure_new_bits(size_t size) +{ + return OSSL_FN_secure_new_bytes(ossl_fn_bits_to_bytes(size)); +} + +void OSSL_FN_free(OSSL_FN *f) +{ + ossl_fn_free_internal(f, false); +} + +void OSSL_FN_clear_free(OSSL_FN *f) +{ + ossl_fn_free_internal(f, true); +} + +void OSSL_FN_clear(OSSL_FN *f) +{ + size_t limbssize = f->dsize * sizeof(OSSL_FN_ULONG); + + OPENSSL_cleanse(f->d, limbssize); +} + +/*- + * Sets a->d[0] to |w| and zeroes the remaining limbs, so the full dsize + * array reflects the value |w|. OSSL_FN is fixed-size: if a->dsize is 0 + * there is no limb to write and the call fails with + * OSSL_FN_R_RESULT_ARG_TOO_SMALL (the same reason ossl_fn_set_words() raises + * for an undersized destination). + * + * Constant-time with respect to |w|'s value: there is no value-dependent + * control flow, since the full dsize array always holds the value. The only + * branch is on the operand's public width (dsize). + */ +int OSSL_FN_set_word(OSSL_FN *a, OSSL_FN_ULONG w) +{ + size_t dsize = (size_t)a->dsize; + + if (ossl_unlikely(dsize < 1)) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL); + return 0; + } + + a->d[0] = w; + if (dsize > 1) + memset(&a->d[1], 0, sizeof(OSSL_FN_ULONG) * (dsize - 1)); + return 1; +} + +/*- + * Equivalent to OSSL_FN_set_word(a, 1). Kept as a named function rather + * than a macro or static inline, consistent with the rest of + * crypto/fn/fn_lib.c. Leak profile as for OSSL_FN_set_word(). + */ +int OSSL_FN_one(OSSL_FN *a) +{ + return OSSL_FN_set_word(a, OSSL_FN_ULONG_C(1)); +} + +/*- + * Equivalent to OSSL_FN_set_word(a, 0). This is a plain value assignment, + * not a secure wipe: the compiler may optimise the writes away if the value + * is not subsequently observed. Use OSSL_FN_clear() (which calls + * OPENSSL_cleanse()) when the limbs may hold secret data and must be wiped + * irreversibly. Leak profile as for OSSL_FN_set_word(). + */ +int OSSL_FN_zero(OSSL_FN *a) +{ + return OSSL_FN_set_word(a, OSSL_FN_ULONG_C(0)); +} + +static size_t ossl_fn_num_bits_word(OSSL_FN_ULONG l) +{ + OSSL_FN_ULONG x, mask; + size_t bits = (size_t)constant_time_select_int( + (unsigned int)constant_time_is_zero_bn(l), 0, 1); + +#if OSSL_FN_BITS > 32 + x = l >> 32; + mask = ~constant_time_is_zero_bn(x); + bits += 32 & (size_t)mask; + l ^= (x ^ l) & mask; +#endif + + x = l >> 16; + mask = ~constant_time_is_zero_bn(x); + bits += 16 & (size_t)mask; + l ^= (x ^ l) & mask; + + x = l >> 8; + mask = ~constant_time_is_zero_bn(x); + bits += 8 & (size_t)mask; + l ^= (x ^ l) & mask; + + x = l >> 4; + mask = ~constant_time_is_zero_bn(x); + bits += 4 & (size_t)mask; + l ^= (x ^ l) & mask; + + x = l >> 2; + mask = ~constant_time_is_zero_bn(x); + bits += 2 & (size_t)mask; + l ^= (x ^ l) & mask; + + x = l >> 1; + mask = ~constant_time_is_zero_bn(x); + bits += 1 & (size_t)mask; + + return bits; +} + +size_t OSSL_FN_num_bits(const OSSL_FN *a) +{ + size_t i; + size_t dsize = (size_t)a->dsize; + size_t ret = 0; + + for (i = 0; i < dsize; i++) { + size_t limb_bits = ossl_fn_num_bits_word(a->d[i]); + size_t bits = i * OSSL_FN_BITS + limb_bits; + size_t mask = (size_t)~constant_time_is_zero_bn(a->d[i]); + + ret = constant_time_select_s(mask, bits, ret); + } + + return ret; +} + +int OSSL_FN_cmp(const OSSL_FN *a, const OSSL_FN *b) +{ + size_t i; + size_t asize = (size_t)a->dsize; + size_t bsize = (size_t)b->dsize; + size_t max = asize > bsize ? asize : bsize; + int res = 0; + + for (i = 0; i < max; i++) { + OSSL_FN_ULONG aw = i < asize ? a->d[i] : 0; + OSSL_FN_ULONG bw = i < bsize ? b->d[i] : 0; + + res = constant_time_select_int( + (unsigned int)constant_time_lt_bn(aw, bw), -1, res); + res = constant_time_select_int( + (unsigned int)constant_time_lt_bn(bw, aw), 1, res); + } + + return res; +} + +/*- + * Returns bit |n| of |a|. An out-of-range index (n < 0 or n >= the + * operand's width in bits) reads as 0. The only control flow branches on + * the operand's public width (dsize); the returned value is the bit itself, + * which is the information the caller asked for. + */ +int OSSL_FN_is_bit_set(const OSSL_FN *a, int n) +{ + size_t limb, off; + + if (n < 0) + return 0; + limb = (size_t)n / OSSL_FN_BITS; + off = (size_t)n % OSSL_FN_BITS; + if (limb >= (size_t)a->dsize) + return 0; + return (a->d[limb] >> off) & OSSL_FN_ULONG_C(1); +} + +/*- + * Returns 1 if the unsigned value of |a| equals the single-limb word |w|. + * Control flow branches only on the operand's public width (dsize); limb + * values are combined with constant-time selects, so the number of limbs + * inspected depends only on the public width, not on the operand's value. + * The returned value is the equality test the caller asked for. + */ +int OSSL_FN_is_word(const OSSL_FN *a, OSSL_FN_ULONG w) +{ + size_t i; + size_t dsize = (size_t)a->dsize; + int res; + + if (dsize == 0) + return w == 0; + + res = constant_time_select_int( + (unsigned int)constant_time_eq_bn(a->d[0], w), 1, 0); + for (i = 1; i < dsize; i++) + res = constant_time_select_int( + (unsigned int)constant_time_is_zero_bn(a->d[i]), res, 0); + return res; +} + +/*- + * Equivalent to OSSL_FN_is_word(a, 0), kept as a named predicate for + * readability at call sites. Leak profile as for OSSL_FN_is_word(): + * branches only on the operand's public width (dsize). + */ +int OSSL_FN_is_zero(const OSSL_FN *a) +{ + return OSSL_FN_is_word(a, 0); +} + +/*- + * Equivalent to OSSL_FN_is_word(a, 1), kept as a named predicate for + * readability at call sites. Leak profile as for OSSL_FN_is_word(): + * branches only on the operand's public width (dsize). + */ +int OSSL_FN_is_one(const OSSL_FN *a) +{ + return OSSL_FN_is_word(a, 1); +} + +/*- + * Returns the least significant bit of |a|, which is the information the + * caller asked for. The only control flow branches on the operand's public + * width (dsize), not on limb values. + */ +int OSSL_FN_is_odd(const OSSL_FN *a) +{ + if (a->dsize <= 0) + return 0; + return (int)(a->d[0] & OSSL_FN_ULONG_C(1)); +} + +OSSL_FN *OSSL_FN_copy(OSSL_FN *a, const OSSL_FN *b) +{ + if (ossl_unlikely(a == b)) + return a; + + size_t al = a->dsize; + size_t bl = b->dsize; + + if (al < bl) { + ERR_raise_data(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL, + "Needs to be at least %zu bytes, but is only %zu bytes", + bl * sizeof(OSSL_FN_ULONG), al * sizeof(OSSL_FN_ULONG)); + return 0; + } + + memcpy(a->d, b->d, bl * sizeof(OSSL_FN_ULONG)); + memset(a->d + bl, 0, (al - bl) * sizeof(OSSL_FN_ULONG)); + return a; +} + +OSSL_FN *OSSL_FN_copy_truncate(OSSL_FN *a, const OSSL_FN *b) +{ + if (ossl_unlikely(a == b)) + return a; + + size_t al = a->dsize; + size_t bl = b->dsize; + + if (ossl_unlikely(al > bl)) { + memcpy(a->d, b->d, bl * sizeof(OSSL_FN_ULONG)); + memset(&a->d[bl], 0, sizeof(OSSL_FN_ULONG) * (al - bl)); + } else { + memcpy(a->d, b->d, al * sizeof(OSSL_FN_ULONG)); + } + + return a; +} diff --git a/crypto/fn/fn_local.h b/crypto/fn/fn_local.h new file mode 100644 index 0000000000..3cb6fc05ad --- /dev/null +++ b/crypto/fn/fn_local.h @@ -0,0 +1,182 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_CRYPTO_FN_LOCAL_H +#define OSSL_CRYPTO_FN_LOCAL_H + +#include +#include +#include +#include +#include +#include "internal/common.h" +#include "crypto/fn.h" +#include "crypto/fn_intern.h" + +#if OSSL_FN_BYTES == 4 +/* 32-bit systems */ +#define OSSL_FN_ULONG_C(n) UINT32_C(n) +#define OSSL_FN_MASK UINT32_MAX +#elif OSSL_FN_BYTES == 8 +#define OSSL_FN_ULONG_C(n) UINT64_C(n) +#define OSSL_FN_MASK UINT64_MAX +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif + +#define OSSL_FN_BITS (OSSL_FN_BYTES * 8) +#define OSSL_FN_HIGH_BIT_MASK (OSSL_FN_ULONG_C(1) << (OSSL_FN_BITS - 1)) +#define OSSL_FN_LOW_HALF_MASK ((OSSL_FN_ULONG_C(1) << (OSSL_FN_BITS / 2)) - 1) +#define OSSL_FN_HIGH_HALF_MASK (OSSL_FN_LOW_HALF_MASK << (OSSL_FN_BITS / 2)) + +struct ossl_fn_st { + /* Flag: alloced with OSSL_FN_new() or OSSL_FN_secure_new() */ + unsigned int is_dynamically_allocated : 1; + /* Flag: alloced with OSSL_FN_secure_new() */ + unsigned int is_securely_allocated : 1; + + /* + * The d array, with its size in number of OSSL_FN_ULONG. + * This stores the number itself. + * + * Note: |dsize| is an int, because it turns out that some lower level + * (possibly assembler) functions expect that type (especially, that + * type size). + * This deviates from the design in doc/designs/fixed-size-large-numbers.md + */ + int dsize; + OSSL_FN_ULONG d[]; +}; + +static ossl_inline size_t ossl_fn_totalsize(size_t limbs) +{ + /* + * TODO(FIXNUM): Since the number of limbs is currently represented + * as an 'int' in OSSL_FN, we must ensure that the desired size isn't + * larger than can be represented. + */ + if (ossl_unlikely(limbs >= INT_MAX)) + return 0; + + /* + * sizeof(OSSL_FN) + limbs * sizeof(OSSL_FN_ULONG) > SIZE_MAX + * => limbs * sizeof(OSSL_FN_ULONG) > SIZE_MAX - sizeof(OSSL_FN) + * => limbs > (SIZE_MAX - sizeof(OSSL_FN)) / sizeof(OSSL_FN_ULONG) + */ + if (ossl_unlikely(limbs > (SIZE_MAX - sizeof(OSSL_FN)) / sizeof(OSSL_FN_ULONG))) + return 0; + return sizeof(OSSL_FN) + limbs * sizeof(OSSL_FN_ULONG); +} + +static ossl_inline size_t ossl_fn_bytes_to_limbs(size_t size) +{ + return (size + sizeof(OSSL_FN_ULONG) - 1) / sizeof(OSSL_FN_ULONG); +} + +static ossl_inline size_t ossl_fn_bits_to_bytes(size_t size) +{ + return (size + 7) / 8; +} + +/* + * Internal functions to support BIGNUM's bn_expand_internal, BN_copy, and + * similar. + * The caller must ensure that src and dest are not NULL. + * With ossl_fn_copy_internal, bn_words may be given -1 to signify that the + * number of BN_ULONG should be found in src. + */ +static ossl_inline OSSL_FN *ossl_fn_copy_internal_limbs(OSSL_FN *dest, + const OSSL_FN_ULONG *src, + int limbs) +{ + if (ossl_unlikely(dest->dsize < limbs)) + return NULL; + memcpy(dest->d, src, limbs * sizeof(dest->d[0])); + memset(dest->d + limbs, 0, (dest->dsize - limbs) * sizeof(dest->d[0])); + return dest; +} + +static ossl_inline OSSL_FN *ossl_fn_copy_internal(OSSL_FN *dest, + const OSSL_FN *src, + int bn_words) +{ + int words = bn_words < 0 ? src->dsize : bn_words; + + if (ossl_fn_copy_internal_limbs(dest, src->d, words) == NULL) + return NULL; + return dest; +} + +/* OSSL_FN_CTX internals */ + +struct ossl_fn_ctx_st { + /* + * Pointer to the last OSSL_FN_CTX_start() location (a simple pointer into + * the memory area). See the struct ossl_fn_ctx_frame_st definition below + * for details. + */ + struct ossl_fn_ctx_frame_st *last_frame; + + /* + * Flags + */ + unsigned int is_securely_allocated : 1; + + /* + * Current and peak usage tracking, by allocation components. + * The |n_*| fields hold the currently active counts; the |peak_n_*| + * fields hold the maximum each count has ever reached simultaneously. + * This allows callers to determine suitable arena parameters for a + * given workload without precise up-front prediction. + */ + size_t n_frames; + size_t n_numbers; + size_t n_limbs; + size_t peak_n_frames; + size_t peak_n_numbers; + size_t peak_n_limbs; + + /* + * The arena itself. + */ + size_t msize; /* Size of the arena, in bytes */ + unsigned char memory[]; +}; + +struct ossl_fn_ctx_frame_st { + /* + * Pointer back to the whole arena where the frame is located, + * for |last_frame| bookkeeping. + */ + struct ossl_fn_ctx_st *arena; + /* + * Pointer to the previous frame in the arena, allowing OSSL_FN_CTX_end() + * to do its job. + */ + struct ossl_fn_ctx_frame_st *previous_frame; + /* + * Tracking for peak usage instrumentation. These count the OSSL_FN + * instances and total limbs allocated within this frame. + */ + size_t n_numbers; + size_t n_limbs; + /* + * Every time OSSL_FN_CTX_get() is called, the current value of + * |free_memory| is returned, and it's updated by incrementing it + * by the number of bytes given by OSSL_FN_CTX_get(). + * The available number of bytes is limited by what's left in the arena. + */ + unsigned char *free_memory; /* Pointer to the free area of the frame */ + size_t msize; /* Size of the frame, in bytes */ + unsigned char memory[]; +}; + +/* end OSSL_FN_CTX internals */ + +#endif diff --git a/crypto/fn/fn_mod.c b/crypto/fn/fn_mod.c new file mode 100644 index 0000000000..110e8dc6b3 --- /dev/null +++ b/crypto/fn/fn_mod.c @@ -0,0 +1,564 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "internal/nelem.h" +#include "internal/safe_math.h" +#include "crypto/fnerr.h" +#include "fn_local.h" + +OSSL_SAFE_MATH_ADDU(size_t, size_t, OSSL_SAFE_MATH_MAXU(size_t)) +OSSL_SAFE_MATH_MULU(size_t, size_t, OSSL_SAFE_MATH_MAXU(size_t)) + +static size_t ctx_add_size(size_t a, size_t b) +{ + int err = 0; + size_t r = safe_add_size_t(a, b, &err); + + return err == 0 ? r : 0; +} + +static size_t ctx_max_size(size_t a, size_t b) +{ + return a > b ? a : b; +} + +/* + * The *_ctx_size helpers below use local OSSL_FN headers with only |dsize| + * set to represent temporaries that the corresponding operation allocates + * with OSSL_FN_CTX_get_limbs(). This is enough for nested ctx-size helpers, + * which only inspect operand sizes. + */ +size_t OSSL_FN_mod_add_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b, const OSSL_FN *m) +{ + size_t tl, own_size, nested_size; + + if (r == NULL || a == NULL || b == NULL || m == NULL) + return 0; + int err = 0; + + tl = safe_add_size_t(a->dsize > b->dsize ? a->dsize : b->dsize, + 1, &err); + if (err != 0 || ossl_fn_totalsize(tl) == 0) + return 0; + + OSSL_FN t = { .dsize = (int)tl }; + + own_size = OSSL_FN_CTX_size(1, 1, tl); + nested_size = OSSL_FN_mod_ctx_size(r, &t, m); + if (own_size == 0 || nested_size == 0) + return 0; + + return ctx_add_size(own_size, nested_size); +} + +int OSSL_FN_mod_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m, OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + OSSL_FN *t; + int ret = 0; + size_t tl = (a->dsize > b->dsize ? a->dsize : b->dsize) + 1; + + if (token == NULL) + return 0; + if ((t = OSSL_FN_CTX_get_limbs(ctx, tl)) == NULL) + goto err; + + ret = OSSL_FN_add(t, a, b) + && OSSL_FN_mod(r, t, m, ctx); + +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} + +/* + * OSSL_FN_mod_add variant that may be used if both a and b are less than m. + * The original formula is: + * + * r' = a + b + * r = r′ − m[r′ ≥ m] + * + * This is replaced with addition, subtracting modulus, and conditional move + * depending on whether or not subtraction borrowed. + */ +int OSSL_FN_mod_add_quick(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m) +{ + size_t al = a->dsize; + size_t bl = b->dsize; + size_t rl = r->dsize; + size_t ml = m->dsize; + size_t aw = al < ml ? al : ml; + size_t bw = bl < ml ? bl : ml; + OSSL_FN_ULONG storage[2 * 1024 / OSSL_FN_BITS]; + OSSL_FN_ULONG *tp = storage; + OSSL_FN_ULONG *mp = storage + ml; + OSSL_FN_ULONG carry, borrow; + size_t i; + + if (2 * ml > OSSL_NELEM(storage)) { + tp = OPENSSL_malloc_array(2 * ml, sizeof(OSSL_FN_ULONG)); + if (tp == NULL) + return 0; + mp = tp + ml; + } + + /* tp = a + b mod 2^(ml*bits) */ + carry = ossl_fn_add_words(tp, ml, a->d, aw, b->d, bw); + + /* mp = tp - m mod 2^(ml*bits) */ + borrow = ossl_fn_sub_words(mp, ml, tp, ml, m->d, ml); + + /* + * Because a, b < m, we have a + b < 2m. Therefore tp < m whenever + * carry = 1, which forces borrow = 1. The mask carry − borrow thus + * only produces 0 (select tp2) or ~0 (select tp), matching exactly + * whether a + b ≥ m. + * + * Thus, we have the cases: + * + * a + b < m => carry == 0, borrow == 1 + * m <= a+b < 2^(ml*bits) => carry == 0, borrow == 0 + * 2^(ml*bits) <= a+b < 2m => carry == 1, borrow == 1 + * + * If (a + b < m), select tp; otherwise select tp2. Done with the + * help of a mask. + */ + OSSL_FN_ULONG mask = carry - borrow; + size_t end = (rl < ml) ? rl : ml; + for (i = 0; i < end; i++) + r->d[i] = (mask & tp[i]) | (~mask & mp[i]); + /* Make sure to pad r with zeroes when rl > ml */ + for (; i < rl; i++) + r->d[i] = 0; + + if (tp != storage) + OPENSSL_clear_free(tp, 2 * ml * sizeof(OSSL_FN_ULONG)); + else + OPENSSL_cleanse(storage, sizeof(storage)); + + return 1; +} + +size_t OSSL_FN_mod_sub_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b, const OSSL_FN *m) +{ + size_t ml, n_numbers, own_size, mod_a_size, mod_b_size, nested_size; + + if (r == NULL || a == NULL || b == NULL || m == NULL) + return 0; + + ml = m->dsize; + n_numbers = (r == m) ? 3 : 2; + if (ossl_fn_totalsize(ml) == 0) + return 0; + + OSSL_FN am = { .dsize = (int)ml }; + OSSL_FN bm = { .dsize = (int)ml }; + + own_size = OSSL_FN_CTX_size(1, n_numbers, n_numbers * ml); + mod_a_size = OSSL_FN_mod_ctx_size(&am, a, m); + mod_b_size = OSSL_FN_mod_ctx_size(&bm, b, m); + nested_size = ctx_max_size(mod_a_size, mod_b_size); + if (own_size == 0 || nested_size == 0) + return 0; + + return ctx_add_size(own_size, nested_size); +} + +int OSSL_FN_mod_sub(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m, OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + OSSL_FN *am, *bm, *rr = r; + int ret = 0; + + if (token == NULL) + return 0; + if ((am = OSSL_FN_CTX_get_limbs(ctx, m->dsize)) == NULL + || (bm = OSSL_FN_CTX_get_limbs(ctx, m->dsize)) == NULL) + goto err; + + if (r == m && (rr = OSSL_FN_CTX_get_limbs(ctx, m->dsize)) == NULL) + goto err; + + ret = OSSL_FN_mod(am, a, m, ctx) + && OSSL_FN_mod(bm, b, m, ctx) + && OSSL_FN_mod_sub_quick(rr, am, bm, m) + && (rr == r || OSSL_FN_copy_truncate(r, rr) != NULL); + +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} + +/* + * OSSL_FN_mod_sub variant that may be used if a is less than m, while b is + * of same bit width as m. It's implemented as subtraction followed by two + * conditional additions. + * + * 0 <= a < m + * 0 <= b < 2^w < 2*m + * + * after subtraction + * + * -2*m < r = a - b < m + * + * The original formula is: + * + * r' = a - b + * r'' = r' + m[r' < 0] + * r = r′' + m[r′' < 0] + * + * Because masking techniques are used, this is most efficiently + * carried out with local loops rather than calling functions like + * ossl_fn_add_words(). + */ +int OSSL_FN_mod_sub_quick(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m) +{ + if (r == m) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + size_t al = a->dsize; + size_t bl = b->dsize; + size_t rl = r->dsize; + size_t ml = m->dsize; + size_t aw = al < ml ? al : ml; + size_t bw = bl < ml ? bl : ml; + OSSL_FN_ULONG storage[1024 / OSSL_FN_BITS]; + OSSL_FN_ULONG *tp = storage; + size_t i; + OSSL_FN_ULONG borrow, carry, ta, mask; + + if (ml > OSSL_NELEM(storage)) { + tp = OPENSSL_malloc_array(ml, sizeof(OSSL_FN_ULONG)); + if (tp == NULL) + return 0; + } + + /* tp = a - b mod 2^(ml*bits) */ + borrow = ossl_fn_sub_words(tp, ml, a->d, aw, b->d, bw); + + /* If borrow, add m */ + for (i = 0, mask = 0 - borrow, carry = 0; i < ml; i++) { + ta = ((m->d[i] & mask) + carry) & OSSL_FN_MASK; + carry = (ta < carry); + tp[i] = (tp[i] + ta) & OSSL_FN_MASK; + carry += (tp[i] < ta); + } + + /* If still borrow, add m again */ + borrow -= carry; + for (i = 0, mask = 0 - borrow, carry = 0; i < ml; i++) { + ta = ((m->d[i] & mask) + carry) & OSSL_FN_MASK; + carry = (ta < carry); + tp[i] = (tp[i] + ta) & OSSL_FN_MASK; + carry += (tp[i] < ta); + } + + for (i = 0; i < rl && i < ml; i++) + r->d[i] = tp[i]; + /* Make sure to pad r with zeroes when rl > ml */ + for (; i < rl; i++) + r->d[i] = 0; + + if (tp != storage) + OPENSSL_clear_free(tp, ml * sizeof(OSSL_FN_ULONG)); + else + OPENSSL_cleanse(storage, sizeof(storage)); + + return 1; +} + +size_t OSSL_FN_mod_mul_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b, const OSSL_FN *m) +{ + size_t tl, own_size, mul_size, mod_size, nested_size; + + if (r == NULL || a == NULL || b == NULL || m == NULL) + return 0; + + if (a == b) { + int err = 0; + + tl = safe_mul_size_t(2, a->dsize, &err); + if (err != 0 || ossl_fn_totalsize(tl) == 0) + return 0; + OSSL_FN t = { .dsize = (int)tl }; + + mul_size = OSSL_FN_sqr_ctx_size(&t, a); + mod_size = OSSL_FN_mod_ctx_size(r, &t, m); + } else { + int err = 0; + + tl = safe_add_size_t(a->dsize, b->dsize, &err); + if (err != 0 || ossl_fn_totalsize(tl) == 0) + return 0; + OSSL_FN t = { .dsize = (int)tl }; + + mul_size = OSSL_FN_mul_ctx_size(&t, a, b); + mod_size = OSSL_FN_mod_ctx_size(r, &t, m); + } + + own_size = OSSL_FN_CTX_size(1, 1, tl); + nested_size = ctx_max_size(mul_size, mod_size); + if (own_size == 0 || nested_size == 0) + return 0; + + return ctx_add_size(own_size, nested_size); +} + +/* slow but works */ +int OSSL_FN_mod_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m, OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + OSSL_FN *t; + int ret = 0; + + if (token == NULL) + return 0; + + if (a == b) { + size_t tl = 2 * a->dsize; + + if ((t = OSSL_FN_CTX_get_limbs(ctx, tl)) == NULL + || !OSSL_FN_sqr(t, a, ctx)) + goto err; + } else { + size_t tl = a->dsize + b->dsize; + + if ((t = OSSL_FN_CTX_get_limbs(ctx, tl)) == NULL + || !OSSL_FN_mul(t, a, b, ctx)) + goto err; + } + if (!OSSL_FN_mod(r, t, m, ctx)) + goto err; + ret = 1; +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} + +size_t OSSL_FN_mod_sqr_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *m) +{ + size_t tl, own_size, sqr_size, mod_size, nested_size; + + if (r == NULL || a == NULL || m == NULL) + return 0; + int err = 0; + + tl = safe_mul_size_t(2, a->dsize, &err); + if (err != 0 || ossl_fn_totalsize(tl) == 0) + return 0; + + OSSL_FN t = { .dsize = (int)tl }; + + own_size = OSSL_FN_CTX_size(1, 1, tl); + sqr_size = OSSL_FN_sqr_ctx_size(&t, a); + mod_size = OSSL_FN_mod_ctx_size(r, &t, m); + nested_size = ctx_max_size(sqr_size, mod_size); + if (own_size == 0 || nested_size == 0) + return 0; + + return ctx_add_size(own_size, nested_size); +} + +int OSSL_FN_mod_sqr(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *m, + OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + OSSL_FN *t; + int ret = 0; + + if (token == NULL) + return 0; + if ((t = OSSL_FN_CTX_get_limbs(ctx, (size_t)(2 * a->dsize))) == NULL) + goto err; + + ret = OSSL_FN_sqr(t, a, ctx) + && OSSL_FN_mod(r, t, m, ctx); + +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} + +size_t OSSL_FN_mod_lshift1_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *m) +{ + size_t tl, own_size, nested_size; + + if (r == NULL || a == NULL || m == NULL) + return 0; + int err = 0; + + tl = safe_add_size_t(m->dsize, 1, &err); + if (err != 0 || ossl_fn_totalsize(tl) == 0) + return 0; + + OSSL_FN t = { .dsize = (int)tl }; + + own_size = OSSL_FN_CTX_size(1, 1, tl); + nested_size = OSSL_FN_mod_ctx_size(r, &t, m); + if (own_size == 0 || nested_size == 0) + return 0; + + return ctx_add_size(own_size, nested_size); +} + +int OSSL_FN_mod_lshift1(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *m, + OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + OSSL_FN *t; + int ret = 0; + + if (token == NULL) + return 0; + if ((t = OSSL_FN_CTX_get_limbs(ctx, (size_t)(m->dsize + 1))) == NULL) + goto err; + + ret = OSSL_FN_lshift1(t, a) + && OSSL_FN_mod(r, t, m, ctx); + +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} + +/* OSSL_FN_mod_lshift1 variant that may be used if a is less than m */ +int OSSL_FN_mod_lshift1_quick(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *m) +{ + OSSL_FN *t = OSSL_FN_new_limbs((size_t)(m->dsize + 1)); + int ret = 0; + + if (t == NULL) + return 0; + if (!OSSL_FN_lshift1(t, a)) + goto err; + if (OSSL_FN_cmp(t, m) >= 0) { + if (!OSSL_FN_sub(t, t, m)) + goto err; + } + OSSL_FN_copy_truncate(r, t); + ret = 1; +err: + OSSL_FN_free(t); + return ret; +} + +size_t OSSL_FN_mod_lshift_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + int n, const OSSL_FN *m) +{ + size_t ml, own_size, nested_size; + + if (r == NULL || a == NULL || m == NULL) + return 0; + (void)n; + + ml = m->dsize; + if (ossl_fn_totalsize(ml) == 0) + return 0; + + OSSL_FN ra = { .dsize = (int)ml }; + + own_size = OSSL_FN_CTX_size(1, 1, ml); + nested_size = OSSL_FN_mod_ctx_size(&ra, a, m); + if (own_size == 0 || nested_size == 0) + return 0; + + return ctx_add_size(own_size, nested_size); +} + +int OSSL_FN_mod_lshift(OSSL_FN *r, const OSSL_FN *a, int n, const OSSL_FN *m, + OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + OSSL_FN *ra; + int ret = 0; + + if (token == NULL) + return 0; + if ((ra = OSSL_FN_CTX_get_limbs(ctx, m->dsize)) == NULL) + goto err; + + ret = OSSL_FN_mod(ra, a, m, ctx) + && OSSL_FN_mod_lshift_quick(r, ra, n, m); + +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} + +/* OSSL_FN_mod_lshift variant that may be used if a is less than m */ +int OSSL_FN_mod_lshift_quick(OSSL_FN *r, const OSSL_FN *a, int n, + const OSSL_FN *m) +{ + OSSL_FN *t = NULL; + int ret = 0; + + if (n <= 0) + return n == 0 ? (OSSL_FN_copy_truncate(r, a) != NULL) : 0; + + t = OSSL_FN_new_limbs((size_t)(m->dsize + 1)); + if (t == NULL) + goto err; + + if (OSSL_FN_copy_truncate(t, a) == NULL) + goto err; + + while (n > 0) { + size_t m_bits = OSSL_FN_num_bits(m); + size_t t_bits = OSSL_FN_num_bits(t); + size_t max_shift; + + /* 0 <= t < m */ + if (m_bits < t_bits) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_INPUT_NOT_REDUCED); + goto err; + } + max_shift = m_bits - t_bits; + + if (max_shift > (size_t)n) + max_shift = (size_t)n; + + if (max_shift) { + int shift = (int)max_shift; + + if (!OSSL_FN_lshift(t, t, shift)) + goto err; + n -= shift; + } else { + if (!OSSL_FN_lshift1(t, t)) + goto err; + n--; + } + + if (OSSL_FN_cmp(t, m) >= 0) { + if (!OSSL_FN_sub(t, t, m)) + goto err; + } + } + + if (OSSL_FN_copy_truncate(r, t) == NULL) + goto err; + ret = 1; + +err: + OSSL_FN_free(t); + return ret; +} diff --git a/crypto/fn/fn_mul.c b/crypto/fn/fn_mul.c new file mode 100644 index 0000000000..4b5b50e83b --- /dev/null +++ b/crypto/fn/fn_mul.c @@ -0,0 +1,78 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "crypto/cryptlib.h" +#include "crypto/fnerr.h" +#include "../bn/bn_local.h" /* For using the low level bignum functions */ +#include "fn_local.h" + +size_t OSSL_FN_mul_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b) +{ + size_t limbs = 0; + + if (r == NULL || a == NULL || b == NULL) + return 0; + if (r == a || r == b) + limbs = r->dsize; + + return OSSL_FN_CTX_size(1, limbs == 0 ? 0 : 1, limbs); +} + +int OSSL_FN_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, OSSL_FN_CTX *ctx) +{ + size_t al = (size_t)a->dsize; + size_t bl = (size_t)b->dsize; + size_t rl = (size_t)r->dsize; + size_t max = (size_t)(al + bl); + const void *token = OSSL_FN_CTX_start(ctx); + if (token == NULL) + return 0; + + int ret = 0; +#ifdef BN_MUL_COMBA + if (al == bl) { + if (rl >= 16 && al == 8) { + bn_mul_comba8(r->d, a->d, b->d); + goto end; + } + } +#endif /* BN_MUL_COMBA */ + + OSSL_FN *rr = r; + if ((r == a) || (r == b)) + if ((rr = OSSL_FN_CTX_get_limbs(ctx, rl)) == NULL) + goto err; + + bn_mul_truncated(rr->d, (int)rl, a->d, (int)al, b->d, (int)bl); + + if (rr != r) + if (OSSL_FN_copy(r, rr) == NULL) + goto err; + +#ifdef BN_MUL_COMBA +end: +#endif + +{ + size_t dif = (rl > max) ? rl - max : 0; + OSSL_FN_ULONG *rp = &r->d[max]; + while (dif > 0) { + *rp++ = 0; + dif--; + } +} + + ret = 1; +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} diff --git a/crypto/fn/fn_rand.c b/crypto/fn/fn_rand.c new file mode 100644 index 0000000000..369b57d9b0 --- /dev/null +++ b/crypto/fn/fn_rand.c @@ -0,0 +1,246 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "crypto/fnerr.h" +#include "fn_local.h" + +/* + * Internal flag selecting which DRBG pool the bytes are drawn from. + * NORMAL routes through RAND_bytes_ex(), PRIVATE through + * RAND_priv_bytes_ex() (a non-forward-linkable source). The same shaping + * code feeds either pool; the flag selects which one, mirroring the + * public/private split exposed by the OSSL_FN_rand() / OSSL_FN_priv_rand() + * entry points. + */ +enum ossl_fn_rand_flag { + NORMAL = 0, + PRIVATE +}; + +/* Set bit |pos| (0 = least significant) of |a|, by absolute position. */ +static void ossl_fn_set_bit(OSSL_FN *a, size_t pos) +{ + a->d[pos / OSSL_FN_BITS] |= OSSL_FN_ULONG_C(1) << (pos % OSSL_FN_BITS); +} + +/*- + * ossl_fn_rand() fills |rnd| with |bits| random bits, shaping the top and + * bottom bits per the |top|/|bottom| requests. The random bytes are drawn + * directly into rnd->d's byte image (a whole number of limbs, so the result + * is a random value regardless of the machine's byte order), and the + * top/bottom/mask shaping is done directly on rnd->d's limbs as value + * operations -- set bit |bits|-1 for TOP_ONE, bits |bits|-1 and |bits|-2 + * for TOP_TWO, clear the high bits of the top limb at |bits| and above, + * set bit 0 for BOTTOM_ODD. No intermediate byte buffer is needed, since + * OSSL_FN's limbs are fixed-size. + * + * A destination too small for |bits| is an error + * (OSSL_FN_R_RESULT_ARG_TOO_SMALL), not an implicit expansion. + * + * The leak profile: control flow branches on |bits|, |top|, |bottom| (all + * caller-chosen, public) and on the byte-draw return value, never on the + * random bytes themselves. The result value of OSSL_FN_rand() / + * OSSL_FN_priv_rand() is, of course, the random number the caller asked for. + */ +static int ossl_fn_rand(enum ossl_fn_rand_flag flag, OSSL_FN *rnd, size_t bits, + int top, int bottom, size_t strength, + OSSL_LIB_CTX *libctx) +{ + size_t limbs_needed, top_limb, i; + + if (rnd == NULL) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (bits == 0) { + if (top != OSSL_FN_RAND_TOP_ANY || bottom != OSSL_FN_RAND_BOTTOM_ANY) + goto toosmall; + return OSSL_FN_zero(rnd); + } + /* TOP_TWO forces two high bits, so it needs at least two bits. */ + if (top == OSSL_FN_RAND_TOP_TWO && bits < 2) + goto toosmall; + + limbs_needed = bits / OSSL_FN_BITS; + limbs_needed += (bits % OSSL_FN_BITS != 0) ? 1 : 0; + if (limbs_needed > (size_t)rnd->dsize) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL); + return 0; + } + top_limb = limbs_needed - 1; + + /* + * Draw random bytes directly into rnd->d's byte image. A whole number + * of limbs is filled so the result is a random value regardless of the + * machine's byte order; the high bits of the top limb beyond |bits| are + * masked off below. The pool is selected by |flag|. + */ + { + size_t fill_bytes = limbs_needed * OSSL_FN_BYTES; + int b = (flag == NORMAL) + ? RAND_bytes_ex(libctx, (unsigned char *)rnd->d, fill_bytes, + (unsigned int)strength) + : RAND_priv_bytes_ex(libctx, (unsigned char *)rnd->d, fill_bytes, + (unsigned int)strength); + + if (b <= 0) + return 0; + } + + /* + * TODO(FIXNUM): a testing variant that mangles the byte buffer to + * generate patterns more likely to trigger library bugs is not wired up + * yet; if an OSSL_FN_bntest_rand() analogue is added for test coverage, + * this is the spot for the mangle step. + */ + + /* Zero any limbs above those the bytes filled. */ + for (i = limbs_needed; i < (size_t)rnd->dsize; i++) + rnd->d[i] = 0; + + /* Clear the high bits of the top limb at |bits| and above. */ + if (bits % OSSL_FN_BITS != 0) + rnd->d[top_limb] &= (OSSL_FN_ULONG_C(1) << (bits % OSSL_FN_BITS)) - 1; + + /* Set the requested top bit(s); |bits| >= 2 is guaranteed for TOP_TWO. */ + if (top != OSSL_FN_RAND_TOP_ANY) { + ossl_fn_set_bit(rnd, bits - 1); + if (top == OSSL_FN_RAND_TOP_TWO) + ossl_fn_set_bit(rnd, bits - 2); + } + + /* Set the bottom bit if requested. */ + if (bottom == OSSL_FN_RAND_BOTTOM_ODD) + rnd->d[0] |= OSSL_FN_ULONG_C(1); + + return 1; + +toosmall: + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_BITS_TOO_SMALL); + return 0; +} + +/* Draw from the public DRBG pool (NORMAL). */ +int OSSL_FN_rand(OSSL_FN *rnd, size_t bits, int top, int bottom, + size_t strength, OSSL_LIB_CTX *libctx) +{ + return ossl_fn_rand(NORMAL, rnd, bits, top, bottom, strength, libctx); +} + +/* Draw from the private DRBG pool (PRIVATE). */ +int OSSL_FN_priv_rand(OSSL_FN *rnd, size_t bits, int top, int bottom, + size_t strength, OSSL_LIB_CTX *libctx) +{ + return ossl_fn_rand(PRIVATE, rnd, bits, top, bottom, strength, libctx); +} + +/*- + * ossl_fn_rand_range() produces 0 <= r < range by rejection sampling. The + * libctx comes directly as an argument, as in ossl_fn_rand(); sign is never + * considered, since OSSL_FN is unsigned. + * + * The leak profile: control flow branches on |range|'s top bit pattern and on + * |r|'s width (both public), and the loop iteration count leaks the magnitude + * of |range| (via OSSL_FN_num_bits) and the rejection probability. + * + * The destination |r| must be sized to hold at least |num_bits(range)| bits. + * The "range = 100..._2" path draws n + 1 bits and is taken only when |r| + * has room for them; an exactly-sized |r| (room for exactly n bits) uses the + * standard n-bit rejection path instead. + */ +static int ossl_fn_rand_range(enum ossl_fn_rand_flag flag, OSSL_FN *r, + const OSSL_FN *range, size_t strength, + OSSL_LIB_CTX *libctx) +{ + size_t n; + int count = 100; + + if (r == NULL) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (OSSL_FN_is_zero(range)) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_INVALID_RANGE); + return 0; + } + + n = OSSL_FN_num_bits(range); /* n > 0 */ + + /* OSSL_FN_is_bit_set(range, n - 1) always holds */ + + if (n == 1) { + return OSSL_FN_zero(r); + } else if (!OSSL_FN_is_bit_set(range, (int)(n - 2)) + && !OSSL_FN_is_bit_set(range, (int)(n - 3)) + && n < (size_t)r->dsize * OSSL_FN_BITS) { + /* + * range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer + * than range. This draws n + 1 bits, so it is taken only when |r| has + * room for them; an exactly-sized |r| (room for exactly n bits) falls + * through to the standard n-bit rejection path below. + */ + do { + if (!ossl_fn_rand(flag, r, n + 1, OSSL_FN_RAND_TOP_ANY, + OSSL_FN_RAND_BOTTOM_ANY, strength, libctx)) + return 0; + + /* + * If r < 3*range, use r := r MOD range (which is either r, r - + * range, or r - 2*range). Otherwise, iterate once more. Since + * 3*range = 11..._2, each iteration succeeds with probability >= + * .75. + */ + if (OSSL_FN_cmp(r, range) >= 0) { + if (!OSSL_FN_sub(r, r, range)) + return 0; + if (OSSL_FN_cmp(r, range) >= 0) + if (!OSSL_FN_sub(r, r, range)) + return 0; + } + + if (!--count) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_TOO_MANY_ITERATIONS); + return 0; + } + + } while (OSSL_FN_cmp(r, range) >= 0); + } else { + do { + /* range = 11..._2 or range = 101..._2 */ + if (!ossl_fn_rand(flag, r, n, OSSL_FN_RAND_TOP_ANY, + OSSL_FN_RAND_BOTTOM_ANY, strength, libctx)) + return 0; + + if (!--count) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_TOO_MANY_ITERATIONS); + return 0; + } + } while (OSSL_FN_cmp(r, range) >= 0); + } + + return 1; +} + +/* Draw from the public DRBG pool (NORMAL). */ +int OSSL_FN_rand_range(OSSL_FN *r, const OSSL_FN *range, size_t strength, + OSSL_LIB_CTX *libctx) +{ + return ossl_fn_rand_range(NORMAL, r, range, strength, libctx); +} + +/* Draw from the private DRBG pool (PRIVATE). */ +int OSSL_FN_priv_rand_range(OSSL_FN *r, const OSSL_FN *range, + size_t strength, OSSL_LIB_CTX *libctx) +{ + return ossl_fn_rand_range(PRIVATE, r, range, strength, libctx); +} diff --git a/crypto/fn/fn_shift.c b/crypto/fn/fn_shift.c new file mode 100644 index 0000000000..fe0dfa5d2c --- /dev/null +++ b/crypto/fn/fn_shift.c @@ -0,0 +1,161 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "crypto/fnerr.h" +#include "fn_local.h" + +/* + * In respect to shift factor the execution time is invariant of + * |n % OSSL_FN_BITS|, but not |n / OSSL_FN_BITS|. Or in other words + * pre-condition for constant-time-ness is |n < OSSL_FN_BITS| or + * |n / OSSL_FN_BITS| being non-secret. + */ +int OSSL_FN_lshift(OSSL_FN *r, const OSSL_FN *a, int n) +{ + size_t i, nw; + unsigned int lb, rb; + const OSSL_FN_ULONG *ap = a->d; + OSSL_FN_ULONG *rp = r->d; + size_t rl = (size_t)r->dsize; + size_t al = (size_t)a->dsize; + + if (n < 0) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_INVALID_SHIFT); + return 0; + } + + nw = (size_t)n / OSSL_FN_BITS; + if (nw >= rl) { + memset(rp, 0, sizeof(*rp) * rl); + return 1; + } + + lb = (unsigned int)n % OSSL_FN_BITS; + rb = OSSL_FN_BITS - lb; + + /* + * Work from the high end to support r == a. Each result limb only + * depends on the corresponding source limb and the limb just below it, + * neither of which has been overwritten yet when walking downward. + */ + for (i = rl; i > 0; i--) { + size_t r_idx = i - 1; + OSSL_FN_ULONG limb = 0; + + if (r_idx >= nw) { + size_t src_idx = r_idx - nw; + + if (src_idx < al) + limb = (ap[src_idx] << lb) & OSSL_FN_MASK; + if (lb != 0 && src_idx > 0 && src_idx - 1 < al) + limb |= ap[src_idx - 1] >> rb; + } + rp[r_idx] = limb; + } + + return 1; +} + +int OSSL_FN_lshift1(OSSL_FN *r, const OSSL_FN *a) +{ + OSSL_FN_ULONG *rp = r->d; + const OSSL_FN_ULONG *ap = a->d; + OSSL_FN_ULONG t, c = 0; + size_t rl = (size_t)r->dsize; + size_t al = (size_t)a->dsize; + size_t l = (rl < al) ? rl : al; + size_t i; + + for (i = 0; i < l; i++) { + t = ap[i]; + rp[i] = ((t << 1) | c) & OSSL_FN_MASK; + c = t >> (OSSL_FN_BITS - 1); + } + + if (i < rl) { + rp[i++] = c; + for (; i < rl; i++) + rp[i] = 0; + } + + return 1; +} + +/* + * In respect to shift factor the execution time is invariant of + * |n % OSSL_FN_BITS|, but not |n / OSSL_FN_BITS|. Or in other words + * pre-condition for constant-time-ness for sufficiently[!] zero-padded + * inputs is |n < OSSL_FN_BITS| or |n / OSSL_FN_BITS| being non-secret. + */ +int OSSL_FN_rshift(OSSL_FN *r, const OSSL_FN *a, int n) +{ + size_t i, nw; + unsigned int lb, rb; + const OSSL_FN_ULONG *ap = a->d; + OSSL_FN_ULONG *rp = r->d; + size_t rl = (size_t)r->dsize; + size_t al = (size_t)a->dsize; + + if (n < 0) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_INVALID_SHIFT); + return 0; + } + + nw = (size_t)n / OSSL_FN_BITS; + rb = (unsigned int)n % OSSL_FN_BITS; + lb = OSSL_FN_BITS - rb; + + /* + * Work from the low end to support r == a. Each result limb only + * depends on the corresponding source limb and the limb just above it, + * neither of which has been overwritten yet when walking upward. + */ + for (i = 0; i < rl; i++) { + size_t src_idx = i + nw; + OSSL_FN_ULONG limb = 0; + + if (src_idx < al) { + limb = ap[src_idx] >> rb; + if (rb != 0 && src_idx + 1 < al) + limb |= (ap[src_idx + 1] << lb) & OSSL_FN_MASK; + } + rp[i] = limb; + } + + return 1; +} + +int OSSL_FN_rshift1(OSSL_FN *r, const OSSL_FN *a) +{ + OSSL_FN_ULONG *rp = r->d; + const OSSL_FN_ULONG *ap = a->d; + size_t rl = (size_t)r->dsize; + size_t al = (size_t)a->dsize; + size_t i; + + /* + * Work from the low end to support r == a. Each result limb only + * depends on the corresponding source limb and the limb just above it, + * neither of which has been overwritten yet when walking upward. + */ + for (i = 0; i < rl; i++) { + OSSL_FN_ULONG limb = 0; + + if (i < al) { + limb = ap[i] >> 1; + if (i + 1 < al) + limb |= (ap[i + 1] << (OSSL_FN_BITS - 1)) & OSSL_FN_MASK; + } + rp[i] = limb; + } + + return 1; +} diff --git a/crypto/fn/fn_sqr.c b/crypto/fn/fn_sqr.c new file mode 100644 index 0000000000..698d33c286 --- /dev/null +++ b/crypto/fn/fn_sqr.c @@ -0,0 +1,95 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/safe_math.h" +#include "crypto/cryptlib.h" +#include "crypto/fnerr.h" +#include "../bn/bn_local.h" /* For using the low level bignum functions */ +#include "fn_local.h" + +OSSL_SAFE_MATH_MULU(size_t, size_t, OSSL_SAFE_MATH_MAXU(size_t)) + +size_t OSSL_FN_sqr_ctx_size(const OSSL_FN *r, const OSSL_FN *a) +{ + size_t max, limbs, n_numbers = 1; + + if (r == NULL || a == NULL) + return 0; + int err = 0; + + max = safe_mul_size_t(2, a->dsize, &err); + if ((size_t)r->dsize < max) + n_numbers++; + limbs = safe_mul_size_t(n_numbers, max, &err); + + return err == 0 ? OSSL_FN_CTX_size(1, n_numbers, limbs) : 0; +} + +int OSSL_FN_sqr(OSSL_FN *r, const OSSL_FN *a, OSSL_FN_CTX *ctx) +{ + const void *token = OSSL_FN_CTX_start(ctx); + if (token == NULL) + return 0; + + size_t al = (size_t)a->dsize; + size_t rl = (size_t)r->dsize; + size_t max = (size_t)(2 * al); + + int ret = 0; +#ifdef BN_SQR_COMBA + if (al == 4 && rl >= 8) { + bn_sqr_comba4(r->d, a->d); + goto end; + } else if (al == 8 && rl >= 16) { + bn_sqr_comba8(r->d, a->d); + goto end; + } +#endif + + /* rl < max is always true when r == a, so covers that case too */ + OSSL_FN *rr = r; + if (rl < max) + if ((rr = OSSL_FN_CTX_get_limbs(ctx, max)) == NULL) + goto err; + + OSSL_FN *tmp = NULL; + if ((tmp = OSSL_FN_CTX_get_limbs(ctx, max)) == NULL) + goto err; + + if (al != 0) + bn_sqr_normal(rr->d, a->d, (int)al, tmp->d); + + if (rr != r) { + /* + * We use OSSL_FN_copy_truncate() here, because OSSL_FN_copy() expects + * to make a full copy, but r may be smaller than rr + */ + OSSL_FN_copy_truncate(r, rr); + } + +#ifdef BN_SQR_COMBA +end: +#endif + + ret = 1; + + /* Zeroise everything above the result, if the r is that large */ + size_t dif = (rl > max) ? rl - max : 0; + OSSL_FN_ULONG *rp = &r->d[max]; + while (dif > 0) { + *rp++ = 0; + dif--; + } + +err: + OSSL_FN_CTX_end(ctx, token); + return ret; +} diff --git a/crypto/getenv.c b/crypto/getenv.c index 8ea7128864..aa01ea8af7 100644 --- a/crypto/getenv.c +++ b/crypto/getenv.c @@ -17,7 +17,7 @@ char *ossl_safe_getenv(const char *name) { -#if defined(_WIN32) && defined(CP_UTF8) +#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE) if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) { char *val = NULL; int vallen = 0; diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c index f12b5bf0b3..400dde4d40 100644 --- a/crypto/hmac/hmac.c +++ b/crypto/hmac/hmac.c @@ -53,11 +53,9 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, return 0; #ifdef OPENSSL_HMAC_S390X - { - int ret = s390x_HMAC_init(ctx, key, len); - if (ret != -1) /* -1 means SW fallback */ - return ret; - } + rv = s390x_HMAC_init(ctx, key, len); + if (rv >= 1) + return rv; #endif if (key != NULL) { diff --git a/crypto/info.c b/crypto/info.c index 4baece2246..2038db5a52 100644 --- a/crypto/info.c +++ b/crypto/info.c @@ -7,7 +7,6 @@ * https://www.openssl.org/source/license.html */ -#include #include #include "crypto/rand.h" #include "crypto/dso_conf.h" @@ -50,75 +49,70 @@ char ossl_cpu_info_str[CPU_INFO_STR_LEN] = ""; static CRYPTO_ONCE init_info = CRYPTO_ONCE_STATIC_INIT; -/* - * Append a printf-formatted suffix to ossl_cpu_info_str, truncating to - * fit. The first call writes the base string (the buffer starts empty, - * so off == 0); subsequent calls extend it. - */ -static ossl_unused void cpu_info_append(const char *fmt, ...) -{ - size_t off = strlen(ossl_cpu_info_str); - va_list args; - - if (off >= sizeof(ossl_cpu_info_str)) - return; - va_start(args, fmt); - (void)vsnprintf(ossl_cpu_info_str + off, - sizeof(ossl_cpu_info_str) - off, fmt, args); - va_end(args); -} - DEFINE_RUN_ONCE_STATIC(init_info_strings) { #if defined(OPENSSL_CPUID_OBJ) #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) const char *env; - cpu_info_append(CPUINFO_PREFIX - "OPENSSL_ia32cap=0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx", + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_ia32cap=0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx", (unsigned long long)OPENSSL_ia32cap_P[0] | (unsigned long long)OPENSSL_ia32cap_P[1] << 32, (unsigned long long)OPENSSL_ia32cap_P[2] | (unsigned long long)OPENSSL_ia32cap_P[3] << 32, (unsigned long long)OPENSSL_ia32cap_P[4] | (unsigned long long)OPENSSL_ia32cap_P[5] << 32, (unsigned long long)OPENSSL_ia32cap_P[6] | (unsigned long long)OPENSSL_ia32cap_P[7] << 32, (unsigned long long)OPENSSL_ia32cap_P[8] | (unsigned long long)OPENSSL_ia32cap_P[9] << 32); + if ((env = getenv("OPENSSL_ia32cap")) != NULL) - cpu_info_append(" env:%s", env); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); #elif defined(__arm__) || defined(__arm) || defined(__aarch64__) const char *env; - cpu_info_append(CPUINFO_PREFIX "OPENSSL_armcap=0x%x", OPENSSL_armcap_P); + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_armcap=0x%x", OPENSSL_armcap_P); if ((env = getenv("OPENSSL_armcap")) != NULL) - cpu_info_append(" env:%s", env); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); #elif defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC) const char *env; - cpu_info_append(CPUINFO_PREFIX "OPENSSL_ppccap=0x%x", OPENSSL_ppccap_P); + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_ppccap=0x%x", OPENSSL_ppccap_P); if ((env = getenv("OPENSSL_ppccap")) != NULL) - cpu_info_append(" env:%s", env); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); #elif defined(__sparcv9) || defined(__sparcv9__) const char *env; - cpu_info_append(CPUINFO_PREFIX "OPENSSL_sparcv9cap=0x%x:0x%x", + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_sparcv9cap=0x%x:0x%x", OPENSSL_sparcv9cap_P[0], OPENSSL_sparcv9cap_P[1]); if ((env = getenv("OPENSSL_sparcv9cap")) != NULL) - cpu_info_append(" env:%s", env); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); #elif defined(__s390__) || defined(__s390x__) const char *env; - cpu_info_append(CPUINFO_PREFIX "OPENSSL_s390xcap=" - "stfle:0x%llx:0x%llx:0x%llx:0x%llx:" - "kimd:0x%llx:0x%llx:" - "klmd:0x%llx:0x%llx:" - "km:0x%llx:0x%llx:" - "kmc:0x%llx:0x%llx:" - "kmac:0x%llx:0x%llx:" - "kmctr:0x%llx:0x%llx:" - "kmo:0x%llx:0x%llx:" - "kmf:0x%llx:0x%llx:" - "prno:0x%llx:0x%llx:" - "kma:0x%llx:0x%llx:" - "pcc:0x%llx:0x%llx:" - "kdsa:0x%llx:0x%llx", + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_s390xcap=" + "stfle:0x%llx:0x%llx:0x%llx:0x%llx:" + "kimd:0x%llx:0x%llx:" + "klmd:0x%llx:0x%llx:" + "km:0x%llx:0x%llx:" + "kmc:0x%llx:0x%llx:" + "kmac:0x%llx:0x%llx:" + "kmctr:0x%llx:0x%llx:" + "kmo:0x%llx:0x%llx:" + "kmf:0x%llx:0x%llx:" + "prno:0x%llx:0x%llx:" + "kma:0x%llx:0x%llx:" + "pcc:0x%llx:0x%llx:" + "kdsa:0x%llx:0x%llx", OPENSSL_s390xcap_P.stfle[0], OPENSSL_s390xcap_P.stfle[1], OPENSSL_s390xcap_P.stfle[2], OPENSSL_s390xcap_P.stfle[3], OPENSSL_s390xcap_P.kimd[0], OPENSSL_s390xcap_P.kimd[1], @@ -134,54 +128,63 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) OPENSSL_s390xcap_P.pcc[0], OPENSSL_s390xcap_P.pcc[1], OPENSSL_s390xcap_P.kdsa[0], OPENSSL_s390xcap_P.kdsa[1]); if ((env = getenv("OPENSSL_s390xcap")) != NULL) - cpu_info_append(" env:%s", env); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); #elif defined(__riscv) const char *env; size_t i; - cpu_info_append(CPUINFO_PREFIX "OPENSSL_riscvcap=RV" + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_riscvcap=RV" #if __riscv_xlen == 32 - "32" + "32" #elif __riscv_xlen == 64 - "64" + "64" #elif __riscv_xlen == 128 - "128" + "128" #endif #if defined(__riscv_i) && defined(__riscv_m) && defined(__riscv_a) \ && defined(__riscv_f) && defined(__riscv_d) \ && defined(__riscv_zicsr) && defined(__riscv_zifencei) - "G" /* shorthand for IMAFD_Zicsr_Zifencei */ + "G" /* shorthand for IMAFD_Zicsr_Zifencei */ #else #ifdef __riscv_i - "I" + "I" #endif #ifdef __riscv_m - "M" + "M" #endif #ifdef __riscv_a - "A" + "A" #endif #ifdef __riscv_f - "F" + "F" #endif #ifdef __riscv_d - "D" + "D" #endif #endif #ifdef __riscv_c - "C" + "C" #endif ); for (i = 0; i < kRISCVNumCaps; i++) { if (OPENSSL_riscvcap_P[RISCV_capabilities[i].index] & (1 << RISCV_capabilities[i].bit_offset)) /* Match, display the name */ - cpu_info_append("_%s", RISCV_capabilities[i].name); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + "_%s", RISCV_capabilities[i].name); } if (RISCV_HAS_V()) - cpu_info_append(" vlen:%lu", riscv_vlen()); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " vlen:%lu", riscv_vlen()); if ((env = getenv("OPENSSL_riscvcap")) != NULL) - cpu_info_append(" env:%s", env); + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); #endif #endif diff --git a/crypto/int.c b/crypto/int.c new file mode 100644 index 0000000000..f782c2aec6 --- /dev/null +++ b/crypto/int.c @@ -0,0 +1,29 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "crypto/cryptlib.h" + +size_t ossl_num_bits(size_t value) +{ + size_t i; + unsigned long ret = 0; + + /* + * It is argued that *on average* constant counter loop performs + * not worse [if not better] than one with conditional break or + * mask-n-table-lookup-style, because of branch misprediction + * penalties. + */ + for (i = 0; i < sizeof(value) * 8; i++) { + ret += (value != 0); + value >>= 1; + } + + return (int)ret; +} diff --git a/crypto/lms/lms_pubkey_decode.c b/crypto/lms/lms_pubkey_decode.c index 29ca1d44af..8c2ee0ff5e 100644 --- a/crypto/lms/lms_pubkey_decode.c +++ b/crypto/lms/lms_pubkey_decode.c @@ -95,7 +95,7 @@ int ossl_lms_pubkey_decode(const unsigned char *pub, size_t publen, { LMS_PUB_KEY *pkey = &lmskey->pub; - if (pkey->encoded != NULL) { + if (pkey->encoded != NULL && pkey->encodedlen != publen) { OPENSSL_free(pkey->encoded); pkey->encodedlen = 0; } @@ -110,7 +110,6 @@ int ossl_lms_pubkey_decode(const unsigned char *pub, size_t publen, err: OPENSSL_free(pkey->encoded); pkey->encoded = NULL; - pkey->encodedlen = 0; return 0; } diff --git a/crypto/md5/md5_riscv.c b/crypto/md5/md5_riscv.c index 3bd87a13c4..64dd1a5a26 100644 --- a/crypto/md5/md5_riscv.c +++ b/crypto/md5/md5_riscv.c @@ -11,10 +11,10 @@ #include #include "arch/riscv_arch.h" -void ossl_md5_block_asm_data_order(void *c, const void *p, size_t num); -void ossl_md5_block_asm_data_order_zbb(void *c, const void *p, size_t num); -void ossl_md5_block_asm_data_order_riscv64(void *c, const void *p, size_t num); -void ossl_md5_block_asm_data_order(void *c, const void *p, size_t num) +void ossl_md5_block_asm_data_order(MD5_CTX *c, const void *p, size_t num); +void ossl_md5_block_asm_data_order_zbb(MD5_CTX *c, const void *p, size_t num); +void ossl_md5_block_asm_data_order_riscv64(MD5_CTX *c, const void *p, size_t num); +void ossl_md5_block_asm_data_order(MD5_CTX *c, const void *p, size_t num) { if (RISCV_HAS_ZBB()) { ossl_md5_block_asm_data_order_zbb(c, p, num); diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c index a727d2008d..3c5de4de8f 100644 --- a/crypto/mem_sec.c +++ b/crypto/mem_sec.c @@ -23,6 +23,7 @@ #ifndef OPENSSL_NO_SECURE_MEMORY #if defined(_WIN32) +#include #if defined(WINAPI_FAMILY_PARTITION) #if !defined(WINAPI_PARTITION_SYSTEM) #define WINAPI_PARTITION_SYSTEM 0 diff --git a/crypto/ml_dsa/ml_dsa_key.c b/crypto/ml_dsa/ml_dsa_key.c index ea5f4ee4da..6b5b8b092f 100644 --- a/crypto/ml_dsa/ml_dsa_key.c +++ b/crypto/ml_dsa/ml_dsa_key.c @@ -332,7 +332,7 @@ int ossl_ml_dsa_key_has(const ML_DSA_KEY *key, int selection) * @returns 1 on success, or 0 on failure. */ static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx, - const OSSL_ML_DSA_SAMPLE_OPS *sample_ops, VECTOR *t1, VECTOR *t0) + VECTOR *t1, VECTOR *t0) { int ret = 0; const ML_DSA_PARAMS *params = key->params; @@ -351,7 +351,7 @@ static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx, matrix_init(&a_ntt, s1_ntt.poly + l, k, l); /* Using rho generate A' = A in NTT form */ - if (!sample_ops->matrix_expand_A(md_ctx, key->shake128_md, key->rho, &a_ntt)) + if (!matrix_expand_A(md_ctx, key->shake128_md, key->rho, &a_ntt)) goto err; /* t = NTT_inv(A' * NTT(s1)) + s2 */ @@ -376,7 +376,6 @@ err: int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key) { int ret = 0; - const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops(); VECTOR t0; EVP_MD_CTX *md_ctx = NULL; @@ -384,7 +383,7 @@ int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key) return 0; ret = ((md_ctx = EVP_MD_CTX_new()) != NULL) && ossl_ml_dsa_key_pub_alloc(key) /* allocate space for t1 */ - && public_from_private(key, md_ctx, sample_ops, &key->t1, &t0) + && public_from_private(key, md_ctx, &key->t1, &t0) && vector_equal(&t0, &key->t0) /* compare the generated t0 to the expected */ && ossl_ml_dsa_pk_encode(key) && shake_xof(md_ctx, key->shake256_md, @@ -398,7 +397,6 @@ int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key) int ossl_ml_dsa_key_pairwise_check(const ML_DSA_KEY *key) { int ret = 0; - const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops(); VECTOR t1, t0; POLY *polys = NULL; uint32_t k = (uint32_t)key->params->k; @@ -416,7 +414,7 @@ int ossl_ml_dsa_key_pairwise_check(const ML_DSA_KEY *key) vector_init(&t1, polys, k); vector_init(&t0, polys + k, k); - if (!public_from_private(key, md_ctx, sample_ops, &t1, &t0)) + if (!public_from_private(key, md_ctx, &t1, &t0)) goto err; ret = vector_equal(&t1, &key->t1) && vector_equal(&t0, &key->t0); @@ -437,7 +435,6 @@ err: static int keygen_internal(ML_DSA_KEY *out) { int ret = 0; - const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops(); uint8_t augmented_seed[ML_DSA_SEED_BYTES + 2]; uint8_t expanded_seed[ML_DSA_RHO_BYTES + ML_DSA_PRIV_SEED_BYTES + ML_DSA_K_BYTES]; const uint8_t *const rho = expanded_seed; /* p = Public Random Seed */ @@ -464,9 +461,8 @@ static int keygen_internal(ML_DSA_KEY *out) memcpy(out->rho, rho, sizeof(out->rho)); memcpy(out->K, K, sizeof(out->K)); - ret = sample_ops->vector_expand_S(md_ctx, out->shake256_md, params->eta, - priv_seed, &out->s1, &out->s2) - && public_from_private(out, md_ctx, sample_ops, &out->t1, &out->t0) + ret = vector_expand_S(md_ctx, out->shake256_md, params->eta, priv_seed, &out->s1, &out->s2) + && public_from_private(out, md_ctx, &out->t1, &out->t0) && ossl_ml_dsa_pk_encode(out) && shake_xof(md_ctx, out->shake256_md, out->pub_encoding, out->params->pk_len, out->tr, sizeof(out->tr)) diff --git a/crypto/ml_dsa/ml_dsa_local.h b/crypto/ml_dsa/ml_dsa_local.h index 23e2db247c..9d01856ce3 100644 --- a/crypto/ml_dsa/ml_dsa_local.h +++ b/crypto/ml_dsa/ml_dsa_local.h @@ -59,21 +59,10 @@ typedef struct vector_st VECTOR; typedef struct matrix_st MATRIX; typedef struct ml_dsa_sig_st ML_DSA_SIG; -typedef int(ML_DSA_MATRIX_EXPAND_A_FN)(EVP_MD_CTX *g_ctx, const EVP_MD *md, +int ossl_ml_dsa_matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md, const uint8_t *rho, MATRIX *out); -typedef int(ML_DSA_VECTOR_EXPAND_S_FN)(EVP_MD_CTX *h_ctx, const EVP_MD *md, - int eta, const uint8_t *seed, VECTOR *s1, VECTOR *s2); -typedef void(ML_DSA_VECTOR_EXPAND_MASK_FN)(VECTOR *out, - const uint8_t rho_prime[ML_DSA_RHO_PRIME_BYTES], uint32_t kappa, uint32_t gamma1, - EVP_MD_CTX *h_ctx, const EVP_MD *md); - -typedef struct ossl_ml_dsa_sample_ops_st { - ML_DSA_MATRIX_EXPAND_A_FN *matrix_expand_A; - ML_DSA_VECTOR_EXPAND_S_FN *vector_expand_S; - ML_DSA_VECTOR_EXPAND_MASK_FN *vector_expand_mask; -} OSSL_ML_DSA_SAMPLE_OPS; - -const OSSL_ML_DSA_SAMPLE_OPS *ossl_ml_dsa_sample_ops(void); +int ossl_ml_dsa_vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta, + const uint8_t *seed, VECTOR *s1, VECTOR *s2); void ossl_ml_dsa_matrix_mult_vector(const MATRIX *matrix_kl, const VECTOR *vl, VECTOR *vk); int ossl_ml_dsa_poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len, diff --git a/crypto/ml_dsa/ml_dsa_matrix.h b/crypto/ml_dsa/ml_dsa_matrix.h index e5f4ebf6d9..3bc053720b 100644 --- a/crypto/ml_dsa/ml_dsa_matrix.h +++ b/crypto/ml_dsa/ml_dsa_matrix.h @@ -41,4 +41,11 @@ matrix_mult_vector(const MATRIX *a, const VECTOR *s, VECTOR *t) ossl_ml_dsa_matrix_mult_vector(a, s, t); } +static ossl_inline ossl_unused int +matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md, const uint8_t *rho, + MATRIX *out) +{ + return ossl_ml_dsa_matrix_expand_A(g_ctx, md, rho, out); +} + #endif /* !defined(OSSL_LIBCRYPTO_ML_DSA_ML_DSA_MATRIX_H) */ diff --git a/crypto/ml_dsa/ml_dsa_ntt_vec128.c b/crypto/ml_dsa/ml_dsa_ntt_vec128.c index 54d59a9a08..8176cbcdfb 100644 --- a/crypto/ml_dsa/ml_dsa_ntt_vec128.c +++ b/crypto/ml_dsa/ml_dsa_ntt_vec128.c @@ -309,47 +309,15 @@ static const int32_t neg_zetas_montgomery_twisted[256] = { static const vec_int32_t vec_q = { ML_DSA_Q, ML_DSA_Q, ML_DSA_Q, ML_DSA_Q }; static const vec_int32_t vec_q_inv = { ML_DSA_Q_INV, ML_DSA_Q_INV, ML_DSA_Q_INV, ML_DSA_Q_INV }; -/* - * @brief Reduce a in (-q, q) to a mod q in [0, q). - * - * @param a in (-q, q) - * @returns a mod q in [0, q) - */ -static ossl_inline - vec_int32_t - reduce_once_signed(vec_int32_t a) -{ - /* mask is 11..11 when a is negative, else 0 */ - vec_uint32_t mask = -(((vec_uint32_t)a) >> 31); - return a + (vec_int32_t)(mask & (vec_uint32_t)vec_q); -} - -/* - * @brief Reduce a in (-2q, q) to a mod q in [0, q). - * - * @param a in (-2q, q) - * @returns a mod q in [0, q) - */ -static ossl_inline - vec_int32_t - reduce_twice_signed(vec_int32_t a) -{ - /* mask is 11..11 when a is negative, else 0 */ - vec_uint32_t mask = -(((vec_uint32_t)a) >> 31); - /* b is in (-q, q) */ - vec_int32_t b = a + (vec_int32_t)(mask & (vec_uint32_t)vec_q); - return reduce_once_signed(b); -} - /* * @brief Computes the Montgomery product of a and b. * See [Seiler 2018, Algorithm 3]. * - * @param a is the first factor, assumed to be in [0, q). + * @param a is the first factor, assumed to be non-negative. * @param a_twist is (int32)((uint32)a * ML_DSA_Q_INV). * @param b is the second factor. * @returns The Montgomery product of a and b in the range - * [0, q). + * -q+1..q-1. */ static ossl_inline @@ -361,7 +329,22 @@ static ossl_inline vec_int32_t c = (vec_int32_t)c_u; vec_int32_t z_high = vec_mulh((vec_int32_alias_t)a, (vec_int32_alias_t)b); vec_int32_t r = z_high - c; - return reduce_twice_signed(r); + return r; +} + +/* + * @brief Reduce a in (-q, q) to a mod q in [0, q-1]. + * + * @param a in (-q, q) + * @returns a mod q in [0, q-1] + */ +static ossl_inline + vec_int32_t + reduce_once_signed(vec_int32_t a) +{ + /* mask is 11..11 when a is negative, else 0 */ + vec_uint32_t mask = -(((vec_uint32_t)a) >> 31); + return a + (vec_int32_t)(mask & (vec_uint32_t)vec_q); } /* @@ -393,8 +376,9 @@ void ossl_poly_ntt_mult_scalar_vec128(const POLY *lhs, const POLY *rhs, POLY *ou for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS / NUM_INT32_IN_VECTOR; i++) { vec_int32_t twist_vec = (vec_int32_t)((vec_uint32_t)lhs_vec_ptr[i] * (vec_uint32_t)vec_q_inv); - out_vec_ptr[i] = montgomery_multiplication_vectorized( + vec_int32_t result = montgomery_multiplication_vectorized( lhs_vec_ptr[i], twist_vec, rhs_vec_ptr[i]); + out_vec_ptr[i] = reduce_once_signed(result); } } @@ -698,10 +682,11 @@ void ossl_ml_dsa_poly_ntt_inverse_vec128(POLY *p) } for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS / NUM_INT32_IN_VECTOR; i += 1) { - p_vec[i] = montgomery_multiplication_vectorized( + vec_int32_t coeff_i_vec = montgomery_multiplication_vectorized( vec_inverse_degree_montgomery, vec_inverse_degree_montgomery_twisted, p_vec[i]); + p_vec[i] = reduce_once_signed(coeff_i_vec); } } diff --git a/crypto/ml_dsa/ml_dsa_sample.c b/crypto/ml_dsa/ml_dsa_sample.c index afa09b7971..5d9dc84a54 100644 --- a/crypto/ml_dsa/ml_dsa_sample.c +++ b/crypto/ml_dsa/ml_dsa_sample.c @@ -8,7 +8,6 @@ */ #include -#include #include "ml_dsa_local.h" #include "ml_dsa_vector.h" #include "ml_dsa_matrix.h" @@ -36,10 +35,6 @@ typedef int(COEFF_FROM_NIBBLE_FUNC)(uint32_t nibble, uint32_t *out); static COEFF_FROM_NIBBLE_FUNC coeff_from_nibble_4; static COEFF_FROM_NIBBLE_FUNC coeff_from_nibble_2; -static ML_DSA_MATRIX_EXPAND_A_FN matrix_expand_A_scalar; -static ML_DSA_VECTOR_EXPAND_S_FN vector_expand_S_scalar; -static ML_DSA_VECTOR_EXPAND_MASK_FN vector_expand_mask_scalar; - /** * @brief Combine 3 bytes to form an coefficient. * See FIPS 204, Algorithm 14, CoeffFromThreeBytes() @@ -165,14 +160,13 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md, COEFF_FROM_NIBBLE_FUNC *coef_from_nibble, const uint8_t *seed, size_t seed_len, POLY *out) { - int ret = 0; int j = 0; uint32_t z0, z1; uint8_t blocks[SHAKE256_BLOCKSIZE], *b, *end = blocks + sizeof(blocks); /* Instead of just squeezing 1 byte at a time, we grab a whole block */ if (!shake_xof(h_ctx, md, seed, seed_len, blocks, sizeof(blocks))) - goto err; + return 0; while (1) { for (b = blocks; b < end; b++) { @@ -180,22 +174,15 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md, z1 = *b >> 4; /* high nibble of byte */ if (coef_from_nibble(z0, &out->coeff[j]) - && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) { - ret = 1; - goto err; - } + && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) + return 1; if (coef_from_nibble(z1, &out->coeff[j]) - && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) { - ret = 1; - goto err; - } + && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) + return 1; } if (!EVP_DigestSqueeze(h_ctx, blocks, sizeof(blocks))) - goto err; + return 0; } -err: - OPENSSL_cleanse(blocks, sizeof(blocks)); - return ret; } /** @@ -211,7 +198,7 @@ err: * in the range of 0..q-1. * @returns 1 if the matrix was generated, or 0 on error. */ -static int matrix_expand_A_scalar(EVP_MD_CTX *g_ctx, const EVP_MD *md, +int ossl_ml_dsa_matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md, const uint8_t *rho, MATRIX *out) { int ret = 0; @@ -221,6 +208,7 @@ static int matrix_expand_A_scalar(EVP_MD_CTX *g_ctx, const EVP_MD *md, /* The seed used for each matrix element is rho + column_index + row_index */ memcpy(derived_seed, rho, ML_DSA_RHO_BYTES); + for (i = 0; i < out->k; i++) { for (j = 0; j < out->l; j++) { derived_seed[ML_DSA_RHO_BYTES + 1] = (uint8_t)i; @@ -253,7 +241,7 @@ err: * the range (q-eta)..0..eta * @returns 1 if s1 and s2 were successfully generated, or 0 otherwise. */ -static int vector_expand_S_scalar(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta, +int ossl_ml_dsa_vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta, const uint8_t *seed, VECTOR *s1, VECTOR *s2) { int ret = 0; @@ -287,7 +275,6 @@ static int vector_expand_S_scalar(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta, } ret = 1; err: - OPENSSL_cleanse(derived_seed, sizeof(derived_seed)); return ret; } @@ -298,11 +285,9 @@ int ossl_ml_dsa_poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len { uint8_t buf[32 * 20]; size_t buf_len = 32 * (gamma1 == ML_DSA_GAMMA1_TWO_POWER_19 ? 20 : 18); - int ret = shake_xof(h_ctx, md, seed, seed_len, buf, buf_len) - && ossl_ml_dsa_poly_decode_expand_mask(out, buf, buf_len, gamma1); - OPENSSL_cleanse(buf, sizeof(buf)); - return ret; + return shake_xof(h_ctx, md, seed, seed_len, buf, buf_len) + && ossl_ml_dsa_poly_decode_expand_mask(out, buf, buf_len, gamma1); } /* @@ -391,46 +376,3 @@ int ossl_ml_dsa_poly_sample_in_ball(POLY *out_c, const uint8_t *seed, int seed_l } return 1; } - -static void vector_expand_mask_scalar(VECTOR *out, - const uint8_t rho_prime[ML_DSA_RHO_PRIME_BYTES], uint32_t kappa, uint32_t gamma1, - EVP_MD_CTX *h_ctx, const EVP_MD *md) -{ - size_t i; - uint8_t derived_seed[ML_DSA_RHO_PRIME_BYTES + 2]; - - memcpy(derived_seed, rho_prime, ML_DSA_RHO_PRIME_BYTES); - - for (i = 0; i < out->num_poly; i++) { - size_t index = kappa + i; - - derived_seed[ML_DSA_RHO_PRIME_BYTES] = index & 0xFF; - derived_seed[ML_DSA_RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF; - poly_expand_mask(out->poly + i, derived_seed, sizeof(derived_seed), - gamma1, h_ctx, md); - } - OPENSSL_cleanse(derived_seed, sizeof(derived_seed)); -} - -static const OSSL_ML_DSA_SAMPLE_OPS ml_dsa_sample_generic_meth = { - matrix_expand_A_scalar, - vector_expand_S_scalar, - vector_expand_mask_scalar -}; - -#if defined(KECCAK1600_ASM) \ - && (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \ - && !defined(OPENSSL_NO_ASM) -#include "ml_dsa_sample_hw_x86_64.inc" -const OSSL_ML_DSA_SAMPLE_OPS *ossl_ml_dsa_sample_ops(void) -{ - if (SHA3_avx512vl_capable()) - return &ml_dsa_sample_x86_64; - return &ml_dsa_sample_generic_meth; -} -#else -const OSSL_ML_DSA_SAMPLE_OPS *ossl_ml_dsa_sample_ops(void) -{ - return &ml_dsa_sample_generic_meth; -} -#endif diff --git a/crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc b/crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc deleted file mode 100644 index fcf5f03323..0000000000 --- a/crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2026 Intel Corporation. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#define ML_DSA_SHAKE_X4_BATCH_SIZE 4 -#define ML_DSA_SHAKE_X4_DONE_MASK ((1 << ML_DSA_SHAKE_X4_BATCH_SIZE) - 1) -#define ML_DSA_EXPAND_MASK_BYTES_PER_COEFF 32 -#define ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_19 20 -#define ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_17 18 -#define ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_19 \ - (ML_DSA_EXPAND_MASK_BYTES_PER_COEFF * ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_19) -#define ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_17 \ - (ML_DSA_EXPAND_MASK_BYTES_PER_COEFF * ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_17) -#define ML_DSA_EXPAND_MASK_BUF_SIZE(gamma1) \ - ((gamma1) == ML_DSA_GAMMA1_TWO_POWER_19 \ - ? ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_19 \ - : ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_17) - -static ossl_unused int rej_ntt_poly_mb(const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE], - const size_t seed_len, POLY *outs[ML_DSA_SHAKE_X4_BATCH_SIZE], const size_t count) -{ - KECCAK1600_X4_AVX512VL_CTX ctx; - uint8_t blocks[ML_DSA_SHAKE_X4_BATCH_SIZE][SHAKE128_BLOCKSIZE]; - int coeff_idx[ML_DSA_SHAKE_X4_BATCH_SIZE] = { 0, 0, 0, 0 }; - size_t done_mask = 0; - size_t lane; - - for (lane = count; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++) - done_mask |= ((size_t)1 << lane); - - ossl_sha3_shake128_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake128_x4_inc_absorb_avx512vl(&ctx, seeds[0], seeds[1], - seeds[2], seeds[3], seed_len); - - while (done_mask != ML_DSA_SHAKE_X4_DONE_MASK) { - ossl_sha3_shake128_x4_inc_squeeze_avx512vl(blocks[0], blocks[1], - blocks[2], blocks[3], SHAKE128_BLOCKSIZE, &ctx); - - for (lane = 0; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++) { - if (done_mask & ((size_t)1 << lane)) - continue; - - const uint8_t *b = blocks[lane]; - const uint8_t *end = b + SHAKE128_BLOCKSIZE; - - for (; b < end && coeff_idx[lane] < ML_DSA_NUM_POLY_COEFFICIENTS; b += 3) { - uint32_t *coeff_ptr = &(outs[lane]->coeff[coeff_idx[lane]]); - - if (coeff_from_three_bytes(b, coeff_ptr)) - coeff_idx[lane]++; - } - - if (coeff_idx[lane] >= ML_DSA_NUM_POLY_COEFFICIENTS) - done_mask |= ((size_t)1 << lane); - } - } - - return 1; -} - -static void vector_expand_mask_mb(VECTOR *out, - const uint8_t rho_prime[ML_DSA_RHO_PRIME_BYTES], const uint32_t kappa, const uint32_t gamma1, - EVP_MD_CTX *h_ctx, const EVP_MD *md) -{ - size_t i; - const size_t num_polys = out->num_poly; - uint8_t derived_seeds[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_RHO_PRIME_BYTES + 2]; - const size_t seed_len = sizeof(derived_seeds[0]); - const size_t buf_size = ML_DSA_EXPAND_MASK_BUF_SIZE(gamma1); - uint8_t buffers[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_19]; - - (void)h_ctx; - (void)md; - - for (i = 0; i < ML_DSA_SHAKE_X4_BATCH_SIZE; i++) - memcpy(derived_seeds[i], rho_prime, ML_DSA_RHO_PRIME_BYTES); - - for (i = 0; i + (ML_DSA_SHAKE_X4_BATCH_SIZE - 1) < num_polys; i += ML_DSA_SHAKE_X4_BATCH_SIZE) { - size_t b; - - for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) { - const size_t index = kappa + i + b; - - derived_seeds[b][ML_DSA_RHO_PRIME_BYTES] = index & 0xFF; - derived_seeds[b][ML_DSA_RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF; - } - - ossl_sha3_shake256_x4_avx512vl(buffers[0], buffers[1], buffers[2], buffers[3], buf_size, - derived_seeds[0], derived_seeds[1], derived_seeds[2], derived_seeds[3], seed_len); - - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 0], buffers[0], buf_size, gamma1); - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 1], buffers[1], buf_size, gamma1); - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 2], buffers[2], buf_size, gamma1); - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 3], buffers[3], buf_size, gamma1); - } - - /* - * num_polys is always 4 (ML-DSA-44), 5 (ML-DSA-65), or 7 (ML-DSA-87), so the - * above loops will always runs at least once, initializing derived_seeds. - * As a result, 'left' below will be 0, 1, or 3, meaning the 4 way shake will - * recalculate values that are not used. - */ - if (i < num_polys) { - const size_t left = num_polys - i; - size_t b; - - for (b = 0; b < left; b++) { - const size_t index = kappa + i + b; - - derived_seeds[b][ML_DSA_RHO_PRIME_BYTES] = (uint8_t)index; - derived_seeds[b][ML_DSA_RHO_PRIME_BYTES + 1] = (uint8_t)(index >> 8); - } - - ossl_sha3_shake256_x4_avx512vl(buffers[0], buffers[1], buffers[2], buffers[3], buf_size, - derived_seeds[0], derived_seeds[1], derived_seeds[2], derived_seeds[3], seed_len); - - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 0], buffers[0], buf_size, gamma1); - - if ((i + 1) < num_polys) - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 1], buffers[1], buf_size, gamma1); - - if ((i + 2) < num_polys) - ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 2], buffers[2], buf_size, gamma1); - } - - OPENSSL_cleanse(buffers, sizeof(buffers)); - OPENSSL_cleanse(derived_seeds, sizeof(derived_seeds)); -} - -static ossl_unused int rej_bounded_poly_mb(COEFF_FROM_NIBBLE_FUNC *coef_from_nibble, - const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE], const size_t seed_len, - POLY *outs[ML_DSA_SHAKE_X4_BATCH_SIZE], const size_t count) -{ - KECCAK1600_X4_AVX512VL_CTX ctx; - uint8_t blocks[ML_DSA_SHAKE_X4_BATCH_SIZE][SHAKE256_BLOCKSIZE]; - int coeff_idx[ML_DSA_SHAKE_X4_BATCH_SIZE] = { 0, 0, 0, 0 }; - size_t done_mask = 0; - size_t lane; - - for (lane = count; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++) - done_mask |= ((size_t)1 << lane); - - ossl_sha3_shake256_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake256_x4_inc_absorb_avx512vl(&ctx, seeds[0], seeds[1], - seeds[2], seeds[3], seed_len); - - while (done_mask != ML_DSA_SHAKE_X4_DONE_MASK) { - ossl_sha3_shake256_x4_inc_squeeze_avx512vl(blocks[0], blocks[1], - blocks[2], blocks[3], SHAKE256_BLOCKSIZE, &ctx); - - for (lane = 0; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++) { - if (done_mask & ((size_t)1 << lane)) - continue; - - const uint8_t *b = blocks[lane]; - const uint8_t *end = b + SHAKE256_BLOCKSIZE; - - for (; b < end && coeff_idx[lane] < ML_DSA_NUM_POLY_COEFFICIENTS; b++) { - uint32_t z0 = *b & 0x0F; - uint32_t z1 = *b >> 4; - - if (coef_from_nibble(z0, &outs[lane]->coeff[coeff_idx[lane]])) - coeff_idx[lane]++; - - if (coeff_idx[lane] >= ML_DSA_NUM_POLY_COEFFICIENTS) { - done_mask |= ((size_t)1 << lane); - break; - } - - if (coef_from_nibble(z1, &outs[lane]->coeff[coeff_idx[lane]])) - coeff_idx[lane]++; - - if (coeff_idx[lane] >= ML_DSA_NUM_POLY_COEFFICIENTS) { - done_mask |= ((size_t)1 << lane); - break; - } - } - } - } - - OPENSSL_cleanse(blocks, sizeof(blocks)); - ossl_sha3_shake256_x4_inc_cleanup_avx512vl(&ctx); - return 1; -} - -static int matrix_expand_A_mb(EVP_MD_CTX *g_ctx, const EVP_MD *md, - const uint8_t *rho, MATRIX *out) -{ - size_t b, idx; - uint8_t derived_seeds[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_RHO_BYTES + 2]; - const size_t seed_len = sizeof(derived_seeds[0]); - const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE]; - POLY *polys[ML_DSA_SHAKE_X4_BATCH_SIZE]; - POLY *poly = out->m_poly; - - for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) { - memcpy(derived_seeds[b], rho, ML_DSA_RHO_BYTES); - seeds[b] = derived_seeds[b]; - } - - for (idx = 0; (idx + ML_DSA_SHAKE_X4_BATCH_SIZE - 1) < (out->k * out->l); - idx += ML_DSA_SHAKE_X4_BATCH_SIZE) { - for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) { - const size_t row = (idx + b) / out->l; - const size_t col = (idx + b) % out->l; - - derived_seeds[b][ML_DSA_RHO_BYTES] = (uint8_t)col; - derived_seeds[b][ML_DSA_RHO_BYTES + 1] = (uint8_t)row; - polys[b] = &poly[idx + b]; - } - - if (!rej_ntt_poly_mb(seeds, seed_len, polys, 4)) - return 0; - } - - if (idx < (out->k * out->l)) { - const size_t left = (out->k * out->l) - idx; - - for (b = 0; b < left; b++) { - const size_t row = (idx + b) / out->l; - const size_t col = (idx + b) % out->l; - - derived_seeds[b][ML_DSA_RHO_BYTES] = (uint8_t)col; - derived_seeds[b][ML_DSA_RHO_BYTES + 1] = (uint8_t)row; - polys[b] = &poly[idx + b]; - } - - if (!rej_ntt_poly_mb(seeds, seed_len, polys, left)) - return 0; - } - - return 1; -} - -static int vector_expand_S_mb(EVP_MD_CTX *h_ctx, const EVP_MD *md, const int eta, - const uint8_t *seed, VECTOR *s1, VECTOR *s2) -{ - int ret = 0; - size_t b, idx; - const size_t l = s1->num_poly; - const size_t total = l + s2->num_poly; - uint8_t derived_seeds[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_PRIV_SEED_BYTES + 2]; - const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE]; - const size_t seed_len = sizeof(derived_seeds[0]); - POLY *polys[ML_DSA_SHAKE_X4_BATCH_SIZE]; - COEFF_FROM_NIBBLE_FUNC *coef_from_nibble_fn = (eta == ML_DSA_ETA_4) ? coeff_from_nibble_4 : coeff_from_nibble_2; - - for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) { - memcpy(derived_seeds[b], seed, ML_DSA_PRIV_SEED_BYTES); - seeds[b] = derived_seeds[b]; - } - - for (idx = 0; (idx + ML_DSA_SHAKE_X4_BATCH_SIZE - 1) < total; idx += ML_DSA_SHAKE_X4_BATCH_SIZE) { - for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) { - const size_t poly_idx = idx + b; - - derived_seeds[b][ML_DSA_PRIV_SEED_BYTES] = (uint8_t)(poly_idx); - derived_seeds[b][ML_DSA_PRIV_SEED_BYTES + 1] = (uint8_t)(poly_idx >> 8); - - if (poly_idx < l) - polys[b] = &s1->poly[poly_idx]; - else - polys[b] = &s2->poly[poly_idx - l]; - } - - if (!rej_bounded_poly_mb(coef_from_nibble_fn, - seeds, seed_len, polys, ML_DSA_SHAKE_X4_BATCH_SIZE)) - goto err; - } - - if (idx < total) { - const size_t batch_count = total - idx; - - for (b = 0; b < batch_count; b++) { - const size_t poly_idx = idx + b; - - derived_seeds[b][ML_DSA_PRIV_SEED_BYTES] = (uint8_t)(poly_idx); - derived_seeds[b][ML_DSA_PRIV_SEED_BYTES + 1] = (uint8_t)(poly_idx >> 8); - - if (poly_idx < l) - polys[b] = &s1->poly[poly_idx]; - else - polys[b] = &s2->poly[poly_idx - l]; - } - - if (!rej_bounded_poly_mb(coef_from_nibble_fn, - seeds, seed_len, polys, batch_count)) - goto err; - } - - ret = 1; -err: - OPENSSL_cleanse(derived_seeds, sizeof(derived_seeds)); - return ret; -} - -static const OSSL_ML_DSA_SAMPLE_OPS ml_dsa_sample_x86_64 = { - matrix_expand_A_mb, - vector_expand_S_mb, - vector_expand_mask_mb -}; diff --git a/crypto/ml_dsa/ml_dsa_sign.c b/crypto/ml_dsa/ml_dsa_sign.c index 62dfd08d53..05251a6dd0 100644 --- a/crypto/ml_dsa/ml_dsa_sign.c +++ b/crypto/ml_dsa/ml_dsa_sign.c @@ -164,7 +164,6 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv, uint8_t *out_sig) { int ret = 0; - const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops(); const ML_DSA_PARAMS *params = priv->params; EVP_MD_CTX *md_ctx = NULL; uint32_t k = (uint32_t)params->k, l = (uint32_t)params->l; @@ -237,7 +236,7 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv, CONSTTIME_SECRET_VECTOR(priv->s2); CONSTTIME_SECRET_VECTOR(priv->t0); - if (!sample_ops->matrix_expand_A(md_ctx, priv->shake128_md, priv->rho, &a_ntt)) + if (!matrix_expand_A(md_ctx, priv->shake128_md, priv->rho, &a_ntt)) goto err; /* @@ -268,8 +267,8 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv, VECTOR *ct0 = &w1; uint32_t z_max, r0_max, ct0_max, h_ones; - sample_ops->vector_expand_mask(&y, rho_prime, - (uint32_t)kappa, gamma1, md_ctx, priv->shake256_md); + vector_expand_mask(&y, rho_prime, sizeof(rho_prime), (uint32_t)kappa, + gamma1, md_ctx, priv->shake256_md); vector_copy(y_ntt, &y); vector_ntt(y_ntt); @@ -392,7 +391,6 @@ static int ml_dsa_verify_internal(const ML_DSA_KEY *pub, const uint8_t *sig_enc, size_t sig_enc_len) { int ret = 0; - const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops(); uint8_t *alloc = NULL, *w1_encoded = NULL; void *alloc_freeptr = NULL; POLY *p, *c_ntt; @@ -450,7 +448,7 @@ static int ml_dsa_verify_internal(const ML_DSA_KEY *pub, vector_init(&ct1_ntt, p + k, k); if (!ossl_ml_dsa_sig_decode(&sig, sig_enc, sig_enc_len, pub->params) - || !sample_ops->matrix_expand_A(md_ctx, pub->shake128_md, pub->rho, &a_ntt)) + || !matrix_expand_A(md_ctx, pub->shake128_md, pub->rho, &a_ntt)) goto err; /* Compute verifiers challenge c_ntt = NTT(SampleInBall(c_tilde)) */ diff --git a/crypto/ml_dsa/ml_dsa_vector.h b/crypto/ml_dsa/ml_dsa_vector.h index 9b83c0420e..6b408acdc2 100644 --- a/crypto/ml_dsa/ml_dsa_vector.h +++ b/crypto/ml_dsa/ml_dsa_vector.h @@ -152,6 +152,33 @@ vector_mult_scalar(const VECTOR *lhs, const POLY *rhs, VECTOR *out) ossl_ml_dsa_poly_ntt_mult(lhs->poly + i, rhs, out->poly + i); } +static ossl_inline ossl_unused int +vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta, + const uint8_t *seed, VECTOR *s1, VECTOR *s2) +{ + return ossl_ml_dsa_vector_expand_S(h_ctx, md, eta, seed, s1, s2); +} + +static ossl_inline ossl_unused void +vector_expand_mask(VECTOR *out, const uint8_t *rho_prime, size_t rho_prime_len, + uint32_t kappa, uint32_t gamma1, + EVP_MD_CTX *h_ctx, const EVP_MD *md) +{ + size_t i; + uint8_t derived_seed[ML_DSA_RHO_PRIME_BYTES + 2]; + + memcpy(derived_seed, rho_prime, ML_DSA_RHO_PRIME_BYTES); + + for (i = 0; i < out->num_poly; i++) { + size_t index = kappa + i; + + derived_seed[ML_DSA_RHO_PRIME_BYTES] = index & 0xFF; + derived_seed[ML_DSA_RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF; + poly_expand_mask(out->poly + i, derived_seed, sizeof(derived_seed), + gamma1, h_ctx, md); + } +} + /* Scale back previously rounded value */ static ossl_inline ossl_unused void vector_scale_power2_round_ntt(const VECTOR *in, VECTOR *out) diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c index 89960dc105..2fc0e5a980 100644 --- a/crypto/ml_kem/ml_kem.c +++ b/crypto/ml_kem/ml_kem.c @@ -1148,7 +1148,7 @@ static __owur int gencbd_vector_ntt(scalar *out, CBD_FUNC cbd, uint8_t *counter, * |A| (our key->m, with the public key holding an expanded (16-bit per scalar * coefficient) key->t vector). * - * Caller passes storage in |tmp| for two temporary vectors. + * Caller passes storage in |tmp| for for two temporary vectors. */ static __owur int encrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES], const uint8_t message[DEGREE / 8], @@ -2032,13 +2032,11 @@ int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen, #endif /* Need a private key here */ - if (!ossl_ml_kem_have_prvkey(key) - || shared_secret == NULL - || slen < ML_KEM_SHARED_SECRET_BYTES) + if (!ossl_ml_kem_have_prvkey(key)) return 0; vinfo = key->vinfo; - if (slen != ML_KEM_SHARED_SECRET_BYTES + if (shared_secret == NULL || slen != ML_KEM_SHARED_SECRET_BYTES || ctext == NULL || clen != vinfo->ctext_bytes || (mdctx = EVP_MD_CTX_new()) == NULL) { (void)RAND_bytes_ex(key->libctx, shared_secret, diff --git a/crypto/o_dir.c b/crypto/o_dir.c index ed92b9f130..36d33fbed4 100644 --- a/crypto/o_dir.c +++ b/crypto/o_dir.c @@ -31,6 +31,8 @@ # include "LPdir_vms.c" #elif defined OPENSSL_SYS_WIN32 # include "LPdir_win32.c" +#elif defined OPENSSL_SYS_WINCE +# include "LPdir_wince.c" #else # include "LPdir_nyi.c" #endif diff --git a/crypto/o_str.c b/crypto/o_str.c index 2192d48775..c2ec1fc261 100644 --- a/crypto/o_str.c +++ b/crypto/o_str.c @@ -377,7 +377,7 @@ char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen) int openssl_strerror_r(int errnum, char *buf, size_t buflen) { -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(_WIN32_WCE) return !strerror_s(buf, buflen, errnum); #elif defined(_GNU_SOURCE) char *err; diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h index 46de3ccf4a..955571e134 100644 --- a/crypto/objects/obj_xref.h +++ b/crypto/objects/obj_xref.h @@ -81,8 +81,6 @@ static const nid_triple sigoid_srt[] = { NID_id_GostR3410_2012_512}, {NID_ED25519, NID_undef, NID_ED25519}, {NID_ED448, NID_undef, NID_ED448}, - {NID_dsa_with_SHA384, NID_sha384, NID_dsa}, - {NID_dsa_with_SHA512, NID_sha512, NID_dsa}, {NID_ecdsa_with_SHA3_224, NID_sha3_224, NID_X9_62_id_ecPublicKey}, {NID_ecdsa_with_SHA3_256, NID_sha3_256, NID_X9_62_id_ecPublicKey}, {NID_ecdsa_with_SHA3_384, NID_sha3_384, NID_X9_62_id_ecPublicKey}, @@ -131,12 +129,10 @@ static const nid_triple *const sigoid_srt_xref[] = { &sigoid_srt[32], &sigoid_srt[37], &sigoid_srt[14], - &sigoid_srt[44], &sigoid_srt[21], &sigoid_srt[33], &sigoid_srt[38], &sigoid_srt[15], - &sigoid_srt[45], &sigoid_srt[22], &sigoid_srt[34], &sigoid_srt[39], @@ -151,15 +147,15 @@ static const nid_triple *const sigoid_srt_xref[] = { &sigoid_srt[28], &sigoid_srt[40], &sigoid_srt[41], + &sigoid_srt[48], + &sigoid_srt[44], + &sigoid_srt[49], + &sigoid_srt[45], &sigoid_srt[50], &sigoid_srt[46], &sigoid_srt[51], &sigoid_srt[47], &sigoid_srt[52], - &sigoid_srt[48], - &sigoid_srt[53], - &sigoid_srt[49], - &sigoid_srt[54], }; /* clang-format on */ diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt index 2f82617a84..71bc12af74 100644 --- a/crypto/objects/obj_xref.txt +++ b/crypto/objects/obj_xref.txt @@ -64,8 +64,6 @@ ecdsa_with_SHA3_512 sha3_512 X9_62_id_ecPublicKey dsa_with_SHA224 sha224 dsa dsa_with_SHA256 sha256 dsa -dsa_with_SHA384 sha384 dsa -dsa_with_SHA512 sha512 dsa id_GostR3411_94_with_GostR3410_2001 id_GostR3411_94 id_GostR3410_2001 id_GostR3411_94_with_GostR3410_94 id_GostR3411_94 id_GostR3410_94 diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c index 038be72b04..e6467aa0ae 100644 --- a/crypto/ocsp/ocsp_ext.c +++ b/crypto/ocsp/ocsp_ext.c @@ -360,7 +360,7 @@ X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim) if (url) { if ((cid->crlUrl = ASN1_IA5STRING_new()) == NULL) goto err; - if (!(ASN1_STRING_set_string(cid->crlUrl, url))) + if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) goto err; } if (n) { @@ -446,7 +446,7 @@ X509_EXTENSION *OCSP_url_svcloc_new(const X509_NAME *issuer, const char **urls) goto err; if ((ia5 = ASN1_IA5STRING_new()) == NULL) goto err; - if (!ASN1_STRING_set_string((ASN1_STRING *)ia5, *urls)) + if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1)) goto err; /* ad->location is allocated inside ACCESS_DESCRIPTION_new */ ad->location->type = GEN_URI; diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c index fa99da8a7f..beecad63a2 100644 --- a/crypto/ocsp/ocsp_srv.c +++ b/crypto/ocsp/ocsp_srv.c @@ -301,7 +301,7 @@ int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OSSL_LIB_CTX *libctx, if (!X509_pubkey_digest(cert, sha1, md, NULL)) goto err; - ret = (ASN1_STRING_length_ex(respid->value.byKey) == SHA_DIGEST_LENGTH) + ret = (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, SHA_DIGEST_LENGTH) == 0); diff --git a/crypto/ocsp/v3_ocsp.c b/crypto/ocsp/v3_ocsp.c index 408c2a1548..d31c74ef45 100644 --- a/crypto/ocsp/v3_ocsp.c +++ b/crypto/ocsp/v3_ocsp.c @@ -143,7 +143,7 @@ static void *ocsp_nonce_new(void) static int i2d_ocsp_nonce(const void *a, unsigned char **pp) { const ASN1_OCTET_STRING *os = a; - if (pp != NULL && os->length > 0) { + if (pp) { memcpy(*pp, os->data, os->length); *pp += os->length; } @@ -164,8 +164,7 @@ static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) if (!ASN1_OCTET_STRING_set(os, *pp, length)) goto err; - if (length > 0) - *pp += length; + *pp += length; if (pos) *pos = os; diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c index fa189f0c5d..8f38fe0580 100644 --- a/crypto/pem/pem_info.c +++ b/crypto/pem/pem_info.c @@ -24,14 +24,6 @@ #include #include "crypto/evp.h" -typedef enum { - PEM_INFO_NONE, - PEM_INFO_X509, - PEM_INFO_X509_AUX, - PEM_INFO_X509_CRL, - PEM_INFO_PKEY -} pem_info_type; - #ifndef OPENSSL_NO_STDIO STACK_OF(X509_INFO) *PEM_X509_INFO_read_ex(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, @@ -71,7 +63,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, int ok = 0; STACK_OF(X509_INFO) *ret = NULL; unsigned int i, raw, ptype; - pem_info_type itype = PEM_INFO_NONE; + d2i_of_void *d2i = 0; if (sk == NULL) { if ((ret = sk_X509_INFO_new_null()) == NULL) { @@ -86,7 +78,6 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, for (;;) { raw = 0; ptype = 0; - itype = PEM_INFO_NONE; ERR_set_mark(); i = PEM_read_bio(bp, &name, &header, &data, &len); if (i == 0) { @@ -111,15 +102,15 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, goto start; } if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) - itype = PEM_INFO_X509_AUX; + d2i = (D2I_OF(void))d2i_X509_AUX; else - itype = PEM_INFO_X509; + d2i = (D2I_OF(void))d2i_X509; xi->x509 = X509_new_ex(libctx, propq); if (xi->x509 == NULL) goto err; pp = &(xi->x509); } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) { - itype = PEM_INFO_X509_CRL; + d2i = (D2I_OF(void))d2i_X509_CRL; if (xi->crl != NULL) { if (!sk_X509_INFO_push(ret, xi)) goto err; @@ -146,7 +137,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, xi->enc_data = NULL; xi->enc_len = 0; - itype = PEM_INFO_PKEY; + d2i = (D2I_OF(void))d2i_AutoPrivateKey; xi->x_pkey = X509_PKEY_new(); if (xi->x_pkey == NULL) goto err; @@ -155,11 +146,11 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, || strcmp(name, PEM_STRING_PKCS8) == 0) raw = 1; } else { /* unknown */ - itype = PEM_INFO_NONE; + d2i = NULL; pp = NULL; } - if (itype != PEM_INFO_NONE) { + if (d2i != NULL) { if (!raw) { EVP_CIPHER_INFO cipher; @@ -169,36 +160,15 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, goto err; p = data; if (ptype) { - if (d2i_PrivateKey_ex(ptype, (EVP_PKEY **)pp, &p, len, + if (d2i_PrivateKey_ex(ptype, pp, &p, len, libctx, propq) == NULL) { ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); goto err; } - } else { - void *decoded = NULL; - - switch (itype) { - case PEM_INFO_X509: - decoded = d2i_X509((X509 **)pp, &p, len); - break; - case PEM_INFO_X509_AUX: - decoded = d2i_X509_AUX((X509 **)pp, &p, len); - break; - case PEM_INFO_X509_CRL: - decoded = d2i_X509_CRL((X509_CRL **)pp, &p, len); - break; - case PEM_INFO_PKEY: - decoded = d2i_AutoPrivateKey_ex((EVP_PKEY **)pp, &p, - len, libctx, propq); - break; - default: - break; - } - if (decoded == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); - goto err; - } + } else if (d2i(pp, &p, len) == NULL) { + ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); + goto err; } } else { /* encrypted key data */ if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher)) diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index 1217317783..8ea41676d8 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -219,6 +219,6 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) } return p7s; err: - sk_PKCS7_pop_free(p7s, PKCS7_free); + sk_PKCS7_free(p7s); return NULL; } diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c index 60843bd951..2888efd689 100644 --- a/crypto/pkcs12/p12_mutl.c +++ b/crypto/pkcs12/p12_mutl.c @@ -350,7 +350,7 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) } } X509_SIG_get0(p12->mac->dinfo, NULL, &macoct); - if ((maclen != ASN1_STRING_length_ex(macoct)) + if ((maclen != (unsigned int)ASN1_STRING_length(macoct)) || CRYPTO_memcmp(mac, ASN1_STRING_get0_data(macoct), maclen) != 0) return 0; diff --git a/crypto/pkcs7/pk7_attr.c b/crypto/pkcs7/pk7_attr.c index 28f073f36f..b865d97356 100644 --- a/crypto/pkcs7/pk7_attr.c +++ b/crypto/pkcs7/pk7_attr.c @@ -30,7 +30,7 @@ int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, } seq->length = ASN1_item_i2d((ASN1_VALUE *)cap, &seq->data, ASN1_ITEM_rptr(X509_ALGORS)); - if (ASN1_STRING_length_ex(seq) == 0 || ASN1_STRING_get0_data(seq) == NULL) { + if (ASN1_STRING_length(seq) <= 0 || ASN1_STRING_get0_data(seq) == NULL) { ASN1_STRING_free(seq); return 1; } @@ -46,17 +46,14 @@ STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si) { const ASN1_TYPE *cap; const unsigned char *p; - size_t len; cap = PKCS7_get_signed_attribute(si, NID_SMIMECapabilities); if (cap == NULL || (cap->type != V_ASN1_SEQUENCE)) return NULL; p = ASN1_STRING_get0_data(cap->value.sequence); - len = ASN1_STRING_length_ex(cap->value.sequence); - if (len > INT_MAX) - return NULL; return (STACK_OF(X509_ALGOR) *) - ASN1_item_d2i(NULL, &p, (int)len, ASN1_ITEM_rptr(X509_ALGORS)); + ASN1_item_d2i(NULL, &p, ASN1_STRING_length(cap->value.sequence), + ASN1_ITEM_rptr(X509_ALGORS)); } /* Basic smime-capabilities OID and optional integer arg */ @@ -132,7 +129,7 @@ int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, os = ASN1_OCTET_STRING_new(); if (os == NULL) return 0; - if (!ASN1_STRING_set_data(os, md, mdlen) + if (!ASN1_STRING_set(os, md, mdlen) || !PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING, os)) { ASN1_OCTET_STRING_free(os); diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index 33d2eaafdf..7b6a3b36b4 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -74,19 +74,16 @@ static ASN1_OCTET_STRING *pkcs7_get1_data(PKCS7 *p7) if (PKCS7_type_is_other(p7) && (p7->d.other != NULL) && (p7->d.other->type == V_ASN1_SEQUENCE) && (p7->d.other->value.sequence != NULL) - && (ASN1_STRING_length_ex(p7->d.other->value.sequence) > 0)) { + && (ASN1_STRING_length(p7->d.other->value.sequence) > 0)) { const unsigned char *data = ASN1_STRING_get0_data(p7->d.other->value.sequence); long len; int inf, tag, class; - size_t tmp; - tmp = ASN1_STRING_length_ex(p7->d.other->value.sequence); - if (tmp > INT_MAX) - return NULL; os = ASN1_OCTET_STRING_new(); if (os == NULL) return NULL; - inf = ASN1_get_object(&data, &len, &tag, &class, (int)tmp); + inf = ASN1_get_object(&data, &len, &tag, &class, + ASN1_STRING_length(p7->d.other->value.sequence)); if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE || !ASN1_OCTET_STRING_set(os, data, len)) { ASN1_OCTET_STRING_free(os); @@ -201,7 +198,7 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, goto err; ret = evp_pkey_decrypt_alloc(pctx, &ek, &eklen, fixlen, - ASN1_STRING_get0_data(ri->enc_key), ASN1_STRING_length_ex(ri->enc_key)); + ASN1_STRING_get0_data(ri->enc_key), ASN1_STRING_length(ri->enc_key)); if (ret <= 0) goto err; @@ -374,7 +371,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) if (bio == NULL) { if (PKCS7_is_detached(p7)) { bio = BIO_new(BIO_s_null()); - } else if (os != NULL && ASN1_STRING_length_ex(os) > 0) { + } else if (os != NULL && ASN1_STRING_length(os) > 0) { /* * bio needs a copy of os->data instead of a pointer because * the data will be used after os has been freed @@ -383,8 +380,8 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) if (bio != NULL) { BIO_set_mem_eof_return(bio, 0); const unsigned char *os_data = ASN1_STRING_get0_data(os); - size_t os_len = ASN1_STRING_length_ex(os); - if (os_len > INT_MAX || BIO_write(bio, os_data, (int)os_len) != (int)os_len) { + int os_len = ASN1_STRING_length(os); + if (BIO_write(bio, os_data, os_len) != os_len) { BIO_free_all(bio); bio = NULL; } @@ -659,12 +656,10 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) if (in_bio != NULL) { bio = in_bio; } else { - size_t data_body_len = ASN1_STRING_length_ex(data_body); - if (data_body_len > INT_MAX) - goto err; + int data_body_len = ASN1_STRING_length(data_body); if (data_body_len > 0) bio = BIO_new_mem_buf(ASN1_STRING_get0_data(data_body), - (int)data_body_len); + data_body_len); else { bio = BIO_new(BIO_s_mem()); if (bio == NULL) @@ -1115,7 +1110,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } - if ((ASN1_STRING_length_ex(message_digest) != md_len) + if ((ASN1_STRING_length(message_digest) != (int)md_len) || (memcmp(ASN1_STRING_get0_data(message_digest), md_dat, md_len))) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_DIGEST_FAILURE); ret = -1; @@ -1147,12 +1142,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, } const unsigned char *sig_data = ASN1_STRING_get0_data(os); - size_t sig_len = ASN1_STRING_length_ex(os); - if (sig_len > INT_MAX) { - ret = -1; - goto err; - } - i = EVP_VerifyFinal_ex(mdc_tmp, sig_data, (int)sig_len, pkey, libctx, propq); + int sig_len = ASN1_STRING_length(os); + i = EVP_VerifyFinal_ex(mdc_tmp, sig_data, sig_len, pkey, libctx, propq); if (i <= 0) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE); ret = -1; @@ -1180,7 +1171,7 @@ PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) rsk = p7->d.signed_and_enveloped->recipientinfo; if (rsk == NULL) return NULL; - if (idx < 0 || sk_PKCS7_RECIP_INFO_num(rsk) <= idx) + if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return NULL; ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); return ri->issuer_and_serial; diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index a9640769cf..0a1d0f61a5 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -537,7 +537,7 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) } ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); - return 0; + return 1; } STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index 7ede4b6694..49129690de 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -199,15 +199,9 @@ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) } } - if (osdig != NULL) { - size_t len; - len = ASN1_STRING_length_ex(osdig); - if (len > INT_MAX) - goto err; - return PKCS7_add1_attrib_digest(si, ASN1_STRING_get0_data(osdig), (int)len); - } + if (osdig != NULL) + return PKCS7_add1_attrib_digest(si, ASN1_STRING_get0_data(osdig), ASN1_STRING_length(osdig)); -err: ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND); return 0; } diff --git a/crypto/poly1305/poly1305_base2_44.c b/crypto/poly1305/poly1305_base2_44.c new file mode 100644 index 0000000000..e64f5294d8 --- /dev/null +++ b/crypto/poly1305/poly1305_base2_44.c @@ -0,0 +1,164 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This module is meant to be used as template for base 2^44 assembly + * implementation[s]. On side note compiler-generated code is not + * slower than compiler-generated base 2^64 code on [high-end] x86_64, + * even though amount of multiplications is 50% higher. Go figure... + */ +#include +#include + +typedef uint128_t u128; + +typedef struct { + uint64_t h[3]; + uint64_t s[2]; + uint64_t r[3]; +} poly1305_internal; + +#define POLY1305_BLOCK_SIZE 16 + +/* pick 64-bit unsigned integer in little endian order */ +static uint64_t U8TOU64(const unsigned char *p) +{ + return (((uint64_t)(p[0] & 0xff)) | ((uint64_t)(p[1] & 0xff) << 8) | ((uint64_t)(p[2] & 0xff) << 16) | ((uint64_t)(p[3] & 0xff) << 24) | ((uint64_t)(p[4] & 0xff) << 32) | ((uint64_t)(p[5] & 0xff) << 40) | ((uint64_t)(p[6] & 0xff) << 48) | ((uint64_t)(p[7] & 0xff) << 56)); +} + +/* store a 64-bit unsigned integer in little endian */ +static void U64TO8(unsigned char *p, uint64_t v) +{ + p[0] = (unsigned char)((v) & 0xff); + p[1] = (unsigned char)((v >> 8) & 0xff); + p[2] = (unsigned char)((v >> 16) & 0xff); + p[3] = (unsigned char)((v >> 24) & 0xff); + p[4] = (unsigned char)((v >> 32) & 0xff); + p[5] = (unsigned char)((v >> 40) & 0xff); + p[6] = (unsigned char)((v >> 48) & 0xff); + p[7] = (unsigned char)((v >> 56) & 0xff); +} + +int poly1305_init(void *ctx, const unsigned char key[16]) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + uint64_t r0, r1; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + + r0 = U8TOU64(&key[0]) & 0x0ffffffc0fffffff; + r1 = U8TOU64(&key[8]) & 0x0ffffffc0ffffffc; + + /* break r1:r0 to three 44-bit digits, masks are 1<<44-1 */ + st->r[0] = r0 & 0x0fffffffffff; + st->r[1] = ((r0 >> 44) | (r1 << 20)) & 0x0fffffffffff; + st->r[2] = (r1 >> 24); + + st->s[0] = (st->r[1] + (st->r[1] << 2)) << 2; + st->s[1] = (st->r[2] + (st->r[2] << 2)) << 2; + + return 0; +} + +void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, + uint32_t padbit) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + uint64_t r0, r1, r2; + uint64_t s1, s2; + uint64_t h0, h1, h2, c; + u128 d0, d1, d2; + uint64_t pad = (uint64_t)padbit << 40; + + r0 = st->r[0]; + r1 = st->r[1]; + r2 = st->r[2]; + + s1 = st->s[0]; + s2 = st->s[1]; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + + while (len >= POLY1305_BLOCK_SIZE) { + uint64_t m0, m1; + + m0 = U8TOU64(inp + 0); + m1 = U8TOU64(inp + 8); + + /* h += m[i], m[i] is broken to 44-bit digits */ + h0 += m0 & 0x0fffffffffff; + h1 += ((m0 >> 44) | (m1 << 20)) & 0x0fffffffffff; + h2 += (m1 >> 24) + pad; + + /* h *= r "%" p, where "%" stands for "partial remainder" */ + d0 = ((u128)h0 * r0) + ((u128)h1 * s2) + ((u128)h2 * s1); + d1 = ((u128)h0 * r1) + ((u128)h1 * r0) + ((u128)h2 * s2); + d2 = ((u128)h0 * r2) + ((u128)h1 * r1) + ((u128)h2 * r0); + + /* "lazy" reduction step */ + h0 = (uint64_t)d0 & 0x0fffffffffff; + h1 = (uint64_t)(d1 += (uint64_t)(d0 >> 44)) & 0x0fffffffffff; + h2 = (uint64_t)(d2 += (uint64_t)(d1 >> 44)) & 0x03ffffffffff; /* last 42 bits */ + + c = (d2 >> 42); + h0 += c + (c << 2); + + inp += POLY1305_BLOCK_SIZE; + len -= POLY1305_BLOCK_SIZE; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; +} + +void poly1305_emit(void *ctx, unsigned char mac[16], const uint32_t nonce[4]) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + uint64_t h0, h1, h2; + uint64_t g0, g1, g2; + u128 t; + uint64_t mask; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + + /* after "lazy" reduction, convert 44+bit digits to 64-bit ones */ + h0 = (uint64_t)(t = (u128)h0 + (h1 << 44)); + h1 >>= 20; + h1 = (uint64_t)(t = (u128)h1 + (h2 << 24) + (t >> 64)); + h2 >>= 40; + h2 += (uint64_t)(t >> 64); + + /* compare to modulus by computing h + -p */ + g0 = (uint64_t)(t = (u128)h0 + 5); + g1 = (uint64_t)(t = (u128)h1 + (t >> 64)); + g2 = h2 + (uint64_t)(t >> 64); + + /* if there was carry into 131st bit, h1:h0 = g1:g0 */ + mask = 0 - (g2 >> 2); + g0 &= mask; + g1 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + + /* mac = (h + nonce) % (2^128) */ + h0 = (uint64_t)(t = (u128)h0 + nonce[0] + ((uint64_t)nonce[1] << 32)); + h1 = (uint64_t)(t = (u128)h1 + nonce[2] + ((uint64_t)nonce[3] << 32) + (t >> 64)); + + U64TO8(mac + 0, h0); + U64TO8(mac + 8, h1); +} diff --git a/crypto/poly1305/poly1305_ieee754.c b/crypto/poly1305/poly1305_ieee754.c new file mode 100644 index 0000000000..16d3d0f5a9 --- /dev/null +++ b/crypto/poly1305/poly1305_ieee754.c @@ -0,0 +1,485 @@ +/* + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This module is meant to be used as template for non-x87 floating- + * point assembly modules. The template itself is x86_64-specific + * though, as it was debugged on x86_64. So that implementer would + * have to recognize platform-specific parts, UxTOy and inline asm, + * and act accordingly. + * + * Huh? x86_64-specific code as template for non-x87? Note seven, which + * is not a typo, but reference to 80-bit precision. This module on the + * other hand relies on 64-bit precision operations, which are default + * for x86_64 code. And since we are at it, just for sense of it, + * large-block performance in cycles per processed byte for *this* code + * is: + * gcc-4.8 icc-15.0 clang-3.4(*) + * + * Westmere 4.96 5.09 4.37 + * Sandy Bridge 4.95 4.90 4.17 + * Haswell 4.92 4.87 3.78 + * Bulldozer 4.67 4.49 4.68 + * VIA Nano 7.07 7.05 5.98 + * Silvermont 10.6 9.61 12.6 + * + * (*) clang managed to discover parallelism and deployed SIMD; + * + * And for range of other platforms with unspecified gcc versions: + * + * Freescale e300 12.5 + * PPC74x0 10.8 + * POWER6 4.92 + * POWER7 4.50 + * POWER8 4.10 + * + * z10 11.2 + * z196+ 7.30 + * + * UltraSPARC III 16.0 + * SPARC T4 16.1 + */ + +#if !(defined(__GNUC__) && __GNUC__ >= 2) +#error "this is gcc-specific template" +#endif + +#include +#include + +typedef union { + double d; + uint64_t u; +} elem64; + +#define TWO(p) ((double)(1ULL << (p))) +#define TWO0 TWO(0) +#define TWO32 TWO(32) +#define TWO64 (TWO32 * TWO(32)) +#define TWO96 (TWO64 * TWO(32)) +#define TWO130 (TWO96 * TWO(34)) + +#define EXP(p) ((1023ULL + (p)) << 52) + +#if defined(__x86_64__) || (defined(__PPC__) && defined(__LITTLE_ENDIAN__)) +#define U8TOU32(p) (*(const uint32_t *)(p)) +#define U32TO8(p, v) (*(uint32_t *)(p) = (v)) +#elif defined(__PPC__) || defined(__POWERPC__) +#define U8TOU32(p) ({uint32_t ret; asm ("lwbrx %0,0,%1":"=r"(ret):"b"(p)); ret; }) +#define U32TO8(p, v) asm("stwbrx %0,0,%1" ::"r"(v), "b"(p) : "memory") +#elif defined(__s390x__) +#define U8TOU32(p) ({uint32_t ret; asm ("lrv %0,%1":"=d"(ret):"m"(*(uint32_t *)(p))); ret; }) +#define U32TO8(p, v) asm("strv %1,%0" : "=m"(*(uint32_t *)(p)) : "d"(v)) +#endif + +#ifndef U8TOU32 +#define U8TOU32(p) ((uint32_t)(p)[0] | (uint32_t)(p)[1] << 8 | (uint32_t)(p)[2] << 16 | (uint32_t)(p)[3] << 24) +#endif +#ifndef U32TO8 +#define U32TO8(p, v) ((p)[0] = (uint8_t)(v), (p)[1] = (uint8_t)((v) >> 8), \ + (p)[2] = (uint8_t)((v) >> 16), (p)[3] = (uint8_t)((v) >> 24)) +#endif + +typedef struct { + elem64 h[4]; + double r[8]; + double s[6]; +} poly1305_internal; + +/* "round toward zero (truncate), mask all exceptions" */ +#if defined(__x86_64__) +static const uint32_t mxcsr = 0x7f80; +#elif defined(__PPC__) || defined(__POWERPC__) +static const uint64_t one = 1; +#elif defined(__s390x__) +static const uint32_t fpc = 1; +#elif defined(__sparc__) +static const uint64_t fsr = 1ULL << 30; +#elif defined(__mips__) +static const uint32_t fcsr = 1; +#else +#error "unrecognized platform" +#endif + +int poly1305_init(void *ctx, const unsigned char key[16]) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + elem64 r0, r1, r2, r3; + + /* h = 0, biased */ +#if 0 + st->h[0].d = TWO(52)*TWO0; + st->h[1].d = TWO(52)*TWO32; + st->h[2].d = TWO(52)*TWO64; + st->h[3].d = TWO(52)*TWO96; +#else + st->h[0].u = EXP(52 + 0); + st->h[1].u = EXP(52 + 32); + st->h[2].u = EXP(52 + 64); + st->h[3].u = EXP(52 + 96); +#endif + + if (key) { + /* + * set "truncate" rounding mode + */ +#if defined(__x86_64__) + uint32_t mxcsr_orig; + + asm volatile("stmxcsr %0" : "=m"(mxcsr_orig)); + asm volatile("ldmxcsr %0" ::"m"(mxcsr)); +#elif defined(__PPC__) || defined(__POWERPC__) + double fpscr_orig, fpscr = *(double *)&one; + + asm volatile("mffs %0" : "=f"(fpscr_orig)); + asm volatile("mtfsf 255,%0" ::"f"(fpscr)); +#elif defined(__s390x__) + uint32_t fpc_orig; + + asm volatile("stfpc %0" : "=m"(fpc_orig)); + asm volatile("lfpc %0" ::"m"(fpc)); +#elif defined(__sparc__) + uint64_t fsr_orig; + + asm volatile("stx %%fsr,%0" : "=m"(fsr_orig)); + asm volatile("ldx %0,%%fsr" ::"m"(fsr)); +#elif defined(__mips__) + uint32_t fcsr_orig; + + asm volatile("cfc1 %0,$31" : "=r"(fcsr_orig)); + asm volatile("ctc1 %0,$31" ::"r"(fcsr)); +#endif + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + r0.u = EXP(52 + 0) | (U8TOU32(&key[0]) & 0x0fffffff); + r1.u = EXP(52 + 32) | (U8TOU32(&key[4]) & 0x0ffffffc); + r2.u = EXP(52 + 64) | (U8TOU32(&key[8]) & 0x0ffffffc); + r3.u = EXP(52 + 96) | (U8TOU32(&key[12]) & 0x0ffffffc); + + st->r[0] = r0.d - TWO(52) * TWO0; + st->r[2] = r1.d - TWO(52) * TWO32; + st->r[4] = r2.d - TWO(52) * TWO64; + st->r[6] = r3.d - TWO(52) * TWO96; + + st->s[0] = st->r[2] * (5.0 / TWO130); + st->s[2] = st->r[4] * (5.0 / TWO130); + st->s[4] = st->r[6] * (5.0 / TWO130); + + /* + * base 2^32 -> base 2^16 + */ + st->r[1] = (st->r[0] + TWO(52) * TWO(16) * TWO0) - TWO(52) * TWO(16) * TWO0; + st->r[0] -= st->r[1]; + + st->r[3] = (st->r[2] + TWO(52) * TWO(16) * TWO32) - TWO(52) * TWO(16) * TWO32; + st->r[2] -= st->r[3]; + + st->r[5] = (st->r[4] + TWO(52) * TWO(16) * TWO64) - TWO(52) * TWO(16) * TWO64; + st->r[4] -= st->r[5]; + + st->r[7] = (st->r[6] + TWO(52) * TWO(16) * TWO96) - TWO(52) * TWO(16) * TWO96; + st->r[6] -= st->r[7]; + + st->s[1] = (st->s[0] + TWO(52) * TWO(16) * TWO0 / TWO96) - TWO(52) * TWO(16) * TWO0 / TWO96; + st->s[0] -= st->s[1]; + + st->s[3] = (st->s[2] + TWO(52) * TWO(16) * TWO32 / TWO96) - TWO(52) * TWO(16) * TWO32 / TWO96; + st->s[2] -= st->s[3]; + + st->s[5] = (st->s[4] + TWO(52) * TWO(16) * TWO64 / TWO96) - TWO(52) * TWO(16) * TWO64 / TWO96; + st->s[4] -= st->s[5]; + + /* + * restore original FPU control register + */ +#if defined(__x86_64__) + asm volatile("ldmxcsr %0" ::"m"(mxcsr_orig)); +#elif defined(__PPC__) || defined(__POWERPC__) + asm volatile("mtfsf 255,%0" ::"f"(fpscr_orig)); +#elif defined(__s390x__) + asm volatile("lfpc %0" ::"m"(fpc_orig)); +#elif defined(__sparc__) + asm volatile("ldx %0,%%fsr" ::"m"(fsr_orig)); +#elif defined(__mips__) + asm volatile("ctc1 %0,$31" ::"r"(fcsr_orig)); +#endif + } + + return 0; +} + +void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, + int padbit) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + elem64 in0, in1, in2, in3; + uint64_t pad = (uint64_t)padbit << 32; + + double x0, x1, x2, x3; + double h0lo, h0hi, h1lo, h1hi, h2lo, h2hi, h3lo, h3hi; + double c0lo, c0hi, c1lo, c1hi, c2lo, c2hi, c3lo, c3hi; + + const double r0lo = st->r[0]; + const double r0hi = st->r[1]; + const double r1lo = st->r[2]; + const double r1hi = st->r[3]; + const double r2lo = st->r[4]; + const double r2hi = st->r[5]; + const double r3lo = st->r[6]; + const double r3hi = st->r[7]; + + const double s1lo = st->s[0]; + const double s1hi = st->s[1]; + const double s2lo = st->s[2]; + const double s2hi = st->s[3]; + const double s3lo = st->s[4]; + const double s3hi = st->s[5]; + + /* + * set "truncate" rounding mode + */ +#if defined(__x86_64__) + uint32_t mxcsr_orig; + + asm volatile("stmxcsr %0" : "=m"(mxcsr_orig)); + asm volatile("ldmxcsr %0" ::"m"(mxcsr)); +#elif defined(__PPC__) || defined(__POWERPC__) + double fpscr_orig, fpscr = *(double *)&one; + + asm volatile("mffs %0" : "=f"(fpscr_orig)); + asm volatile("mtfsf 255,%0" ::"f"(fpscr)); +#elif defined(__s390x__) + uint32_t fpc_orig; + + asm volatile("stfpc %0" : "=m"(fpc_orig)); + asm volatile("lfpc %0" ::"m"(fpc)); +#elif defined(__sparc__) + uint64_t fsr_orig; + + asm volatile("stx %%fsr,%0" : "=m"(fsr_orig)); + asm volatile("ldx %0,%%fsr" ::"m"(fsr)); +#elif defined(__mips__) + uint32_t fcsr_orig; + + asm volatile("cfc1 %0,$31" : "=r"(fcsr_orig)); + asm volatile("ctc1 %0,$31" ::"r"(fcsr)); +#endif + + /* + * load base 2^32 and de-bias + */ + h0lo = st->h[0].d - TWO(52) * TWO0; + h1lo = st->h[1].d - TWO(52) * TWO32; + h2lo = st->h[2].d - TWO(52) * TWO64; + h3lo = st->h[3].d - TWO(52) * TWO96; + +#ifdef __clang__ + h0hi = 0; + h1hi = 0; + h2hi = 0; + h3hi = 0; +#else + in0.u = EXP(52 + 0) | U8TOU32(&inp[0]); + in1.u = EXP(52 + 32) | U8TOU32(&inp[4]); + in2.u = EXP(52 + 64) | U8TOU32(&inp[8]); + in3.u = EXP(52 + 96) | U8TOU32(&inp[12]) | pad; + + x0 = in0.d - TWO(52) * TWO0; + x1 = in1.d - TWO(52) * TWO32; + x2 = in2.d - TWO(52) * TWO64; + x3 = in3.d - TWO(52) * TWO96; + + x0 += h0lo; + x1 += h1lo; + x2 += h2lo; + x3 += h3lo; + + goto fast_entry; +#endif + + do { + in0.u = EXP(52 + 0) | U8TOU32(&inp[0]); + in1.u = EXP(52 + 32) | U8TOU32(&inp[4]); + in2.u = EXP(52 + 64) | U8TOU32(&inp[8]); + in3.u = EXP(52 + 96) | U8TOU32(&inp[12]) | pad; + + x0 = in0.d - TWO(52) * TWO0; + x1 = in1.d - TWO(52) * TWO32; + x2 = in2.d - TWO(52) * TWO64; + x3 = in3.d - TWO(52) * TWO96; + + /* + * note that there are multiple ways to accumulate input, e.g. + * one can as well accumulate to h0lo-h1lo-h1hi-h2hi... + */ + h0lo += x0; + h0hi += x1; + h2lo += x2; + h2hi += x3; + + /* + * carries that cross 32n-bit (and 130-bit) boundaries + */ + c0lo = (h0lo + TWO(52) * TWO32) - TWO(52) * TWO32; + c1lo = (h1lo + TWO(52) * TWO64) - TWO(52) * TWO64; + c2lo = (h2lo + TWO(52) * TWO96) - TWO(52) * TWO96; + c3lo = (h3lo + TWO(52) * TWO130) - TWO(52) * TWO130; + + c0hi = (h0hi + TWO(52) * TWO32) - TWO(52) * TWO32; + c1hi = (h1hi + TWO(52) * TWO64) - TWO(52) * TWO64; + c2hi = (h2hi + TWO(52) * TWO96) - TWO(52) * TWO96; + c3hi = (h3hi + TWO(52) * TWO130) - TWO(52) * TWO130; + + /* + * base 2^48 -> base 2^32 with last reduction step + */ + x1 = (h1lo - c1lo) + c0lo; + x2 = (h2lo - c2lo) + c1lo; + x3 = (h3lo - c3lo) + c2lo; + x0 = (h0lo - c0lo) + c3lo * (5.0 / TWO130); + + x1 += (h1hi - c1hi) + c0hi; + x2 += (h2hi - c2hi) + c1hi; + x3 += (h3hi - c3hi) + c2hi; + x0 += (h0hi - c0hi) + c3hi * (5.0 / TWO130); + +#ifndef __clang__ + fast_entry: +#endif + /* + * base 2^32 * base 2^16 = base 2^48 + */ + h0lo = s3lo * x1 + s2lo * x2 + s1lo * x3 + r0lo * x0; + h1lo = r0lo * x1 + s3lo * x2 + s2lo * x3 + r1lo * x0; + h2lo = r1lo * x1 + r0lo * x2 + s3lo * x3 + r2lo * x0; + h3lo = r2lo * x1 + r1lo * x2 + r0lo * x3 + r3lo * x0; + + h0hi = s3hi * x1 + s2hi * x2 + s1hi * x3 + r0hi * x0; + h1hi = r0hi * x1 + s3hi * x2 + s2hi * x3 + r1hi * x0; + h2hi = r1hi * x1 + r0hi * x2 + s3hi * x3 + r2hi * x0; + h3hi = r2hi * x1 + r1hi * x2 + r0hi * x3 + r3hi * x0; + + inp += 16; + len -= 16; + + } while (len >= 16); + + /* + * carries that cross 32n-bit (and 130-bit) boundaries + */ + c0lo = (h0lo + TWO(52) * TWO32) - TWO(52) * TWO32; + c1lo = (h1lo + TWO(52) * TWO64) - TWO(52) * TWO64; + c2lo = (h2lo + TWO(52) * TWO96) - TWO(52) * TWO96; + c3lo = (h3lo + TWO(52) * TWO130) - TWO(52) * TWO130; + + c0hi = (h0hi + TWO(52) * TWO32) - TWO(52) * TWO32; + c1hi = (h1hi + TWO(52) * TWO64) - TWO(52) * TWO64; + c2hi = (h2hi + TWO(52) * TWO96) - TWO(52) * TWO96; + c3hi = (h3hi + TWO(52) * TWO130) - TWO(52) * TWO130; + + /* + * base 2^48 -> base 2^32 with last reduction step + */ + x1 = (h1lo - c1lo) + c0lo; + x2 = (h2lo - c2lo) + c1lo; + x3 = (h3lo - c3lo) + c2lo; + x0 = (h0lo - c0lo) + c3lo * (5.0 / TWO130); + + x1 += (h1hi - c1hi) + c0hi; + x2 += (h2hi - c2hi) + c1hi; + x3 += (h3hi - c3hi) + c2hi; + x0 += (h0hi - c0hi) + c3hi * (5.0 / TWO130); + + /* + * store base 2^32, with bias + */ + st->h[1].d = x1 + TWO(52) * TWO32; + st->h[2].d = x2 + TWO(52) * TWO64; + st->h[3].d = x3 + TWO(52) * TWO96; + st->h[0].d = x0 + TWO(52) * TWO0; + + /* + * restore original FPU control register + */ +#if defined(__x86_64__) + asm volatile("ldmxcsr %0" ::"m"(mxcsr_orig)); +#elif defined(__PPC__) || defined(__POWERPC__) + asm volatile("mtfsf 255,%0" ::"f"(fpscr_orig)); +#elif defined(__s390x__) + asm volatile("lfpc %0" ::"m"(fpc_orig)); +#elif defined(__sparc__) + asm volatile("ldx %0,%%fsr" ::"m"(fsr_orig)); +#elif defined(__mips__) + asm volatile("ctc1 %0,$31" ::"r"(fcsr_orig)); +#endif +} + +void poly1305_emit(void *ctx, unsigned char mac[16], const uint32_t nonce[4]) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + uint64_t h0, h1, h2, h3, h4; + uint32_t g0, g1, g2, g3, g4; + uint64_t t; + uint32_t mask; + + /* + * thanks to bias masking exponent gives integer result + */ + h0 = st->h[0].u & 0x000fffffffffffffULL; + h1 = st->h[1].u & 0x000fffffffffffffULL; + h2 = st->h[2].u & 0x000fffffffffffffULL; + h3 = st->h[3].u & 0x000fffffffffffffULL; + + /* + * can be partially reduced, so reduce... + */ + h4 = h3 >> 32; + h3 &= 0xffffffffU; + g4 = h4 & -4; + h4 &= 3; + g4 += g4 >> 2; + + h0 += g4; + h1 += h0 >> 32; + h0 &= 0xffffffffU; + h2 += h1 >> 32; + h1 &= 0xffffffffU; + h3 += h2 >> 32; + h2 &= 0xffffffffU; + + /* compute h + -p */ + g0 = (uint32_t)(t = h0 + 5); + g1 = (uint32_t)(t = h1 + (t >> 32)); + g2 = (uint32_t)(t = h2 + (t >> 32)); + g3 = (uint32_t)(t = h3 + (t >> 32)); + g4 = h4 + (uint32_t)(t >> 32); + + /* if there was carry, select g0-g3 */ + mask = 0 - (g4 >> 2); + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + mask = ~mask; + g0 |= (h0 & mask); + g1 |= (h1 & mask); + g2 |= (h2 & mask); + g3 |= (h3 & mask); + + /* mac = (h + nonce) % (2^128) */ + g0 = (uint32_t)(t = (uint64_t)g0 + nonce[0]); + g1 = (uint32_t)(t = (uint64_t)g1 + (t >> 32) + nonce[1]); + g2 = (uint32_t)(t = (uint64_t)g2 + (t >> 32) + nonce[2]); + g3 = (uint32_t)(t = (uint64_t)g3 + (t >> 32) + nonce[3]); + + U32TO8(mac + 0, g0); + U32TO8(mac + 4, g1); + U32TO8(mac + 8, g2); + U32TO8(mac + 12, g3); +} diff --git a/crypto/ppccap.c b/crypto/ppccap.c index e029eb3051..a2acf6b6ed 100644 --- a/crypto/ppccap.c +++ b/crypto/ppccap.c @@ -134,7 +134,7 @@ static unsigned long getauxval(unsigned long key) #define HWCAP_ARCH_3_00 (1U << 23) #define HWCAP_ARCH_3_1 (1U << 18) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 __attribute__((constructor)) #endif void OPENSSL_cpuid_setup(void) diff --git a/crypto/property/property.c b/crypto/property/property.c index aa0bb283f1..e807f06995 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -830,18 +830,10 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, } } fin: - if (ret) { + if (ret && ossl_method_up_ref(&best_impl->method)) { *method = best_impl->method.method; if (prov_rw != NULL) *prov_rw = best_impl->provider; -#ifdef OPENSSL_NO_CACHED_FETCH - if (!ossl_method_up_ref(&best_impl->method)) { - ret = 0; - *method = NULL; - if (prov_rw != NULL) - *prov_rw = NULL; - } -#endif } else { ret = 0; } @@ -946,15 +938,9 @@ static ossl_inline int ossl_method_store_cache_get_atomic(OSSL_METHOD_STORE *sto r = ossl_method_store_atomic_find_in_list(sa, nid, prov, prop_query); - if (r != NULL) { + if (r != NULL && ossl_method_up_ref(&r->method)) { *method = r->method.method; res = 1; -#ifdef OPENSSL_NO_CACHED_FETCH - if (!ossl_method_up_ref(&r->method)) { - *method = NULL; - res = 0; - } -#endif } return res; diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 93732995be..6094882947 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -486,7 +486,7 @@ int ossl_provider_up_ref(OSSL_PROVIDER *prov) { int ref = 0; - if (!CRYPTO_UP_REF(&prov->refcnt, &ref)) + if (CRYPTO_UP_REF(&prov->refcnt, &ref) <= 0) return 0; #ifndef FIPS_MODULE @@ -1134,7 +1134,7 @@ static int provider_init(OSSL_PROVIDER *prov) prov->error_strings[0].error = ERR_PACK(prov->error_lib, 0, 0); prov->error_strings[0].string = prov->name; /* - * Copy reasonstrings item 0..cnt-1 to prov->error_strings positions + * Copy reasonstrings item 0..cnt-1 to prov->error_trings positions * 1..cnt. */ for (cnt2 = 1; cnt2 <= cnt; cnt2++) { @@ -1576,7 +1576,7 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx, * to avoid upping the ref count on the parent provider, which we * must not do while holding locks. */ - if (!CRYPTO_UP_REF(&prov->refcnt, &ref)) { + if (CRYPTO_UP_REF(&prov->refcnt, &ref) <= 0) { CRYPTO_THREAD_unlock(prov->flag_lock); goto err_unlock; } diff --git a/crypto/rand/rand_deprecated.c b/crypto/rand/rand_deprecated.c index 07b6ff04e8..d838f3cd70 100644 --- a/crypto/rand/rand_deprecated.c +++ b/crypto/rand/rand_deprecated.c @@ -12,6 +12,7 @@ #include #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +#include #ifndef OPENSSL_NO_DEPRECATED_1_1_0 #define DEPRECATED_RAND_FUNCTIONS_DEFINED diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 63a3d1bca8..c8d77c68e9 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -25,6 +25,12 @@ #include "internal/provider.h" #include "internal/common.h" +/* clang-format off */ +#ifndef OPENSSL_DEFAULT_SEED_SRC +#define OPENSSL_DEFAULT_SEED_SRC SEED-SRC +#endif +/* clang-format on */ + typedef struct rand_global_st { /* * The three shared DRBG instances @@ -539,10 +545,10 @@ static EVP_RAND_CTX *rand_new_seed(OSSL_LIB_CTX *libctx) name = dgbl->seed_name; } else { fallback = 1; - name = OPENSSL_SEED_SRC_NAME; + name = OPENSSL_MSTR(OPENSSL_DEFAULT_SEED_SRC); } #else /* !OPENSSL_NO_FIPS_JITTER */ - name = OPENSSL_SEED_SRC_NAME; + name = "JITTER"; propq = ""; #endif /* OPENSSL_NO_FIPS_JITTER */ diff --git a/crypto/rand/rand_uniform.c b/crypto/rand/rand_uniform.c index 0b7f7a3c0a..877150af4e 100644 --- a/crypto/rand/rand_uniform.c +++ b/crypto/rand/rand_uniform.c @@ -47,7 +47,7 @@ uint32_t ossl_rand_uniform_uint32(OSSL_LIB_CTX *ctx, uint32_t upper, int *err) * We are generating a fixed point number on the interval [0, 1). * Multiplying this by the range gives us a number on [0, upper). * The high word of the multiplication result represents the integral - * part we want. The lower word is the fractional part. We can early exit + * part we want. The lower word is the fractional part. We can early exit if * if the fractional part is small enough that no carry from the next lower * word can cause an overflow and carry into the integer part. This * happens when the fractional part is bounded by 2^32 - upper which @@ -69,7 +69,7 @@ uint32_t ossl_rand_uniform_uint32(OSSL_LIB_CTX *ctx, uint32_t upper, int *err) * repeat the process with the next lower word. * * Each *bit* of randomness has a probability of one half of terminating - * this process, so each word beyond the first has a probability + * this process, so each each word beyond the first has a probability * of 2^-32 of not terminating the process. That is, we're extremely * likely to stop very rapidly. */ diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index c2be28a122..ab059bb5e8 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -35,7 +35,8 @@ #ifndef OPENSSL_NO_POSIX_IO #include #include -#if defined(_WIN32) +#if defined(_WIN32) && !defined(_WIN32_WCE) +#include #include #define stat _stat #define chmod _chmod @@ -69,8 +70,7 @@ * This declaration is a nasty hack to get around vms' extension to fopen for * passing in sharing options being disabled by /STANDARD=ANSI89 */ -static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) - = (__FILE_ptr32 (*)(const char *, const char *, ...))fopen; +static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) = (__FILE_ptr32 (*)(const char *, const char *, ...))fopen; #define VMS_OPEN_ATTRS \ "shr=get,put,upd,del", "ctx=bin,stm", "rfm=stm", "rat=none", "mrs=0" #define openssl_fopen(fname, mode) vms_fopen((fname), (mode), VMS_OPEN_ATTRS) @@ -272,7 +272,7 @@ const char *RAND_file_name(char *buf, size_t size) size_t len; int use_randfile = 1; -#if defined(_WIN32) && defined(CP_UTF8) +#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE) DWORD envlen; WCHAR *var; diff --git a/crypto/rc4/asm/rc4-md5-x86_64.pl b/crypto/rc4/asm/rc4-md5-x86_64.pl index c4440ab32c..f814d6f86f 100644 --- a/crypto/rc4/asm/rc4-md5-x86_64.pl +++ b/crypto/rc4/asm/rc4-md5-x86_64.pl @@ -26,7 +26,7 @@ # and Jim Guilford of Intel. MD5 is fresh implementation aiming to # minimize register usage, which was used as "main thread" with RC4 # weaved into it, one RC4 round per one MD5 round. In addition to the -# stitched subroutine the script can generate standalone replacement +# stiched subroutine the script can generate standalone replacement # ossl_md5_block_asm_data_order and RC4. Below are performance numbers in # cycles per processed byte, less is better, for these the standalone # subroutines, sum of them, and stitched one: diff --git a/crypto/rc5/rc5_local.h b/crypto/rc5/rc5_local.h index 7b5f8c847b..a1fbe61fec 100644 --- a/crypto/rc5/rc5_local.h +++ b/crypto/rc5/rc5_local.h @@ -19,7 +19,7 @@ #elif defined(__ICC) #define ROTATE_l32(a, n) _rotl(a, n) #define ROTATE_r32(a, n) _rotr(a, n) -#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) +#elif defined(__GNUC__) && __GNUC__ >= 2 && !defined(__STRICT_ANSI__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) #if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) #define ROTATE_l32(a, n) ({ \ register unsigned int ret; \ diff --git a/crypto/riscvcap.c b/crypto/riscvcap.c index 760fc5b0dd..cdec9a0216 100644 --- a/crypto/riscvcap.c +++ b/crypto/riscvcap.c @@ -129,7 +129,7 @@ size_t riscv_vlen(void) return vlen; } -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 __attribute__((constructor)) #endif void OPENSSL_cpuid_setup(void) diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index 161d9a9c56..00b4880c80 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -227,7 +227,7 @@ int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private) if (!ossl_rsa_check_factors(rsa)) { ERR_raise_data(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR, - "RSA factors/exponents are too big for n-modulus\n"); + "RSA factors/exponents are too big for for n-modulus\n"); goto err; } @@ -532,8 +532,7 @@ RSA *ossl_rsa_dup(const RSA *rsa, int selection) } if (rsa->pss != NULL) { - if ((dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss)) == NULL) - goto err; + dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss); if (rsa->pss->maskGenAlgorithm != NULL && dupkey->pss->maskGenAlgorithm == NULL) { dupkey->pss->maskHash = ossl_x509_algor_mgf1_decode(rsa->pss->maskGenAlgorithm); diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 88a7a2b93f..a7d5798c88 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -163,7 +163,7 @@ int RSA_up_ref(RSA *r) { int i; - if (!CRYPTO_UP_REF(&r->references, &i)) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; REF_PRINT_COUNT("RSA", i, r); diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index 674ee4b10d..b883baa58f 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -1184,12 +1184,9 @@ static int rsa_ossl_finish(RSA *rsa) static int rsa_ossl_s390x_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx) { - int rc; - if (rsa->version != RSA_ASN1_VERSION_MULTI) { - rc = s390x_crt(r0, i, rsa->p, rsa->q, rsa->dmp1, rsa->dmq1, rsa->iqmp); - if (rc >= 0) - return rc; + if (s390x_crt(r0, i, rsa->p, rsa->q, rsa->dmp1, rsa->dmq1, rsa->iqmp) == 1) + return 1; } return rsa_ossl_mod_exp(r0, i, rsa, ctx); } diff --git a/crypto/sha/asm/keccak1600-avx512.pl b/crypto/sha/asm/keccak1600-avx512.pl index 1b40130a6e..2a295d1c85 100755 --- a/crypto/sha/asm/keccak1600-avx512.pl +++ b/crypto/sha/asm/keccak1600-avx512.pl @@ -22,7 +22,7 @@ # It's impossible to have one that is optimal for every step, hence # it's changing as algorithm progresses. Data is saved in linear order, # but in-register order morphs between rounds. Even rounds take in -# linear layout, and odd rounds - transposed, or "vertically-shaped"... +# linear layout, and odd rounds - transposed, or "verticaly-shaped"... # ######################################################################## # Numbers are cycles per processed byte out of large message. diff --git a/crypto/sha/asm/keccak1600x4-avx512vl.pl b/crypto/sha/asm/keccak1600x4-avx512vl.pl deleted file mode 100755 index a7fc1814f5..0000000000 --- a/crypto/sha/asm/keccak1600x4-avx512vl.pl +++ /dev/null @@ -1,2349 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# Copyright (c) 2026 Intel Corporation. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -############################################################################### -# Keccak x4 AVX512VL SHA3/SHAKE Assembly Routines -# -# Description: -# This file emits x86_64 assembly for AVX512VL accelerated Keccak-f[1600] -# processing of 4 independent states in parallel ("x4"). -# -# It provides the core 24-round Keccak permutation and x4 helper routines -# used by SHA3 and SHAKE absorb/finalize/squeeze paths. Data from four -# input/output lanes is packed across YMM registers so lane-local operations -# execute in SIMD. -# -############################################################################### - -# $output is the last argument if it looks like a file (it has an extension) -# $flavour is the first argument if it doesn't look like a file -$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; -$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; - -$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); - -$avx512vl = 0; - -$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; -( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or -( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or -die "can't locate x86_64-xlate.pl"; - -# Check for AVX512VL support in assembler -if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` =~ /GNU assembler version (\d+)\.(\d+)/) { - my ($gas_major, $gas_minor) = ($1, $2); - $avx512vl = ($gas_major > 2 || ($gas_major == 2 && $gas_minor >= 26)); -} - -if (!$avx512vl - && $win64 - && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) - && `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) -{ - $avx512vl = ($1 >= 2.12); -} - -if (!$avx512vl && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0-9]+\.[0-9]+)/) { - $avx512vl = ($2>=3.9); -} - -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" - or die "can't call $xlate: $!"; -*STDOUT=*OUT; - -$arg1="%rdi"; -$arg2="%rsi"; -$arg3="%rdx"; -$arg4="%rcx"; -$arg5="%r8"; -$arg6="%r9"; -$roundn="%r13d"; -$tblptr="%r14"; - -# Define SHAKE rates -$SHAKE128_RATE="\$168"; -$SHAKE256_RATE="\$136"; - -# Stack frame offsets for SHAKE x4 wrapper functions -$STATE_SIZE="808"; # (25 * 8 * 4) + 8 = 808 bytes -$sf_arg1="0"; -$sf_arg2="8"; -$sf_arg3="16"; -$sf_arg4="24"; -$sf_arg5="32"; -$sf_state_ptr="40"; -$sf_state_x4="48"; -$sf_size="856"; # 48 + 808 = 856 bytes - -# Emit an internal helper call used by one-shot wrappers. -# - Win64: call the provided *_internal shim and bracket it with 32-byte -# shadow space so shim entry can use xlate-compatible [rsp+8]/[rsp+16]. -# - non-Win64: call the local function entry label (.L_), which -# sits at the same address as the public symbol. Calling the public -# global symbol by name here would break Mach-O builds: the call textually -# precedes the symbol's .globl declaration, so x86_64-xlate.pl never gets -# a chance to prepend the platform's leading-underscore, leaving an -# undefined reference to the un-decorated name. -# The argument must be the shim/internal symbol name, e.g. -# SHA3_shake128_x4_inc_squeeze_avx512vl_internal -sub call_internal { - my ($shim_name) = @_; - my $external_name = $shim_name; - - $external_name =~ s/_internal$//; - - return <<___ if ($win64); - sub \$32, %rsp - call $shim_name - add \$32, %rsp -___ - - return <<___; - call .L_$external_name -___ -} - -if ($avx512vl>0) {{{ - -my $avx512_mask = (1<<31)|(1<<30)|(1<<17)|(1<<16); # AVX512VL|BW|DQ|F - -$code .= <<___; -.text - -.extern OPENSSL_ia32cap_P - -.globl SHA3_avx512vl_capable -.type SHA3_avx512vl_capable,\@abi-omnipotent -.align 32 -SHA3_avx512vl_capable: - mov OPENSSL_ia32cap_P+8(%rip), %ecx - xor %eax, %eax - # 1<<31|1<<30|1<<17|1<<16: AVX512VL|AVX512BW|AVX512DQ|AVX512F - and \$$avx512_mask, %ecx - cmp \$$avx512_mask, %ecx - cmove %ecx, %eax - ret -.size SHA3_avx512vl_capable, .-SHA3_avx512vl_capable -___ - -$code.=<<___; -.text - -# Perform Keccak permutation -# -# YMM registers 0 to 24 are used as Keccak state registers. -# This function, as is, can work on 1 to 4 independent states at the same time. -# -# There is no clear boundary between Theta, Rho, Pi, Chi and Iota steps. -# Instructions corresponding to these steps overlap for better efficiency. -# -# Arguments: -# ymm0-ymm24 [in/out] Keccak state registers (one SIMD per one state register) -# ymm25-ymm31 [clobbered] temporary SIMD registers -# $roundn [clobbered] used for round tracking -# $tblptr [clobbered] used for access to SHA3 constant table -.type keccak_1600_permute,\@abi-omnipotent -.align 32 -keccak_1600_permute: -.cfi_startproc - mov \$24, $roundn # 24 rounds - lea iotas(%rip), $tblptr # Load the address of the SHA3 round constants - -.align 32 -.Lkeccak_rnd_loop: - # Theta step - - # Compute column parities - # C[5] = [0, 0, 0, 0, 0] - # for x in 0 to 4: - # C[x] = state[x][0] XOR state[x][1] XOR state[x][2] XOR state[x][3] XOR state[x][4] - - vmovdqa64 %ymm0, %ymm25 - vpternlogq \$0x96, %ymm5, %ymm10, %ymm25 - vmovdqa64 %ymm1, %ymm26 - vpternlogq \$0x96, %ymm11, %ymm6, %ymm26 - vmovdqa64 %ymm2, %ymm27 - vpternlogq \$0x96, %ymm12, %ymm7, %ymm27 - - vmovdqa64 %ymm3, %ymm28 - vpternlogq \$0x96, %ymm13, %ymm8, %ymm28 - vmovdqa64 %ymm4, %ymm29 - vpternlogq \$0x96, %ymm14, %ymm9, %ymm29 - vpternlogq \$0x96, %ymm20, %ymm15, %ymm25 - - vpternlogq \$0x96, %ymm21, %ymm16, %ymm26 - vpternlogq \$0x96, %ymm22, %ymm17, %ymm27 - vpternlogq \$0x96, %ymm23, %ymm18, %ymm28 - - # Start computing D values and keep computing column parity - # D[5] = [0, 0, 0, 0, 0] - # for x in 0 to 4: - # D[x] = C[(x+4) mod 5] XOR ROTATE_LEFT(C[(x+1) mod 5], 1) - - vprolq \$1, %ymm26, %ymm30 - vprolq \$1, %ymm27, %ymm31 - vpternlogq \$0x96, %ymm24, %ymm19, %ymm29 - - # Continue computing D values and apply Theta - # for x in 0 to 4: - # for y in 0 to 4: - # state[x][y] = state[x][y] XOR D[x] - - vpternlogq \$0x96, %ymm30, %ymm29, %ymm0 - vpternlogq \$0x96, %ymm30, %ymm29, %ymm10 - vpternlogq \$0x96, %ymm30, %ymm29, %ymm20 - - vpternlogq \$0x96, %ymm30, %ymm29, %ymm5 - vpternlogq \$0x96, %ymm30, %ymm29, %ymm15 - vprolq \$1, %ymm28, %ymm30 - - vpternlogq \$0x96, %ymm31, %ymm25, %ymm6 - vpternlogq \$0x96, %ymm31, %ymm25, %ymm16 - vpternlogq \$0x96, %ymm31, %ymm25, %ymm1 - - vpternlogq \$0x96, %ymm31, %ymm25, %ymm11 - vpternlogq \$0x96, %ymm31, %ymm25, %ymm21 - vprolq \$1, %ymm29, %ymm31 - - vpbroadcastq ($tblptr), %ymm29 # Load the round constant into ymm29 (Iota) - add \$8, $tblptr # Increment the pointer to the next round constant - - vpternlogq \$0x96, %ymm30, %ymm26, %ymm12 - vpternlogq \$0x96, %ymm30, %ymm26, %ymm7 - vpternlogq \$0x96, %ymm30, %ymm26, %ymm22 - - vpternlogq \$0x96, %ymm30, %ymm26, %ymm17 - vpternlogq \$0x96, %ymm30, %ymm26, %ymm2 - vprolq \$1, %ymm25, %ymm30 - - # Rho step - # Keep applying Theta and start Rho step - # - # ROTATION_OFFSETS[5][5] = [ - # [0, 1, 62, 28, 27], - # [36, 44, 6, 55, 20], - # [3, 10, 43, 25, 39], - # [41, 45, 15, 21, 8], - # [18, 2, 61, 56, 14] ] - # - # for x in 0 to 4: - # for y in 0 to 4: - # state[x][y] = ROTATE_LEFT(state[x][y], ROTATION_OFFSETS[x][y]) - - vpternlogq \$0x96, %ymm31, %ymm27, %ymm3 - vpternlogq \$0x96, %ymm31, %ymm27, %ymm13 - vpternlogq \$0x96, %ymm31, %ymm27, %ymm23 - - vprolq \$44, %ymm6, %ymm6 - vpternlogq \$0x96, %ymm31, %ymm27, %ymm18 - vpternlogq \$0x96, %ymm31, %ymm27, %ymm8 - - vprolq \$43, %ymm12, %ymm12 - vprolq \$21, %ymm18, %ymm18 - vpternlogq \$0x96, %ymm30, %ymm28, %ymm24 - - vprolq \$14, %ymm24, %ymm24 - vprolq \$28, %ymm3, %ymm3 - vpternlogq \$0x96, %ymm30, %ymm28, %ymm9 - - vprolq \$20, %ymm9, %ymm9 - vprolq \$3, %ymm10, %ymm10 - vpternlogq \$0x96, %ymm30, %ymm28, %ymm19 - - vprolq \$45, %ymm16, %ymm16 - vprolq \$61, %ymm22, %ymm22 - vpternlogq \$0x96, %ymm30, %ymm28, %ymm4 - - vprolq \$1, %ymm1, %ymm1 - vprolq \$6, %ymm7, %ymm7 - vpternlogq \$0x96, %ymm30, %ymm28, %ymm14 - - # Continue with Rho and start Pi and Chi steps at the same time - # Ternary logic 0xD2 is used for Chi step - # - # for x in 0 to 4: - # for y in 0 to 4: - # state[x][y] = state[x][y] XOR ((NOT state[(x+1) mod 5][y]) AND state[(x+2) mod 5][y]) - - vprolq \$25, %ymm13, %ymm13 - vprolq \$8, %ymm19, %ymm19 - vmovdqa64 %ymm0, %ymm30 - vpternlogq \$0xD2, %ymm12, %ymm6, %ymm30 - - vprolq \$18, %ymm20, %ymm20 - vprolq \$27, %ymm4, %ymm4 - vpxorq %ymm29, %ymm30, %ymm30 # Iota step - - vprolq \$36, %ymm5, %ymm5 - vprolq \$10, %ymm11, %ymm11 - vmovdqa64 %ymm6, %ymm31 - vpternlogq \$0xD2, %ymm18, %ymm12, %ymm31 - - vprolq \$15, %ymm17, %ymm17 - vprolq \$56, %ymm23, %ymm23 - vpternlogq \$0xD2, %ymm24, %ymm18, %ymm12 - - vprolq \$62, %ymm2, %ymm2 - vprolq \$55, %ymm8, %ymm8 - vpternlogq \$0xD2, %ymm0, %ymm24, %ymm18 - - vprolq \$39, %ymm14, %ymm14 - vprolq \$41, %ymm15, %ymm15 - vpternlogq \$0xD2, %ymm6, %ymm0, %ymm24 - vmovdqa64 %ymm30, %ymm0 - vmovdqa64 %ymm31, %ymm6 - - vprolq \$2, %ymm21, %ymm21 - vmovdqa64 %ymm3, %ymm30 - vpternlogq \$0xD2, %ymm10, %ymm9, %ymm30 - vmovdqa64 %ymm9, %ymm31 - vpternlogq \$0xD2, %ymm16, %ymm10, %ymm31 - - vpternlogq \$0xD2, %ymm22, %ymm16, %ymm10 - vpternlogq \$0xD2, %ymm3, %ymm22, %ymm16 - vpternlogq \$0xD2, %ymm9, %ymm3, %ymm22 - vmovdqa64 %ymm30, %ymm3 - vmovdqa64 %ymm31, %ymm9 - - vmovdqa64 %ymm1, %ymm30 - vpternlogq \$0xD2, %ymm13, %ymm7, %ymm30 - vmovdqa64 %ymm7, %ymm31 - vpternlogq \$0xD2, %ymm19, %ymm13, %ymm31 - vpternlogq \$0xD2, %ymm20, %ymm19, %ymm13 - - vpternlogq \$0xD2, %ymm1, %ymm20, %ymm19 - vpternlogq \$0xD2, %ymm7, %ymm1, %ymm20 - vmovdqa64 %ymm30, %ymm1 - vmovdqa64 %ymm31, %ymm7 - vmovdqa64 %ymm4, %ymm30 - vpternlogq \$0xD2, %ymm11, %ymm5, %ymm30 - - vmovdqa64 %ymm5, %ymm31 - vpternlogq \$0xD2, %ymm17, %ymm11, %ymm31 - vpternlogq \$0xD2, %ymm23, %ymm17, %ymm11 - vpternlogq \$0xD2, %ymm4, %ymm23, %ymm17 - - vpternlogq \$0xD2, %ymm5, %ymm4, %ymm23 - vmovdqa64 %ymm30, %ymm4 - vmovdqa64 %ymm31, %ymm5 - vmovdqa64 %ymm2, %ymm30 - vpternlogq \$0xD2, %ymm14, %ymm8, %ymm30 - vmovdqa64 %ymm8, %ymm31 - vpternlogq \$0xD2, %ymm15, %ymm14, %ymm31 - - vpternlogq \$0xD2, %ymm21, %ymm15, %ymm14 - vpternlogq \$0xD2, %ymm2, %ymm21, %ymm15 - vpternlogq \$0xD2, %ymm8, %ymm2, %ymm21 - vmovdqa64 %ymm30, %ymm2 - vmovdqa64 %ymm31, %ymm8 - - # Complete the steps and get updated state registers in ymm0 to ymm24 - vmovdqa64 %ymm3, %ymm30 - vmovdqa64 %ymm18, %ymm3 - vmovdqa64 %ymm17, %ymm18 - vmovdqa64 %ymm11, %ymm17 - vmovdqa64 %ymm7, %ymm11 - vmovdqa64 %ymm10, %ymm7 - vmovdqa64 %ymm1, %ymm10 - vmovdqa64 %ymm6, %ymm1 - vmovdqa64 %ymm9, %ymm6 - vmovdqa64 %ymm22, %ymm9 - vmovdqa64 %ymm14, %ymm22 - vmovdqa64 %ymm20, %ymm14 - vmovdqa64 %ymm2, %ymm20 - vmovdqa64 %ymm12, %ymm2 - vmovdqa64 %ymm13, %ymm12 - vmovdqa64 %ymm19, %ymm13 - vmovdqa64 %ymm23, %ymm19 - vmovdqa64 %ymm15, %ymm23 - vmovdqa64 %ymm4, %ymm15 - vmovdqa64 %ymm24, %ymm4 - vmovdqa64 %ymm21, %ymm24 - vmovdqa64 %ymm8, %ymm21 - vmovdqa64 %ymm16, %ymm8 - vmovdqa64 %ymm5, %ymm16 - vmovdqa64 %ymm30, %ymm5 - - dec $roundn # Decrement the round counter - jnz .Lkeccak_rnd_loop # Jump to the start of the loop if r13d is not zero - ret -.cfi_endproc -.size keccak_1600_permute,.-keccak_1600_permute - -# Initialize YMM registers 0-24 to zero -.globl keccak_1600_init_state -.type keccak_1600_init_state,\@abi-omnipotent -.align 32 -keccak_1600_init_state: -.cfi_startproc - vpxorq %ymm0, %ymm0, %ymm0 - vmovdqa64 %ymm0, %ymm1 - vmovdqa64 %ymm0, %ymm2 - vmovdqa64 %ymm0, %ymm3 - vmovdqa64 %ymm0, %ymm4 - vmovdqa64 %ymm0, %ymm5 - vmovdqa64 %ymm0, %ymm6 - vmovdqa64 %ymm0, %ymm7 - vmovdqa64 %ymm0, %ymm8 - vmovdqa64 %ymm0, %ymm9 - vmovdqa64 %ymm0, %ymm10 - vmovdqa64 %ymm0, %ymm11 - vmovdqa64 %ymm0, %ymm12 - vmovdqa64 %ymm0, %ymm13 - vmovdqa64 %ymm0, %ymm14 - vmovdqa64 %ymm0, %ymm15 - vmovdqa64 %ymm0, %ymm16 - vmovdqa64 %ymm0, %ymm17 - vmovdqa64 %ymm0, %ymm18 - vmovdqa64 %ymm0, %ymm19 - vmovdqa64 %ymm0, %ymm20 - vmovdqa64 %ymm0, %ymm21 - vmovdqa64 %ymm0, %ymm22 - vmovdqa64 %ymm0, %ymm23 - vmovdqa64 %ymm0, %ymm24 - ret -.cfi_endproc -.size keccak_1600_init_state,.-keccak_1600_init_state - -.globl keccak_1600_load_state_x4 -.type keccak_1600_load_state_x4,\@abi-omnipotent -.align 32 -keccak_1600_load_state_x4: -.cfi_startproc - vmovdqu64 32*0($arg1), %ymm0 - vmovdqu64 32*1($arg1), %ymm1 - vmovdqu64 32*2($arg1), %ymm2 - vmovdqu64 32*3($arg1), %ymm3 - vmovdqu64 32*4($arg1), %ymm4 - vmovdqu64 32*5($arg1), %ymm5 - vmovdqu64 32*6($arg1), %ymm6 - vmovdqu64 32*7($arg1), %ymm7 - vmovdqu64 32*8($arg1), %ymm8 - vmovdqu64 32*9($arg1), %ymm9 - vmovdqu64 32*10($arg1), %ymm10 - vmovdqu64 32*11($arg1), %ymm11 - vmovdqu64 32*12($arg1), %ymm12 - vmovdqu64 32*13($arg1), %ymm13 - vmovdqu64 32*14($arg1), %ymm14 - vmovdqu64 32*15($arg1), %ymm15 - vmovdqu64 32*16($arg1), %ymm16 - vmovdqu64 32*17($arg1), %ymm17 - vmovdqu64 32*18($arg1), %ymm18 - vmovdqu64 32*19($arg1), %ymm19 - vmovdqu64 32*20($arg1), %ymm20 - vmovdqu64 32*21($arg1), %ymm21 - vmovdqu64 32*22($arg1), %ymm22 - vmovdqu64 32*23($arg1), %ymm23 - vmovdqu64 32*24($arg1), %ymm24 - ret -.cfi_endproc -.size keccak_1600_load_state_x4,.-keccak_1600_load_state_x4 - - -.globl keccak_1600_save_state_x4 -.type keccak_1600_save_state_x4,\@abi-omnipotent -.align 32 -keccak_1600_save_state_x4: -.cfi_startproc - vmovdqu64 %ymm0, 32*0($arg1) - vmovdqu64 %ymm1, 32*1($arg1) - vmovdqu64 %ymm2, 32*2($arg1) - vmovdqu64 %ymm3, 32*3($arg1) - vmovdqu64 %ymm4, 32*4($arg1) - vmovdqu64 %ymm5, 32*5($arg1) - vmovdqu64 %ymm6, 32*6($arg1) - vmovdqu64 %ymm7, 32*7($arg1) - vmovdqu64 %ymm8, 32*8($arg1) - vmovdqu64 %ymm9, 32*9($arg1) - vmovdqu64 %ymm10, 32*10($arg1) - vmovdqu64 %ymm11, 32*11($arg1) - vmovdqu64 %ymm12, 32*12($arg1) - vmovdqu64 %ymm13, 32*13($arg1) - vmovdqu64 %ymm14, 32*14($arg1) - vmovdqu64 %ymm15, 32*15($arg1) - vmovdqu64 %ymm16, 32*16($arg1) - vmovdqu64 %ymm17, 32*17($arg1) - vmovdqu64 %ymm18, 32*18($arg1) - vmovdqu64 %ymm19, 32*19($arg1) - vmovdqu64 %ymm20, 32*20($arg1) - vmovdqu64 %ymm21, 32*21($arg1) - vmovdqu64 %ymm22, 32*22($arg1) - vmovdqu64 %ymm23, 32*23($arg1) - vmovdqu64 %ymm24, 32*24($arg1) - ret -.cfi_endproc -.size keccak_1600_save_state_x4,.-keccak_1600_save_state_x4 - - -# Add input data to state when message length is less than rate -# Arguments: -# r10: state pointer to absorb into (clobbered) -# arg2 (rsi): message pointer lane 0 (updated on output) -# arg3 (rdx): message pointer lane 1 (updated on output) -# arg4 (rcx): message pointer lane 2 (updated on output) -# arg5 (r8): message pointer lane 3 (updated on output) -# r12: length in bytes (clobbered on output) -# Clobbers: r9, rbx, r15, k1, ymm31-ymm29 -.globl keccak_1600_partial_add_x4 -.type keccak_1600_partial_add_x4,\@abi-omnipotent -.align 32 -keccak_1600_partial_add_x4: -.cfi_startproc - mov 8*100(%r10), %r9 - test \$7, %r9d - jz .Lstart_aligned_to_4x8 - - # Start offset is not aligned to register size - mov %r9, %r15 # %r15 = s[100] - - and \$7, %r9d - neg %r9d - add \$8, %r9d # register capacity = 8 - (offset % 8) - cmp %r9d, %r12d - cmovnae %r12d, %r9d # %r9d = min(register capacity, length) - - lea byte_kmask_0_to_7(%rip), %rbx - kmovb (%rbx,%r9), %k1 # message load mask - - mov %r15, %rbx - and \$~7, %ebx - lea (%r10,%rbx,4), %r10 # get to state starting register - - mov %r15, %rbx - and \$7, %ebx - - vmovdqu8 (%r10), %ymm31 # load & store / allocate SB for the register - vmovdqu8 %ymm31, (%r10) - - vmovdqu8 ($arg2), %xmm31{%k1}{z} # Read 1 to 7 bytes from lane 0 - vmovdqu8 8*0(%r10,%rbx), %xmm30{%k1}{z} # Read 1 to 7 bytes from state reg lane 0 - vpxorq %xmm30, %xmm31, %xmm31 - vmovdqu8 %xmm31, 8*0(%r10,%rbx){%k1} # Write 1 to 7 bytes to state reg lane 0 - - vmovdqu8 ($arg3), %xmm31{%k1}{z} # Read 1 to 7 bytes from lane 1 - vmovdqu8 8*1(%r10,%rbx), %xmm30{%k1}{z} # Read 1 to 7 bytes from state reg lane 1 - vpxorq %xmm30, %xmm31, %xmm31 - vmovdqu8 %xmm31, 8*1(%r10,%rbx){%k1} # Write 1 to 7 bytes to state reg lane 1 - - vmovdqu8 ($arg4), %xmm31{%k1}{z} # Read 1 to 7 bytes from lane 2 - vmovdqu8 8*2(%r10,%rbx), %xmm30{%k1}{z} # Read 1 to 7 bytes from state reg lane 2 - vpxorq %xmm30, %xmm31, %xmm31 - vmovdqu8 %xmm31, 8*2(%r10,%rbx){%k1} # Write 1 to 7 bytes to state reg lane 2 - - vmovdqu8 ($arg5), %xmm31{%k1}{z} # Read 1 to 7 bytes from lane 3 - vmovdqu8 8*3(%r10,%rbx), %xmm30{%k1}{z} # Read 1 to 7 bytes from state reg lane 3 - vpxorq %xmm30, %xmm31, %xmm31 - vmovdqu8 %xmm31, 8*3(%r10,%rbx){%k1} # Write 1 to 7 bytes to state reg lane 3 - - sub %r9, %r12 - jz .Lzero_bytes - - add %r9, $arg2 - add %r9, $arg3 - add %r9, $arg4 - add %r9, $arg5 - add \$32, %r10 - xor %r9, %r9 - jmp .Lymm_loop - -.Lstart_aligned_to_4x8: - lea (%r10,%r9,4), %r10 - xor %r9, %r9 - -.align 32 -.Lymm_loop: - cmp \$8, %r12d - jb .Llt_8_bytes - - vmovq ($arg2,%r9), %xmm31 # Read 8 bytes from lane 0 - vpinsrq \$1, ($arg3,%r9), %xmm31, %xmm31 # Read 8 bytes from lane 1 - vmovq ($arg4,%r9), %xmm30 # Read 8 bytes from lane 2 - vpinsrq \$1, ($arg5,%r9),%xmm30, %xmm30 # Read 8 bytes from lane 3 - vinserti32x4 \$1, %xmm30, %ymm31, %ymm31 - vpxorq (%r10,%r9,4), %ymm31, %ymm31 # Add data with the state - vmovdqu64 %ymm31, (%r10,%r9,4) - add \$8, %r9 - sub \$8, %r12 - jz .Lzero_bytes - - jmp .Lymm_loop - -.align 32 -.Lzero_bytes: - add %r9, $arg2 - add %r9, $arg3 - add %r9, $arg4 - add %r9, $arg5 - ret - -.align 32 -.Llt_8_bytes: - add %r9, $arg2 - add %r9, $arg3 - add %r9, $arg4 - add %r9, $arg5 - lea (%r10,%r9,4), %r10 - - lea byte_kmask_0_to_7(%rip), %rbx - kmovb (%rbx,%r12), %k1 # message load mask - - vmovdqu8 ($arg2), %xmm31{%k1}{z} # Read 1 to 7 bytes from lane 0 - vmovdqu8 ($arg3), %xmm30{%k1}{z} # Read 1 to 7 bytes from lane 1 - vpunpcklqdq %xmm30, %xmm31, %xmm31 # Interleave data from lane 0 and lane 1 - vmovdqu8 ($arg4), %xmm30{%k1}{z} # Read 1 to 7 bytes from lane 2 - vmovdqu8 ($arg5), %xmm29{%k1}{z} # Read 1 to 7 bytes from lane 3 - vpunpcklqdq %xmm29, %xmm30, %xmm30 # Interleave data from lane 2 and lane 3 - vinserti32x4 \$1, %xmm30, %ymm31, %ymm31 - - vpxorq (%r10), %ymm31, %ymm31 # Add data to the state - vmovdqu64 %ymm31, (%r10) # Update state in memory - - add %r12, $arg2 # increment message pointer lane 0 - add %r12, $arg3 # increment message pointer lane 1 - add %r12, $arg4 # increment message pointer lane 2 - add %r12, $arg5 # increment message pointer lane 3 - ret -.cfi_endproc -.size keccak_1600_partial_add_x4,.-keccak_1600_partial_add_x4 - - -# Extract bytes from state and write to outputs -# Arguments: -# r10: state pointer to start extracting from (clobbered) -# arg1 (rdi): output pointer lane 0 (updated on output) -# arg2 (rsi): output pointer lane 1 (updated on output) -# arg3 (rdx): output pointer lane 2 (updated on output) -# arg4 (rcx): output pointer lane 3 (updated on output) -# r12: length in bytes (clobbered on output) -# r11: state offset to start extract from -.globl keccak_1600_extract_bytes_x4 -.type keccak_1600_extract_bytes_x4,\@abi-omnipotent -.align 32 -keccak_1600_extract_bytes_x4: -.cfi_startproc - or %r12, %r12 - jz .Lextract_zero_bytes - - test \$7, %r11d - jz .Lextract_start_aligned_to_4x8 - - # Extract offset is not aligned to the register size (8 bytes) - mov %r11, %r9 - - and \$7, %r9d - neg %r9d - add \$8, %r9d # register capacity = 8 - (offset % 8) - cmp %r9d, %r12d - cmovnae %r12d, %r9d # %r9d = min(register capacity, length) - - lea byte_kmask_0_to_7(%rip), %rbx - kmovb (%rbx,%r9), %k1 # message store mask - - mov %r11, %rbx - and \$~7, %ebx - lea (%r10,%rbx,4), %r10 # get to state starting register - - mov %r11, %rbx - and \$7, %ebx - - vmovdqu8 8*0(%r10,%rbx), %xmm31{%k1}{z} # Read 1-7 bytes from state reg lane 0 - vmovdqu8 %xmm31, ($arg1){%k1} # Write 1-7 bytes to lane 0 output - - vmovdqu8 8*1(%r10,%rbx), %xmm31{%k1}{z} # Read 1-7 bytes from state reg lane 1 - vmovdqu8 %xmm31, ($arg2){%k1} # Write 1-7 bytes to lane 1 output - - vmovdqu8 8*2(%r10,%rbx), %xmm31{%k1}{z} # Read 1-7 bytes from state reg lane 2 - vmovdqu8 %xmm31, ($arg3){%k1} # Write 1-7 bytes to lane 2 output - - vmovdqu8 8*3(%r10,%rbx), %xmm31{%k1}{z} # Read 1-7 bytes from state reg lane 3 - vmovdqu8 %xmm31, ($arg4){%k1} # Write 1-7 bytes to lane 3 output - - # Increment output registers - add %r9, $arg1 - add %r9, $arg2 - add %r9, $arg3 - add %r9, $arg4 - - # Decrement length to extract - sub %r9, %r12 - jz .Lextract_zero_bytes - - # More data to extract, update state register pointer - add \$32, %r10 - xor %r9, %r9 - jmp .Lextract_ymm_loop - -.Lextract_start_aligned_to_4x8: - lea (%r10,%r11,4), %r10 - xor %r9, %r9 - -.align 32 -.Lextract_ymm_loop: - cmp \$8, %r12 - jb .Lextract_lt_8_bytes - - vmovdqu64 (%r10), %xmm31 - vmovdqu64 16(%r10), %xmm30 - vmovq %xmm31, ($arg1,%r9) - vpextrq \$1, %xmm31, ($arg2,%r9) - vmovq %xmm30, ($arg3,%r9) - vpextrq \$1, %xmm30, ($arg4,%r9) - add \$8, %r9 - sub \$8, %r12 - jz .Lzero_bytes_left - - add \$32, %r10 - jmp .Lextract_ymm_loop - -.align 32 -.Lzero_bytes_left: - # Increment output pointers - add %r9, $arg1 - add %r9, $arg2 - add %r9, $arg3 - add %r9, $arg4 -.Lextract_zero_bytes: - ret - -.align 32 -.Lextract_lt_8_bytes: - add %r9, $arg1 - add %r9, $arg2 - add %r9, $arg3 - add %r9, $arg4 - - lea byte_kmask_0_to_7(%rip), %r9 - kmovb (%r9,%r12), %k1 # k1 is the mask of message bytes to read - - vmovq 0*8(%r10), %xmm31 # Read 8 bytes from state lane 0 - vmovdqu8 %xmm31, ($arg1){%k1} # Extract 1-7 bytes into output 0 - vmovq 1*8(%r10), %xmm31 # Read 8 bytes from state lane 1 - vmovdqu8 %xmm31, ($arg2){%k1} # Extract 1-7 bytes into output 1 - vmovq 2*8(%r10), %xmm31 # Read 8 bytes from state lane 2 - vmovdqu8 %xmm31, ($arg3){%k1} # Extract 1-7 bytes into output 2 - vmovq 3*8(%r10), %xmm31 # Read 8 bytes from state lane 3 - vmovdqu8 %xmm31, ($arg4){%k1} # Extract 1-7 bytes into output 3 - - # Increment output pointers - add %r12, $arg1 - add %r12, $arg2 - add %r12, $arg3 - add %r12, $arg4 - ret -.cfi_endproc -.size keccak_1600_extract_bytes_x4,.-keccak_1600_extract_bytes_x4 - - -# SHAKE128 x4 multi-buffer functions -# These functions process 4 independent SHAKE128 streams in parallel using AVX-512VL -# State layout: 25 ymm registers (200 bytes each) + 1 qword = 808 bytes per context -# Rate: 168 bytes for SHAKE128 - -# SHA3_shake128_x4_avx512vl -# One-shot SHAKE-128 x4 function: init + absorb + finalize + squeeze -# Arguments: -# arg1 (rdi): pointer to output lane 0 -# arg2 (rsi): pointer to output lane 1 -# arg3 (rdx): pointer to output lane 2 -# arg4 (rcx): pointer to output lane 3 -# arg5 (r8): output length in bytes (must be same for all lanes) -# arg6 (r9): pointer to input lane 0 -# [stack+0]: pointer to input lane 1 -# [stack+8]: pointer to input lane 2 -# [stack+16]: pointer to input lane 3 -# [stack+24]: input length in bytes (must be same for all lanes) -# Returns: void -.globl SHA3_shake128_x4_avx512vl -.type SHA3_shake128_x4_avx512vl,\@function,10 -.align 32 -SHA3_shake128_x4_avx512vl: -.cfi_startproc - push %rbp -.cfi_push %rbp - mov %rsp, %rbp - push %rbx -.cfi_push %rbx -___ -$code .= <<___ if ($win64); - sub \$160, %rsp - vmovups %xmm6, 0(%rsp) - vmovups %xmm7, 16(%rsp) - vmovups %xmm8, 32(%rsp) - vmovups %xmm9, 48(%rsp) - vmovups %xmm10, 64(%rsp) - vmovups %xmm11, 80(%rsp) - vmovups %xmm12, 96(%rsp) - vmovups %xmm13, 112(%rsp) - vmovups %xmm14, 128(%rsp) - vmovups %xmm15, 144(%rsp) -___ -$code.=<<___; - - sub \$$sf_size, %rsp - mov %rsp, %rbx - -.Lshake128_x4_body: - mov $arg1, $sf_arg1(%rbx) - mov $arg2, $sf_arg2(%rbx) - mov $arg3, $sf_arg3(%rbx) - mov $arg4, $sf_arg4(%rbx) - mov $arg5, $sf_arg5(%rbx) - - lea $sf_state_x4(%rbx), $arg1 # start of x4 state on the stack frame - mov $arg1, $sf_state_ptr(%rbx) - - # Initialize the state array to zero - call keccak_1600_init_state - - call keccak_1600_save_state_x4 - - movq \$0, 8*100($arg1) # clear s[100] - - mov $sf_state_ptr(%rbx), $arg1 - mov $arg6, $arg2 -___ -$code .= <<___ if ($win64); - # xlate prologue handles up to six arguments. For one-shot x4 wrappers - # (10 args), the remaining four stay in Win64 stack slots. - mov 64(%rbp), $arg3 # arg7 from stack - mov 72(%rbp), $arg4 # arg8 from stack - mov 80(%rbp), $arg5 # arg9 from stack - mov 88(%rbp), $arg6 # arg10 from stack -___ -$code .= <<___ if (!$win64); - mov 16(%rbp), $arg3 # arg7 from stack - mov 24(%rbp), $arg4 # arg8 from stack - mov 32(%rbp), $arg5 # arg9 from stack - mov 40(%rbp), $arg6 # arg10 from stack -___ -$code.=<<___; - # Internal entry avoids Win64 xlate prologue argument remapping. -___ -$code .= call_internal("SHA3_shake128_x4_inc_absorb_avx512vl_internal"); -$code.=<<___; - - mov $sf_state_ptr(%rbx), $arg1 - call .L_SHA3_shake128_x4_inc_finalize_avx512vl - - # squeeze - mov $sf_arg1(%rbx), $arg1 - mov $sf_arg2(%rbx), $arg2 - mov $sf_arg3(%rbx), $arg3 - mov $sf_arg4(%rbx), $arg4 - mov $sf_arg5(%rbx), $arg5 - mov $sf_state_ptr(%rbx), $arg6 -___ -$code .= call_internal("SHA3_shake128_x4_inc_squeeze_avx512vl_internal"); -$code.=<<___; - - # Clear the temporary buffer - lea $sf_state_x4(%rbx), %r9 - vpxorq %ymm31, %ymm31, %ymm31 - vmovdqu64 %ymm31, 32*0(%r9) - vmovdqu64 %ymm31, 32*1(%r9) - vmovdqu64 %ymm31, 32*2(%r9) - vmovdqu64 %ymm31, 32*3(%r9) - vmovdqu64 %ymm31, 32*4(%r9) - vmovdqu64 %ymm31, 32*5(%r9) - vmovdqu64 %ymm31, 32*6(%r9) - vmovdqu64 %ymm31, 32*7(%r9) - vmovdqu64 %ymm31, 32*8(%r9) - vmovdqu64 %ymm31, 32*9(%r9) - vmovdqu64 %ymm31, 32*10(%r9) - vmovdqu64 %ymm31, 32*11(%r9) - vmovdqu64 %ymm31, 32*12(%r9) - vmovdqu64 %ymm31, 32*13(%r9) - vmovdqu64 %ymm31, 32*14(%r9) - vmovdqu64 %ymm31, 32*15(%r9) - vmovdqu64 %ymm31, 32*16(%r9) - vmovdqu64 %ymm31, 32*17(%r9) - vmovdqu64 %ymm31, 32*18(%r9) - vmovdqu64 %ymm31, 32*19(%r9) - vmovdqu64 %ymm31, 32*20(%r9) - vmovdqu64 %ymm31, 32*21(%r9) - vmovdqu64 %ymm31, 32*22(%r9) - vmovdqu64 %ymm31, 32*23(%r9) - vmovdqu64 %ymm31, 32*24(%r9) - vmovq %xmm31, 32*25(%r9) - -.Lshake128_x4_epilogue: -___ -$code .= <<___ if ($win64); - vmovups $sf_size+0(%rsp), %xmm6 - vmovups $sf_size+16(%rsp), %xmm7 - vmovups $sf_size+32(%rsp), %xmm8 - vmovups $sf_size+48(%rsp), %xmm9 - vmovups $sf_size+64(%rsp), %xmm10 - vmovups $sf_size+80(%rsp), %xmm11 - vmovups $sf_size+96(%rsp), %xmm12 - vmovups $sf_size+112(%rsp), %xmm13 - vmovups $sf_size+128(%rsp), %xmm14 - vmovups $sf_size+144(%rsp), %xmm15 - add \$160, %rsp -___ -$code.=<<___; - add \$$sf_size, %rsp - pop %rbx -.cfi_pop %rbx - pop %rbp -.cfi_pop %rbp - ret -.cfi_endproc -.size SHA3_shake128_x4_avx512vl,.-SHA3_shake128_x4_avx512vl - -___ - -$code .= <<___ if ($win64); -# Internal Win64 shim for absorb entry. It establishes xlate-compatible -# unwind state and then jumps to the function entry after the prologue. -# This is required for internal calls since the xlate ABI conversion -# is already done in the caller function. -.type SHA3_shake128_x4_inc_absorb_avx512vl_internal,\@abi-omnipotent -.align 32 -.LSEH_begin_SHA3_shake128_x4_inc_absorb_avx512vl_internal: -SHA3_shake128_x4_inc_absorb_avx512vl_internal: - mov %rsp, %rax - mov $arg1, 8(%rsp) - mov $arg2, 16(%rsp) - jmp .L_SHA3_shake128_x4_inc_absorb_avx512vl -.LSEH_end_SHA3_shake128_x4_inc_absorb_avx512vl_internal: -.size SHA3_shake128_x4_inc_absorb_avx512vl_internal,.-SHA3_shake128_x4_inc_absorb_avx512vl_internal -___ -$code.=<<___; - -# SHA3_shake128_x4_inc_absorb_avx512vl -# Absorb input data into 4 parallel SHAKE128 states -# Arguments: -# arg1 (rdi): pointer to state context (808 bytes) -# arg2 (rsi): pointer to lane 0 input data -# arg3 (rdx): pointer to lane 1 input data -# arg4 (rcx): pointer to lane 2 input data -# arg5 (r8): pointer to lane 3 input data -# arg6 (r9): input length in bytes (must be same for all lanes) -# Returns: void -# Note: Input is XORed into state and Keccak permutation is applied for each rate-sized block -.globl SHA3_shake128_x4_inc_absorb_avx512vl -.type SHA3_shake128_x4_inc_absorb_avx512vl,\@function,6 -.align 32 -SHA3_shake128_x4_inc_absorb_avx512vl: -.L_SHA3_shake128_x4_inc_absorb_avx512vl: -.cfi_startproc - push %rbp -.cfi_push %rbp - push %rbx -.cfi_push %rbx - push %r12 -.cfi_push %r12 - push %r13 -.cfi_push %r13 - push %r14 -.cfi_push %r14 - push %r15 -.cfi_push %r15 -___ -$code .= <<___ if ($win64); - sub \$160, %rsp - vmovups %xmm6, 0(%rsp) - vmovups %xmm7, 16(%rsp) - vmovups %xmm8, 32(%rsp) - vmovups %xmm9, 48(%rsp) - vmovups %xmm10, 64(%rsp) - vmovups %xmm11, 80(%rsp) - vmovups %xmm12, 96(%rsp) - vmovups %xmm13, 112(%rsp) - vmovups %xmm14, 128(%rsp) - vmovups %xmm15, 144(%rsp) -___ -$code.=<<___; - -.Lshake128_absorb_body: - # check for partially processed block - mov 8*100($arg1), %r14 - or %r14, %r14 # s[100] == 0? - je .Lshake128_absorb_main_loop_start - - # process remaining bytes if message long enough - mov \$168, %r12 # SHAKE128_RATE = 168 - sub %r14, %r12 # %r12 = capacity - - cmp %r12, $arg6 # if mlen <= capacity then no permute - jbe .Lshake128_absorb_skip_permute - - sub %r12, $arg6 - mov $arg6, %r11 # preserve remaining length across helper calls - - # r10/state, arg2-arg5/inputs, r12/length - mov $arg1, %r10 # %r10 = state - call keccak_1600_partial_add_x4 # arg2-arg5 are updated - - call keccak_1600_load_state_x4 - - call keccak_1600_permute - - movq \$0, 8*100($arg1) # clear s[100] - jmp .Lshake128_absorb_partial_block_done - -.Lshake128_absorb_skip_permute: - # r10/state, arg2-arg5/inputs, r12/length - mov $arg1, %r10 - mov $arg6, %r12 - mov $arg6, %r11 # preserve input length across helper call - call keccak_1600_partial_add_x4 - - lea (%r11,%r14), %r15 - mov %r15, 8*100($arg1) # s[100] += inlen - - cmp \$168, %r15 # check s[100] below SHAKE128_RATE - jb .Lshake128_absorb_exit - - call keccak_1600_load_state_x4 - - call keccak_1600_permute - - call keccak_1600_save_state_x4 - - movq \$0, 8*100($arg1) # clear s[100] - jmp .Lshake128_absorb_exit - -.Lshake128_absorb_main_loop_start: - call keccak_1600_load_state_x4 - mov $arg6, %r11 # full input length when no prior partial block - -.Lshake128_absorb_partial_block_done: - xor %r12, %r12 # zero message offset - - # Process the input message in blocks -.align 32 -.Lshake128_absorb_while_loop: - cmp \$168, %r11 # compare mlen to SHAKE128_RATE - jb .Lshake128_absorb_while_loop_done - - # Inline absorb_bytes_x4 for SHAKE128_RATE (168 bytes = 21 ymm registers) -___ - -# Generate absorb code for SHAKE128 rate (168 bytes) -for (my $i = 0; $i < 21; $i++) { - my $offset = $i * 8; - $code.=<<___; - vmovq $offset($arg2,%r12), %xmm31 - vpinsrq \$1, $offset($arg3,%r12), %xmm31, %xmm31 - vmovq $offset($arg4,%r12), %xmm30 - vpinsrq \$1, $offset($arg5,%r12), %xmm30, %xmm30 - vinserti32x4 \$1, %xmm30, %ymm31, %ymm31 - vpxorq %ymm31, %ymm$i, %ymm$i -___ -} - -$code.=<<___; - sub \$168, %r11 # Subtract the rate from the remaining length - add \$168, %r12 # Adjust offset to next block - call keccak_1600_permute # Perform the Keccak permutation - - jmp .Lshake128_absorb_while_loop - -.align 32 -.Lshake128_absorb_while_loop_done: - call keccak_1600_save_state_x4 - - mov %r11, 8*100($arg1) # update s[100] - or %r11, %r11 - jz .Lshake128_absorb_exit - - movq \$0, 8*100($arg1) # clear s[100] - - # r10/state, arg2-arg5/input, r12/length - mov $arg1, %r10 - add %r12, $arg2 - add %r12, $arg3 - add %r12, $arg4 - add %r12, $arg5 - mov %r11, %r12 - call keccak_1600_partial_add_x4 - - mov %r11, 8*100($arg1) # update s[100] - -.Lshake128_absorb_exit: - # Clear sensitive registers - vpxorq %xmm16, %xmm16, %xmm16 - vmovdqa64 %ymm16, %ymm17 - vmovdqa64 %ymm16, %ymm18 - vmovdqa64 %ymm16, %ymm19 - vmovdqa64 %ymm16, %ymm20 - vmovdqa64 %ymm16, %ymm21 - vmovdqa64 %ymm16, %ymm22 - vmovdqa64 %ymm16, %ymm23 - vmovdqa64 %ymm16, %ymm24 - vmovdqa64 %ymm16, %ymm25 - vmovdqa64 %ymm16, %ymm26 - vmovdqa64 %ymm16, %ymm27 - vmovdqa64 %ymm16, %ymm28 - vmovdqa64 %ymm16, %ymm29 - vmovdqa64 %ymm16, %ymm30 - vmovdqa64 %ymm16, %ymm31 -.Lshake128_absorb_epilogue: - vzeroall -___ -$code .= <<___ if ($win64); - vmovups 0(%rsp), %xmm6 - vmovups 16(%rsp), %xmm7 - vmovups 32(%rsp), %xmm8 - vmovups 48(%rsp), %xmm9 - vmovups 64(%rsp), %xmm10 - vmovups 80(%rsp), %xmm11 - vmovups 96(%rsp), %xmm12 - vmovups 112(%rsp), %xmm13 - vmovups 128(%rsp), %xmm14 - vmovups 144(%rsp), %xmm15 - add \$160, %rsp -___ -$code.=<<___; - - pop %r15 -.cfi_pop %r15 - pop %r14 -.cfi_pop %r14 - pop %r13 -.cfi_pop %r13 - pop %r12 -.cfi_pop %r12 - pop %rbx -.cfi_pop %rbx - pop %rbp -.cfi_pop %rbp - ret -.cfi_endproc -.size SHA3_shake128_x4_inc_absorb_avx512vl,.-SHA3_shake128_x4_inc_absorb_avx512vl - - -# SHA3_shake128_x4_inc_finalize_avx512vl -# Finalize absorption phase for 4 parallel SHAKE-128 states -# Adds padding and terminator bytes and clears the absorb offset -# Arguments: -# arg1 (rdi): pointer to state context (808 bytes) -# Returns: void -# Note: After this call, state is ready for squeezing output -.globl SHA3_shake128_x4_inc_finalize_avx512vl -.type SHA3_shake128_x4_inc_finalize_avx512vl,\@function,1 -.align 32 -SHA3_shake128_x4_inc_finalize_avx512vl: -.L_SHA3_shake128_x4_inc_finalize_avx512vl: -.cfi_startproc - mov 8*100($arg1), %r11 # load state offset from s[100] - mov %r11, %r10 - and \$~7, %r10d # offset to the state register - and \$7, %r11d # offset within the register - - # add EOM byte right after the message - vmovdqu32 ($arg1,%r10,4), %ymm31 - lea shake_msg_pad_x4(%rip), %r9 - sub %r11, %r9 - vmovdqu32 (%r9), %ymm30 - vpxorq %ymm30, %ymm31, %ymm31 - vmovdqu32 %ymm31, ($arg1,%r10,4) - - # add terminating byte at offset equal to rate - 1 (SHAKE128_RATE = 168) - vmovdqu32 640($arg1), %ymm31 # 168*4 - 32 = 672 - 32 = 640 - vmovdqa32 shake_terminator_byte_x4(%rip), %ymm30 - vpxorq %ymm30, %ymm31, %ymm31 - vmovdqu32 %ymm31, 640($arg1) - - movq \$0, 8*100($arg1) # clear s[100] - vpxorq %ymm31, %ymm31, %ymm31 - ret -.cfi_endproc -.size SHA3_shake128_x4_inc_finalize_avx512vl,.-SHA3_shake128_x4_inc_finalize_avx512vl - -___ - -$code .= <<___ if ($win64); -# Internal Win64 shim for squeeze entry. It establishes xlate-compatible -# unwind state and then jumps to the function entry after the prologue. -# This is required for internal calls since the xlate ABI conversion -# is already done in the caller function. -.type SHA3_shake128_x4_inc_squeeze_avx512vl_internal,\@abi-omnipotent -.align 32 -.LSEH_begin_SHA3_shake128_x4_inc_squeeze_avx512vl_internal: -SHA3_shake128_x4_inc_squeeze_avx512vl_internal: - mov %rsp, %rax - mov $arg1, 8(%rsp) - mov $arg2, 16(%rsp) - jmp .L_SHA3_shake128_x4_inc_squeeze_avx512vl -.LSEH_end_SHA3_shake128_x4_inc_squeeze_avx512vl_internal: -.size SHA3_shake128_x4_inc_squeeze_avx512vl_internal,.-SHA3_shake128_x4_inc_squeeze_avx512vl_internal -___ -$code.=<<___; - -# SHA3_shake128_x4_inc_squeeze_avx512vl -# Squeeze output from 4 parallel SHAKE128 states -# Arguments: -# arg1 (rdi): pointer to lane 0 output buffer -# arg2 (rsi): pointer to lane 1 output buffer -# arg3 (rdx): pointer to lane 2 output buffer -# arg4 (rcx): pointer to lane 3 output buffer -# arg5 (r8): output length in bytes (must be same for all lanes) -# arg6 (r9): pointer to state context (808 bytes) -# Returns: void -# Note: Can be called multiple times to generate arbitrary-length output -.globl SHA3_shake128_x4_inc_squeeze_avx512vl -.type SHA3_shake128_x4_inc_squeeze_avx512vl,\@function,6 -.align 32 -SHA3_shake128_x4_inc_squeeze_avx512vl: -.L_SHA3_shake128_x4_inc_squeeze_avx512vl: -.cfi_startproc - push %rbp -.cfi_push %rbp - push %rbx -.cfi_push %rbx - push %r12 -.cfi_push %r12 - push %r13 -.cfi_push %r13 - push %r14 -.cfi_push %r14 - push %r15 -.cfi_push %r15 -___ -$code .= <<___ if ($win64); - sub \$160, %rsp - vmovups %xmm6, 0(%rsp) - vmovups %xmm7, 16(%rsp) - vmovups %xmm8, 32(%rsp) - vmovups %xmm9, 48(%rsp) - vmovups %xmm10, 64(%rsp) - vmovups %xmm11, 80(%rsp) - vmovups %xmm12, 96(%rsp) - vmovups %xmm13, 112(%rsp) - vmovups %xmm14, 128(%rsp) - vmovups %xmm15, 144(%rsp) -___ -$code.=<<___; - -.Lshake128_squeeze_body: - or $arg5, $arg5 - jz .Lshake128_squeeze_done - - # check for partially processed block - mov 8*100($arg6), %r15 # s[100] - capacity - or %r15, %r15 - jnz .Lshake128_squeeze_no_init_permute - - mov $arg1, %r14 - mov $arg6, $arg1 - call keccak_1600_load_state_x4 - - mov %r14, $arg1 - - xor %rbp, %rbp - jmp .Lshake128_squeeze_loop - -.align 32 -.Lshake128_squeeze_no_init_permute: - # extract bytes: r10 - state/src, arg1-arg4 - output/dst, r12 - length = min(capacity, outlen), r11 - offset - mov $arg6, %r10 - mov $arg6, %r14 # preserve state pointer across extract helper - - mov %r15, %r12 - cmp %r15, $arg5 - cmovnae $arg5, %r12 # %r12 = min(capacity, outlen) - - sub %r12, $arg5 # outlen -= length - - mov \$168, %r11d # SHAKE128_RATE - sub %r15, %r11 # state offset - - sub %r12, %r15 # capacity -= length - mov %r15, 8*100($arg6) # update s[100] - - call keccak_1600_extract_bytes_x4 - mov %r14, $arg6 # restore state pointer after helper clobbers - - or %r15, %r15 - jnz .Lshake128_squeeze_done # check s[100] not zero - - mov $arg1, %r13 # preserve arg1 - mov %r14, $arg1 - call keccak_1600_load_state_x4 - - mov %r13, $arg1 - xor %rbp, %rbp - -.align 32 -.Lshake128_squeeze_loop: - cmp \$168, $arg5 # outlen > SHAKE128_RATE - jb .Lshake128_squeeze_final_extract - - call keccak_1600_permute - - # Extract SHAKE128 rate bytes (168 bytes = 21 x 8 bytes) inline -___ - -# Generate extract code for SHAKE128 rate (168 bytes = 21 ymm registers) -for (my $i = 0; $i < 21; $i++) { - my $offset = $i * 8; - $code.=<<___; - vextracti64x2 \$1, %ymm$i, %xmm31 - vmovq %xmm$i, $offset($arg1,%rbp) - vpextrq \$1, %xmm$i, $offset($arg2,%rbp) - vmovq %xmm31, $offset($arg3,%rbp) - vpextrq \$1, %xmm31, $offset($arg4,%rbp) -___ -} - -$code.=<<___; - add \$168, %rbp # dst offset += SHAKE128_RATE - sub \$168, $arg5 # outlen -= SHAKE128_RATE - jmp .Lshake128_squeeze_loop - -.align 32 -.Lshake128_squeeze_final_extract: - or $arg5, $arg5 - jz .Lshake128_squeeze_no_end_permute - - # update output pointers - add %rbp, $arg1 - add %rbp, $arg2 - add %rbp, $arg3 - add %rbp, $arg4 - - mov \$168, %r15d # SHAKE128_RATE - sub $arg5, %r15 - mov %r15, 8*100($arg6) # s[100] = capacity - - call keccak_1600_permute - - mov $arg1, %r14 - mov $arg6, $arg1 - call keccak_1600_save_state_x4 - - mov %r14, $arg1 - - # extract bytes: r10 - state/src, arg1-arg4 - output/dst, r12 - length, r11 - offset = 0 - mov $arg6, %r10 - mov $arg5, %r12 - xor %r11, %r11 - call keccak_1600_extract_bytes_x4 - - jmp .Lshake128_squeeze_done - -.Lshake128_squeeze_no_end_permute: - movq \$0, 8*100($arg6) # s[100] = 0 - mov $arg6, $arg1 - call keccak_1600_save_state_x4 - -.Lshake128_squeeze_done: - # Clear sensitive registers - vpxorq %xmm16, %xmm16, %xmm16 - vmovdqa64 %ymm16, %ymm17 - vmovdqa64 %ymm16, %ymm18 - vmovdqa64 %ymm16, %ymm19 - vmovdqa64 %ymm16, %ymm20 - vmovdqa64 %ymm16, %ymm21 - vmovdqa64 %ymm16, %ymm22 - vmovdqa64 %ymm16, %ymm23 - vmovdqa64 %ymm16, %ymm24 - vmovdqa64 %ymm16, %ymm25 - vmovdqa64 %ymm16, %ymm26 - vmovdqa64 %ymm16, %ymm27 - vmovdqa64 %ymm16, %ymm28 - vmovdqa64 %ymm16, %ymm29 - vmovdqa64 %ymm16, %ymm30 - vmovdqa64 %ymm16, %ymm31 -.Lshake128_squeeze_epilogue: - vzeroall -___ -$code .= <<___ if ($win64); - vmovups 0(%rsp), %xmm6 - vmovups 16(%rsp), %xmm7 - vmovups 32(%rsp), %xmm8 - vmovups 48(%rsp), %xmm9 - vmovups 64(%rsp), %xmm10 - vmovups 80(%rsp), %xmm11 - vmovups 96(%rsp), %xmm12 - vmovups 112(%rsp), %xmm13 - vmovups 128(%rsp), %xmm14 - vmovups 144(%rsp), %xmm15 - add \$160, %rsp -___ -$code.=<<___; - - pop %r15 -.cfi_pop %r15 - pop %r14 -.cfi_pop %r14 - pop %r13 -.cfi_pop %r13 - pop %r12 -.cfi_pop %r12 - pop %rbx -.cfi_pop %rbx - pop %rbp -.cfi_pop %rbp - ret -.cfi_endproc -.size SHA3_shake128_x4_inc_squeeze_avx512vl,.-SHA3_shake128_x4_inc_squeeze_avx512vl - - -# SHAKE256 x4 multi-buffer functions -# These functions process 4 independent SHAKE256 streams in parallel using AVX-512VL -# State layout: 25 ymm registers (200 bytes each) + 1 qword = 808 bytes per context -# Rate: 136 bytes for SHAKE256 - -# SHA3_shake256_x4_avx512vl -# One-shot SHAKE-256 x4 function: init + absorb + finalize + squeeze -# Arguments: -# arg1 (rdi): pointer to output lane 0 -# arg2 (rsi): pointer to output lane 1 -# arg3 (rdx): pointer to output lane 2 -# arg4 (rcx): pointer to output lane 3 -# arg5 (r8): output length in bytes (must be same for all lanes) -# arg6 (r9): pointer to input lane 0 -# [stack+0]: pointer to input lane 1 -# [stack+8]: pointer to input lane 2 -# [stack+16]: pointer to input lane 3 -# [stack+24]: input length in bytes (must be same for all lanes) -# Returns: void -.globl SHA3_shake256_x4_avx512vl -.type SHA3_shake256_x4_avx512vl,\@function,10 -.align 32 -SHA3_shake256_x4_avx512vl: -.cfi_startproc - push %rbp -.cfi_push %rbp - mov %rsp, %rbp - push %rbx -.cfi_push %rbx -___ -$code .= <<___ if ($win64); - sub \$160, %rsp - vmovups %xmm6, 0(%rsp) - vmovups %xmm7, 16(%rsp) - vmovups %xmm8, 32(%rsp) - vmovups %xmm9, 48(%rsp) - vmovups %xmm10, 64(%rsp) - vmovups %xmm11, 80(%rsp) - vmovups %xmm12, 96(%rsp) - vmovups %xmm13, 112(%rsp) - vmovups %xmm14, 128(%rsp) - vmovups %xmm15, 144(%rsp) -___ -$code.=<<___; - - sub \$$sf_size, %rsp - mov %rsp, %rbx - -.Lshake256_x4_body: - mov $arg1, $sf_arg1(%rbx) - mov $arg2, $sf_arg2(%rbx) - mov $arg3, $sf_arg3(%rbx) - mov $arg4, $sf_arg4(%rbx) - mov $arg5, $sf_arg5(%rbx) - - lea $sf_state_x4(%rbx), $arg1 # start of x4 state on the stack frame - mov $arg1, $sf_state_ptr(%rbx) - - # Initialize the state array to zero - call keccak_1600_init_state - - call keccak_1600_save_state_x4 - - movq \$0, 8*100($arg1) # clear s[100] - - mov $sf_state_ptr(%rbx), $arg1 - mov $arg6, $arg2 -___ -$code .= <<___ if ($win64); - # xlate prologue handles up to six arguments. For one-shot x4 wrappers - # (10 args), the remaining four stay in Win64 stack slots. - mov 64(%rbp), $arg3 # arg7 from stack - mov 72(%rbp), $arg4 # arg8 from stack - mov 80(%rbp), $arg5 # arg9 from stack - mov 88(%rbp), $arg6 # arg10 from stack -___ -$code .= <<___ if (!$win64); - mov 16(%rbp), $arg3 # arg7 from stack - mov 24(%rbp), $arg4 # arg8 from stack - mov 32(%rbp), $arg5 # arg9 from stack - mov 40(%rbp), $arg6 # arg10 from stack -___ -$code.=<<___; - # Internal entry avoids Win64 xlate prologue argument remapping. -___ -$code .= call_internal("SHA3_shake256_x4_inc_absorb_avx512vl_internal"); -$code.=<<___; - - mov $sf_state_ptr(%rbx), $arg1 - call .L_SHA3_shake256_x4_inc_finalize_avx512vl - - # squeeze - mov $sf_arg1(%rbx), $arg1 - mov $sf_arg2(%rbx), $arg2 - mov $sf_arg3(%rbx), $arg3 - mov $sf_arg4(%rbx), $arg4 - mov $sf_arg5(%rbx), $arg5 - mov $sf_state_ptr(%rbx), $arg6 -___ -$code .= call_internal("SHA3_shake256_x4_inc_squeeze_avx512vl_internal"); -$code.=<<___; - - # Clear the temporary buffer - lea $sf_state_x4(%rbx), %r9 - vpxorq %ymm31, %ymm31, %ymm31 - vmovdqu64 %ymm31, 32*0(%r9) - vmovdqu64 %ymm31, 32*1(%r9) - vmovdqu64 %ymm31, 32*2(%r9) - vmovdqu64 %ymm31, 32*3(%r9) - vmovdqu64 %ymm31, 32*4(%r9) - vmovdqu64 %ymm31, 32*5(%r9) - vmovdqu64 %ymm31, 32*6(%r9) - vmovdqu64 %ymm31, 32*7(%r9) - vmovdqu64 %ymm31, 32*8(%r9) - vmovdqu64 %ymm31, 32*9(%r9) - vmovdqu64 %ymm31, 32*10(%r9) - vmovdqu64 %ymm31, 32*11(%r9) - vmovdqu64 %ymm31, 32*12(%r9) - vmovdqu64 %ymm31, 32*13(%r9) - vmovdqu64 %ymm31, 32*14(%r9) - vmovdqu64 %ymm31, 32*15(%r9) - vmovdqu64 %ymm31, 32*16(%r9) - vmovdqu64 %ymm31, 32*17(%r9) - vmovdqu64 %ymm31, 32*18(%r9) - vmovdqu64 %ymm31, 32*19(%r9) - vmovdqu64 %ymm31, 32*20(%r9) - vmovdqu64 %ymm31, 32*21(%r9) - vmovdqu64 %ymm31, 32*22(%r9) - vmovdqu64 %ymm31, 32*23(%r9) - vmovdqu64 %ymm31, 32*24(%r9) - vmovq %xmm31, 32*25(%r9) - -.Lshake256_x4_epilogue: -___ -$code .= <<___ if ($win64); - vmovups $sf_size+0(%rsp), %xmm6 - vmovups $sf_size+16(%rsp), %xmm7 - vmovups $sf_size+32(%rsp), %xmm8 - vmovups $sf_size+48(%rsp), %xmm9 - vmovups $sf_size+64(%rsp), %xmm10 - vmovups $sf_size+80(%rsp), %xmm11 - vmovups $sf_size+96(%rsp), %xmm12 - vmovups $sf_size+112(%rsp), %xmm13 - vmovups $sf_size+128(%rsp), %xmm14 - vmovups $sf_size+144(%rsp), %xmm15 - add \$160, %rsp -___ -$code.=<<___; - add \$$sf_size, %rsp - pop %rbx -.cfi_pop %rbx - pop %rbp -.cfi_pop %rbp - ret -.cfi_endproc -.size SHA3_shake256_x4_avx512vl,.-SHA3_shake256_x4_avx512vl - -___ - -$code .= <<___ if ($win64); -# Internal Win64 shim for absorb entry. It establishes xlate-compatible -# unwind state and then jumps to the function entry after the prologue. -# This is required for internal calls since the xlate ABI conversion -# is already done in the caller function. -.type SHA3_shake256_x4_inc_absorb_avx512vl_internal,\@abi-omnipotent -.align 32 -.LSEH_begin_SHA3_shake256_x4_inc_absorb_avx512vl_internal: -SHA3_shake256_x4_inc_absorb_avx512vl_internal: - mov %rsp, %rax - mov $arg1, 8(%rsp) - mov $arg2, 16(%rsp) - jmp .L_SHA3_shake256_x4_inc_absorb_avx512vl -.LSEH_end_SHA3_shake256_x4_inc_absorb_avx512vl_internal: -.size SHA3_shake256_x4_inc_absorb_avx512vl_internal,.-SHA3_shake256_x4_inc_absorb_avx512vl_internal -___ -$code.=<<___; - -# SHA3_shake256_x4_inc_absorb_avx512vl -# Absorb input data into 4 parallel SHAKE256 states -# Arguments: -# arg1 (rdi): pointer to state context (808 bytes) -# arg2 (rsi): pointer to lane 0 input data -# arg3 (rdx): pointer to lane 1 input data -# arg4 (rcx): pointer to lane 2 input data -# arg5 (r8): pointer to lane 3 input data -# arg6 (r9): input length in bytes (must be same for all lanes) -# Returns: void -# Note: Input is XORed into state and Keccak permutation is applied for each rate-sized block -.globl SHA3_shake256_x4_inc_absorb_avx512vl -.type SHA3_shake256_x4_inc_absorb_avx512vl,\@function,6 -.align 32 -SHA3_shake256_x4_inc_absorb_avx512vl: -.L_SHA3_shake256_x4_inc_absorb_avx512vl: -.cfi_startproc - push %rbp -.cfi_push %rbp - push %rbx -.cfi_push %rbx - push %r12 -.cfi_push %r12 - push %r13 -.cfi_push %r13 - push %r14 -.cfi_push %r14 - push %r15 -.cfi_push %r15 -___ -$code .= <<___ if ($win64); - sub \$160, %rsp - vmovups %xmm6, 0(%rsp) - vmovups %xmm7, 16(%rsp) - vmovups %xmm8, 32(%rsp) - vmovups %xmm9, 48(%rsp) - vmovups %xmm10, 64(%rsp) - vmovups %xmm11, 80(%rsp) - vmovups %xmm12, 96(%rsp) - vmovups %xmm13, 112(%rsp) - vmovups %xmm14, 128(%rsp) - vmovups %xmm15, 144(%rsp) -___ -$code.=<<___; - -.Lshake256_absorb_body: - # check for partially processed block - mov 8*100($arg1), %r14 - or %r14, %r14 # s[100] == 0? - je .Lshake256_absorb_main_loop_start - - # process remaining bytes if message long enough - mov \$136, %r12 # SHAKE256_RATE = 136 - sub %r14, %r12 # %r12 = capacity - - cmp %r12, $arg6 # if mlen <= capacity then no permute - jbe .Lshake256_absorb_skip_permute - - sub %r12, $arg6 - mov $arg6, %r11 # preserve remaining length across helper calls - - # r10/state, arg2-arg5/inputs, r12/length - mov $arg1, %r10 # %r10 = state - call keccak_1600_partial_add_x4 # arg2-arg5 are updated - - call keccak_1600_load_state_x4 - - call keccak_1600_permute - - movq \$0, 8*100($arg1) # clear s[100] - jmp .Lshake256_absorb_partial_block_done - -.Lshake256_absorb_skip_permute: - # r10/state, arg2-arg5/inputs, r12/length - mov $arg1, %r10 - mov $arg6, %r12 - mov $arg6, %r11 # preserve input length across helper call - call keccak_1600_partial_add_x4 - - lea (%r11,%r14), %r15 - mov %r15, 8*100($arg1) # s[100] += inlen - - cmp \$136, %r15 # check s[100] below SHAKE256_RATE - jb .Lshake256_absorb_exit - - call keccak_1600_load_state_x4 - - call keccak_1600_permute - - call keccak_1600_save_state_x4 - - movq \$0, 8*100($arg1) # clear s[100] - jmp .Lshake256_absorb_exit - -.Lshake256_absorb_main_loop_start: - call keccak_1600_load_state_x4 - mov $arg6, %r11 # full input length when no prior partial block - -.Lshake256_absorb_partial_block_done: - xor %r12, %r12 # zero message offset - - # Process the input message in blocks -.align 32 -.Lshake256_absorb_while_loop: - cmp \$136, %r11 # compare mlen to SHAKE256_RATE - jb .Lshake256_absorb_while_loop_done - - # Inline absorb_bytes_x4 for SHAKE256_RATE (136 bytes = 17 ymm registers) -___ - -# Generate absorb code for SHAKE256 rate (136 bytes) -for (my $i = 0; $i < 17; $i++) { - my $offset = $i * 8; - $code.=<<___; - vmovq $offset($arg2,%r12), %xmm31 - vpinsrq \$1, $offset($arg3,%r12), %xmm31, %xmm31 - vmovq $offset($arg4,%r12), %xmm30 - vpinsrq \$1, $offset($arg5,%r12), %xmm30, %xmm30 - vinserti32x4 \$1, %xmm30, %ymm31, %ymm31 - vpxorq %ymm31, %ymm$i, %ymm$i -___ -} - -$code.=<<___; - sub \$136, %r11 # Subtract the rate from the remaining length - add \$136, %r12 # Adjust offset to next block - call keccak_1600_permute # Perform the Keccak permutation - - jmp .Lshake256_absorb_while_loop - -.align 32 -.Lshake256_absorb_while_loop_done: - call keccak_1600_save_state_x4 - - mov %r11, 8*100($arg1) # update s[100] - or %r11, %r11 - jz .Lshake256_absorb_exit - - movq \$0, 8*100($arg1) # clear s[100] - - # r10/state, arg2-arg5/input, r12/length - mov $arg1, %r10 - add %r12, $arg2 - add %r12, $arg3 - add %r12, $arg4 - add %r12, $arg5 - mov %r11, %r12 - call keccak_1600_partial_add_x4 - - mov %r11, 8*100($arg1) # update s[100] - -.Lshake256_absorb_exit: - # Clear sensitive registers - vpxorq %xmm16, %xmm16, %xmm16 - vmovdqa64 %ymm16, %ymm17 - vmovdqa64 %ymm16, %ymm18 - vmovdqa64 %ymm16, %ymm19 - vmovdqa64 %ymm16, %ymm20 - vmovdqa64 %ymm16, %ymm21 - vmovdqa64 %ymm16, %ymm22 - vmovdqa64 %ymm16, %ymm23 - vmovdqa64 %ymm16, %ymm24 - vmovdqa64 %ymm16, %ymm25 - vmovdqa64 %ymm16, %ymm26 - vmovdqa64 %ymm16, %ymm27 - vmovdqa64 %ymm16, %ymm28 - vmovdqa64 %ymm16, %ymm29 - vmovdqa64 %ymm16, %ymm30 - vmovdqa64 %ymm16, %ymm31 -.Lshake256_absorb_epilogue: - vzeroall -___ -$code .= <<___ if ($win64); - vmovups 0(%rsp), %xmm6 - vmovups 16(%rsp), %xmm7 - vmovups 32(%rsp), %xmm8 - vmovups 48(%rsp), %xmm9 - vmovups 64(%rsp), %xmm10 - vmovups 80(%rsp), %xmm11 - vmovups 96(%rsp), %xmm12 - vmovups 112(%rsp), %xmm13 - vmovups 128(%rsp), %xmm14 - vmovups 144(%rsp), %xmm15 - add \$160, %rsp -___ -$code.=<<___; - - pop %r15 -.cfi_pop %r15 - pop %r14 -.cfi_pop %r14 - pop %r13 -.cfi_pop %r13 - pop %r12 -.cfi_pop %r12 - pop %rbx -.cfi_pop %rbx - pop %rbp -.cfi_pop %rbp - ret -.cfi_endproc -.size SHA3_shake256_x4_inc_absorb_avx512vl,.-SHA3_shake256_x4_inc_absorb_avx512vl - - -# SHA3_shake256_x4_inc_finalize_avx512vl -# Finalize absorption phase for 4 parallel SHAKE-256 states -# Adds padding and terminator bytes and clears the absorb offset -# Arguments: -# arg1 (rdi): pointer to state context (808 bytes) -# Returns: void -# Note: After this call, state is ready for squeezing output -.globl SHA3_shake256_x4_inc_finalize_avx512vl -.type SHA3_shake256_x4_inc_finalize_avx512vl,\@function,1 -.align 32 -SHA3_shake256_x4_inc_finalize_avx512vl: -.L_SHA3_shake256_x4_inc_finalize_avx512vl: -.cfi_startproc - mov 8*100($arg1), %r11 # load state offset from s[100] - mov %r11, %r10 - and \$~7, %r10d # offset to the state register - and \$7, %r11d # offset within the register - - # add EOM byte right after the message - vmovdqu32 ($arg1,%r10,4), %ymm31 - lea shake_msg_pad_x4(%rip), %r9 - sub %r11, %r9 - vmovdqu32 (%r9), %ymm30 - vpxorq %ymm30, %ymm31, %ymm31 - vmovdqu32 %ymm31, ($arg1,%r10,4) - - # add terminating byte at offset equal to rate - 1 (SHAKE256_RATE = 136) - vmovdqu32 512($arg1), %ymm31 # 136*4 - 32 = 544 - 32 = 512 - vmovdqa32 shake_terminator_byte_x4(%rip), %ymm30 - vpxorq %ymm30, %ymm31, %ymm31 - vmovdqu32 %ymm31, 512($arg1) - - movq \$0, 8*100($arg1) # clear s[100] - vpxorq %ymm31, %ymm31, %ymm31 - ret -.cfi_endproc -.size SHA3_shake256_x4_inc_finalize_avx512vl,.-SHA3_shake256_x4_inc_finalize_avx512vl - -___ - -$code .= <<___ if ($win64); -# Internal Win64 shim for squeeze entry. It establishes xlate-compatible -# unwind state and then jumps to the function entry after the prologue. -# This is required for internal calls since the xlate ABI conversion -# is already done in the caller function. -.type SHA3_shake256_x4_inc_squeeze_avx512vl_internal,\@abi-omnipotent -.align 32 -.LSEH_begin_SHA3_shake256_x4_inc_squeeze_avx512vl_internal: -SHA3_shake256_x4_inc_squeeze_avx512vl_internal: - mov %rsp, %rax - mov $arg1, 8(%rsp) - mov $arg2, 16(%rsp) - jmp .L_SHA3_shake256_x4_inc_squeeze_avx512vl -.LSEH_end_SHA3_shake256_x4_inc_squeeze_avx512vl_internal: -.size SHA3_shake256_x4_inc_squeeze_avx512vl_internal,.-SHA3_shake256_x4_inc_squeeze_avx512vl_internal -___ -$code.=<<___; - -# SHA3_shake256_x4_inc_squeeze_avx512vl -# Squeeze output from 4 parallel SHAKE256 states -# Arguments: -# arg1 (rdi): pointer to lane 0 output buffer -# arg2 (rsi): pointer to lane 1 output buffer -# arg3 (rdx): pointer to lane 2 output buffer -# arg4 (rcx): pointer to lane 3 output buffer -# arg5 (r8): output length in bytes (must be same for all lanes) -# arg6 (r9): pointer to state context (808 bytes) -# Returns: void -# Note: Can be called multiple times to generate arbitrary-length output -.globl SHA3_shake256_x4_inc_squeeze_avx512vl -.type SHA3_shake256_x4_inc_squeeze_avx512vl,\@function,6 -.align 32 -SHA3_shake256_x4_inc_squeeze_avx512vl: -.L_SHA3_shake256_x4_inc_squeeze_avx512vl: -.cfi_startproc - push %rbp -.cfi_push %rbp - push %rbx -.cfi_push %rbx - push %r12 -.cfi_push %r12 - push %r13 -.cfi_push %r13 - push %r14 -.cfi_push %r14 - push %r15 -.cfi_push %r15 -___ -$code .= <<___ if ($win64); - sub \$160, %rsp - vmovups %xmm6, 0(%rsp) - vmovups %xmm7, 16(%rsp) - vmovups %xmm8, 32(%rsp) - vmovups %xmm9, 48(%rsp) - vmovups %xmm10, 64(%rsp) - vmovups %xmm11, 80(%rsp) - vmovups %xmm12, 96(%rsp) - vmovups %xmm13, 112(%rsp) - vmovups %xmm14, 128(%rsp) - vmovups %xmm15, 144(%rsp) -___ -$code.=<<___; - -.Lshake256_squeeze_body: - or $arg5, $arg5 - jz .Lshake256_squeeze_done - - # check for partially processed block - mov 8*100($arg6), %r15 # s[100] - capacity - or %r15, %r15 - jnz .Lshake256_squeeze_no_init_permute - - mov $arg1, %r14 - mov $arg6, $arg1 - call keccak_1600_load_state_x4 - - mov %r14, $arg1 - - xor %rbp, %rbp - jmp .Lshake256_squeeze_loop - -.align 32 -.Lshake256_squeeze_no_init_permute: - # extract bytes: r10 - state/src, arg1-arg4 - output/dst, r12 - length = min(capacity, outlen), r11 - offset - mov $arg6, %r10 - mov $arg6, %r14 # preserve state pointer across extract helper - - mov %r15, %r12 - cmp %r15, $arg5 - cmovnae $arg5, %r12 # %r12 = min(capacity, outlen) - - sub %r12, $arg5 # outlen -= length - - mov \$136, %r11d # SHAKE256_RATE - sub %r15, %r11 # state offset - - sub %r12, %r15 # capacity -= length - mov %r15, 8*100($arg6) # update s[100] - - call keccak_1600_extract_bytes_x4 - mov %r14, $arg6 # restore state pointer after helper clobbers - - or %r15, %r15 - jnz .Lshake256_squeeze_done # check s[100] not zero - - mov $arg1, %r13 # preserve arg1 - mov %r14, $arg1 - call keccak_1600_load_state_x4 - - mov %r13, $arg1 - xor %rbp, %rbp - -.align 32 -.Lshake256_squeeze_loop: - cmp \$136, $arg5 # outlen > SHAKE256_RATE - jb .Lshake256_squeeze_final_extract - - call keccak_1600_permute - - # Extract SHAKE256 rate bytes (136 bytes = 17 x 8 bytes) inline -___ - -# Generate extract code for SHAKE256 rate (136 bytes = 17 ymm registers) -for (my $i = 0; $i < 17; $i++) { - my $offset = $i * 8; - $code.=<<___; - vextracti64x2 \$1, %ymm$i, %xmm31 - vmovq %xmm$i, $offset($arg1,%rbp) - vpextrq \$1, %xmm$i, $offset($arg2,%rbp) - vmovq %xmm31, $offset($arg3,%rbp) - vpextrq \$1, %xmm31, $offset($arg4,%rbp) -___ -} - -$code.=<<___; - add \$136, %rbp # dst offset += SHAKE256_RATE - sub \$136, $arg5 # outlen -= SHAKE256_RATE - jmp .Lshake256_squeeze_loop - -.align 32 -.Lshake256_squeeze_final_extract: - or $arg5, $arg5 - jz .Lshake256_squeeze_no_end_permute - - # update output pointers - add %rbp, $arg1 - add %rbp, $arg2 - add %rbp, $arg3 - add %rbp, $arg4 - - mov \$136, %r15d # SHAKE256_RATE - sub $arg5, %r15 - mov %r15, 8*100($arg6) # s[100] = capacity - - call keccak_1600_permute - - mov $arg1, %r14 - mov $arg6, $arg1 - call keccak_1600_save_state_x4 - - mov %r14, $arg1 - - # extract bytes: r10 - state/src, arg1-arg4 - output/dst, r12 - length, r11 - offset = 0 - mov $arg6, %r10 - mov $arg5, %r12 - xor %r11, %r11 - call keccak_1600_extract_bytes_x4 - - jmp .Lshake256_squeeze_done - -.Lshake256_squeeze_no_end_permute: - movq \$0, 8*100($arg6) # s[100] = 0 - mov $arg6, $arg1 - call keccak_1600_save_state_x4 - -.Lshake256_squeeze_done: - # Clear sensitive registers - vpxorq %xmm16, %xmm16, %xmm16 - vmovdqa64 %ymm16, %ymm17 - vmovdqa64 %ymm16, %ymm18 - vmovdqa64 %ymm16, %ymm19 - vmovdqa64 %ymm16, %ymm20 - vmovdqa64 %ymm16, %ymm21 - vmovdqa64 %ymm16, %ymm22 - vmovdqa64 %ymm16, %ymm23 - vmovdqa64 %ymm16, %ymm24 - vmovdqa64 %ymm16, %ymm25 - vmovdqa64 %ymm16, %ymm26 - vmovdqa64 %ymm16, %ymm27 - vmovdqa64 %ymm16, %ymm28 - vmovdqa64 %ymm16, %ymm29 - vmovdqa64 %ymm16, %ymm30 - vmovdqa64 %ymm16, %ymm31 -.Lshake256_squeeze_epilogue: - vzeroall -___ -$code .= <<___ if ($win64); - vmovups 0(%rsp), %xmm6 - vmovups 16(%rsp), %xmm7 - vmovups 32(%rsp), %xmm8 - vmovups 48(%rsp), %xmm9 - vmovups 64(%rsp), %xmm10 - vmovups 80(%rsp), %xmm11 - vmovups 96(%rsp), %xmm12 - vmovups 112(%rsp), %xmm13 - vmovups 128(%rsp), %xmm14 - vmovups 144(%rsp), %xmm15 - add \$160, %rsp -___ -$code.=<<___; - - pop %r15 -.cfi_pop %r15 - pop %r14 -.cfi_pop %r14 - pop %r13 -.cfi_pop %r13 - pop %r12 -.cfi_pop %r12 - pop %rbx -.cfi_pop %rbx - pop %rbp -.cfi_pop %rbp - ret -.cfi_endproc -.size SHA3_shake256_x4_inc_squeeze_avx512vl,.-SHA3_shake256_x4_inc_squeeze_avx512vl -___ - -if ($win64) { -my $context = "%r8"; -my $disp = "%r9"; - -$code.=<<___; -.extern __imp_RtlVirtualUnwind -.type keccak_se_handler,\@abi-omnipotent -.align 16 -keccak_se_handler: - push %rsi - push %rdi - push %rbx - push %rbp - push %r12 - push %r13 - push %r14 - push %r15 - pushfq - sub \$64, %rsp - - mov 120($context), %rax # context->Rax = original %rsp from xlate prologue - mov 248($context), %rbx # context->Rip - - mov 8($disp), %rsi # disp->ImageBase - mov 56($disp), %r11 # disp->HandlerData - - mov 0(%r11), %r10d # HandlerData[0]: body label (rva) - lea (%rsi,%r10), %r10 - cmp %r10, %rbx # Rip < body? - jb .Lkeccak_in_prologue - - mov 4(%r11), %r10d # HandlerData[1]: epilogue label (rva) - lea (%rsi,%r10), %r10 - cmp %r10, %rbx # Rip >= epilogue? - jae .Lkeccak_in_epilogue - - # In function body: - # HandlerData[2]: delta from context->Rsp(body) to original %rsp - # HandlerData[3]: offset of XMM6 save area from context->Rsp(body), -1 if none - # HandlerData[4]: number of saved non-volatiles in stack frame layout (2 or 6) - # HandlerData[5]: delta from context->Rsp(epilogue) to original %rsp - mov 152($context), %rdx # body rsp - mov 8(%r11), %r10d - lea (%rdx,%r10), %rax # original rsp - jmp .Lkeccak_restore_body_or_epilogue - -.Lkeccak_in_epilogue: - mov 152($context), %rdx # epilogue rsp - mov 20(%r11), %r10d - lea (%rdx,%r10), %rax # original rsp - -.Lkeccak_restore_body_or_epilogue: - mov 8(%rax), %rcx # xlate shadow save of original rdi - mov 16(%rax), %rsi # xlate shadow save of original rsi - mov %rax, 152($context) # context->Rsp = original rsp - mov %rsi, 168($context) # context->Rsi - mov %rcx, 176($context) # context->Rdi - - mov 16(%r11), %r10d # gpr save count - cmp \$6, %r10d - jne .Lkeccak_restore_two - - mov -24(%rax), %r12 - mov -32(%rax), %r13 - mov -40(%rax), %r14 - mov -48(%rax), %r15 - mov %r12, 216($context) # context->R12 - mov %r13, 224($context) # context->R13 - mov %r14, 232($context) # context->R14 - mov %r15, 240($context) # context->R15 - -.Lkeccak_restore_two: - mov -8(%rax), %rbp - mov -16(%rax), %rbx - mov %rbp, 160($context) # context->Rbp - mov %rbx, 144($context) # context->Rbx - - mov 12(%r11), %r10d # xmm save offset from body rsp - cmp \$-1, %r10d - je .Lkeccak_in_prologue - - lea (%rdx,%r10), %rsi # source = xmm save area - lea 512($context), %rdi # &context->Xmm6 - mov \$20, %ecx # 10 XMM * 2 qwords - .long 0xa548f3fc # cld; rep movsq - -.Lkeccak_in_prologue: - mov 8(%rax), %rcx - mov 16(%rax), %rdx - mov %rcx, 176($context) # context->Rdi - mov %rdx, 168($context) # context->Rsi - mov %rax, 152($context) # context->Rsp = original rsp - - mov 40($disp), %rdi # disp->ContextRecord - mov $context, %rsi - mov \$154, %ecx # sizeof(CONTEXT)/8 - .long 0xa548f3fc # cld; rep movsq - - mov $disp, %rsi - xor %rcx, %rcx # UNW_FLAG_NHANDLER - mov 8(%rsi), %rdx # disp->ImageBase - mov 0(%rsi), %r8 # disp->ControlPc - mov 16(%rsi), %r9 # disp->FunctionEntry - mov 40(%rsi), %r10 # disp->ContextRecord - lea 56(%rsi), %r11 # &disp->HandlerData - lea 24(%rsi), %r12 # &disp->EstablisherFrame - mov %r10, 32(%rsp) - mov %r11, 40(%rsp) - mov %r12, 48(%rsp) - mov %rcx, 56(%rsp) - call *__imp_RtlVirtualUnwind(%rip) - - mov \$1, %eax # ExceptionContinueSearch - add \$64, %rsp - popfq - pop %r15 - pop %r14 - pop %r13 - pop %r12 - pop %rbp - pop %rbx - pop %rdi - pop %rsi - ret -.size keccak_se_handler,.-keccak_se_handler - -.section .pdata -.align 4 - .rva .LSEH_begin_SHA3_shake128_x4_avx512vl - .rva .LSEH_end_SHA3_shake128_x4_avx512vl - .rva .LSEH_info_SHA3_shake128_x4_avx512vl - .rva .LSEH_begin_SHA3_shake128_x4_inc_absorb_avx512vl_internal - .rva .LSEH_end_SHA3_shake128_x4_inc_absorb_avx512vl_internal - .rva .LSEH_info_SHA3_shake128_x4_inc_absorb_avx512vl_internal - .rva .LSEH_begin_SHA3_shake128_x4_inc_absorb_avx512vl - .rva .LSEH_end_SHA3_shake128_x4_inc_absorb_avx512vl - .rva .LSEH_info_SHA3_shake128_x4_inc_absorb_avx512vl - .rva .LSEH_begin_SHA3_shake128_x4_inc_squeeze_avx512vl_internal - .rva .LSEH_end_SHA3_shake128_x4_inc_squeeze_avx512vl_internal - .rva .LSEH_info_SHA3_shake128_x4_inc_squeeze_avx512vl_internal - .rva .LSEH_begin_SHA3_shake128_x4_inc_squeeze_avx512vl - .rva .LSEH_end_SHA3_shake128_x4_inc_squeeze_avx512vl - .rva .LSEH_info_SHA3_shake128_x4_inc_squeeze_avx512vl - .rva .LSEH_begin_SHA3_shake256_x4_avx512vl - .rva .LSEH_end_SHA3_shake256_x4_avx512vl - .rva .LSEH_info_SHA3_shake256_x4_avx512vl - .rva .LSEH_begin_SHA3_shake256_x4_inc_absorb_avx512vl_internal - .rva .LSEH_end_SHA3_shake256_x4_inc_absorb_avx512vl_internal - .rva .LSEH_info_SHA3_shake256_x4_inc_absorb_avx512vl_internal - .rva .LSEH_begin_SHA3_shake256_x4_inc_absorb_avx512vl - .rva .LSEH_end_SHA3_shake256_x4_inc_absorb_avx512vl - .rva .LSEH_info_SHA3_shake256_x4_inc_absorb_avx512vl - .rva .LSEH_begin_SHA3_shake256_x4_inc_squeeze_avx512vl_internal - .rva .LSEH_end_SHA3_shake256_x4_inc_squeeze_avx512vl_internal - .rva .LSEH_info_SHA3_shake256_x4_inc_squeeze_avx512vl_internal - .rva .LSEH_begin_SHA3_shake256_x4_inc_squeeze_avx512vl - .rva .LSEH_end_SHA3_shake256_x4_inc_squeeze_avx512vl - .rva .LSEH_info_SHA3_shake256_x4_inc_squeeze_avx512vl - -.section .xdata -.align 8 -.LSEH_info_SHA3_shake128_x4_avx512vl: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake128_x4_body,.Lshake128_x4_epilogue - .long 1032,856,2,1032 -.LSEH_info_SHA3_shake128_x4_inc_absorb_avx512vl: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake128_absorb_body,.Lshake128_absorb_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake128_x4_inc_absorb_avx512vl_internal: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake128_absorb_body,.Lshake128_absorb_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake128_x4_inc_squeeze_avx512vl: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake128_squeeze_body,.Lshake128_squeeze_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake128_x4_inc_squeeze_avx512vl_internal: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake128_squeeze_body,.Lshake128_squeeze_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake256_x4_avx512vl: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake256_x4_body,.Lshake256_x4_epilogue - .long 1032,856,2,1032 -.LSEH_info_SHA3_shake256_x4_inc_absorb_avx512vl: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake256_absorb_body,.Lshake256_absorb_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake256_x4_inc_absorb_avx512vl_internal: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake256_absorb_body,.Lshake256_absorb_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake256_x4_inc_squeeze_avx512vl: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake256_squeeze_body,.Lshake256_squeeze_epilogue - .long 208,0,6,208 -.LSEH_info_SHA3_shake256_x4_inc_squeeze_avx512vl_internal: - .byte 9,0,0,0 - .rva keccak_se_handler - .rva .Lshake256_squeeze_body,.Lshake256_squeeze_epilogue - .long 208,0,6,208 -___ -} - -$code.=<<___; - -.section .rodata align=128 -.align 128 -.type iotas,\@object -iotas: - .quad 0x0000000000000001 - .quad 0x0000000000008082 - .quad 0x800000000000808a - .quad 0x8000000080008000 - .quad 0x000000000000808b - .quad 0x0000000080000001 - .quad 0x8000000080008081 - .quad 0x8000000000008009 - .quad 0x000000000000008a - .quad 0x0000000000000088 - .quad 0x0000000080008009 - .quad 0x000000008000000a - .quad 0x000000008000808b - .quad 0x800000000000008b - .quad 0x8000000000008089 - .quad 0x8000000000008003 - .quad 0x8000000000008002 - .quad 0x8000000000000080 - .quad 0x000000000000800a - .quad 0x800000008000000a - .quad 0x8000000080008081 - .quad 0x8000000000008080 - .quad 0x0000000080000001 - .quad 0x8000000080008008 -.size iotas,.-iotas - -.align 8 -byte_kmask_0_to_7: - .byte 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f - -.align 32 -shake_terminator_byte_x4: - .byte 0, 0, 0, 0, 0, 0, 0, 0x80 - .byte 0, 0, 0, 0, 0, 0, 0, 0x80 - .byte 0, 0, 0, 0, 0, 0, 0, 0x80 - .byte 0, 0, 0, 0, 0, 0, 0, 0x80 - -.align 8 - .byte 0, 0, 0, 0, 0, 0, 0, 0 -shake_msg_pad_x4: - .byte 0x1F, 0, 0, 0, 0, 0, 0, 0 - .byte 0x1F, 0, 0, 0, 0, 0, 0, 0 - .byte 0x1F, 0, 0, 0, 0, 0, 0, 0 - .byte 0x1F, 0, 0, 0, 0, 0, 0, 0 - -.asciz "Keccak-1600 absorb and squeeze for AVX512VL, CRYPTOGAMS by " -___ - -}}} else {{{ - -# When AVX512VL is not available, output stub functions -# The capable function returns 0, and the operation functions are not defined (will use C fallback) - -$code .= <<___; -.text - -.globl SHA3_avx512vl_capable -.type SHA3_avx512vl_capable,\@abi-omnipotent -SHA3_avx512vl_capable: - xor %eax, %eax - ret -.size SHA3_avx512vl_capable, .-SHA3_avx512vl_capable - -.globl SHA3_shake128_x4_inc_absorb_avx512vl -.globl SHA3_shake256_x4_inc_absorb_avx512vl -.globl SHA3_shake128_x4_inc_finalize_avx512vl -.globl SHA3_shake256_x4_inc_finalize_avx512vl -.globl SHA3_shake128_x4_inc_squeeze_avx512vl -.globl SHA3_shake256_x4_inc_squeeze_avx512vl -.globl SHA3_shake128_x4_avx512vl -.globl SHA3_shake256_x4_avx512vl -.type SHA3_shake128_x4_inc_absorb_avx512vl,\@abi-omnipotent -SHA3_shake128_x4_inc_absorb_avx512vl: -SHA3_shake256_x4_inc_absorb_avx512vl: -SHA3_shake128_x4_inc_finalize_avx512vl: -SHA3_shake256_x4_inc_finalize_avx512vl: -SHA3_shake128_x4_inc_squeeze_avx512vl: -SHA3_shake256_x4_inc_squeeze_avx512vl: -SHA3_shake128_x4_avx512vl: -SHA3_shake256_x4_avx512vl: - .byte 0x0f,0x0b # ud2 - ret -.size SHA3_shake128_x4_inc_absorb_avx512vl, .-SHA3_shake128_x4_inc_absorb_avx512vl -___ -}}} - -print $code; -close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/sha/build.info b/crypto/sha/build.info index 88e8b9cc5e..457ac8d06a 100644 --- a/crypto/sha/build.info +++ b/crypto/sha/build.info @@ -65,7 +65,7 @@ ENDIF $KECCAK1600ASM=keccak1600.c IF[{- !$disabled{asm} -}] $KECCAK1600ASM_x86= - $KECCAK1600ASM_x86_64=keccak1600-x86_64.s keccak1600x4-avx512vl.s sha3_x4_avx512vl.c + $KECCAK1600ASM_x86_64=keccak1600-x86_64.s $KECCAK1600ASM_s390x=keccak1600-s390x.S @@ -198,8 +198,4 @@ GENERATE[keccak1600-avx512vl.S]=asm/keccak1600-avx512vl.pl GENERATE[keccak1600-mmx.S]=asm/keccak1600-mmx.pl GENERATE[keccak1600p8-ppc.S]=asm/keccak1600p8-ppc.pl -# keccak1600x4-avx512vl.s supports multi-squeeze -# Currently only used in ML-DSA on x86_64 with AVX-512VL support -GENERATE[keccak1600x4-avx512vl.s]=asm/keccak1600x4-avx512vl.pl - GENERATE[sha1-thumb.S]=asm/sha1-thumb.pl diff --git a/crypto/sha/keccak1600.c b/crypto/sha/keccak1600.c index 26d75f1b8e..59e688ce43 100644 --- a/crypto/sha/keccak1600.c +++ b/crypto/sha/keccak1600.c @@ -111,7 +111,7 @@ static const uint64_t iotas[] = { /* * This is straightforward or "maximum clarity" implementation aiming * to resemble section 3.2 of the FIPS PUB 202 "SHA-3 Standard: - * Permutation-Based Hash and Extendable-Output Functions" as much as + * Permutation-Based Hash and Extendible-Output Functions" as much as * possible. With one caveat. Because of the way C stores matrices, * references to A[x,y] in the specification are presented as A[y][x]. * Implementation unrolls inner x-loops so that modulo 5 operations are diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c index 8cbbfdbb30..eab9487622 100644 --- a/crypto/sha/sha256.c +++ b/crypto/sha/sha256.c @@ -164,7 +164,7 @@ static const SHA_LONG K256[64] = { }; #ifndef PEDANTIC -#if defined(__GNUC__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) #if defined(__riscv_zknh) #define Sigma0(x) ({ MD32_REG_T ret; \ asm ("sha256sum0 %0, %1" \ diff --git a/crypto/sha/sha3_x4_avx512vl.c b/crypto/sha/sha3_x4_avx512vl.c deleted file mode 100644 index 86a8282814..0000000000 --- a/crypto/sha/sha3_x4_avx512vl.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2026 Intel Corporation. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * SHAKE x4 multi-buffer implementation for AVX-512VL - * - * This file provides incremental API wrappers around the AVX-512VL - * assembly implementations for processing 4 SHAKE instances in parallel. - * - * Callers should check SHA3_avx512vl_capable() before calling. - */ - -#include "internal/sha3.h" -#include -#include - -#if defined(KECCAK1600_ASM) \ - && (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \ - && !defined(OPENSSL_NO_ASM) - -/* External assembly function declarations */ -extern void SHA3_shake128_x4_inc_absorb_avx512vl( - uint64_t *state, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -extern void SHA3_shake256_x4_inc_absorb_avx512vl( - uint64_t *state, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -extern void SHA3_shake128_x4_inc_finalize_avx512vl(uint64_t *state); -extern void SHA3_shake256_x4_inc_finalize_avx512vl(uint64_t *state); - -extern void SHA3_shake128_x4_inc_squeeze_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - uint64_t *state); - -extern void SHA3_shake256_x4_inc_squeeze_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - uint64_t *state); - -/* One-shot assembly function declarations */ -extern void SHA3_shake128_x4_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -extern void SHA3_shake256_x4_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -/* - * SHAKE-128 x4 Implementation - */ - -void ossl_sha3_shake128_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - memset(ctx->A, 0, sizeof(ctx->A)); - ctx->rate = SHA3_BLOCKSIZE(128); - ctx->finalized = 0; -} - -void ossl_sha3_shake128_x4_inc_absorb_avx512vl( - KECCAK1600_X4_AVX512VL_CTX *ctx, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen) -{ - if (ctx->finalized) { - /* Error: cannot absorb after finalize */ - return; - } - - SHA3_shake128_x4_inc_absorb_avx512vl( - ctx->A, in0, in1, in2, in3, inlen); -} - -void ossl_sha3_shake128_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - OPENSSL_cleanse(ctx, sizeof(*ctx)); -} - -static void ossl_sha3_shake128_x4_inc_finalize_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - if (ctx->finalized) { - return; /* Already finalized */ - } - - SHA3_shake128_x4_inc_finalize_avx512vl(ctx->A); - ctx->finalized = 1; -} - -void ossl_sha3_shake128_x4_inc_squeeze_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - if (!ctx->finalized) { - /* Auto-finalize on first squeeze */ - ossl_sha3_shake128_x4_inc_finalize_avx512vl(ctx); - } - - SHA3_shake128_x4_inc_squeeze_avx512vl( - out0, out1, out2, out3, outlen, ctx->A); -} - -/* - * SHAKE-256 x4 Implementation - */ - -void ossl_sha3_shake256_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - memset(ctx->A, 0, sizeof(ctx->A)); - ctx->rate = SHA3_BLOCKSIZE(256); - ctx->finalized = 0; -} - -void ossl_sha3_shake256_x4_inc_absorb_avx512vl( - KECCAK1600_X4_AVX512VL_CTX *ctx, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen) -{ - if (ctx->finalized) { - /* Error: cannot absorb after finalize */ - return; - } - - SHA3_shake256_x4_inc_absorb_avx512vl( - ctx->A, in0, in1, in2, in3, inlen); -} - -void ossl_sha3_shake256_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - OPENSSL_cleanse(ctx, sizeof(*ctx)); -} - -static void ossl_sha3_shake256_x4_inc_finalize_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - if (ctx->finalized) { - return; /* Already finalized */ - } - - SHA3_shake256_x4_inc_finalize_avx512vl(ctx->A); - ctx->finalized = 1; -} - -void ossl_sha3_shake256_x4_inc_squeeze_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - KECCAK1600_X4_AVX512VL_CTX *ctx) -{ - if (!ctx->finalized) { - /* Auto-finalize on first squeeze */ - ossl_sha3_shake256_x4_inc_finalize_avx512vl(ctx); - } - - SHA3_shake256_x4_inc_squeeze_avx512vl( - out0, out1, out2, out3, outlen, ctx->A); -} - -/* - * Single-call wrapper APIs - */ - -void ossl_sha3_shake128_x4_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen) -{ - SHA3_shake128_x4_avx512vl(out0, out1, out2, out3, outlen, - in0, in1, in2, in3, inlen); -} - -void ossl_sha3_shake256_x4_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen) -{ - SHA3_shake256_x4_avx512vl(out0, out1, out2, out3, outlen, - in0, in1, in2, in3, inlen); -} - -#endif /* KECCAK1600_ASM && x86_64 && !OPENSSL_NO_ASM */ diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c index 9ba32f2926..6ccc0070e0 100644 --- a/crypto/sha/sha512.c +++ b/crypto/sha/sha512.c @@ -343,7 +343,7 @@ static const SHA_LONG64 K512[80] = { }; #ifndef PEDANTIC -#if defined(__GNUC__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) #if defined(__x86_64) || defined(__x86_64__) #define ROTR(a, n) ({ SHA_LONG64 ret; \ asm ("rorq %1,%0" \ diff --git a/crypto/sha/sha_loongarch.c b/crypto/sha/sha_loongarch.c index 1576e6f493..55ececfe04 100644 --- a/crypto/sha/sha_loongarch.c +++ b/crypto/sha/sha_loongarch.c @@ -16,9 +16,9 @@ void sha256_block_data_order_la64v100(void *ctx, const void *in, size_t num); void sha256_block_data_order_lsx(void *ctx, const void *in, size_t num); -void sha256_block_data_order(void *ctx, const void *in, size_t num); +void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); -void sha256_block_data_order(void *ctx, const void *in, size_t num) +void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num) { if (OPENSSL_loongarch_hwcap_P & LOONGARCH_HWCAP_LSX) { sha256_block_data_order_lsx(ctx, in, num); @@ -29,9 +29,9 @@ void sha256_block_data_order(void *ctx, const void *in, size_t num) void sha512_block_data_order_la64v100(void *ctx, const void *in, size_t num); void sha512_block_data_order_lsx(void *ctx, const void *in, size_t num); -void sha512_block_data_order(void *ctx, const void *in, size_t num); +void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); -void sha512_block_data_order(void *ctx, const void *in, size_t num) +void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num) { if (OPENSSL_loongarch_hwcap_P & LOONGARCH_HWCAP_LSX) { sha512_block_data_order_lsx(ctx, in, num); diff --git a/crypto/sha/sha_riscv.c b/crypto/sha/sha_riscv.c index 100ecacdde..28248fd5ac 100644 --- a/crypto/sha/sha_riscv.c +++ b/crypto/sha/sha_riscv.c @@ -18,9 +18,9 @@ void sha256_block_data_order_zvkb_zvknha_or_zvknhb(void *ctx, const void *in, size_t num); void sha256_block_data_order_zbb(void *ctx, const void *in, size_t num); void sha256_block_data_order_riscv64(void *ctx, const void *in, size_t num); -void sha256_block_data_order(void *ctx, const void *in, size_t num); +void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); -void sha256_block_data_order(void *ctx, const void *in, size_t num) +void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num) { if (RISCV_HAS_ZVKB() && (RISCV_HAS_ZVKNHA() || RISCV_HAS_ZVKNHB()) && riscv_vlen() >= 128) { sha256_block_data_order_zvkb_zvknha_or_zvknhb(ctx, in, num); @@ -34,9 +34,9 @@ void sha256_block_data_order(void *ctx, const void *in, size_t num) void sha512_block_data_order_zvkb_zvknhb(void *ctx, const void *in, size_t num); void sha512_block_data_order_zbb(void *ctx, const void *in, size_t num); void sha512_block_data_order_c(void *ctx, const void *in, size_t num); -void sha512_block_data_order(void *ctx, const void *in, size_t num); +void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); -void sha512_block_data_order(void *ctx, const void *in, size_t num) +void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num) { if (RISCV_HAS_ZVKB_AND_ZVKNHB() && riscv_vlen() >= 128) { sha512_block_data_order_zvkb_zvknhb(ctx, in, num); diff --git a/crypto/sleep.c b/crypto/sleep.c index 3d8be852c9..9273995be6 100644 --- a/crypto/sleep.c +++ b/crypto/sleep.c @@ -67,6 +67,7 @@ static void ossl_sleep_millis(uint64_t millis) #endif #elif defined(_WIN32) && !defined(OPENSSL_SYS_UEFI) +#include static void ossl_sleep_millis(uint64_t millis) { diff --git a/crypto/slh_dsa/slh_fors.c b/crypto/slh_dsa/slh_fors.c index 10335cc5df..78587589db 100644 --- a/crypto/slh_dsa/slh_fors.c +++ b/crypto/slh_dsa/slh_fors.c @@ -156,7 +156,7 @@ int ossl_slh_fors_sign(SLH_DSA_HASH_CTX *ctx, const uint8_t *md, /* * Give each of the k trees a unique range at each level. * e.g. If we have 4096 leaf nodes (2^a = 2^12) for each tree - * i will use indexes from 4096 * i + (0..4095) for its bottom level. + * tree i will use indexes from 4096 * i + (0..4095) for its bottom level. * For the next level up from the bottom there would be 2048 nodes * (so tree i uses indexes 2048 * i + (0...2047) for this level) */ diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c index 6e787f5d28..a1cbd88c2d 100644 --- a/crypto/sm2/sm2_crypt.c +++ b/crypto/sm2/sm2_crypt.c @@ -78,7 +78,7 @@ int ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size, return 0; } - *pt_size = ASN1_STRING_length_ex(sm2_ctext->C2); + *pt_size = ASN1_STRING_length(sm2_ctext->C2); SM2_Ciphertext_free(sm2_ctext); return 1; @@ -309,7 +309,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, uint8_t *msg_mask = NULL; const uint8_t *C2 = NULL; const uint8_t *C3 = NULL; - size_t c3_len, msg_len = 0; + int msg_len = 0; EVP_MD_CTX *hash = NULL; OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); const char *propq = ossl_ec_key_get0_propq(key); @@ -326,18 +326,14 @@ int ossl_sm2_decrypt(const EC_KEY *key, goto done; } - msg_len = ASN1_STRING_length_ex(sm2_ctext->C2); - if (msg_len > INT_MAX) - goto done; - - c3_len = ASN1_STRING_length_ex(sm2_ctext->C3); - if (c3_len > INT_MAX || c3_len != (size_t)hash_size) { + if (ASN1_STRING_length(sm2_ctext->C3) != hash_size) { ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); goto done; } C2 = ASN1_STRING_get0_data(sm2_ctext->C2); C3 = ASN1_STRING_get0_data(sm2_ctext->C3); + msg_len = ASN1_STRING_length(sm2_ctext->C2); if (*ptext_len < (size_t)msg_len) { ERR_raise(ERR_LIB_SM2, SM2_R_BUFFER_TOO_SMALL); goto done; @@ -382,7 +378,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, if (BN_bn2binpad(x2, x2y2, field_size) < 0 || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0 - || !ossl_ecdh_kdf_X9_63(msg_mask, (int)msg_len, x2y2, 2 * field_size, + || !ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, digest, libctx, propq)) { ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); goto done; @@ -393,7 +389,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, goto done; } - for (i = 0; i != (int)msg_len; ++i) + for (i = 0; i != msg_len; ++i) ptext_buf[i] = C2[i] ^ msg_mask[i]; hash = EVP_MD_CTX_new(); @@ -404,7 +400,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, if (!EVP_DigestInit(hash, digest) || !EVP_DigestUpdate(hash, x2y2, field_size) - || !EVP_DigestUpdate(hash, ptext_buf, (int)msg_len) + || !EVP_DigestUpdate(hash, ptext_buf, msg_len) || !EVP_DigestUpdate(hash, x2y2 + field_size, field_size) || !EVP_DigestFinal(hash, computed_C3, NULL)) { ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); @@ -417,7 +413,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, } rc = 1; - *ptext_len = (int)msg_len; + *ptext_len = msg_len; done: if (rc == 0) diff --git a/crypto/sm3/asm/sm3-armv8.pl b/crypto/sm3/asm/sm3-armv8.pl index 6c51df28f8..e0c33ecb95 100644 --- a/crypto/sm3/asm/sm3-armv8.pl +++ b/crypto/sm3/asm/sm3-armv8.pl @@ -51,7 +51,7 @@ $code.=<<___; ___ } -# A round of compression function +# A round of compresson function # Input: # ab - choose instruction among sm3tt1a, sm3tt1b, sm3tt2a, sm3tt2b # vstate0 - vstate1, store digest status(A - H) diff --git a/crypto/sm3/asm/sm3-x86_64.pl b/crypto/sm3/asm/sm3-x86_64.pl index 2f6ddf5616..d3c9d0541a 100755 --- a/crypto/sm3/asm/sm3-x86_64.pl +++ b/crypto/sm3/asm/sm3-x86_64.pl @@ -35,8 +35,8 @@ if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` } if (!$avx2_sm3_ni && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && - `nasm -v 2>&1` =~ /NASM version ([2-9])\.([0-9]+)(?:\.([0-9]+))?/) { - my ($major, $minor, $patch) = ($1, $2, defined($3) ? $3 : 0); + `nasm -v 2>&1` =~ /NASM version ([2-9])\.([0-9]+)\.([0-9]+)/) { + my ($major, $minor, $patch) = ($1, $2, $3); $avx2_sm3_ni = ($major > 2) || ($major == 2 && $minor > 10); # minimal avx2 supported version, binary translation for SM3 instructions (sub sm3op) is used $avx2_sm3_ni_native = ($major > 2) || ($major == 2 && $minor > 16) || ($major == 2 && $minor == 16 && $patch >= 2); # support added at NASM 2.16.02 } diff --git a/crypto/sm3/sm3_local.h b/crypto/sm3/sm3_local.h index 41639b3c95..6cb8dca61b 100644 --- a/crypto/sm3/sm3_local.h +++ b/crypto/sm3/sm3_local.h @@ -77,7 +77,7 @@ void ossl_sm3_transform(SM3_CTX *c, const unsigned char *data); /* clang-format on */ #ifndef PEDANTIC -#if defined(__GNUC__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) #if defined(__riscv_zksh) #define P0(x) ({ MD32_REG_T ret; \ asm ("sm3p0 %0, %1" \ diff --git a/crypto/sm4/asm/sm4-x86_64.pl b/crypto/sm4/asm/sm4-x86_64.pl index f5b485968e..9fc40fb96a 100644 --- a/crypto/sm4/asm/sm4-x86_64.pl +++ b/crypto/sm4/asm/sm4-x86_64.pl @@ -35,8 +35,8 @@ if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` } if (!$avx2_sm4_ni && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && - `nasm -v 2>&1` =~ /NASM version ([2-9])\.([0-9]+)(?:\.([0-9]+))?/) { - my ($major, $minor, $patch) = ($1, $2, defined($3) ? $3 : 0); + `nasm -v 2>&1` =~ /NASM version ([2-9])\.([0-9]+)\.([0-9]+)/) { + my ($major, $minor, $patch) = ($1, $2, $3); $avx2_sm4_ni = ($major > 2) || ($major == 2 && $minor > 10); # minimal avx2 supported version, binary translation for SM4 instructions (sub sm4op) is used $avx2_sm4_ni_native = ($major > 2) || ($major == 2 && $minor > 16) || ($major == 2 && $minor == 16 && $patch >= 2); # support added at NASM 2.16.02 } diff --git a/crypto/sparcv9cap.c b/crypto/sparcv9cap.c index cea44ada9b..c9cc2b9575 100644 --- a/crypto/sparcv9cap.c +++ b/crypto/sparcv9cap.c @@ -71,7 +71,7 @@ static void common_handler(int sig) } #if defined(__sun) && defined(__SVR4) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 extern unsigned int getisax(unsigned int vec[], unsigned int sz) __attribute__((weak)); #elif defined(__SUNPRO_C) #pragma weak getisax diff --git a/crypto/ssl_err.c b/crypto/ssl_err.c index 9766b64314..0dca54bb1d 100644 --- a/crypto/ssl_err.c +++ b/crypto/ssl_err.c @@ -426,6 +426,36 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "srtp protection profile list too long" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE), "srtp unknown protection profile" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH), + "tls ext invalid max fragment length" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_EXT_INVALID_SERVERNAME), + "tls ext invalid servername" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE), + "tls ext invalid servername type" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_SESSION_ID_TOO_LONG), + "tls session id too long" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_BAD_CERTIFICATE), + "tls alert bad certificate" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_BAD_RECORD_MAC), + "tls alert bad record mac" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED), + "tls alert certificate expired" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_CERTIFICATE_REVOKED), + "tls alert certificate revoked" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN), + "tls alert certificate unknown" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE), + "tls alert decompression failure" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_HANDSHAKE_FAILURE), + "tls alert handshake failure" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_ILLEGAL_PARAMETER), + "tls alert illegal parameter" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_NO_CERTIFICATE), + "tls alert no certificate" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE), + "tls alert unexpected message" }, + { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE), + "tls alert unsupported certificate" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_COMMAND_SECTION_EMPTY), "ssl command section empty" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_COMMAND_SECTION_NOT_FOUND), @@ -504,40 +534,10 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "tlsv1 unrecognized name" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNSUPPORTED_EXTENSION), "tlsv1 unsupported extension" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_BAD_CERTIFICATE), - "tls alert bad certificate" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_BAD_RECORD_MAC), - "tls alert bad record mac" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED), - "tls alert certificate expired" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_CERTIFICATE_REVOKED), - "tls alert certificate revoked" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN), - "tls alert certificate unknown" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE), - "tls alert decompression failure" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_HANDSHAKE_FAILURE), - "tls alert handshake failure" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_ILLEGAL_PARAMETER), - "tls alert illegal parameter" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_NO_CERTIFICATE), - "tls alert no certificate" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE), - "tls alert unexpected message" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE), - "tls alert unsupported certificate" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH), - "tls ext invalid max fragment length" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_EXT_INVALID_SERVERNAME), - "tls ext invalid servername" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE), - "tls ext invalid servername type" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL), "tls illegal exporter label" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST), "tls invalid ecpointformat list" }, - { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_SESSION_ID_TOO_LONG), - "tls session id too long" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TOO_MANY_KEY_UPDATES), "too many key updates" }, { ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TOO_MANY_WARN_ALERTS), diff --git a/crypto/sslerr.h b/crypto/sslerr.h index f2936b7d99..968f27b00a 100644 --- a/crypto/sslerr.h +++ b/crypto/sslerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index 995024d5c9..f668d4bbbc 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -104,7 +104,6 @@ struct ossl_store_loader_st { const char *propdef; const char *description; - int no_store; CRYPTO_REF_COUNT refcnt; OSSL_FUNC_store_open_fn *p_open; diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c index 1d54d89978..04c8a8d5f9 100644 --- a/crypto/store/store_meth.c +++ b/crypto/store/store_meth.c @@ -16,20 +16,17 @@ #include "store_local.h" #include "crypto/context.h" -static int up_ref_loader(void *method) +int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader) { - OSSL_STORE_LOADER *loader = (OSSL_STORE_LOADER *)method; int ref = 0; if (loader->prov != NULL) - return CRYPTO_UP_REF(&loader->refcnt, &ref); + CRYPTO_UP_REF(&loader->refcnt, &ref); return 1; } -static void free_loader(void *method) +void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) { - OSSL_STORE_LOADER *loader = (OSSL_STORE_LOADER *)method; - if (loader != NULL && loader->prov != NULL) { int i; @@ -42,27 +39,6 @@ static void free_loader(void *method) OPENSSL_free(loader); } -int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader) -{ -#ifdef OPENSSL_NO_CACHED_FETCH - return up_ref_loader(loader); -#else - if (loader->no_store != 0) - return up_ref_loader(loader); - return 1; -#endif -} - -void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) -{ -#ifdef OPENSSL_NO_CACHED_FETCH - free_loader(loader); -#else - if (loader != NULL && (loader->no_store != 0)) - free_loader(loader); -#endif -} - /* * OSSL_STORE_LOADER_new() expects the scheme as a constant string, * which we currently don't have, so we need an alternative allocator. @@ -85,6 +61,16 @@ static OSSL_STORE_LOADER *new_loader(OSSL_PROVIDER *prov) return loader; } +static int up_ref_loader(void *method) +{ + return OSSL_STORE_LOADER_up_ref(method); +} + +static void free_loader(void *method) +{ + OSSL_STORE_LOADER_free(method); +} + /* Data to be passed through ossl_method_construct() */ struct loader_data_st { OSSL_LIB_CTX *libctx; @@ -190,7 +176,7 @@ static int put_loader_in_store(void *store, void *method, } static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store) + OSSL_PROVIDER *prov) { OSSL_STORE_LOADER *loader = NULL; const OSSL_DISPATCH *fns = algodef->implementation; @@ -200,7 +186,6 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, loader->scheme_id = scheme_id; loader->propdef = algodef->property_definition; loader->description = algodef->algorithm_description; - loader->no_store = no_store; for (; fns->function_id != 0; fns++) { switch (fns->function_id) { @@ -252,7 +237,7 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, || loader->p_eof == NULL || loader->p_close == NULL) { /* Only set_ctx_params is optional */ - free_loader(loader); + OSSL_STORE_LOADER_free(loader); ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE); return NULL; } @@ -265,7 +250,7 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, * then call loader_from_algorithm() with that identity number. */ static void *construct_loader(const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, void *data, int no_store) + OSSL_PROVIDER *prov, void *data) { /* * This function is only called if get_loader_from_store() returned @@ -281,7 +266,7 @@ static void *construct_loader(const OSSL_ALGORITHM *algodef, void *method = NULL; if (id != 0) - method = loader_from_algorithm(id, algodef, prov, no_store); + method = loader_from_algorithm(id, algodef, prov); /* * Flag to indicate that there was actual construction errors. This @@ -297,7 +282,7 @@ static void *construct_loader(const OSSL_ALGORITHM *algodef, /* Intermediary function to avoid ugly casts, used below */ static void destruct_loader(void *method, void *data) { - free_loader(method); + OSSL_STORE_LOADER_free(method); } /* Fetching support. Can fetch by numeric identity or by scheme */ @@ -353,19 +338,8 @@ inner_loader_fetch(struct loader_data_st *methdata, */ if (id == 0) id = ossl_namemap_name2num(namemap, scheme); - if (id != 0 && methdata->tmp_store == NULL) { - ossl_method_store_cache_set(store, prov, id, propq, method, - up_ref_loader, free_loader); - } else { - /* - * Like with EVP methods, if the provider requests no caching we need - * to take an extra refcount here so that the tmp_stored loader - * lives beyond the freeing of that tmp_store - */ -#ifndef OPENSSL_NO_CACHED_FETCH - OSSL_STORE_LOADER_up_ref((OSSL_STORE_LOADER *)method); -#endif - } + ossl_method_store_cache_set(store, prov, id, propq, method, + up_ref_loader, free_loader); } /* diff --git a/crypto/thread/arch/thread_win.c b/crypto/thread/arch/thread_win.c index 1026ed3de3..b26a1d917a 100644 --- a/crypto/thread/arch/thread_win.c +++ b/crypto/thread/arch/thread_win.c @@ -7,11 +7,11 @@ * https://www.openssl.org/source/license.html */ -#include "internal/thread_arch.h" -#include "internal/e_os.h" +#include #if defined(OPENSSL_THREADS_WINNT) #include +#include static unsigned __stdcall thread_start_thunk(LPVOID vthread) { diff --git a/crypto/threads_win.c b/crypto/threads_win.c index d777010cd8..4fedf24e90 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -7,13 +7,14 @@ * https://www.openssl.org/source/license.html */ -#include "internal/e_os.h" - +#if defined(_WIN32) +#include #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 #define USE_RWLOCK #endif - +#endif #include + #include #include #include "internal/common.h" @@ -442,11 +443,15 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) /* Don't set error, to avoid recursion blowup. */ return NULL; +#if !defined(_WIN32_WCE) /* 0x400 is the spin count value suggested in the documentation */ if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) { OPENSSL_free(lock); return NULL; } +#else + InitializeCriticalSection(lock); +#endif #endif return lock; @@ -527,20 +532,6 @@ int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); if (result == ONCE_UNINITED) { init(); - /* - * On weakly ordered systems, it may happen that the write to *lock - * below completes prior to some writes in whatever the init() - * callback routine above may do. In this case, other threads - * entering here may see unsynchronized data in whatever the init - * routine initializes, leading to erroneous behavior. - * - * We should use InitOnceExecuteOnce here to implement this, but - * doing so requires that we modify the definition of the - * CRYPTO_ONCE type, which is an ABI breakage. So instead - * just insert a memory barrier here to ensure that any pending - * writes are flushed to memory prior to setting ONCE_DONE below - */ - MemoryBarrier(); *lock = ONCE_DONE; return 1; } diff --git a/crypto/ts/ts_asn1.c b/crypto/ts/ts_asn1.c index 56d41df554..b44002ef2f 100644 --- a/crypto/ts/ts_asn1.c +++ b/crypto/ts/ts_asn1.c @@ -208,7 +208,6 @@ TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token) ASN1_TYPE *tst_info_wrapper; ASN1_OCTET_STRING *tst_info_der; const unsigned char *p; - size_t len; if (!PKCS7_type_is_signed(token)) { ERR_raise(ERR_LIB_TS, TS_R_BAD_PKCS7_TYPE); @@ -231,10 +230,5 @@ TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token) } tst_info_der = tst_info_wrapper->value.octet_string; p = ASN1_STRING_get0_data(tst_info_der); - len = ASN1_STRING_length_ex(tst_info_der); - if (len > INT_MAX) { - ERR_raise(ERR_LIB_TS, TS_R_BAD_TYPE); - return NULL; - } - return d2i_TS_TST_INFO(NULL, &p, (int)len); + return d2i_TS_TST_INFO(NULL, &p, ASN1_STRING_length(tst_info_der)); } diff --git a/crypto/ts/ts_lib.c b/crypto/ts/ts_lib.c index 26b3994ccb..8b46fb4744 100644 --- a/crypto/ts/ts_lib.c +++ b/crypto/ts/ts_lib.c @@ -86,7 +86,7 @@ int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *a) BIO_printf(bio, "Message data:\n"); msg = a->hashed_msg; BIO_dump_indent(bio, (const char *)ASN1_STRING_get0_data(msg), - (int)ASN1_STRING_length_ex(msg), 4); + ASN1_STRING_length(msg), 4); return 1; } diff --git a/crypto/ts/ts_rsp_sign.c b/crypto/ts/ts_rsp_sign.c index e9151f750e..1421275fd9 100644 --- a/crypto/ts/ts_rsp_sign.c +++ b/crypto/ts/ts_rsp_sign.c @@ -298,7 +298,7 @@ int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, } if (text) { if ((utf8_text = ASN1_UTF8STRING_new()) == NULL - || !ASN1_STRING_set_string(utf8_text, text)) { + || !ASN1_STRING_set(utf8_text, text, (int)strlen(text))) { ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); goto err; } @@ -487,7 +487,7 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx) return 0; } digest = msg_imprint->hashed_msg; - if (ASN1_STRING_length_ex(digest) != (size_t)md_size) { + if (ASN1_STRING_length(digest) != md_size) { TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, "Bad message digest."); TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT); @@ -645,7 +645,7 @@ static int ossl_ess_add1_signing_cert(PKCS7_SIGNER_INFO *si, p = pp; i2d_ESS_SIGNING_CERT(sc, &p); - if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set_data(seq, pp, len)) { + if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { ASN1_STRING_free(seq); OPENSSL_free(pp); return 0; @@ -676,7 +676,7 @@ static int ossl_ess_add1_signing_cert_v2(PKCS7_SIGNER_INFO *si, p = pp; i2d_ESS_SIGNING_CERT_V2(sc, &p); - if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set_data(seq, pp, len)) { + if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { ASN1_STRING_free(seq); OPENSSL_free(pp); return 0; diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index 1b45243ca8..1dc70c125b 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -207,32 +207,24 @@ static ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const PKCS7_SIGNER_INFO *si) { const ASN1_TYPE *attr; const unsigned char *p; - size_t len; attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); if (attr == NULL || attr->type != V_ASN1_SEQUENCE) return NULL; p = ASN1_STRING_get0_data(attr->value.sequence); - len = ASN1_STRING_length_ex(attr->value.sequence); - if (len > INT_MAX) - return NULL; - return d2i_ESS_SIGNING_CERT(NULL, &p, (int)len); + return d2i_ESS_SIGNING_CERT(NULL, &p, ASN1_STRING_length(attr->value.sequence)); } static ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si) { const ASN1_TYPE *attr; const unsigned char *p; - size_t len; attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); if (attr == NULL || attr->type != V_ASN1_SEQUENCE) return NULL; p = ASN1_STRING_get0_data(attr->value.sequence); - len = ASN1_STRING_length_ex(attr->value.sequence); - if (len > INT_MAX) - return NULL; - return d2i_ESS_SIGNING_CERT_V2(NULL, &p, (int)len); + return d2i_ESS_SIGNING_CERT_V2(NULL, &p, ASN1_STRING_length(attr->value.sequence)); } static int ts_check_signing_certs(const PKCS7_SIGNER_INFO *si, @@ -490,7 +482,6 @@ static int ts_check_imprints(X509_ALGOR *algor_a, TS_MSG_IMPRINT *b = tst_info->msg_imprint; X509_ALGOR *algor_b = b->hash_algo; int ret = 0; - size_t len; if (algor_a) { if (OBJ_cmp(algor_a->algorithm, algor_b->algorithm)) @@ -504,11 +495,7 @@ static int ts_check_imprints(X509_ALGOR *algor_a, goto err; } - len = ASN1_STRING_length_ex(b->hashed_msg); - if (len > INT_MAX) - goto err; - - ret = len_a == (unsigned)len && memcmp(imprint_a, ASN1_STRING_get0_data(b->hashed_msg), len) == 0; + ret = len_a == (unsigned)ASN1_STRING_length(b->hashed_msg) && memcmp(imprint_a, ASN1_STRING_get0_data(b->hashed_msg), len_a) == 0; err: if (!ret) ERR_raise(ERR_LIB_TS, TS_R_MESSAGE_IMPRINT_MISMATCH); diff --git a/crypto/ts/ts_verify_ctx.c b/crypto/ts/ts_verify_ctx.c index 76835866d7..ec9993ed9f 100644 --- a/crypto/ts/ts_verify_ctx.c +++ b/crypto/ts/ts_verify_ctx.c @@ -142,7 +142,6 @@ TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx) X509_ALGOR *md_alg; ASN1_OCTET_STRING *msg; const ASN1_INTEGER *nonce; - size_t tmp; OPENSSL_assert(req != NULL); if (ret) @@ -163,11 +162,8 @@ TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx) if ((ret->md_alg = X509_ALGOR_dup(md_alg)) == NULL) goto err; msg = imprint->hashed_msg; - tmp = ASN1_STRING_length_ex(msg); - if (tmp > INT_MAX) - goto err; - ret->imprint_len = (unsigned int)tmp; - if (ret->imprint_len == 0) + ret->imprint_len = ASN1_STRING_length(msg); + if (ret->imprint_len <= 0) goto err; if ((ret->imprint = OPENSSL_malloc(ret->imprint_len)) == NULL) goto err; diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c index 5b97cc6448..1da5369287 100644 --- a/crypto/ui/ui_openssl.c +++ b/crypto/ui/ui_openssl.c @@ -60,8 +60,11 @@ #endif #ifdef WIN_CONSOLE_BUG +#include +#ifndef OPENSSL_SYS_WINCE #include #endif +#endif /* * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS, @@ -163,7 +166,7 @@ static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this * structures? */ static long status; static unsigned short channel = 0; -#elif defined(_WIN32) +#elif defined(_WIN32) && !defined(_WIN32_WCE) static DWORD tty_orig, tty_new; #else #if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__) @@ -174,10 +177,12 @@ static FILE *tty_in, *tty_out; static int is_a_tty; /* Declare static functions */ +#if !defined(OPENSSL_SYS_WINCE) static int read_till_nl(FILE *); static void recsig(int); static void pushsig(void); static void popsig(void); +#endif #if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) static int noecho_fgets(char *buf, int size, FILE *tty); #endif @@ -251,6 +256,7 @@ static int read_string(UI *ui, UI_STRING *uis) return 1; } +#if !defined(OPENSSL_SYS_WINCE) /* Internal functions to read a string without echoing */ static int read_till_nl(FILE *in) { @@ -265,6 +271,7 @@ static int read_till_nl(FILE *in) } static volatile sig_atomic_t intr_signal; +#endif static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) { @@ -272,6 +279,7 @@ static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) int ok; char result[BUFSIZ]; int maxsize = BUFSIZ - 1; +#if !defined(OPENSSL_SYS_WINCE) char *p = NULL; int echo_eol = !echo; @@ -351,6 +359,9 @@ error: if (ps >= 1) popsig(); +#else + ok = 1; +#endif OPENSSL_cleanse(result, BUFSIZ); return ok; @@ -366,7 +377,7 @@ static int open_console(UI *ui) #if defined(OPENSSL_SYS_VXWORKS) tty_in = stdin; tty_out = stderr; -#elif defined(_WIN32) +#elif defined(_WIN32) && !defined(_WIN32_WCE) if ((tty_out = fopen("conout$", "w")) == NULL) tty_out = stderr; @@ -495,7 +506,7 @@ static int noecho_console(UI *ui) } } #endif -#if defined(_WIN32) +#if defined(_WIN32) && !defined(_WIN32_WCE) if (is_a_tty) { tty_new = tty_orig; tty_new &= ~ENABLE_ECHO_INPUT; @@ -527,7 +538,7 @@ static int echo_console(UI *ui) } } #endif -#if defined(_WIN32) +#if defined(_WIN32) && !defined(_WIN32_WCE) if (is_a_tty) { tty_new = tty_orig; SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); @@ -557,6 +568,7 @@ static int close_console(UI *ui) return ret; } +#if !defined(OPENSSL_SYS_WINCE) /* Internal functions to handle signals and act on them */ static void pushsig(void) { @@ -637,6 +649,7 @@ static void recsig(int i) { intr_signal = i; } +#endif /* Internal functions specific for Windows */ #if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) diff --git a/crypto/whrlpool/wp_block.c b/crypto/whrlpool/wp_block.c index 62fa849dad..13b3f7b37f 100644 --- a/crypto/whrlpool/wp_block.c +++ b/crypto/whrlpool/wp_block.c @@ -103,7 +103,7 @@ typedef uint64_t u64_aX; #pragma intrinsic(_rotl64) #define ROTATE(a, n) _rotl64((a), n) #endif -#elif defined(__GNUC__) +#elif defined(__GNUC__) && __GNUC__ >= 2 #if defined(__x86_64) || defined(__x86_64__) #if defined(L_ENDIAN) #define ROTATE(a, n) ({ uint64_t ret; asm ("rolq %1,%0" \ diff --git a/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c index bffa96fd6c..d1ee35377b 100644 --- a/crypto/x509/pcy_cache.c +++ b/crypto/x509/pcy_cache.c @@ -134,7 +134,6 @@ static int policy_cache_new(X509 *x) /* If not absent some problem with extension */ if (i != -1) goto bad_cache; - POLICY_CONSTRAINTS_free(ext_pcons); return 1; } @@ -142,10 +141,8 @@ static int policy_cache_new(X509 *x) /* NB: ext_cpols freed by policy_cache_set_policies */ - if (i <= 0) { - POLICY_CONSTRAINTS_free(ext_pcons); + if (i <= 0) return i; - } ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c index abe1b7557d..cf8062a902 100644 --- a/crypto/x509/t_x509.c +++ b/crypto/x509/t_x509.c @@ -244,7 +244,7 @@ int X509_ocspid_print(BIO *bp, const X509 *x) goto err; if (!EVP_Digest(ASN1_STRING_get0_data(keybstr), - ASN1_STRING_length_ex(keybstr), SHA1md, NULL, md, NULL)) + ASN1_STRING_length(keybstr), SHA1md, NULL, md, NULL)) goto err; for (i = 0; i < SHA_DIGEST_LENGTH; i++) { if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) diff --git a/crypto/x509/v3_addr.c b/crypto/x509/v3_addr.c index e245e2b08a..1e0d94babf 100644 --- a/crypto/x509/v3_addr.c +++ b/crypto/x509/v3_addr.c @@ -409,11 +409,6 @@ static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, { int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; IPAddressOrRange *aor; - unsigned char *prefix = NULL; - uint8_t unused_bits = 0; - - if (bitlen > 0) - unused_bits = 8 - bitlen; if (prefixlen < 0 || prefixlen > (afilen * 8)) return 0; @@ -422,23 +417,19 @@ static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, aor->type = IPAddressOrRange_addressPrefix; if (aor->u.addressPrefix == NULL && (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) goto err; - if (bytelen > 0) { - prefix = OPENSSL_malloc(bytelen); - if (prefix == NULL) - goto err; - memcpy(prefix, addr, bytelen); - if (unused_bits) - prefix[bytelen - 1] &= ~(0xFF >> bitlen); - } - if (!ASN1_BIT_STRING_set1(aor->u.addressPrefix, prefix, bytelen, unused_bits)) + /* BIT_STRING is a typedef of STRING + * this function allows to set value without checking invalid bits + * as they are nullified after setting */ + if (!ASN1_STRING_set(aor->u.addressPrefix, addr, bytelen)) goto err; - *result = aor; + if (bitlen > 0) + aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); + ossl_asn1_bit_string_set_unused_bits(aor->u.addressPrefix, 8 - bitlen); - OPENSSL_free(prefix); + *result = aor; return 1; err: - OPENSSL_free(prefix); IPAddressOrRange_free(aor); return 0; } @@ -769,7 +760,6 @@ int X509v3_addr_is_canonical(IPAddrBlocks *addr) aors = f->ipAddressChoice->u.addressesOrRanges; if (sk_IPAddressOrRange_num(aors) == 0) return 0; - for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); @@ -824,106 +814,78 @@ int X509v3_addr_is_canonical(IPAddrBlocks *addr) /* * Whack an IPAddressOrRanges into canonical form. - * - * After the initial sort, the merge runs as a single linear sweep - * over the list using a write index. Adjacent entries are folded - * into the previous output by replacing it with a freshly built - * merged range; both old entries are then freed and the source slot - * is left NULL so the asn1 free machinery does not double-free on a - * subsequent abort. Total cost is O(N log N) sort + O(N) merge, - * with no stack deletes inside the loop. */ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi) { - int length = length_from_afi(afi); - int read, write = 0, n; - - sk_IPAddressOrRange_sort(aors); - n = sk_IPAddressOrRange_num(aors); + int i, j, length = length_from_afi(afi); /* - * Error paths below all `return 0` directly. Slots at - * [write..read-1] are NULL (from earlier iterations) and slots at - * [read..n-1] still hold their original entries; the caller's - * normal teardown walks the whole stack and frees each non-NULL - * slot safely, so leaving the stack in this mixed state is sound. + * Sort the IPAddressOrRanges sequence. */ - for (read = 0; read < n; read++) { - IPAddressOrRange *cur = sk_IPAddressOrRange_value(aors, read); - unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN]; + sk_IPAddressOrRange_sort(aors); - if (!extract_min_max(cur, c_min, c_max, length)) + /* + * Clean up representation issues, punt on duplicates or overlaps. + */ + for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i); + IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1); + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + + if (!extract_min_max(a, a_min, a_max, length) || !extract_min_max(b, b_min, b_max, length)) return 0; /* - * Punt inverted range. + * Punt inverted ranges. */ - if (memcmp(c_min, c_max, length) > 0) + if (memcmp(a_min, a_max, length) > 0 || memcmp(b_min, b_max, length) > 0) return 0; - if (write > 0) { - IPAddressOrRange *prev = sk_IPAddressOrRange_value(aors, - write - 1); - unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN]; - unsigned char c_min_minus_one[ADDR_RAW_BUF_LEN]; - int j; - - if (!extract_min_max(prev, p_min, p_max, length)) - return 0; - - /* - * Reject overlap with the previous accepted entry. - */ - if (memcmp(p_max, c_min, length) >= 0) - return 0; - - /* - * Adjacency test: does c_min - 1 equal p_max? Work on a - * scratch copy so the original c_min stays intact for use - * as the lower bound if we end up keeping cur. - */ - memcpy(c_min_minus_one, c_min, length); - for (j = length - 1; - j >= 0 && c_min_minus_one[j]-- == 0x00; - j--) - ; - if (memcmp(p_max, c_min_minus_one, length) == 0) { - IPAddressOrRange *merged; - - if (!make_addressRange(&merged, p_min, c_max, length)) - return 0; - /* - * Replace prev with merged, free the originals, and - * NULL the source slot so the stack does not retain a - * second reference to cur. - */ - (void)sk_IPAddressOrRange_set(aors, write - 1, merged); - IPAddressOrRange_free(prev); - IPAddressOrRange_free(cur); - (void)sk_IPAddressOrRange_set(aors, read, NULL); - continue; - } - } + /* + * Punt overlaps. + */ + if (memcmp(a_max, b_min, length) >= 0) + return 0; /* - * Keep cur. Slide it forward into the write slot if we have - * fallen behind, and NULL the source slot to avoid duplicate - * ownership. + * Merge if a and b are adjacent. We check for + * adjacency by subtracting one from b_min first. */ - if (write != read) { - (void)sk_IPAddressOrRange_set(aors, write, cur); - (void)sk_IPAddressOrRange_set(aors, read, NULL); + for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) + ; + if (memcmp(a_max, b_min, length) == 0) { + IPAddressOrRange *merged; + + if (!make_addressRange(&merged, a_min, b_max, length)) + return 0; + (void)sk_IPAddressOrRange_set(aors, i, merged); + (void)sk_IPAddressOrRange_delete(aors, i + 1); + IPAddressOrRange_free(a); + IPAddressOrRange_free(b); + --i; + continue; } - write++; } /* - * Compaction succeeded: every slot at [write..n-1] is NULL, so - * popping the tail leaves the canonicalised list at [0..write-1]. + * Check for inverted final range. */ - while (sk_IPAddressOrRange_num(aors) > write) - (void)sk_IPAddressOrRange_pop(aors); + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + } + return 1; } diff --git a/crypto/x509/v3_akid.c b/crypto/x509/v3_akid.c index 95b904c757..9c93e88267 100644 --- a/crypto/x509/v3_akid.c +++ b/crypto/x509/v3_akid.c @@ -179,14 +179,14 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, /* * The subject key identifier of the issuer cert is acceptable unless * the issuer cert is same as subject cert, but the subject will not - * be self-signed (i.e. will be signed with a different key). + * not be self-signed (i.e. will be signed with a different key). */ i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1); if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL && !(same_issuer && !ss)) { ikeyid = X509V3_EXT_d2i(ext); /* Ignore empty keyids in the issuer cert */ - if (ASN1_STRING_length_ex(ikeyid) == 0) { + if (ASN1_STRING_length(ikeyid) == 0) { ASN1_OCTET_STRING_free(ikeyid); ikeyid = NULL; } diff --git a/crypto/x509/v3_asid.c b/crypto/x509/v3_asid.c index c00ded15f9..8470e0f134 100644 --- a/crypto/x509/v3_asid.c +++ b/crypto/x509/v3_asid.c @@ -347,22 +347,13 @@ int X509v3_asid_is_canonical(ASIdentifiers *asid) /* * Whack an ASIdentifierChoice into canonical form. - * - * After the initial sort, the merge runs as a single linear sweep - * over the list using a write index. Each entry is examined once; - * adjacent / mergeable entries extend the previous output's upper - * bound in O(1) and the source slot is left NULL so the asn1 free - * machinery does not double-free on a subsequent abort. Total cost - * is O(N log N) sort + O(N) merge, with no stack deletes inside the - * loop. */ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) { ASN1_INTEGER *a_max_plus_one = NULL; ASN1_INTEGER *orig; BIGNUM *bn = NULL; - int read, write = 0, n; - int ret = 0; + int i, ret = 0; /* * Nothing to do for empty element or inheritance. @@ -379,135 +370,112 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) } /* - * Sort the list, then merge in a single sweep using a write index. + * We have a non-empty list. Sort it. */ sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); - n = sk_ASIdOrRange_num(choice->u.asIdsOrRanges); - for (read = 0; read < n; read++) { - ASIdOrRange *cur = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, read); - ASN1_INTEGER *c_min = NULL, *c_max = NULL; + /* + * Now check for errors and suboptimal encoding, rejecting the + * former and fixing the latter. + */ + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); + ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = NULL; - if (!extract_min_max(cur, &c_min, &c_max)) + if (!extract_min_max(a, &a_min, &a_max) + || !extract_min_max(b, &b_min, &b_max)) goto done; /* - * Punt inverted range. + * Make sure we're properly sorted (paranoia). */ - if (ASN1_INTEGER_cmp(c_min, c_max) > 0) + if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0)) goto done; - if (write > 0) { - ASIdOrRange *prev = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, - write - 1); - ASN1_INTEGER *p_min = NULL, *p_max = NULL; + /* + * Punt inverted ranges. + */ + if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || ASN1_INTEGER_cmp(b_min, b_max) > 0) + goto done; - if (!extract_min_max(prev, &p_min, &p_max)) - goto done; - - /* - * Make sure we're properly sorted (paranoia). - */ - if (!ossl_assert(ASN1_INTEGER_cmp(p_min, c_min) <= 0)) - goto done; - - /* - * Reject overlap with the previous accepted entry. - */ - if (ASN1_INTEGER_cmp(p_max, c_min) >= 0) { - ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR); - goto done; - } - - /* - * Calculate p_max + 1 to check for adjacency. - */ - if ((bn == NULL && (bn = BN_new()) == NULL) - || ASN1_INTEGER_to_BN(p_max, bn) == NULL - || !BN_add_word(bn, 1)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_BN_LIB); - goto done; - } - if ((a_max_plus_one = BN_to_ASN1_INTEGER(bn, - orig = a_max_plus_one)) - == NULL) { - a_max_plus_one = orig; - ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); - goto done; - } - - /* - * If prev and cur are adjacent, fold cur into prev. - */ - if (ASN1_INTEGER_cmp(a_max_plus_one, c_min) == 0) { - ASRange *r; - - switch (prev->type) { - case ASIdOrRange_id: - if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) - goto done; - r->min = p_min; - r->max = c_max; - prev->type = ASIdOrRange_range; - prev->u.range = r; - break; - case ASIdOrRange_range: - ASN1_INTEGER_free(prev->u.range->max); - prev->u.range->max = c_max; - break; - } - /* - * Detach c_max from cur so freeing cur does not free - * the value we just transferred to prev. - */ - switch (cur->type) { - case ASIdOrRange_id: - cur->u.id = NULL; - break; - case ASIdOrRange_range: - cur->u.range->max = NULL; - break; - } - ASIdOrRange_free(cur); - /* - * NULL the source slot so any later teardown does not - * walk a freed pointer. We do not advance `write`. - */ - (void)sk_ASIdOrRange_set(choice->u.asIdsOrRanges, read, NULL); - continue; - } + /* + * Check for overlaps. + */ + if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { + ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR); + goto done; } /* - * Keep cur. Slide it forward into the write slot if we have - * fallen behind, and NULL the source slot to avoid duplicate - * ownership. + * Calculate a_max + 1 to check for adjacency. */ - if (write != read) { - (void)sk_ASIdOrRange_set(choice->u.asIdsOrRanges, write, cur); - (void)sk_ASIdOrRange_set(choice->u.asIdsOrRanges, read, NULL); + if ((bn == NULL && (bn = BN_new()) == NULL) || ASN1_INTEGER_to_BN(a_max, bn) == NULL || !BN_add_word(bn, 1)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_BN_LIB); + goto done; + } + + if ((a_max_plus_one = BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) { + a_max_plus_one = orig; + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto done; + } + + /* + * If a and b are adjacent, merge them. + */ + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { + ASRange *r; + switch (a->type) { + case ASIdOrRange_id: + if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) + goto done; + r->min = a_min; + r->max = b_max; + a->type = ASIdOrRange_range; + a->u.range = r; + break; + case ASIdOrRange_range: + ASN1_INTEGER_free(a->u.range->max); + a->u.range->max = b_max; + break; + } + switch (b->type) { + case ASIdOrRange_id: + b->u.id = NULL; + break; + case ASIdOrRange_range: + b->u.range->max = NULL; + break; + } + ASIdOrRange_free(b); + (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); + i--; + continue; } - write++; } + /* + * Check for final inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + if (!extract_min_max(a, &a_min, &a_max) + || ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + + /* Paranoia */ + if (!ossl_assert(ASIdentifierChoice_is_canonical(choice))) + goto done; + ret = 1; done: - /* - * On success every slot at [write..n-1] is NULL, so popping the - * tail leaves the canonicalised list at [0..write-1]. On error we - * leave the tail untouched; the slots are either NULL (from earlier - * iterations) or original entries the loop never reached, both of - * which the caller's ASIdentifierChoice_free path handles safely. - */ - if (ret) { - while (sk_ASIdOrRange_num(choice->u.asIdsOrRanges) > write) - (void)sk_ASIdOrRange_pop(choice->u.asIdsOrRanges); - /* Paranoia */ - if (!ossl_assert(ASIdentifierChoice_is_canonical(choice))) - ret = 0; - } - ASN1_INTEGER_free(a_max_plus_one); BN_free(bn); return ret; diff --git a/crypto/x509/v3_bitst.c b/crypto/x509/v3_bitst.c index 1b0204bf75..89c3deddd3 100644 --- a/crypto/x509/v3_bitst.c +++ b/crypto/x509/v3_bitst.c @@ -52,7 +52,7 @@ STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, for (bnam = method->usr_data; bnam->lname; bnam++) { /* * If the bitnumber did not change from the last iteration, this entry - * is an alias for the previous bit; treat the first result as + * is an an alias for the previous bit; treat the first result as * canonical and ignore the rest. */ if (last_seen_bit == bnam->bitnum) diff --git a/crypto/x509/v3_cpols.c b/crypto/x509/v3_cpols.c index 2cc71f567b..0dc8f76ad4 100644 --- a/crypto/x509/v3_cpols.c +++ b/crypto/x509/v3_cpols.c @@ -208,7 +208,8 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } - if (!ASN1_STRING_set_string(qual->d.cpsuri, cnf->value)) { + if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, + (int)strlen(cnf->value))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } @@ -324,7 +325,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, if (tag_len != 0) value += tag_len + 1; len = (int)strlen(value); - if (!ASN1_STRING_set_data(not->exptext, (uint8_t *)value, len)) { + if (!ASN1_STRING_set(not->exptext, value, len)) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } @@ -343,7 +344,8 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, nref->organization->type = V_ASN1_IA5STRING; else nref->organization->type = V_ASN1_VISIBLESTRING; - if (!ASN1_STRING_set_string(nref->organization, cnf->value)) { + if (!ASN1_STRING_set(nref->organization, cnf->value, + (int)strlen(cnf->value))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/x509/v3_genn.c b/crypto/x509/v3_genn.c index 23a2435842..d63168a77a 100644 --- a/crypto/x509/v3_genn.c +++ b/crypto/x509/v3_genn.c @@ -49,7 +49,13 @@ ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES) IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES) -IMPLEMENT_ASN1_DUP_FUNCTION(GENERAL_NAME) + +GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a) +{ + return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME, + (d2i_of_void *)d2i_GENERAL_NAME, + (char *)a); +} int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src) { diff --git a/crypto/x509/v3_ia5.c b/crypto/x509/v3_ia5.c index a8fa52a439..539c43a141 100644 --- a/crypto/x509/v3_ia5.c +++ b/crypto/x509/v3_ia5.c @@ -52,7 +52,7 @@ ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } - if (!ASN1_STRING_set_string((ASN1_STRING *)ia5, str)) { + if (!ASN1_STRING_set((ASN1_STRING *)ia5, str, (int)strlen(str))) { ASN1_IA5STRING_free(ia5); return NULL; } diff --git a/crypto/x509/v3_ist.c b/crypto/x509/v3_ist.c index a4d3437192..0409b52d60 100644 --- a/crypto/x509/v3_ist.c +++ b/crypto/x509/v3_ist.c @@ -52,28 +52,28 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_ if (strcmp(cnf->name, "signTool") == 0) { if (ist->signTool == NULL || cnf->value == NULL - || !ASN1_STRING_set_string(ist->signTool, cnf->value)) { + || !ASN1_STRING_set(ist->signTool, cnf->value, (int)strlen(cnf->value))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else if (strcmp(cnf->name, "cATool") == 0) { if (ist->cATool == NULL || cnf->value == NULL - || !ASN1_STRING_set_string(ist->cATool, cnf->value)) { + || !ASN1_STRING_set(ist->cATool, cnf->value, (int)strlen(cnf->value))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else if (strcmp(cnf->name, "signToolCert") == 0) { if (ist->signToolCert == NULL || cnf->value == NULL - || !ASN1_STRING_set_string(ist->signToolCert, cnf->value)) { + || !ASN1_STRING_set(ist->signToolCert, cnf->value, (int)strlen(cnf->value))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else if (strcmp(cnf->name, "cAToolCert") == 0) { if (ist->cAToolCert == NULL || cnf->value == NULL - || !ASN1_STRING_set_string(ist->cAToolCert, cnf->value)) { + || !ASN1_STRING_set(ist->cAToolCert, cnf->value, (int)strlen(cnf->value))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/x509/v3_lib.c b/crypto/x509/v3_lib.c index a099177dba..aee7ad119f 100644 --- a/crypto/x509/v3_lib.c +++ b/crypto/x509/v3_lib.c @@ -169,18 +169,16 @@ void *X509V3_EXT_d2i(const X509_EXTENSION *ext) const X509V3_EXT_METHOD *method; const unsigned char *p; const ASN1_STRING *extvalue; - size_t extlen; + int extlen; if ((method = X509V3_EXT_get(ext)) == NULL) return NULL; extvalue = X509_EXTENSION_get_data(ext); p = ASN1_STRING_get0_data(extvalue); - extlen = ASN1_STRING_length_ex(extvalue); - if (extlen > INT_MAX) - return NULL; + extlen = ASN1_STRING_length(extvalue); if (method->it) - return ASN1_item_d2i(NULL, &p, (int)extlen, ASN1_ITEM_ptr(method->it)); - return method->d2i(NULL, &p, (int)extlen); + return ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it)); + return method->d2i(NULL, &p, extlen); } /*- diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index 5f2710e9f5..1a9cf61122 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -615,12 +615,6 @@ static int nc_dn(const X509_NAME *nm, const X509_NAME *base) return X509_V_ERR_OUT_OF_MEM; if (base->canon_enclen > nm->canon_enclen) return X509_V_ERR_PERMITTED_VIOLATION; - /* - * An empty base Name has no canonical encoding (canon_enc == NULL) and is - * a prefix of every Name, so it matches unconditionally. - */ - if (base->canon_enclen == 0) - return X509_V_OK; if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) return X509_V_ERR_PERMITTED_VIOLATION; return X509_V_OK; @@ -797,7 +791,6 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) if (scheme == NULL || *scheme == '\0') { ERR_raise_data(ERR_LIB_X509V3, X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, "x509: missing scheme in URI: %s\n", uri_copy); - OPENSSL_free(scheme); OPENSSL_free(uri_copy); ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; goto end; diff --git a/crypto/x509/v3_prn.c b/crypto/x509/v3_prn.c index 0fb7c9e38a..4a0df33ea3 100644 --- a/crypto/x509/v3_prn.c +++ b/crypto/x509/v3_prn.c @@ -73,26 +73,24 @@ int X509V3_EXT_print(BIO *out, const X509_EXTENSION *ext, unsigned long flag, char *value = NULL; const ASN1_OCTET_STRING *extoct; const unsigned char *p; - size_t extlen; + int extlen; const X509V3_EXT_METHOD *method; STACK_OF(CONF_VALUE) *nval = NULL; int ok = 1; extoct = X509_EXTENSION_get_data(ext); p = ASN1_STRING_get0_data(extoct); - extlen = ASN1_STRING_length_ex(extoct); - if (extlen > INT_MAX) - return 0; + extlen = ASN1_STRING_length(extoct); if ((method = X509V3_EXT_get(ext)) == NULL) - return unknown_ext_print(out, p, (int)extlen, flag, indent, 0); + return unknown_ext_print(out, p, extlen, flag, indent, 0); if (method->it) - ext_str = ASN1_item_d2i(NULL, &p, (int)extlen, ASN1_ITEM_ptr(method->it)); + ext_str = ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it)); else - ext_str = method->d2i(NULL, &p, (int)extlen); + ext_str = method->d2i(NULL, &p, extlen); if (!ext_str) - return unknown_ext_print(out, p, (int)extlen, flag, indent, 1); + return unknown_ext_print(out, p, extlen, flag, indent, 1); if (method->i2s) { if ((value = method->i2s(method, ext_str)) == NULL) { diff --git a/crypto/x509/v3_san.c b/crypto/x509/v3_san.c index f1b028f78c..0f12939d6d 100644 --- a/crypto/x509/v3_san.c +++ b/crypto/x509/v3_san.c @@ -575,8 +575,7 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, } if (is_string) { - if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL - || !ASN1_STRING_set_string(gen->d.ia5, value)) { + if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL || !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, (int)strlen(value))) { ASN1_IA5STRING_free(gen->d.ia5); gen->d.ia5 = NULL; ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); diff --git a/crypto/x509/v3_utf8.c b/crypto/x509/v3_utf8.c index dc7c86fb7f..49095ffdd9 100644 --- a/crypto/x509/v3_utf8.c +++ b/crypto/x509/v3_utf8.c @@ -55,7 +55,7 @@ ASN1_UTF8STRING *s2i_ASN1_UTF8STRING(X509V3_EXT_METHOD *method, ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } - if (!ASN1_STRING_set_string(utf8, str)) { + if (!ASN1_STRING_set((ASN1_STRING *)utf8, str, (int)strlen(str))) { ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); ASN1_UTF8STRING_free(utf8); return NULL; diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index e08e490274..ee631db75a 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -365,7 +365,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, atype = stmp->type; } else if (len != -1) { if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL - || !ASN1_STRING_set_data(stmp, data, len)) { + || !ASN1_STRING_set(stmp, data, len)) { ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/x509/x509_ext.c b/crypto/x509/x509_ext.c index 8c9c5d96bc..3cd4ac51fc 100644 --- a/crypto/x509/x509_ext.c +++ b/crypto/x509/x509_ext.c @@ -84,7 +84,7 @@ int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) { - return X509v3_get_ext_by_critical(x->cert_info.extensions, crit, lastpos); + return (X509v3_get_ext_by_critical(x->cert_info.extensions, crit, lastpos)); } const X509_EXTENSION *X509_get_ext(const X509 *x, int loc) diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 5be50c2195..e9cc7145e3 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -287,7 +287,7 @@ int X509_STORE_up_ref(X509_STORE *xs) { int i; - if (!CRYPTO_UP_REF(&xs->references, &i)) + if (CRYPTO_UP_REF(&xs->references, &i) <= 0) return 0; REF_PRINT_COUNT("X509_STORE", i, xs); @@ -741,12 +741,7 @@ static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj) ret->type = obj->type; ret->data = obj->data; - - if (!X509_OBJECT_up_ref_count(ret)) { - OPENSSL_free(ret); - return NULL; - } - + X509_OBJECT_up_ref_count(ret); return ret; } @@ -769,7 +764,6 @@ static int obj_ht_foreach_object(HT_VALUE *v, void *arg) return 1; err: - X509_OBJECT_free(dup); sk_X509_OBJECT_pop_free(*sk, X509_OBJECT_free); *sk = NULL; diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c index 11439bcafb..8a2a12e4b6 100644 --- a/crypto/x509/x509_set.c +++ b/crypto/x509/x509_set.c @@ -117,7 +117,7 @@ int X509_up_ref(X509 *x) { int i; - if (!CRYPTO_UP_REF(&x->references, &i)) + if (CRYPTO_UP_REF(&x->references, &i) <= 0) return 0; REF_PRINT_COUNT("X509", i, x); diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 44b116923b..f0858e357e 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -35,7 +35,7 @@ static X509_BUFFER *buffer_from_bytes(const uint8_t *bytes, size_t length) { X509_BUFFER *buf; - if ((buf = OPENSSL_zalloc(sizeof(*buf))) != NULL + if ((buf = OPENSSL_zalloc(sizeof *buf)) != NULL && (buf->data = OPENSSL_memdup(bytes, length)) != NULL) { buf->len = length; } else { @@ -56,7 +56,7 @@ static X509_BUFFER *buffer_from_string(const uint8_t *bytes, size_t length) X509_BUFFER *buf, *ret = NULL; uint8_t *data = NULL; - if ((buf = OPENSSL_zalloc(sizeof(*buf))) == NULL) + if ((buf = OPENSSL_zalloc(sizeof *buf)) == NULL) goto err; if ((data = (uint8_t *)OPENSSL_strndup((char *)bytes, length)) == NULL) diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c index ec3e1f5360..20de6a340e 100644 --- a/crypto/x509/x509cset.c +++ b/crypto/x509/x509cset.c @@ -75,7 +75,7 @@ int X509_CRL_up_ref(X509_CRL *crl) { int i; - if (!CRYPTO_UP_REF(&crl->references, &i)) + if (CRYPTO_UP_REF(&crl->references, &i) <= 0) return 0; REF_PRINT_COUNT("X509_CRL", i, crl); diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c index 58167d9a78..ebd58a2012 100644 --- a/crypto/x509/x509name.c +++ b/crypto/x509/x509name.c @@ -332,12 +332,9 @@ int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, OBJ_obj2nid(ne->object)) ? 1 : 0; - if (len < -1) - return 0; - if (len == -1) - i = ASN1_STRING_set_string(ne->value, (const char *)bytes); - else - i = ASN1_STRING_set_data(ne->value, bytes, (size_t)len); + if (len < 0) + len = (int)strlen((const char *)bytes); + i = ASN1_STRING_set(ne->value, bytes, len); if (!i) return 0; if (type != V_ASN1_UNDEF) { diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index ef16a7fc88..2659886748 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -32,103 +32,6 @@ #include "crypto/rsa.h" #include "x509_local.h" -static void *RSA_new_thunk(void) -{ - return RSA_new(); -} - -static void *d2i_RSA_PUBKEY_thunk(void **a, const unsigned char **in, long len) -{ - return d2i_RSA_PUBKEY((RSA **)a, in, len); -} - -static int i2d_RSA_PUBKEY_thunk(const void *a, unsigned char **out) -{ - return i2d_RSA_PUBKEY((const RSA *)a, out); -} - -static void *EVP_PKEY_new_thunk(void) -{ - return EVP_PKEY_new(); -} - -static void *d2i_AutoPrivateKey_thunk(void **a, const unsigned char **in, - long len) -{ - return d2i_AutoPrivateKey((EVP_PKEY **)a, in, len); -} - -static void *d2i_PUBKEY_thunk(void **a, const unsigned char **in, long len) -{ - return d2i_PUBKEY((EVP_PKEY **)a, in, len); -} - -static int i2d_PrivateKey_thunk(const void *a, unsigned char **out) -{ - return i2d_PrivateKey((const EVP_PKEY *)a, out); -} - -static int i2d_PUBKEY_thunk(const void *a, unsigned char **out) -{ - return i2d_PUBKEY((const EVP_PKEY *)a, out); -} - -#ifndef OPENSSL_NO_DSA -static void *DSA_new_thunk(void) -{ - return DSA_new(); -} - -static void *d2i_DSAPrivateKey_thunk(void **a, const unsigned char **in, - long len) -{ - return d2i_DSAPrivateKey((DSA **)a, in, len); -} - -static int i2d_DSAPrivateKey_thunk(const void *a, unsigned char **out) -{ - return i2d_DSAPrivateKey((const DSA *)a, out); -} - -static void *d2i_DSA_PUBKEY_thunk(void **a, const unsigned char **in, long len) -{ - return d2i_DSA_PUBKEY((DSA **)a, in, len); -} - -static int i2d_DSA_PUBKEY_thunk(const void *a, unsigned char **out) -{ - return i2d_DSA_PUBKEY((const DSA *)a, out); -} -#endif - -#ifndef OPENSSL_NO_EC -static void *EC_KEY_new_thunk(void) -{ - return EC_KEY_new(); -} - -static void *d2i_EC_PUBKEY_thunk(void **a, const unsigned char **in, long len) -{ - return d2i_EC_PUBKEY((EC_KEY **)a, in, len); -} - -static int i2d_EC_PUBKEY_thunk(const void *a, unsigned char **out) -{ - return i2d_EC_PUBKEY((const EC_KEY *)a, out); -} - -static void *d2i_ECPrivateKey_thunk(void **a, const unsigned char **in, - long len) -{ - return d2i_ECPrivateKey((EC_KEY **)a, in, len); -} - -static int i2d_ECPrivateKey_thunk(const void *a, unsigned char **out) -{ - return i2d_ECPrivateKey((const EC_KEY *)a, out); -} -#endif - int X509_verify(const X509 *a, EVP_PKEY *r) { if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature) != 0) @@ -487,8 +390,10 @@ RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) { - return ASN1_d2i_fp(RSA_new_thunk, d2i_RSA_PUBKEY_thunk, fp, - CHECKED_PPTR_OF(RSA, rsa)); + return ASN1_d2i_fp((void *(*)(void)) + RSA_new, + (D2I_OF(void))d2i_RSA_PUBKEY, fp, + (void **)rsa); } int i2d_RSAPublicKey_fp(FILE *fp, const RSA *rsa) @@ -498,7 +403,7 @@ int i2d_RSAPublicKey_fp(FILE *fp, const RSA *rsa) int i2d_RSA_PUBKEY_fp(FILE *fp, const RSA *rsa) { - return ASN1_i2d_fp(i2d_RSA_PUBKEY_thunk, fp, rsa); + return ASN1_i2d_fp((I2D_OF(void))i2d_RSA_PUBKEY, fp, rsa); } #endif @@ -519,8 +424,7 @@ RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) { - return ASN1_d2i_bio(RSA_new_thunk, d2i_RSA_PUBKEY_thunk, bp, - CHECKED_PPTR_OF(RSA, rsa)); + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa); } int i2d_RSAPublicKey_bio(BIO *bp, const RSA *rsa) @@ -530,55 +434,50 @@ int i2d_RSAPublicKey_bio(BIO *bp, const RSA *rsa) int i2d_RSA_PUBKEY_bio(BIO *bp, const RSA *rsa) { - return ASN1_i2d_bio(i2d_RSA_PUBKEY_thunk, bp, rsa); + return ASN1_i2d_bio_of(RSA, i2d_RSA_PUBKEY, bp, rsa); } #ifndef OPENSSL_NO_DSA #ifndef OPENSSL_NO_STDIO DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) { - return ASN1_d2i_fp(DSA_new_thunk, d2i_DSAPrivateKey_thunk, fp, - CHECKED_PPTR_OF(DSA, dsa)); + return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa); } int i2d_DSAPrivateKey_fp(FILE *fp, const DSA *dsa) { - return ASN1_i2d_fp(i2d_DSAPrivateKey_thunk, fp, - CHECKED_PTR_OF(const DSA, dsa)); + return ASN1_i2d_fp_of(DSA, i2d_DSAPrivateKey, fp, dsa); } DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) { - return ASN1_d2i_fp(DSA_new_thunk, d2i_DSA_PUBKEY_thunk, fp, - CHECKED_PPTR_OF(DSA, dsa)); + return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa); } int i2d_DSA_PUBKEY_fp(FILE *fp, const DSA *dsa) { - return ASN1_i2d_fp(i2d_DSA_PUBKEY_thunk, fp, - CHECKED_PTR_OF(const DSA, dsa)); + return ASN1_i2d_fp_of(DSA, i2d_DSA_PUBKEY, fp, dsa); } #endif DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa) { - return ASN1_d2i_bio(DSA_new_thunk, d2i_DSAPrivateKey_thunk, bp, (void **)dsa); + return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa); } int i2d_DSAPrivateKey_bio(BIO *bp, const DSA *dsa) { - return ASN1_i2d_bio(i2d_DSAPrivateKey_thunk, bp, - CHECKED_PTR_OF(const DSA, dsa)); + return ASN1_i2d_bio_of(DSA, i2d_DSAPrivateKey, bp, dsa); } DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) { - return ASN1_d2i_bio(DSA_new_thunk, d2i_DSA_PUBKEY_thunk, bp, (void **)dsa); + return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa); } int i2d_DSA_PUBKEY_bio(BIO *bp, const DSA *dsa) { - return ASN1_i2d_bio(i2d_DSA_PUBKEY_thunk, bp, dsa); + return ASN1_i2d_bio_of(DSA, i2d_DSA_PUBKEY, bp, dsa); } #endif @@ -587,49 +486,42 @@ int i2d_DSA_PUBKEY_bio(BIO *bp, const DSA *dsa) #ifndef OPENSSL_NO_STDIO EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey) { - return ASN1_d2i_fp(EC_KEY_new_thunk, d2i_EC_PUBKEY_thunk, fp, - CHECKED_PPTR_OF(EC_KEY, eckey)); + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey); } int i2d_EC_PUBKEY_fp(FILE *fp, const EC_KEY *eckey) { - return ASN1_i2d_fp(i2d_EC_PUBKEY_thunk, fp, CHECKED_PTR_OF(const EC_KEY, eckey)); + return ASN1_i2d_fp_of(EC_KEY, i2d_EC_PUBKEY, fp, eckey); } EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey) { - return ASN1_d2i_fp(EC_KEY_new_thunk, d2i_ECPrivateKey_thunk, fp, - CHECKED_PPTR_OF(EC_KEY, eckey)); + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey); } int i2d_ECPrivateKey_fp(FILE *fp, const EC_KEY *eckey) { - return ASN1_i2d_fp(i2d_ECPrivateKey_thunk, fp, - CHECKED_PTR_OF(const EC_KEY, eckey)); + return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey); } #endif EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey) { - return ASN1_d2i_bio(EC_KEY_new_thunk, d2i_EC_PUBKEY_thunk, bp, - CHECKED_PPTR_OF(EC_KEY, eckey)); + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey); } int i2d_EC_PUBKEY_bio(BIO *bp, const EC_KEY *ecdsa) { - return ASN1_i2d_bio(i2d_EC_PUBKEY_thunk, bp, - CHECKED_PTR_OF(const EC_KEY, ecdsa)); + return ASN1_i2d_bio_of(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa); } EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey) { - return ASN1_d2i_bio(EC_KEY_new_thunk, d2i_ECPrivateKey_thunk, bp, - CHECKED_PPTR_OF(EC_KEY, eckey)); + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey); } int i2d_ECPrivateKey_bio(BIO *bp, const EC_KEY *eckey) { - return ASN1_i2d_bio(i2d_ECPrivateKey_thunk, bp, - CHECKED_PTR_OF(const EC_KEY, eckey)); + return ASN1_i2d_bio_of(EC_KEY, i2d_ECPrivateKey, bp, eckey); } #endif @@ -797,57 +689,61 @@ int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, #ifndef OPENSSL_NO_STDIO X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_SIG), fp, p8); + return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8); } int i2d_PKCS8_fp(FILE *fp, const X509_SIG *p8) { - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_SIG), fp, p8); + return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8); } #endif X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_SIG), bp, p8); + return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8); } int i2d_PKCS8_bio(BIO *bp, const X509_SIG *p8) { - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_SIG), bp, p8); + return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8); } #ifndef OPENSSL_NO_STDIO X509_PUBKEY *d2i_X509_PUBKEY_fp(FILE *fp, X509_PUBKEY **xpk) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_PUBKEY), fp, xpk); + return ASN1_d2i_fp_of(X509_PUBKEY, X509_PUBKEY_new, d2i_X509_PUBKEY, + fp, xpk); } int i2d_X509_PUBKEY_fp(FILE *fp, const X509_PUBKEY *xpk) { - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_PUBKEY), fp, xpk); + return ASN1_i2d_fp_of(X509_PUBKEY, i2d_X509_PUBKEY, fp, xpk); } #endif X509_PUBKEY *d2i_X509_PUBKEY_bio(BIO *bp, X509_PUBKEY **xpk) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_PUBKEY), bp, xpk); + return ASN1_d2i_bio_of(X509_PUBKEY, X509_PUBKEY_new, d2i_X509_PUBKEY, + bp, xpk); } int i2d_X509_PUBKEY_bio(BIO *bp, const X509_PUBKEY *xpk) { - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_PUBKEY), bp, xpk); + return ASN1_i2d_bio_of(X509_PUBKEY, i2d_X509_PUBKEY, bp, xpk); } #ifndef OPENSSL_NO_STDIO PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO **p8inf) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), fp, p8inf); + return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, + d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf); } int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, const PKCS8_PRIV_KEY_INFO *p8inf) { - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), fp, p8inf); + return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp, + p8inf); } int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, const EVP_PKEY *key) @@ -865,14 +761,12 @@ int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, const EVP_PKEY *key) int i2d_PrivateKey_fp(FILE *fp, const EVP_PKEY *pkey) { - return ASN1_i2d_fp(i2d_PrivateKey_thunk, fp, - CHECKED_PTR_OF(const EVP_PKEY, pkey)); + return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey); } EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a) { - return ASN1_d2i_fp(EVP_PKEY_new_thunk, d2i_AutoPrivateKey_thunk, - fp, CHECKED_PPTR_OF(EVP_PKEY, a)); + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a); } EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, @@ -893,8 +787,7 @@ EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey) { - return ASN1_i2d_fp(i2d_PUBKEY_thunk, fp, - CHECKED_PTR_OF(const EVP_PKEY, pkey)); + return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey); } EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, @@ -915,8 +808,7 @@ EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) { - return ASN1_d2i_fp(EVP_PKEY_new_thunk, d2i_PUBKEY_thunk, fp, - CHECKED_PPTR_OF(EVP_PKEY, a)); + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a); } #endif @@ -924,12 +816,14 @@ EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO **p8inf) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), bp, p8inf); + return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, + d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf); } int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, const PKCS8_PRIV_KEY_INFO *p8inf) { - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), bp, p8inf); + return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp, + p8inf); } int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, const EVP_PKEY *key) @@ -947,14 +841,12 @@ int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, const EVP_PKEY *key) int i2d_PrivateKey_bio(BIO *bp, const EVP_PKEY *pkey) { - return ASN1_i2d_bio(i2d_PrivateKey_thunk, bp, - CHECKED_PTR_OF(const EVP_PKEY, pkey)); + return ASN1_i2d_bio_of(EVP_PKEY, i2d_PrivateKey, bp, pkey); } EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a) { - return ASN1_d2i_bio(EVP_PKEY_new_thunk, d2i_AutoPrivateKey_thunk, - bp, CHECKED_PPTR_OF(EVP_PKEY, a)); + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a); } EVP_PKEY *d2i_PrivateKey_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, @@ -978,8 +870,7 @@ err: int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey) { - return ASN1_i2d_bio(i2d_PUBKEY_thunk, bp, - CHECKED_PTR_OF(const EVP_PKEY, pkey)); + return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey); } EVP_PKEY *d2i_PUBKEY_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, @@ -1003,8 +894,7 @@ err: EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) { - return ASN1_d2i_bio(EVP_PKEY_new_thunk, d2i_PUBKEY_thunk, bp, - CHECKED_PPTR_OF(EVP_PKEY, a)); + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); } #ifndef OPENSSL_NO_STDIO diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c index 961f474e5b..90588c8c67 100644 --- a/crypto/x509/x_name.c +++ b/crypto/x509/x_name.c @@ -404,10 +404,8 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in) out->type = V_ASN1_UTF8STRING; out->length = ASN1_STRING_to_UTF8(&out->data, in); - if (out->length < 0) + if (out->length == -1) return 0; - if (out->length == 0) - return 1; to = out->data; from = to; diff --git a/crypto/x509/x_x509a.c b/crypto/x509/x_x509a.c index 3fa17fb925..6dfd68f74d 100644 --- a/crypto/x509/x_x509a.c +++ b/crypto/x509/x_x509a.c @@ -50,8 +50,6 @@ static X509_CERT_AUX *aux_get(X509 *x) int X509_alias_set1(X509 *x, const unsigned char *name, int len) { X509_CERT_AUX *aux; - size_t len_s; - if (!name) { if (!x || !x->aux || !x->aux->alias) return 1; @@ -61,25 +59,14 @@ int X509_alias_set1(X509 *x, const unsigned char *name, int len) } if ((aux = aux_get(x)) == NULL) return 0; - - if (len < -1) - return 0; - - if (len == -1) - len_s = strlen((const char *)name); - else - len_s = len; - if (aux->alias == NULL && (aux->alias = ASN1_UTF8STRING_new()) == NULL) return 0; - return ASN1_STRING_set_data(aux->alias, name, len_s); + return ASN1_STRING_set(aux->alias, name, len); } int X509_keyid_set1(X509 *x, const unsigned char *id, int len) { X509_CERT_AUX *aux; - size_t len_s; - if (!id) { if (!x || !x->aux || !x->aux->keyid) return 1; @@ -89,19 +76,10 @@ int X509_keyid_set1(X509 *x, const unsigned char *id, int len) } if ((aux = aux_get(x)) == NULL) return 0; - - if (len < -1) - return 0; - - if (len == -1) - len_s = strlen((const char *)id); - else - len_s = len; - if (aux->keyid == NULL && (aux->keyid = ASN1_OCTET_STRING_new()) == NULL) return 0; - return ASN1_STRING_set_data(aux->keyid, id, len_s); + return ASN1_STRING_set(aux->keyid, id, len); } const unsigned char *X509_alias_get0(const X509 *x, int *len) diff --git a/demos/Makefile b/demos/Makefile index 3b411fe052..208249e0fd 100644 --- a/demos/Makefile +++ b/demos/Makefile @@ -6,7 +6,6 @@ MODULES = bio \ encrypt \ guide \ http3 \ - info \ kdf \ keyexch \ mac \ diff --git a/demos/README.txt b/demos/README.txt index 9caafcad77..1a7d4f447f 100644 --- a/demos/README.txt +++ b/demos/README.txt @@ -36,18 +36,12 @@ guide: Sample code from the OpenSSL Guide tutorials. See quic-client-block.c: A simple blocking QUIC client quic-client-non-block.c: A simple non-blocking QUIC client quic-multi-stream.c: A simple QUIC client using multiple streams -quic-server-block.c: A simple blocking QUIC server -quic-server-non-block.c: A simple non-blocking QUIC server tls-client-block.c: A simple blocking SSL/TLS client tls-client-non-block.c: A simple non-blocking SSL/TLS client -tls-server-block.c: A simple blocking SSL/TLS server http3: Demonstration of how to use OpenSSL's QUIC capabilities for HTTP/3. -info: -fips-version.c Demonstration of how to query the FIPS provider version - kdf: hkdf.c Demonstration of HMAC based key derivation pbkdf2.c Demonstration of PBKDF2 password based key derivation @@ -84,5 +78,4 @@ rsa_pss_hash.c Compute and verify an RSA-PSS signature over a buffer smime: Demonstrations related to S/MIME sslecho: -echecho.c Simple SSL/TLS echo client/server that uses ECH. main.c Simple SSL/TLS echo client/server. diff --git a/demos/build.info b/demos/build.info index be3252fa9d..3c74e8f331 100644 --- a/demos/build.info +++ b/demos/build.info @@ -1,4 +1,4 @@ -SUBDIRS=bio cipher digest info keyexch mac kdf pkcs12 pkey signature \ +SUBDIRS=bio cipher digest keyexch mac kdf pkey signature \ encrypt encode sslecho IF[{- !$disabled{"h3demo"} -}] diff --git a/demos/guide/build.info b/demos/guide/build.info index 7b5b54f073..de184ff0d1 100644 --- a/demos/guide/build.info +++ b/demos/guide/build.info @@ -5,7 +5,6 @@ # LD_LIBRARY_PATH=../.. ./tls-client-block www.example.com 443 PROGRAMS{noinst} = tls-client-block \ - tls-server-block \ quic-client-block \ quic-multi-stream \ tls-client-non-block \ @@ -18,10 +17,6 @@ INCLUDE[tls-client-block]=../../include SOURCE[tls-client-block]=tls-client-block.c DEPEND[tls-client-block]=../../libcrypto ../../libssl -INCLUDE[tls-server-block]=../../include -SOURCE[tls-server-block]=tls-server-block.c -DEPEND[tls-server-block]=../../libcrypto ../../libssl - INCLUDE[quic-client-block]=../../include SOURCE[quic-client-block]=quic-client-block.c DEPEND[quic-client-block]=../../libcrypto ../../libssl diff --git a/demos/guide/tls-server-block.c b/demos/guide/tls-server-block.c index 8e8410f995..2bee2219ed 100644 --- a/demos/guide/tls-server-block.c +++ b/demos/guide/tls-server-block.c @@ -64,7 +64,6 @@ int main(int argc, char *argv[]) { int res = EXIT_FAILURE; long opts; - long old_timeout; const char *hostport; SSL_CTX *ctx = NULL; BIO *acceptor_bio; @@ -175,11 +174,7 @@ int main(int argc, char *argv[]) * byte array, that identifies the server application, and reduces the * chance of inappropriate cache sharing. */ - if (SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id)) <= 0) { - SSL_CTX_free(ctx); - ERR_print_errors_fp(stderr); - errx(res, "Failed to set server session ID context"); - } + SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id)); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); /* @@ -196,9 +191,7 @@ int main(int argc, char *argv[]) * loaded servers with sporadic connections from any given client, a longer * time may be appropriate. */ - old_timeout = SSL_CTX_set_timeout(ctx, 3600); - if (old_timeout != 3600) - warnx("Changing session timeout from %ld to 3600", old_timeout); + SSL_CTX_set_timeout(ctx, 3600); /* * Clients rarely employ certificate-based authentication, and so we don't diff --git a/demos/http3/ossl-nghttp3-demo-server.c b/demos/http3/ossl-nghttp3-demo-server.c index 227ac6e264..92cc10c067 100644 --- a/demos/http3/ossl-nghttp3-demo-server.c +++ b/demos/http3/ossl-nghttp3-demo-server.c @@ -291,7 +291,7 @@ static int on_recv_header(nghttp3_conn *conn, int64_t stream_id, int32_t token, fprintf(stdout, "\n"); if (token == NGHTTP3_QPACK_TOKEN__PATH) { - int len = (((vvalue.len) < (MAXURL)) ? (vvalue.len) : (MAXURL - 1)); + int len = (((vvalue.len) < (MAXURL)) ? (vvalue.len) : (MAXURL)); memset(h3ssl->url, 0, sizeof(h3ssl->url)); if (vvalue.base[0] == '/') { @@ -1035,7 +1035,7 @@ static int wait_for_activity(SSL *ssl) * "select" (with updated timeouts). */ - return select(sock + 1, &read_fd, &write_fd, NULL, tvp); + return (select(sock + 1, &read_fd, &write_fd, NULL, tvp)); } /* Main loop for server to accept QUIC connections. */ diff --git a/demos/http3/ossl-nghttp3.c b/demos/http3/ossl-nghttp3.c index e75f226221..2461df73c2 100644 --- a/demos/http3/ossl-nghttp3.c +++ b/demos/http3/ossl-nghttp3.c @@ -543,7 +543,7 @@ static void h3_conn_pump_stream(OSSL_DEMO_H3_STREAM *s, void *conn_) break; /* - * This function is confusingly named as it is named from nghttp3's + * This function is confusingly named as it is is named from nghttp3's * 'perspective'; it is used to pass data *into* the HTTP/3 stack which * has been received from the network. */ diff --git a/demos/info/Makefile b/demos/info/Makefile deleted file mode 100644 index 05f1707ba5..0000000000 --- a/demos/info/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# To run the demos when linked with a shared library (default) ensure -# that libcrypto is on the library path. For example: -# - -TESTS = fips-version - -CFLAGS = -I../../include -g -Wall -LDFLAGS = -L../.. -LDLIBS = -lcrypto - -all: $(TESTS) - -fips-version: fips-version.o - -$(TESTS): - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) - -clean: - $(RM) *.o $(TESTS) - -.PHONY: test -test: all - @echo "\nINFO tests:" - @set -e; for tst in $(TESTS); do \ - echo "\n"$$tst; \ - LD_LIBRARY_PATH=../.. \ - OPENSSL_CONF=../../test/fips-and-base.cnf \ - OPENSSL_MODULES=../../providers \ - OPENSSL_CONF_INCLUDE=../../providers \ - ./$$tst; \ - done diff --git a/demos/info/build.info b/demos/info/build.info deleted file mode 100644 index b5339cec91..0000000000 --- a/demos/info/build.info +++ /dev/null @@ -1,11 +0,0 @@ -# -# To run the demos when linked with a shared library (default) ensure -# that libcrypto is on the library path. For example: -# -# LD_LIBRARY_PATH=../.. ./info - -PROGRAMS{noinst} = fips-version - -INCLUDE[fips-version]=../../include -SOURCE[fips-version]=fips-version.c -DEPEND[fips-version]=../../libcrypto diff --git a/demos/info/fips-version.c b/demos/info/fips-version.c deleted file mode 100644 index 6b1bb4bfab..0000000000 --- a/demos/info/fips-version.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - int ret = EXIT_FAILURE; - OSSL_LIB_CTX *libctx; - OSSL_PROVIDER *fips_provider = NULL; - OSSL_PARAM params[2]; - char *version; - - /* Replace this with your libctx if you are using a non-default one */ - libctx = NULL; - - /* Check if the FIPS provider is available in this libctx */ - if (!OSSL_PROVIDER_available(libctx, "fips")) { - puts("FIPS provider is not available"); - goto done; - } - - /* Load the FIPS provider */ - fips_provider = OSSL_PROVIDER_load(libctx, "fips"); - if (fips_provider == NULL) { - puts("Failed to load FIPS provider"); - goto done; - } - - /* Query the FIPS provider version */ - params[0] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION, - &version, 0); - params[1] = OSSL_PARAM_construct_end(); - OSSL_PARAM_set_all_unmodified(params); - if (!OSSL_PROVIDER_get_params(fips_provider, params)) { - puts("Failed to query FIPS provider version"); - goto done; - } - - /* Check if the FIPS provider returned a version to us */ - if (!OSSL_PARAM_modified(params)) { - puts("FIPS provider failed to set version"); - goto done; - } - - printf("FIPS provider version is %s\n", version); - ret = EXIT_SUCCESS; -done: - OSSL_PROVIDER_unload(fips_provider); - return ret; -} diff --git a/demos/pkcs12/build.info b/demos/pkcs12/build.info deleted file mode 100644 index 6fd35d1822..0000000000 --- a/demos/pkcs12/build.info +++ /dev/null @@ -1,16 +0,0 @@ -# -# To run the demos when linked with a shared library (default) ensure that -# libcrypto is on the library path. For example: -# -# LD_LIBRARY_PATH=../.. ./pkread - -PROGRAMS{noinst} = pkread \ - pkwrite - -INCLUDE[pkread]=../../include -SOURCE[pkread]=pkread.c -DEPEND[pkread]=../../libcrypto - -INCLUDE[pkwrite]=../../include -SOURCE[pkwrite]=pkwrite.c -DEPEND[pkwrite]=../../libcrypto diff --git a/demos/pkcs12/pkwrite.c b/demos/pkcs12/pkwrite.c index b274943ce8..7bb73f35a4 100644 --- a/demos/pkcs12/pkwrite.c +++ b/demos/pkcs12/pkwrite.c @@ -25,6 +25,8 @@ int main(int argc, char **argv) fprintf(stderr, "Usage: pkwrite infile password name p12file\n"); exit(EXIT_FAILURE); } + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); if ((fp = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(EXIT_FAILURE); diff --git a/demos/sslecho/build.info b/demos/sslecho/build.info index 7784357ed6..d42716cd51 100644 --- a/demos/sslecho/build.info +++ b/demos/sslecho/build.info @@ -6,15 +6,6 @@ PROGRAMS{noinst} = sslecho - INCLUDE[sslecho]=../../include SOURCE[sslecho]=main.c DEPEND[sslecho]=../../libcrypto ../../libssl - -IF[{- !$disabled{"ech"} -}] - PROGRAMS{noinst} = echecho - - INCLUDE[echecho]=../../include - SOURCE[echecho]=echecho.c - DEPEND[echecho]=../../libcrypto ../../libssl -ENDIF diff --git a/demos/sslecho/echecho.c b/demos/sslecho/echecho.c index d9c757cba2..bcd097d383 100644 --- a/demos/sslecho/echecho.c +++ b/demos/sslecho/echecho.c @@ -7,38 +7,27 @@ * https://www.openssl.org/source/license.html */ -#include #include +#include #include +#include +#include #include #include -#if !defined(OPENSSL_SYS_WINDOWS) -#include -#include -#include - -#define SOCKET int -#define INVALID_SOCKET -1 -#define closesocket(s) close(s) -#else /* defined(OPENSSL_SYS_WINDOWS) */ -#include -#include -#endif /* !defined(OPENSSL_SYS_WINDOWS) */ - static const int server_port = 4433; -static const char echconfig[] - = "AD7+DQA65wAgACA8wVN2BtscOl3vQheUzHeIkVmKIiydUhDCliA4iyQRCwAEAAEA" - "AQALZXhhbXBsZS5jb20AAA=="; -static const char echprivbuf[] - = "-----BEGIN PRIVATE KEY-----\n" - "MC4CAQAwBQYDK2VuBCIEICjd4yGRdsoP9gU7YT7My8DHx1Tjme8GYDXrOMCi8v1V\n" - "-----END PRIVATE KEY-----\n" - "-----BEGIN ECHCONFIG-----\n" - "AD7+DQA65wAgACA8wVN2BtscOl3vQheUzHeIkVmKIiydUhDCliA4iyQRCwAEAAEA" - "AQALZXhhbXBsZS5jb20AAA==\n" - "-----END ECHCONFIG-----\n"; +static const char echconfig[] = "AD7+DQA65wAgACA8wVN2BtscOl3vQheUzHeIkVmKIiydUhDCliA4iyQRCwAEAAEAAQALZXhhbXBsZS5jb20AAA=="; +static const char echprivbuf[] = "-----BEGIN PRIVATE KEY-----\n" + "MC4CAQAwBQYDK2VuBCIEICjd4yGRdsoP9gU7YT7My8DHx1Tjme8GYDXrOMCi8v1V\n" + "-----END PRIVATE KEY-----\n" + "-----BEGIN ECHCONFIG-----\n" + "AD7+DQA65wAgACA8wVN2BtscOl3vQheUzHeIkVmKIiydUhDCliA4iyQRCwAEAAEAAQALZXhhbXBsZS5jb20AAA==\n" + "-----END ECHCONFIG-----\n"; + +typedef unsigned char bool; +#define true 1 +#define false 0 /* * This flag won't be useful until both accept/read (TCP & SSL) methods @@ -46,14 +35,14 @@ static const char echprivbuf[] */ static volatile bool server_running = true; -static SOCKET create_socket(bool isServer) +int create_socket(bool isServer) { - SOCKET s; + int s; int optval = 1; struct sockaddr_in addr = { 0 }; s = socket(AF_INET, SOCK_STREAM, 0); - if (s == INVALID_SOCKET) { + if (s < 0) { perror("Unable to create socket"); exit(EXIT_FAILURE); } @@ -64,7 +53,7 @@ static SOCKET create_socket(bool isServer) addr.sin_addr.s_addr = INADDR_ANY; /* Reuse the address; good for quick restarts */ - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(optval)) + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { perror("setsockopt(SO_REUSEADDR) failed"); exit(EXIT_FAILURE); @@ -84,7 +73,7 @@ static SOCKET create_socket(bool isServer) return s; } -static SSL_CTX *create_context(bool isServer) +SSL_CTX *create_context(bool isServer) { const SSL_METHOD *method; SSL_CTX *ctx; @@ -108,7 +97,7 @@ static int configure_ech(SSL_CTX *ctx, int server, unsigned char *buf, size_t len) { OSSL_ECHSTORE *es = NULL; - BIO *es_in = BIO_new_mem_buf(buf, (int)len); + BIO *es_in = BIO_new_mem_buf(buf, len); if (es_in == NULL || (es = OSSL_ECHSTORE_new(NULL, NULL)) == NULL) goto err; @@ -126,7 +115,7 @@ err: return 0; } -static void configure_server_context(SSL_CTX *ctx) +void configure_server_context(SSL_CTX *ctx) { /* Set the key and cert */ if (SSL_CTX_use_certificate_chain_file(ctx, "cert.pem") <= 0) { @@ -147,7 +136,7 @@ static void configure_server_context(SSL_CTX *ctx) } } -static void configure_client_context(SSL_CTX *ctx) +void configure_client_context(SSL_CTX *ctx) { /* * Configure the client to abort the handshake if certificate verification @@ -155,11 +144,9 @@ static void configure_client_context(SSL_CTX *ctx) */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); /* - * In a real application you would probably just use the default system - * certificate trust store and call: + * In a real application you would probably just use the default system certificate trust store and call: * SSL_CTX_set_default_verify_paths(ctx); - * In this demo though we are using a self-signed certificate, - * so the client must trust it directly. + * In this demo though we are using a self-signed certificate, so the client must trust it directly. */ if (!SSL_CTX_load_verify_locations(ctx, "cert.pem", NULL)) { ERR_print_errors_fp(stderr); @@ -173,7 +160,7 @@ static void configure_client_context(SSL_CTX *ctx) } } -static void usage(void) +void usage() { printf("Usage: echecho s\n"); printf(" --or--\n"); @@ -182,7 +169,6 @@ static void usage(void) exit(1); } -#define BUFFERSIZE 1024 int main(int argc, char **argv) { bool isServer; @@ -191,13 +177,13 @@ int main(int argc, char **argv) SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; - SOCKET server_skt = INVALID_SOCKET; - SOCKET client_skt = INVALID_SOCKET; + int server_skt = -1; + int client_skt = -1; - /* used by fgets */ - char buffer[BUFFERSIZE]; + /* used by getline relying on realloc, can't be statically allocated */ char *txbuf = NULL; size_t txcap = 0; + int txlen; char rxbuf[128]; size_t rxcap = sizeof(rxbuf); @@ -206,7 +192,7 @@ int main(int argc, char **argv) char *rem_server_ip = NULL; struct sockaddr_in addr = { 0 }; - socklen_t addr_len = (socklen_t)sizeof(addr); + unsigned int addr_len = sizeof(addr); char *outer_sni = NULL, *inner_sni = NULL; int ech_status; @@ -253,7 +239,7 @@ int main(int argc, char **argv) /* Wait for TCP connection from client */ client_skt = accept(server_skt, (struct sockaddr *)&addr, &addr_len); - if (client_skt == INVALID_SOCKET) { + if (client_skt < 0) { perror("Unable to accept"); exit(EXIT_FAILURE); } @@ -262,11 +248,7 @@ int main(int argc, char **argv) /* Create server SSL structure using newly accepted client socket */ ssl = SSL_new(ssl_ctx); - if (SSL_set_fd(ssl, (int)client_skt) <= 0) { - puts("Unable to set fd for the SSL object"); - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + SSL_set_fd(ssl, client_skt); /* Wait for SSL connection from the client */ if (SSL_accept(ssl) <= 0) { @@ -286,11 +268,8 @@ int main(int argc, char **argv) /* Echo loop */ while (true) { - /* - * Get message from client; will fail if client closes - * connection - */ - if ((rxlen = SSL_read(ssl, rxbuf, (int)rxcap)) <= 0) { + /* Get message from client; will fail if client closes connection */ + if ((rxlen = SSL_read(ssl, rxbuf, rxcap)) <= 0) { if (rxlen == 0) { printf("Client closed connection\n"); } @@ -318,12 +297,7 @@ int main(int argc, char **argv) /* Cleanup for next client */ SSL_shutdown(ssl); SSL_free(ssl); - closesocket(client_skt); - /* - * Set client_skt to INVALID_SOCKET to avoid double close when - * server_running become false before next accept - */ - client_skt = INVALID_SOCKET; + close(client_skt); } } printf("Server exiting...\n"); @@ -352,19 +326,11 @@ int main(int argc, char **argv) /* Create client SSL structure using dedicated client socket */ ssl = SSL_new(ssl_ctx); - if (SSL_set_fd(ssl, (int)client_skt) <= 0) { - puts("Unable to set fd for the SSL object"); - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + SSL_set_fd(ssl, client_skt); /* Set hostname for SNI */ SSL_set_tlsext_host_name(ssl, rem_server_ip); /* Configure server hostname check */ - if (SSL_set1_ipaddr(ssl, rem_server_ip) <= 0) { - puts("Unable to set IP address for the SSL object"); - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + SSL_set1_host(ssl, rem_server_ip); /* Now do SSL connect with server */ if (SSL_connect(ssl) == 1) { @@ -382,11 +348,9 @@ int main(int argc, char **argv) /* Loop to send input from keyboard */ while (true) { /* Get a line of input */ - memset(buffer, 0, BUFFERSIZE); - txbuf = fgets(buffer, BUFFERSIZE, stdin); - + txlen = getline(&txbuf, &txcap, stdin); /* Exit loop on error */ - if (txbuf == NULL) { + if (txlen < 0 || txbuf == NULL) { break; } /* Exit loop if just a carriage return */ @@ -394,14 +358,14 @@ int main(int argc, char **argv) break; } /* Send it to the server */ - if ((result = SSL_write(ssl, txbuf, (int)strlen(txbuf))) <= 0) { + if ((result = SSL_write(ssl, txbuf, txlen)) <= 0) { printf("Server closed connection\n"); ERR_print_errors_fp(stderr); break; } /* Wait for the echo */ - rxlen = SSL_read(ssl, rxbuf, (int)rxcap); + rxlen = SSL_read(ssl, rxbuf, rxcap); if (rxlen <= 0) { printf("Server closed connection\n"); ERR_print_errors_fp(stderr); @@ -428,10 +392,10 @@ exit: } SSL_CTX_free(ssl_ctx); - if (client_skt != INVALID_SOCKET) - closesocket(client_skt); - if (server_skt != INVALID_SOCKET) - closesocket(server_skt); + if (client_skt != -1) + close(client_skt); + if (server_skt != -1) + close(server_skt); if (txbuf != NULL && txcap > 0) free(txbuf); diff --git a/doc/build.info b/doc/build.info index 44b06941e4..6e8dfedb5c 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1499,10 +1499,6 @@ DEPEND[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod GENERATE[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod DEPEND[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod GENERATE[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod -DEPEND[html/man3/NAME_CONSTRAINTS_check.html]=man3/NAME_CONSTRAINTS_check.pod -GENERATE[html/man3/NAME_CONSTRAINTS_check.html]=man3/NAME_CONSTRAINTS_check.pod -DEPEND[man/man3/NAME_CONSTRAINTS_check.3]=man3/NAME_CONSTRAINTS_check.pod -GENERATE[man/man3/NAME_CONSTRAINTS_check.3]=man3/NAME_CONSTRAINTS_check.pod DEPEND[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod GENERATE[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod DEPEND[man/man3/NCONF_new_ex.3]=man3/NCONF_new_ex.pod @@ -3430,7 +3426,6 @@ html/man3/GENERAL_NAME.html \ html/man3/HMAC.html \ html/man3/MD5.html \ html/man3/MDC2_Init.html \ -html/man3/NAME_CONSTRAINTS_check.html \ html/man3/NCONF_new_ex.html \ html/man3/OBJ_nid2obj.html \ html/man3/OCSP_REQUEST_new.html \ @@ -4106,7 +4101,6 @@ man/man3/GENERAL_NAME.3 \ man/man3/HMAC.3 \ man/man3/MD5.3 \ man/man3/MDC2_Init.3 \ -man/man3/NAME_CONSTRAINTS_check.3 \ man/man3/NCONF_new_ex.3 \ man/man3/OBJ_nid2obj.3 \ man/man3/OCSP_REQUEST_new.3 \ diff --git a/doc/designs/fixed-size-large-numbers.md b/doc/designs/fixed-size-large-numbers.md new file mode 100644 index 0000000000..e6f059cd80 --- /dev/null +++ b/doc/designs/fixed-size-large-numbers.md @@ -0,0 +1,623 @@ +Fixed size large numbers +======================== + +*`BIGNUM` redesign for better constant time calculations* +--------------------------------------------------------- + +
+

Abstract

+ +

+In this design, we explore and define how OpenSSL's `BIGNUM` library can +be remodelled for constant-size calculations. Furthermore, we explore and +define a fixed size large number library, which never changes the in-memory +size of a number once it has been allocated. +

+ +
+ +### Table of contents: + +- [Background][] +- [Goals][] +- [Challenges][] +- [Design][] + - [The `OSSL_FN` type][] + - [The `OSSL_FN_CTX` type][] + - [The `OSSL_FN_CTX` type, with frames][] + - [The `OSSL_FN_CTX` type, without frames][] + - [The `BIGNUM` type][] + - [Mutability][] + - [Memory functionality for `OSSL_FN`][] + - [Memory functionality for `OSSL_FN_CTX`][] + - [Failures][] +- [Repurposing existing code][] +- [How to apply `OSSL_FN`][] +- [Where to apply `OSSL_FN`][] +- [How to apply `OSSL_FN_CTX`][] + - [The variant with frames][] + - [The variant without frames][] +- [Testing][] +- [Appendix][] + - [Using the C99 flexible array member feature][] + +Background +========== + +[Background]: #background + +The current internal definition of OpenSSL's `BIGNUM` looks like this: + +```c +struct bignum_st { + BN_ULONG *d; /* + * Pointer to an array of 'BN_BITS2' bit + * chunks. These chunks are organised in + * a least significant chunk first order. + */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; +}; +``` + +The fields `d`, `top` and `dmax` allow the numbers to be quite dynamic in +terms of its memory footprint, as it can both increase in size[^1] and +decrease in size.[^2] + +Furthermore, the result of any `BIGNUM` operation may be the same `BIGNUM` +instance as any of the operands, which means that any `BIGNUM` may have its +memory footprint adjusted at any time. + +While this is very flexible, it leaves uncertainties about the time any +calculation may take, following any earlier calculation, which is a security +vulnerability. + +[^1]: the array `d` is reallocated to a larger size and `dmax` as well as top + are updated +[^2]: `top` is diminished + +Goals +===== + +[Goals]: #goals + +Overall goal: Introduce a new type and API that are inherently constant size +to replace the existing `BIGNUM` usage. + +The intention is to enhance this one aspect of constant time calculations. +Other aspects are considered out of scope for this design. + +The included sub-goals are: + +* To define a new large number type and accompanying API, that doesn't allow + size adjustments of the large numbers once their individual size has been + established +* To define that large number type and API in such a way it's compatible + with the `BIGNUM` type, so that a `BIGNUM` may use an `OSSL_FN` as its + backing storage and selected call sites may acquire an `OSSL_FN` view of + a `BIGNUM`. +* To ensure that the new large number API is constant-size +* To repurpose as much as possible of our current `BIGNUM` code for the new + large number API, especially our assembler code (with the assumption that + everything that doesn't change the `BIGNUM` sizes can be repurposed as is) +* To replace all security critical large number calculations so that they + are not just constant-size in themselves, but that the whole set of + calculations remains constant-size, within OpenSSL code + +Challenges +========== + +[Challenges]: #challenges + +The challenges we have are: + +- **`BIGNUM` usage** + + Because `BIGNUM` is a public facing API, it's likely to be used by OpenSSL + users. This existing API needs to be backward compatible, but performance + isn't necessarily critical. + +- **constant-time through constant-size** + + To make calculation time predictable on a broader scale than on a + per-operation basis, there's a need to ensure that each large number being + used in the calculations involved has a fixed size, i.e. to avoid the sort + of dynamic sizing that the `BIGNUM` functionality does. + +Design +====== + +[Design]: #design + +The overall design defines a new type, `OSSL_FN` (where FN is short for +"FIXNUM"), which can somehow be made compatible with `BIGNUM`, but yet be +distinct. Early thoughts on this was to make them essentially the same type +internally, and cast between them, but unfortunately, a compliant C compiler +is very likely to auto-cast between them, making it difficult to keep them +separate yet castable back and forth. + +To allow a stricter or more explicit way to remedy the flexibility of the C +language, this design therefore defines a `OSSL_FN` which is separate from +the `BIGNUM`, yet compatible with BIGNUM insofar that the `BIGNUM` type +wraps around the `OSSL_FN` type. + +The compatibility is primarily at the storage and acquisition boundary. A +`BIGNUM` may use an `OSSL_FN` as its backing storage, and selected internal +crypto call sites that already receive `BIGNUM` values may acquire the +embedded `OSSL_FN` and perform security-critical calculations with `OSSL_FN` +functions. + +This does not mean that ordinary `BIGNUM` (`BN_`) operation functions are +wrappers around corresponding `OSSL_FN` operation functions. `BN_` +functions retain their dynamic `BIGNUM` semantics. Conversely, once +execution has entered an `OSSL_FN` operation, that operation must remain +inside the "`OSSL_FN` only" bubble and must not call functions that take +`BIGNUM` arguments. + +This restriction does not apply to low-level helpers that operate only on +`BN_ULONG` arrays or primitive limb values, such as existing `bn_` word +functions. `BN_ULONG` and `OSSL_FN_ULONG` are compatible, so such helpers +may be reused by `OSSL_FN` code as long as they do not allocate, resize, or +otherwise operate on `BIGNUM` objects. + +The overall design also defines new associated types to replace their +`BIGNUM` counterparts: `OSSL_FN_CTX`, `OSSL_FN_BLINDING`, `OSSL_FN_MONT_CTX`, +and `OSSL_FN_RECP_CTX`. Notably, however, the callback type `BN_GENCB` +isn't replaced, as it contains nothing `BIGNUM`, and can therefore be reused +unchanged with an `OSSL_FN` API. + +The `OSSL_FN` type and API will be designed in such a way to enable it to +become public at some point in the future. *The initial version will not be +public and will only be used internally within OpenSSL.* + +Let's go over the details + +The `OSSL_FN` type +------------------ + +[The `OSSL_FN` type]: #the-ossl_fn-type + +The `OSSL_FN` type would be a structure derived from the existing `BIGNUM` +type, retaining a minimum amount of data. Just as was previously with +`BIGNUM`, the absolute value of the number is stored in a `BN_ULONG` array. +`OSSL_FN` itself is unsigned; sign handling remains with `BIGNUM` when +`BIGNUM` values are used as carriers. + +```c +typedef struct ossl_fn_st OSSL_FN; + +struct ossl_fn_st { + /* Flag: alloced with OSSL_FN_new() or OSSL_FN_secure_new() */ + unsigned int is_dynamically_allocated : 1; + /* Flag: alloced with OSSL_FN_secure_new() */ + unsigned int is_securely_allocated : 1; + + /* + * The d array, with its size in number of BN_ULONG. + * This stores the number itself + */ + size_t dsize; + BN_ULONG d[]; +}; +``` + +The `OSSL_FN_CTX` type +---------------------- + +[The `OSSL_FN_CTX` type]: #the-ossl_fn_ctx-type + +The `OSSL_FN_CTX` type is made to replace the `BN_CTX` type where `OSSL_FN` +type is used instead of `BIGNUM`. + +The `OSSL_FN_CTX` type is to be implemented as an arena (a large enough chunk +of memory) in which `OSSL_FN` instances are allocated. More in detail, there +are two possibilities. + +### The `OSSL_FN_CTX` type, with frames + +[The `OSSL_FN_CTX` type, with frames]: #the-ossl_fn_ctx-type-with-frames + +This variant is intended to mimic all `BN_CTX` functionality. The idea is to +create a large `OSSL_FN_CTX` at the top function of a complex calculation, and +pass it around to all sub-function calls. + +Each sub-function would begin with starting a frame (using `OSSL_FN_CTX_begin()`, +similar in spirit to `BN_CTX_start()`) in the passed `OSSL_FN_CTX` arena, +obtain what temporary `OSSL_FN`s it needs from it (using `OSSL_FN_CTX_get()`, +similar in spirit to `BN_CTX_get()`), perform what calculations it needs, and +finish with ending the frame (using `OSSL_FN_CTX_end()`, similar in spirit to +`BN_CTX_end()`), which relinquishing that frame's space in the `OSSL_FN_CTX` +arena, and thereby making that same space available for the next sub-function. + +```c +typedef struct ossl_fn_ctx_st OSSL_FN_CTX; + +struct ossl_fn_ctx_frame_st; /* forwarding, see below */ +struct ossl_fn_ctx_st { + /* + * Pointer to the last OSSL_FN_CTX_start() location (a simple pointer into + * the memory area). See the struct ossl_fn_ctx_frame_st definition below + * for details. + */ + struct ossl_fn_ctx_frame_st *last_frame; + /* + * The arena itself. + */ + size_t msize; /* bytes */ + unsigned char memory[]; +}; + +struct ossl_fn_ctx_frame_st { + /* + * Pointer back to the whole arena where the frame is located, to access + * |msize| and |memory| from it. + */ + struct ossl_fn_ctx_st *arena; + /* + * Pointer to the previous frame in the arena, allowing OSSL_FN_CTX_end() + * to do its job. + */ + struct ossl_fn_ctx_frame_st *previous_frame; + /* + * Pointer to the free area of the frame. Every time OSSL_FN_CTX_get() is + * called, the current value of this pointer is returned, and it's updated + * by incrementing it by the number of bytes given by OSSL_FN_CTX_get(). + * The available number of bytes is limited by what's left in the arena. + */ + unsigned char *free_memory; + unsigned char memory[]; +}; +``` + +The arena design requires that the total use of the arena can be predicted +at the point of allocating the arena. There is an inherent uncertainty how +large an arena should be to accommodate the needs of a large tree of +function calls using it. A possible solution is to allocate a very large +arena (could 32kB be considered enough?), but it may require some +investigation to find out what's reasonable. + +Looking at the current use of `BN_CTX_new`, it can be noted that they are +allocated all over current OpenSSL code, so it's easy to assume that each is +used in a fairly limited fashion. Furthermore, the `BN_CTX` internals allow +for a maximum of 16 `BIGNUM`s. A corresponding arena could the reasonably +have the size 16 \* *size of largest fixed number* plus a little extra for +bookkeeping purposes. + +### The `OSSL_FN_CTX` type, without frames + +[The `OSSL_FN_CTX` type, without frames]: #the-ossl_fn_ctx-type-without-frames + +Compared to the variant with frames, this `OSSL_FN_CTX` variant is much +simpler, but also more heap allocation intense. + +The idea with this one is that each function that needs to obtain temporary +`OSSL_FN`s would also create their own `OSSL_FN_CTX`, independently from any +other function. + +```c +typedef struct ossl_fn_ctx_st OSSL_FN_CTX; + +struct ossl_fn_ctx_st { + /* + * Pointer to the free area of the arena. Every time OSSL_FN_CTX_get() is + * called, the current value of this pointer is returned, and it's updated + * by incrementing it by the number of bytes given by OSSL_FN_CTX_get(). + * The available number of bytes is limited by what's left in the arena. + */ + unsigned char *free_memory; + /* + * The arena itself. + */ + size_t msize; /* bytes */ + unsigned char memory[]; +}; +``` + +Other associated types +---------------------- + +[Other associated types]: #other-associated-types + +There are a few types that, like `BN_CTX` / `OSSL_FN_CTX`, are used to hold +a context around some more complicated calculations. Just like `OSSL_FN_CTX`, +The `OSSL_FN` variants of these types are made into strictly separate types, +not compatible with their `BIGNUM` counterparts. + +| `BIGNUM` types | `OSSL_FN` types | +|----------------|--------------------| +| `BN_BLINDING` | `OSSL_FN_BLINDING` | +| `BN_MONT_CTX` | `OSSL_FN_MONT_CTX` | +| `BN_RECP_CTX` | `OSSL_FN_RECP_CTX` | + +Their `OSSL_FN` APIs for these types should be possible to create by +repurposing the corresponding `BIGNUM` APIs, with adjustments for the +constant-size requirements of all `OSSL_FN` functions. + +The `BIGNUM` type +----------------- + +[The `BIGNUM` type]: #the-bignum-type + +The `BIGNUM` type is changed to include a `OSSL_FN` for its data, while +retaining the fields that support the dynamic `BIGNUM` semantics: + +```c +struct bignum_st { + OSSL_FN *data; + /* Some of these flags are replicated in OSSL_FN, some are not */ + int flags; + + BN_ULONG *d; /* Pointer to |data->d| */ + int top; /* Index of last used d +1. */ + int dmax; /* Copy of |data->dsize| */ + int neg; /* One if the number is negative */ +}; +``` + +In normal public use, `data` is non-NULL and `d` points at `data->d`. +Certain internal or otherwise special `BIGNUM`s may still have `data` set to +NULL, in which case `d` points directly at a `BN_ULONG` array. Such cases +must not be forced to grow an `OSSL_FN` backing object solely to fit this +structure. How `OSSL_FN` code should use the `BN_ULONG` data from such +`BIGNUM`s remains an implementation detail. + +When structured this way, it's easy to get an `OSSL_FN` out of a `BIGNUM`: + +```c +/* + * BN_acquire_fn() and BN_release_fn() function together. It is done this + * way as a safety measure, to make sure that a BIGNUM doesn't expand an OSSL_FN + * that the caller currently has a handle on. However, it's possible to + * adjust the size of the OSSL_FN while acquiring it. + */ +OSSL_FN *BN_acquire_fn(BIGNUM *a, size_t bits) +{ + if ((bn_expand(a, bits)) <= 0) + return NULL; + /* Implementation may do further acquisition bookkeeping here. */ + return a->data; +} +void BN_release_fn(BIGNUM *a) +{ + /* Implementation may do further release bookkeeping here. */ +} +``` + +Note that these functions are not designed to be thread-safe. By design, +holding pointers to a `BIGNUM` and its wrapped `OSSL_FN` at the same time +should only happen in a very short term. + +Mutability +---------- + +[Mutability]: #mutability + +The understanding is that within a `OSSL_FN` API, `dsize` is immutable as +soon as a `OSSL_FN` has been allocated to its target size, except for when +the `OSSL_FN` instance is freed. + +When accessed through the `BIGNUM` type (i.e. by the `BIGNUM` API), the +`OSSL_FN` size may be reallocated to allow a larger size than initially +allocated, and `dsize` may be modified accordingly. The exception is an +acquired `OSSL_FN` view. Once a caller has acquired the backing `OSSL_FN` +from a `BIGNUM`, that backing size must be treated as immutable until +release. The owning `BIGNUM` must not simultaneously be used through `BN_` +operations that could resize or otherwise reinterpret the same storage. + +The `OSSL_FN_CTX` API is much more strict. The size of an `OSSL_FN_CTX` +instance is immutable after it has been allocated, except when it is freed. + +Memory functionality for `OSSL_FN` +---------------------------------- + +[Memory functionality for `OSSL_FN`]: #memory-functionality-for-ossl_fn + +We anticipate that we will need the following functions to allocate and +deallocate `OSSL_FN`s: + +```c +OSSL_FN *OSSL_FN_new(size_t size); +void OSSL_FN_free(OSSL_FN *f); +``` + +Memory functionality for `OSSL_FN_CTX` +-------------------------------------- + +[Memory functionality for `OSSL_FN_CTX`]: #memory-functionality-for-ossl_fn_ctx + +We anticipate that the `OSSL_FN_CTX` API will look very much like the +`BN_CTX` API, except for the allocation functionality: + +```c +OSSL_FN_CTX *OSSL_FN_CTX_new(OSSL_LIB_CTX *libctx, size_t arena_size); +OSSL_FN_CTX *OSSL_FN_CTX_secure_new(OSSL_LIB_CTX *libctx, size_t arena_size); +void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx); + +OSSL_FN *OSSL_FN_CTX_get(OSSL_FN_CTX *ctx, size_t size); +``` + +*Something to be noted is that `OSSL_FN_CTX_secure_new()` allocates the +whole arena in secure memory. The impact compared to allocating individual +`OSSL_FN` instances in secure memory is considered minimal.* + +If the variant of `OSSL_FN_CTX` *with frames* is chosen, the following +functions will also have to be defined: + +```c +int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx); +int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx); +``` + +Failures +-------- + +[Failures]: #failures + +A fixed size large number introduces new problems, which introduces new ways +that the `OSSL_FN` API can fail: + +* Overflow: this will happen when the caller has allocated an improperly + sized `OSSL_FN` to store future calculation results in. *This is akin to + memory allocation failures in so far that there isn't enough memory space* + +Repurposing existing code +========================= + +[Repurposing existing code]: #repurposing-existing-code + +A majority of existing internal `BIGNUM` code operates directly on the `d` +array of the existing `BIGNUM` structure, with the size of that array given +separately, and are already essentially operating on fixed size numbers. +This design assumes that such functions can be repurposed for `OSSL_FN` +functionality with zero change, apart from function name changes. + +Furthermore, the remaining functions, which do manipulate the size of the +`BIGNUM`, or are public facing `BIGNUM` functions, retain their current +`BIGNUM` functionality, including size manipulation within the `BIGNUM` +"bubble". They are not wrapped around `OSSL_FN` functions; conversion +between `BIGNUM` and `OSSL_FN` happens at top-level crypto call sites, +where the embedded `OSSL_FN` is acquired and passed to `OSSL_FN` +functions, during whose execution the `OSSL_FN` size is immutable (see +[Mutability][]). + +How to apply `OSSL_FN` +====================== + +[How to apply `OSSL_FN`]: #how-to-apply-ossl_fn + +The purpose of `OSSL_FN` is to make the number constant size (implying +enhanced constant time) for a crypto system. To guarantee this with high +confidence, any function that performs some sort of numeric operation on a +set of input `OSSL_FN`s must only use other functions that only affect the +contents of their `d` array, but not its size. Those are typically other +`OSSL_FN` functions, or reused bignum functions that receive the `d` array +and its size directly. + +Where to apply `OSSL_FN` +======================== + +[Where to apply `OSSL_FN`]: #where-to-apply-ossl_fn + +`OSSL_FN` should primarily be used instead of `BIGNUM` in internal +calculations throughout OpenSSLs libraries. Exceptions can be made where +calculations aren't security critical. + +In this, "calculations" is meant in a mathematical sense, i.e. whatever what +would be expressed as a mathematical formula is considered a "calculation". + +However, `BIGNUM` has other uses than mere calculations. For example, +`BIGNUM` is used as storage of numbers that were originally ASN.1 INTEGERs, +and while individual ASN.1 INTEGERs always have a known size, they are +usually just one number in a set, and it's often only known at a later time +what are the size requirements of the cryptosystem that use them. +For example, the size of an RSA key can only be determined when a known +number in that key - usually *n* - has been seen by code, and this affects +what size all numbers in an RSA key should be adjusted to before doing +calculations on them. + +How to apply `OSSL_FN_CTX` +========================== + +[How to apply `OSSL_FN_CTX`]: #how-to-apply-ossl_fn_ctx + +The variant with frames +----------------------- + +[The variant with frames]: #the-variant-with-frames + +All internal uses of `BN_CTX_new()` and `BN_CTX_new_ex()` are to be replaced +with calls of `OSSL_FN_CTX_new()`. + +All internal uses of `BN_CTX_secure_new()` and `BN_CTX_secure_new_ex()` are to +be replaced with calls of `OSSL_FN_CTX_secure_new()`. + +All internal uses of `BN_CTX_free()` are to be replaced with calls of +`OSSL_FN_CTX_free()`. + +All internal uses of `BN_CTX_start()` are to be replaced with calls of +`OSSL_FN_CTX_start()`. + +All internal uses of `BN_CTX_get()` are to be replaced with calls of +`OSSL_FN_CTX_get()`. + +All internal uses of `BN_CTX_end()` are to be replaced with calls of +`OSSL_FN_CTX_end()`. + +The variant without frames +-------------------------- + +[The variant without frames]: #the-variant-without-frames + +All internal uses of `BN_CTX_new()`, `BN_CTX_new_ex()`, `BN_CTX_secure_new()`, +`BN_CTX_secure_new_ex()`, and `BN_CTX_free()` are to be dropped. + +All internal uses of `BN_CTX_start()` are to be replaced with calls of +`OSSL_FN_CTX_new()`. + +All internal uses of `BN_CTX_get()` are to be replaced with calls of +`OSSL_FN_CTX_get()`. + +All internal uses of `BN_CTX_end()` are to be replaced with calls of +`OSSL_FN_CTX_free()`. + +Testing +======= + +[Testing]: #testing + +Functional tests similar to `test/recipes/10-test_bn.t` must be added. + +Timing tests to compare operations on a variety of inputs of different sizes +must also be added. These tests should perform operations based on a given +fixed number size. + +It should also prove interesting to collect timing statistics for a set of +operations using `BIGNUM` in previous OpenSSL versions and compare them with +similar timing statistics using `BIGNUM` when reimplemented according to this +design. + +Appendix +======== + +[Appendix]: #appendix + +Using the C99 flexible array member feature +------------------------------------------- + +[Using the C99 flexible array member feature]: #using-the-c99-flexible-array-member-feature + +In this design, the C99 feature that's dubbed "flexible array member" is used +extensively. This a `struct` member that's an array, that must come last in +the struct, and that is incomplete in so far that no array size is given. It +can look like this: + +``` C +struct t { + size_t a; + char b; + char c[]; /**< flexible array member */ +}; +``` + +Some attention must be paid to how it's arranged in memory. It's debated +whether the offset of a flexible array member's offset from the start of the +`struct` is set to be before or after the `struct`'s end padding, i.e. whether +`sizeof(struct t) == offsetof(struct t, c)` is true or not in all circumstances. + +Here's how that would differ on a 64-bit system: + +| location of `c` | `offsetof(struct t, a)` | `offsetof(struct t, b)` | `offsetof(struct t, c)` | `sizeof(struct t)` | +|-----------------|:-----------------------:|:-----------------------:|:-----------------------:|:------------------:| +| before padding | 0 | 8 | 9 | 16 | +| after padding | 0 | 8 | 16 | 16 | + +To be noted, `gcc` and `clang` favor "before padding". + +For consistent placement of the flexible array member, one therefore needs to +pay attention to possible `struct` padding. Among other methods, one chosen +here is to precede the flexible array member with a member whose type is +assumed to be large enough that no padding is needed after it, such as +`size_t` or a pointer. diff --git a/doc/designs/passing-algorithmidentifier-parameters.md b/doc/designs/passing-algorithmidentifier-parameters.md index 0e6126b056..9c5669e86b 100644 --- a/doc/designs/passing-algorithmidentifier-parameters.md +++ b/doc/designs/passing-algorithmidentifier-parameters.md @@ -129,10 +129,10 @@ at all when such parameter data needs to be passed. Background / tl;dr ------------------ -### AlgorithmIdentifier parameter and how it's used +### AlgorithmIdenfier parameter and how it's used OpenSSL has historically done a few tricks to not have to pass -AlgorithmIdentifier parameter data to the backend implementations of +AlgorithmIdenfier parameter data to the backend implementations of cryptographic operations: - In some cases, they were passed as part of the lower level key structure diff --git a/doc/designs/quic-design/quic-ackm.md b/doc/designs/quic-design/quic-ackm.md index 38d72aac3c..488fded5e1 100644 --- a/doc/designs/quic-design/quic-ackm.md +++ b/doc/designs/quic-design/quic-ackm.md @@ -424,7 +424,7 @@ This should be called for a packet before attempting to process its contents. Failure to do so may may result in processing a duplicated packet in violation of the RFC. -The return value of this function transitions from 1 to 0 for a given PN once +The returrn value of this function transitions from 1 to 0 for a given PN once that PN is passed to ossl_ackm_on_rx_packet, thus this function must be used before calling `ossl_ackm_on_rx_packet`. diff --git a/doc/designs/quic-design/quic-api-ssl-funcs.md b/doc/designs/quic-design/quic-api-ssl-funcs.md index 37229c26e6..6333bafab8 100644 --- a/doc/designs/quic-design/quic-api-ssl-funcs.md +++ b/doc/designs/quic-design/quic-api-ssl-funcs.md @@ -108,6 +108,9 @@ Notes: | `SSL_test_functions` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | | `SSL_select_next_proto` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | | **⇒ Methods** | | | | | | +| `SSLv3_method` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | +| `SSLv3_client_method` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | +| `SSLv3_server_method` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | | `TLS_method` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | | `TLS_client_method` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | | `TLS_server_method` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done | diff --git a/doc/designs/quic-design/quic-requirements.md b/doc/designs/quic-design/quic-requirements.md index daeb50db66..c8aeedc7b7 100644 --- a/doc/designs/quic-design/quic-requirements.md +++ b/doc/designs/quic-design/quic-requirements.md @@ -60,7 +60,7 @@ and that were specific to QUIC * For the MVP a single interop target (i.e. the server implementation list): - 1. [Cloudflare](https://cloudflare-quic.com/) + 1. [Cloudfare](https://cloudflare-quic.com/) * Testing against other implementations is not a release requirement for the MVP. diff --git a/doc/internal/man3/bn_mul_words.pod b/doc/internal/man3/bn_mul_words.pod index d2d8e3397a..7dc4267fd6 100644 --- a/doc/internal/man3/bn_mul_words.pod +++ b/doc/internal/man3/bn_mul_words.pod @@ -4,7 +4,7 @@ bn_mul_words, bn_mul_add_words, bn_sqr_words, bn_div_words, bn_add_words, bn_sub_words, bn_mul_comba4, bn_mul_comba8, -bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_normal, +bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_truncated, bn_mul_normal, bn_mul_low_normal, bn_mul_recursive, bn_mul_part_recursive, bn_mul_low_recursive, bn_sqr_normal, bn_sqr_recursive, bn_expand, bn_wexpand, bn_expand2, bn_fix_top, bn_check_top, @@ -32,6 +32,8 @@ library internal functions int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n); + void bn_mul_truncated(BN_ULONG *r, int rn, BN_ULONG *a, int na, + BN_ULONG *b, int nb); void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb); void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n); @@ -151,6 +153,11 @@ bn_cmp_words(B, B, B) operates on the B word arrays B and B. It returns 1, 0 and -1 if B is greater than, equal and less than B. +bn_mul_truncated(B, B, B, B, B, B) operates on the +B word array B, the B word array B and the B word array +B. It computes B*B and places the result in B, truncated to +B words. + bn_mul_normal(B, B, B, B, B) operates on the B word array B, the B word array B and the B+B word array B. It computes B*B and places the result in B. diff --git a/doc/internal/man3/evp_generic_fetch.pod b/doc/internal/man3/evp_generic_fetch.pod index 53f29c1e98..016494239e 100644 --- a/doc/internal/man3/evp_generic_fetch.pod +++ b/doc/internal/man3/evp_generic_fetch.pod @@ -187,7 +187,8 @@ And here's the implementation of the FOO method fetcher: EVP_FOO *foo = vfoo; int ref = 0; - return CRYPTO_UP_REF(&foo->refcnt, &ref); + CRYPTO_UP_REF(&foo->refcnt, &ref); + return 1; } static void foo_free(void *vfoo) diff --git a/doc/internal/man7/VERSION.pod b/doc/internal/man7/VERSION.pod index 8ffd836c13..4bc8ba6b93 100644 --- a/doc/internal/man7/VERSION.pod +++ b/doc/internal/man7/VERSION.pod @@ -26,7 +26,7 @@ The keys that are recognised are: The three parts of OpenSSL's 3 numbered version number, MAJOR.MINOR.PATCH. These are used to compose the values for the C macros B, -B, B. +B, B. =item B diff --git a/doc/man1/openssl-ciphers.pod.in b/doc/man1/openssl-ciphers.pod.in index db8b6e55e1..c7e1291c83 100644 --- a/doc/man1/openssl-ciphers.pod.in +++ b/doc/man1/openssl-ciphers.pod.in @@ -269,12 +269,12 @@ Cipher suites using DSS authentication, i.e. the certificates carry DSS keys. Cipher suites using ECDSA authentication, i.e. the certificates carry ECDSA keys. -=item B, B +=item B, B, B -Lists cipher suites introduced in TLS v1.2 or TLS v1.0 respectively. +Lists cipher suites introduced in TLS v1.2, TLS v1.0 or SSL v3.0 respectively. Note: there are no cipher suites specific to TLS v1.1. -Since this is only the minimum version, if, for example, TLSv1.2 is negotiated -then both TLSv1.2 and TLSv1.0 cipher suites are available. +Since this is only the minimum version, if, for example, TLSv1.0 is negotiated +then both TLSv1.0 and SSLv3.0 cipher suites are available. Note: these cipher strings B change the negotiated version of SSL or TLS, they only affect the list of available cipher suites. diff --git a/doc/man1/openssl-ec.pod.in b/doc/man1/openssl-ec.pod.in index 2fd397da00..a60b796c00 100644 --- a/doc/man1/openssl-ec.pod.in +++ b/doc/man1/openssl-ec.pod.in @@ -122,6 +122,9 @@ This specifies how the points on the elliptic curve are converted into octet strings. Possible values are: B, B (the default value) and B. For more information regarding the point conversion forms please read the X9.62 standard. +B Due to patent issues the B option is disabled +by default for binary curves and can be enabled by defining +the preprocessor macro B at compile time. =item B<-param_enc> I diff --git a/doc/man1/openssl-ecparam.pod.in b/doc/man1/openssl-ecparam.pod.in index d48f19d789..ca4e002762 100644 --- a/doc/man1/openssl-ecparam.pod.in +++ b/doc/man1/openssl-ecparam.pod.in @@ -98,6 +98,9 @@ This specifies how the points on the elliptic curve are converted into octet strings. Possible values are: B, B (the default value) and B. For more information regarding the point conversion forms please read the X9.62 standard. +B Due to patent issues the B option is disabled +by default for binary curves and can be enabled by defining +the preprocessor macro B at compile time. =item B<-param_enc> I diff --git a/doc/man1/openssl-pkey.pod.in b/doc/man1/openssl-pkey.pod.in index bb6fcde863..52cc5712b2 100644 --- a/doc/man1/openssl-pkey.pod.in +++ b/doc/man1/openssl-pkey.pod.in @@ -179,9 +179,12 @@ This cannot be combined with encoded output in DER format. This option only applies to elliptic-curve based keys. This specifies how the points on the elliptic curve are converted -into octet strings. Possible values are: B (the default -value), B and B. For more information regarding +into octet strings. Possible values are: B (the default +value), B and B. For more information regarding the point conversion forms please read the X9.62 standard. +B Due to patent issues the B option is disabled +by default for binary curves and can be enabled by defining +the preprocessor macro B at compile time. =item B<-ec_param_enc> I diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in index 590bfe3a6d..053385ca0b 100644 --- a/doc/man1/openssl-pkeyutl.pod.in +++ b/doc/man1/openssl-pkeyutl.pod.in @@ -677,10 +677,8 @@ L, =head1 HISTORY Since OpenSSL 3.5, -the B<-digest> option implies B<-rawin>. The B<-rawin> option is no longer -required when signing or verifying with a key type that does not support a -prehash digest, such as Ed25519, Ed448, ML-DSA, or SLH-DSA. For these key -types, B<-digest> is not supported. +the B<-digest> option implies B<-rawin>, and these two options are +no longer required when signing or verifying with an Ed25519 or Ed448 key. Also since OpenSSL 3.5, the B<-kemop> option is no longer required for any of the supported algorithms, the only supported B is now the default. diff --git a/doc/man1/openssl-rand.pod.in b/doc/man1/openssl-rand.pod.in index 4d4cda2b4d..d38961acc3 100644 --- a/doc/man1/openssl-rand.pod.in +++ b/doc/man1/openssl-rand.pod.in @@ -12,7 +12,6 @@ B [B<-out> I] [B<-base64>] [B<-hex>] -[B<-n>] {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_provider_synopsis -} I[K|M|G|T] @@ -56,10 +55,6 @@ Perform base64 encoding on the output. Show the output as a hex string. -=item B<-n> - -Do not output the trailing newline. - {- $OpenSSL::safe::opt_r_item -} {- $OpenSSL::safe::opt_provider_item -} diff --git a/doc/man3/ASN1_INTEGER_get_int64.pod b/doc/man3/ASN1_INTEGER_get_int64.pod index d25c87a5e2..4ba6c4c0d7 100644 --- a/doc/man3/ASN1_INTEGER_get_int64.pod +++ b/doc/man3/ASN1_INTEGER_get_int64.pod @@ -108,7 +108,7 @@ B structure respectively or NULL if an error occurs. They will only fail due to a memory allocation error. ASN1_INTEGER_to_BN() and ASN1_ENUMERATED_to_BN() return a B structure -or NULL if an error occurs. They can fail if the passed type is incorrect +of NULL if an error occurs. They can fail if the passed type is incorrect (due to programming error) or due to a memory allocation failure. =head1 SEE ALSO diff --git a/doc/man3/ASN1_STRING_length.pod b/doc/man3/ASN1_STRING_length.pod index 5b047f084a..47cacb253a 100644 --- a/doc/man3/ASN1_STRING_length.pod +++ b/doc/man3/ASN1_STRING_length.pod @@ -2,7 +2,6 @@ =head1 NAME -ASN1_STRING_set_data, ASN1_STRING_set_string, ASN1_STRING_length_ex, ASN1_STRING_dup, ASN1_STRING_cmp, ASN1_STRING_set, ASN1_STRING_length, ASN1_STRING_type, ASN1_STRING_get0_data, ASN1_STRING_to_UTF8 - ASN1_STRING utility functions @@ -11,30 +10,19 @@ ASN1_STRING_to_UTF8 - ASN1_STRING utility functions #include + int ASN1_STRING_length(ASN1_STRING *x); const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x); ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a); int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b); + int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); + int ASN1_STRING_type(const ASN1_STRING *x); int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in); - int ASN1_STRING_set_data(ASN1_STRING *str, const uint8_t *data, size_t len); - - int ASN1_STRING_set_string(ASN1_STRING *str, const char *data); - - size_t ASN1_STRING_length_ex(const ASN1_STRING *x); - -The following functions have been deprecated since OpenSSL 4.1, and can be -hidden entirely by defining B with a suitable version value, -see L: - - int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); - - int ASN1_STRING_length(ASN1_STRING *x); - =head1 DESCRIPTION These functions allow an B structure to be manipulated. @@ -50,25 +38,9 @@ ASN1_STRING_dup() returns a copy of the structure I. ASN1_STRING_cmp() compares I and I returning 0 if the two are identical. The string types and content are compared. -ASN1_STRING_set() allocates memory for string I to hold I -bytes of data. Any previously allocated memory owned by I will be -freed or re-used. If I is not NULL, I bytes are copied -from the memory pointed to by I to I. If I is -1 then -the length is determined by strlen(data). - -ASN1_STRING_set_data() allocates memory for string I to hold -I bytes of data. Any previously allocated memory owned by I -will be freed or re-used. If I is not NULL, I bytes are -copied from the memory pointed to by I to I. It is an error -to use this function on a string of type B. - -ASN1_STRING_set_string() allocates memory for the string I and makes -a copy of the characters from I. Any previously -allocated memory owned by I will be freed or re-used. I -must point to a valid NUL-terminated C string, and must not be -NULL. The terminating NUL byte is not included in the data copied into -I. It is an error to use this function on a string of type -B. +ASN1_STRING_set() sets the data of string I to the buffer +I or length I. The supplied data is copied. If I +is -1 then the length is determined by strlen(data). ASN1_STRING_type() returns the type of I, using standard constants such as B. @@ -98,9 +70,8 @@ actual string type itself: for example for an IA5String the data will be ASCII, for a BMPString two bytes per character in big endian format, and for a UTF8String it will be in UTF8 format. -Similar care should be taken to ensure the data is in the correct -format when calling ASN1_STRING_set(), ASN1_STRING_set_data(), or -ASN1_STRING_set_string(). +Similar care should be take to ensure the data is in the correct format +when calling ASN1_STRING_set(). =head1 RETURN VALUES @@ -115,8 +86,7 @@ error occurred. ASN1_STRING_cmp() returns an integer greater than, equal to, or less than 0, according to whether I is greater than, equal to, or less than I. -ASN1_STRING_set(), ASN1_STRING_set_data(), and -ASN1_STRING_set_string() return 1 on success or 0 on error or failure. +ASN1_STRING_set() returns 1 on success or 0 on error. ASN1_STRING_type() returns the type of I. @@ -127,11 +97,6 @@ negative value if an error occurred. L -=head1 HISTORY - -ASN1_STRING_set_data(), ASN1_STRING_set_string(), and ASN1_STRING_length_ex() -were added in OpenSSL 4.1. - =head1 COPYRIGHT Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/ASN1_aux_cb.pod b/doc/man3/ASN1_aux_cb.pod index 9a38ab168f..9963ea1350 100644 --- a/doc/man3/ASN1_aux_cb.pod +++ b/doc/man3/ASN1_aux_cb.pod @@ -59,7 +59,7 @@ Arbitrary application data =item I -Flags which indicate the auxiliary functionality supported. +Flags which indicate the auxiliarly functionality supported. The B flag indicates that objects support reference counting. @@ -106,11 +106,9 @@ During the processing of an B object the callbacks set via I or I will be invoked as a result of various events indicated via the I parameter. The value of I<*in> will be the B object being processed based on the template in I. An -additional operation specific parameter may be passed in I. The -currently supported operations are as follows. Unless noted otherwise below, -the callbacks should return a positive value on success and zero on error; -some operations recognise additional return values, and a few do not consult -the return value at all. +additional operation specific parameter may be passed in I. The currently +supported operations are as follows. The callbacks should return a positive +value on success or zero on error, unless otherwise noted below. =over 4 @@ -132,15 +130,13 @@ I<*pval>. Invoked when processing a B, B or B structure immediately before an B is freed. If the callback originally constructed the B via B then it should free it at -this point and return 2; the caller will then skip its normal freeing. Any -other return value (including zero) causes the caller to proceed with normal -freeing; the hook cannot signal an error. +this point and return 2 from the callback. Otherwise it should return 1 for +success or 0 on error. =item B Invoked when processing a B, B or B structure -immediately after B sub-structures are freed. The caller does not -consult the return value from this hook. +immediately after B sub-structures are freed. =item B @@ -166,10 +162,7 @@ immediately after a "i2d" operation for the B. Invoked when processing a B or B structure immediately before printing the B. The I argument will be a pointer to an -B structure (see below). If the callback has fully printed the -value itself it should return 2; the caller will then skip the per-field -printing loop and the matching B callback. Return zero on -error or any other positive value to continue with normal printing. +B structure (see below). =item B @@ -267,41 +260,8 @@ The streaming I/O boundary. =head1 RETURN VALUES -In general the callbacks return zero on error and a positive value on -success. Several operations have additional or different return-value -semantics, summarised here: - -=over 4 - -=item * - -B recognises a return of 2, meaning that the callback has -allocated the B itself and normal allocation should be skipped. - -=item * - -B recognises a return of 2, meaning that the callback has -freed the B itself and normal freeing should be skipped. Other -return values (including zero) cause normal freeing to proceed; the hook -cannot signal an error. - -=item * - -B's return value is not consulted by the caller. - -=item * - -B recognises a return of 2, meaning that the callback -has printed the value itself; the caller will skip the per-field printing -loop and the matching B invocation. - -=item * - -B, B, B, and -B treat any non-positive return value (zero or -negative) as an error. - -=back +The callbacks return 0 on error and a positive value on success. Some operations +require specific positive success values as noted above. =head1 SEE ALSO diff --git a/doc/man3/ASN1_item_d2i_bio.pod b/doc/man3/ASN1_item_d2i_bio.pod index 9b3f389a23..f8e4678367 100644 --- a/doc/man3/ASN1_item_d2i_bio.pod +++ b/doc/man3/ASN1_item_d2i_bio.pod @@ -59,16 +59,6 @@ B provided in the I parameter and the property query string in I. See L for more information about algorithm fetching. -When reading from I, decoding consumes one complete DER-encoded structure -and leaves any following bytes in the BIO, so concatenated structures can be -read with successive calls. Reaching the end of the input cleanly, at a -structure boundary, is not treated as an error: the function returns NULL -without adding to the error queue. If the end of the input is reached in the -middle of a structure, or an indefinite-length value is missing its -end-of-contents octets (that is, the input is truncated), an error is queued -with reason code B. The same applies to -ASN1_item_d2i_fp_ex(). - ASN1_item_d2i_bio() is the same as ASN1_item_d2i_bio_ex() except that the default B is used (i.e. NULL) and with a NULL property query string. @@ -102,12 +92,6 @@ that the I and I can be used when doing algorithm fetching. ASN1_item_d2i_bio(), ASN1_item_unpack_ex() and ASN1_item_unpack() return a pointer to an B or NULL on error. -The ASN1_item_d2i_bio() and ASN1_item_d2i_fp() functions, including their -B<_ex> variants, also return NULL at a clean end of input. In that case the -error queue is left unchanged, so a caller reading concatenated structures in -a loop can distinguish a clean end of input from a decoding error by -inspecting the error queue, for example with L. - ASN1_item_i2d_mem_bio() returns a pointer to a memory BIO or NULL on error. ASN1_item_pack() returns a pointer to an B or NULL on error. @@ -121,7 +105,7 @@ The function ASN1_item_unpack_ex() was added in OpenSSL 3.2. =head1 COPYRIGHT -Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/BIO_s_datagram.pod b/doc/man3/BIO_s_datagram.pod index b28dcf088c..634c3a9af4 100644 --- a/doc/man3/BIO_s_datagram.pod +++ b/doc/man3/BIO_s_datagram.pod @@ -65,7 +65,7 @@ the underlying socket is configured and how it is to be used; see below. =item -Use of BIO_s_datagram() with an unconnected network socket is hazardous because +Use of BIO_s_datagram() with an unconnected network socket is hazardous hecause any successful call to BIO_read() results in the peer address used for any subsequent call to BIO_write() being set to the source address of the datagram received by that call to BIO_read(). Thus, unless the caller calls diff --git a/doc/man3/BIO_s_file.pod b/doc/man3/BIO_s_file.pod index 6cd1da02a3..5dcd4bbbca 100644 --- a/doc/man3/BIO_s_file.pod +++ b/doc/man3/BIO_s_file.pod @@ -14,8 +14,8 @@ BIO_rw_filename - FILE bio BIO *BIO_new_file(const char *filename, const char *mode); BIO *BIO_new_fp(FILE *stream, int flags); - long BIO_set_fp(BIO *b, FILE *fp, int flags); - long BIO_get_fp(BIO *b, FILE **fpp); + BIO_set_fp(BIO *b, FILE *fp, int flags); + BIO_get_fp(BIO *b, FILE **fpp); int BIO_read_filename(BIO *b, char *name); int BIO_write_filename(BIO *b, char *name); @@ -87,7 +87,8 @@ BIO_s_file() returns the file BIO method. BIO_new_file() and BIO_new_fp() return a file BIO or NULL if an error occurred. -BIO_set_fp() and BIO_get_fp() return 1 for success or <=0 for failure. +BIO_set_fp() and BIO_get_fp() return 1 for success or <=0 for failure +(although the current implementation never return 0). BIO_seek() returns 0 for success or negative values for failure. diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod index f7375f2c58..80bbdcc95f 100644 --- a/doc/man3/CMS_EncryptedData_decrypt.pod +++ b/doc/man3/CMS_EncryptedData_decrypt.pod @@ -46,7 +46,7 @@ are used when retrieving algorithms from providers. CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise returns 1. CMS_EnvelopedData_decrypt() returns NULL if an error occurred, -otherwise a BIO containing the decrypted content. +otherwise a BIO containing the decypted content. =head1 SEE ALSO diff --git a/doc/man3/EVP_KDF.pod b/doc/man3/EVP_KDF.pod index 6df44e8643..b9cc14eb79 100644 --- a/doc/man3/EVP_KDF.pod +++ b/doc/man3/EVP_KDF.pod @@ -6,7 +6,7 @@ EVP_KDF, EVP_KDF_fetch, EVP_KDF_free, EVP_KDF_up_ref, EVP_KDF_CTX, EVP_KDF_CTX_new, EVP_KDF_CTX_free, EVP_KDF_CTX_dup, EVP_KDF_CTX_reset, EVP_KDF_derive, EVP_KDF_CTX_set_SKEY, EVP_KDF_derive_SKEY, -EVP_KDF_CTX_get_kdf_size, EVP_KDF_CTX_get0_kdf, EVP_KDF_CTX_get1_kdf, +EVP_KDF_CTX_get_kdf_size, EVP_KDF_get0_provider, EVP_KDF_CTX_kdf, EVP_KDF_is_a, EVP_KDF_get0_name, EVP_KDF_names_do_all, EVP_KDF_get0_description, EVP_KDF_CTX_get_params, EVP_KDF_CTX_set_params, EVP_KDF_do_all_provided, @@ -22,8 +22,7 @@ EVP_KDF_CTX_gettable_params, EVP_KDF_CTX_settable_params - EVP KDF routines typedef struct evp_kdf_ctx_st EVP_KDF_CTX; EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf); - const EVP_KDF *EVP_KDF_CTX_get0_kdf(const EVP_KDF_CTX *ctx); - EVP_KDF *EVP_KDF_CTX_get1_kdf(EVP_KDF_CTX *ctx); + const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx); void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx); EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src); void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx); @@ -58,12 +57,6 @@ EVP_KDF_CTX_gettable_params, EVP_KDF_CTX_settable_params - EVP KDF routines const OSSL_PARAM *EVP_KDF_CTX_settable_params(const EVP_KDF *kdf); const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf); -The following functions have been deprecated since OpenSSL 4.1, -and can be hidden entirely by defining B with a suitable -version value, see L: - - const EVP_KDF *EVP_KDF_CTX_kdf(const EVP_KDF_CTX *ctx); - =head1 DESCRIPTION The EVP KDF routines are a high-level interface to Key Derivation Function @@ -106,10 +99,8 @@ EVP_KDF_CTX_new() creates a new context for the KDF implementation I. EVP_KDF_CTX_free() frees up the context I. If I is NULL, nothing is done. -EVP_KDF_CTX_get0_kdf() returns the B associated with the context -I. EVP_KDF_CTX_get1_kdf() is the same, except ownership is passed -to the caller. -EVP_KDF_CTX_kdf() is an alias for EVP_KDF_CTX_get0_kdf(). +EVP_KDF_CTX_kdf() returns the B associated with the context +I. =head2 Computing functions @@ -333,12 +324,6 @@ This functionality was added in OpenSSL 3.0. EVP_KDF_derive_SKEY() and EVP_KDF_CTX_set_SKEY() functions were introduced in OpenSSL 3.6. -EVP_KDF_CTX_get0_kdf() and EVP_KDF_CTX_get1_kdf() functions were introduced -in OpenSSL 4.1. - -EVP_KDF_CTX_kdf() function was deprecated in favour of EVP_KDF_CTX_get0_kdf() -in OpenSSL 4.1. - =head1 COPYRIGHT Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod index 1ca411e5d7..e5b05701f7 100644 --- a/doc/man3/EVP_MAC.pod +++ b/doc/man3/EVP_MAC.pod @@ -147,7 +147,7 @@ as part of this call or separately using EVP_MAC_CTX_set_params(). Providing non-NULL I to this function is equivalent to calling EVP_MAC_CTX_set_params() with those I for the same I beforehand. Note: There are additional requirements for some MAC algorithms during -re-initialization (i.e. calling EVP_MAC_init() on an EVP_MAC after EVP_MAC_final() +re-initalization (i.e. calling EVP_MAC_init() on an EVP_MAC after EVP_MAC_final() has been called on the same object). See the NOTES section below. EVP_MAC_init() should be called before EVP_MAC_update() and EVP_MAC_final(). @@ -352,7 +352,7 @@ The usage of the parameter names "custom", "iv" and "salt" correspond to the names used in the standard where the algorithm was defined. Some MAC algorithms store internal state that cannot be extracted during -re-initialization. For example GMAC cannot extract an B from the +re-initalization. For example GMAC cannot extract an B from the underlying CIPHER context, and so calling EVP_MAC_init() on an EVP_MAC object after EVP_MAC_final() has been called cannot reset its cipher state to what it was when the B was initially generated. For such instances, an diff --git a/doc/man3/EVP_PKEY_CTX_new.pod b/doc/man3/EVP_PKEY_CTX_new.pod index 9ded13de5d..fff102a769 100644 --- a/doc/man3/EVP_PKEY_CTX_new.pod +++ b/doc/man3/EVP_PKEY_CTX_new.pod @@ -48,9 +48,6 @@ EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_from_name() are normally used when no B structure is associated with the operations, for example during parameter generation or key generation for some algorithms. -The key returned by L is not associated with the -generation context. To perform operations using that key, create a new context -with L. EVP_PKEY_CTX_dup() duplicates the context I. It is not supported for a keygen operation. @@ -128,7 +125,7 @@ added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2026 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_decrypt.pod b/doc/man3/EVP_PKEY_decrypt.pod index 6b46329793..5e624e8c61 100644 --- a/doc/man3/EVP_PKEY_decrypt.pod +++ b/doc/man3/EVP_PKEY_decrypt.pod @@ -17,13 +17,12 @@ EVP_PKEY_decrypt - decrypt using a public key algorithm =head1 DESCRIPTION -The EVP_PKEY_decrypt_init() function initializes the public key algorithm -context I for a decryption operation. A key must already be associated -with I; this is normally done by creating it with -L or L. +The EVP_PKEY_decrypt_init() function initializes a public key algorithm +context using key I for a decryption operation. -The EVP_PKEY_decrypt_init_ex() function is the same as -EVP_PKEY_decrypt_init() but additionally sets the algorithm-specific I. +The EVP_PKEY_decrypt_init_ex() function initializes a public key algorithm +context using key I for a decryption operation and sets the +algorithm specific I. The EVP_PKEY_decrypt() function performs a public key decryption operation using I. The data to be decrypted is specified using the I and @@ -89,7 +88,7 @@ Decrypt data using OAEP (for RSA keys): * NB: assumes key, in, inlen are already set up * and that key is an RSA private key */ - ctx = EVP_PKEY_CTX_new_from_pkey(NULL, key, NULL); + ctx = EVP_PKEY_CTX_new(key, NULL); if (!ctx) /* Error occurred */ if (EVP_PKEY_decrypt_init(ctx) <= 0) @@ -126,7 +125,7 @@ These functions were added in OpenSSL 1.0.0. =head1 COPYRIGHT -Copyright 2006-2026 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_encrypt.pod b/doc/man3/EVP_PKEY_encrypt.pod index fda95c218e..1fb41f99f4 100644 --- a/doc/man3/EVP_PKEY_encrypt.pod +++ b/doc/man3/EVP_PKEY_encrypt.pod @@ -17,13 +17,12 @@ EVP_PKEY_encrypt_init, EVP_PKEY_encrypt - encrypt using a public key algorithm =head1 DESCRIPTION -The EVP_PKEY_encrypt_init() function initializes the public key algorithm -context I for an encryption operation. A key must already be associated -with I; this is normally done by creating it with -L or L. +The EVP_PKEY_encrypt_init() function initializes a public key algorithm +context using key B for an encryption operation. -The EVP_PKEY_encrypt_init_ex() function is the same as -EVP_PKEY_encrypt_init() but additionally sets the algorithm-specific I. +The EVP_PKEY_encrypt_init_ex() function initializes a public key algorithm +context using key B for an encryption operation and sets the +algorithm specific B. The EVP_PKEY_encrypt() function performs a public key encryption operation using B. The data to be encrypted is specified using the B and @@ -67,7 +66,7 @@ L for means to load a public key. * NB: assumes key, in, inlen are already set up, * and that key is an RSA public key */ - ctx = EVP_PKEY_CTX_new_from_pkey(NULL, key, NULL); + ctx = EVP_PKEY_CTX_new(key, NULL); if (!ctx) /* Error occurred */ if (EVP_PKEY_encrypt_init(ctx) <= 0) @@ -105,7 +104,7 @@ These functions were added in OpenSSL 1.0.0. =head1 COPYRIGHT -Copyright 2006-2026 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_keygen.pod b/doc/man3/EVP_PKEY_keygen.pod index 71daed31c0..1d5180ef6f 100644 --- a/doc/man3/EVP_PKEY_keygen.pod +++ b/doc/man3/EVP_PKEY_keygen.pod @@ -66,12 +66,6 @@ parameters or key are written to I<*ppkey>. If I<*ppkey> is NULL when this function is called, it will be allocated, and should be freed by the caller when no longer useful, using L. -When a key is generated, EVP_PKEY_generate() does not associate it with I -or change I into a context for operations using that key. To use the -generated key, create a new context with L, -passing I<*ppkey>. The generation context can be reused for further generation -operations or freed. - EVP_PKEY_paramgen() and EVP_PKEY_keygen() do exactly the same thing as EVP_PKEY_generate(), after checking that the corresponding EVP_PKEY_paramgen_init() or EVP_PKEY_keygen_init() was used to initialize I. @@ -159,7 +153,7 @@ in functions which require the use of a public key or parameters. =head1 EXAMPLES -Generate a 2048 bit RSA key, then initialize a context for encryption: +Generate a 2048 bit RSA key: #include #include @@ -167,7 +161,7 @@ Generate a 2048 bit RSA key, then initialize a context for encryption: EVP_PKEY_CTX *ctx; EVP_PKEY *pkey = NULL; - ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!ctx) /* Error occurred */ if (EVP_PKEY_keygen_init(ctx) <= 0) @@ -176,15 +170,7 @@ Generate a 2048 bit RSA key, then initialize a context for encryption: /* Error */ /* Generate key */ - if (EVP_PKEY_generate(ctx, &pkey) <= 0) - /* Error */ - - /* ctx is still a generation context; pkey contains the generated key */ - EVP_PKEY_CTX_free(ctx); - ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); - if (!ctx) - /* Error occurred */ - if (EVP_PKEY_encrypt_init(ctx) <= 0) + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) /* Error */ Generate a key from a set of parameters: diff --git a/doc/man3/EVP_PKEY_verify_recover.pod b/doc/man3/EVP_PKEY_verify_recover.pod index 52682f2aa5..10084d61c1 100644 --- a/doc/man3/EVP_PKEY_verify_recover.pod +++ b/doc/man3/EVP_PKEY_verify_recover.pod @@ -22,10 +22,10 @@ EVP_PKEY_verify_recover_init_ex2, EVP_PKEY_verify_recover =head1 DESCRIPTION EVP_PKEY_verify_recover_init() initializes a public key algorithm context -I for a verify-recover operation using the algorithm given when the -context was created using L or variants thereof. The -algorithm is used to fetch a B method implicitly, see -L for more information about implicit fetches. +I for signing using the algorithm given when the context was created +using L or variants thereof. The algorithm is used to +fetch a B method implicitly, see L +for more information about implicit fetches. EVP_PKEY_verify_recover_init_ex() is the same as EVP_PKEY_verify_recover_init() but additionally sets the passed parameters @@ -35,8 +35,8 @@ EVP_PKEY_verify_recover_init_ex2() is the same as EVP_PKEY_verify_recover_init_e but works with an explicitly fetched B I. A context I without a pre-loaded key cannot be used with this function. Depending on what algorithm was fetched, certain details revolving around the -treatment of the input to EVP_PKEY_verify_recover() may be pre-determined, and -in that case, those details may normally not be changed. +treatment of the input to EVP_PKEY_verify() may be pre-determined, and in that +case, those details may normally not be changed. See L below for a deeper explanation. The EVP_PKEY_verify_recover() function recovers signed data @@ -132,7 +132,7 @@ The EVP_PKEY_verify_recover_init_ex() function was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2013-2026 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/HMAC.pod b/doc/man3/HMAC.pod index d6cd404ab6..53a3853eb2 100644 --- a/doc/man3/HMAC.pod +++ b/doc/man3/HMAC.pod @@ -112,9 +112,6 @@ be authenticated (I bytes at I). HMAC_Final() places the message authentication code in I, which must have space for the hash function output. -After calling HMAC_Final() no calls to HMAC_Update() or HMAC_Final() can be -made, but HMAC_Init_ex() can be called to initialize a new HMAC -operation. HMAC_CTX_copy() copies all of the internal state from I into I. diff --git a/doc/man3/NAME_CONSTRAINTS_check.pod b/doc/man3/NAME_CONSTRAINTS_check.pod deleted file mode 100644 index 3dfe39ea29..0000000000 --- a/doc/man3/NAME_CONSTRAINTS_check.pod +++ /dev/null @@ -1,211 +0,0 @@ -=pod - -=head1 NAME - -NAME_CONSTRAINTS_check, -NAME_CONSTRAINTS_check_CN - check a certificate's names against a name -constraints extension - -=head1 SYNOPSIS - - #include - - int NAME_CONSTRAINTS_check(const X509 *x, NAME_CONSTRAINTS *nc); - int NAME_CONSTRAINTS_check_CN(const X509 *x, NAME_CONSTRAINTS *nc); - -=head1 DESCRIPTION - -NAME_CONSTRAINTS_check() tests whether the names asserted by certificate -I satisfy the name constraints I. It implements the matching -primitive of RFC 5280 section 4.2.1.10: given a constraint set (a -B structure containing zero or more B -and B) and a candidate certificate, decide whether the -certificate's names fall within the permitted subtrees and outside the -excluded subtrees. - -The names considered by NAME_CONSTRAINTS_check() are: - -=over 4 - -=item * - -The certificate's subject distinguished name, matched as a B -general-name type. The subject is considered only when it is nonempty. - -=item * - -Each B attribute appearing within the subject distinguished -name, matched as an B general-name type. These attributes are -the historical, pre-SAN way of expressing an email address in a -certificate's subject, and RFC 5280 requires that they be subjected to -name-constraint checking. - -=item * - -Each entry in the certificate's subject alternative name extension, matched -according to its declared general-name type. - -=back - -NAME_CONSTRAINTS_check() implements matching for the following -general-name types: B, B, B, -B, and B. The B form -B (RFC 8398) is additionally matched against -B subtrees. Any other general-name type, including -B, B, B, and other B -forms, yields B. - -For each name considered, the function evaluates two conditions: - -=over 4 - -=item * - -If I contains at least one B of the same general-name -type as the name, the name must match at least one of those permitted -subtrees. If I contains no permitted subtrees of that type, no -permitted-subtrees test is imposed on names of that type. - -=item * - -The name must not match any B of the same general-name -type in I. - -=back - -The function returns at the first violation encountered; it does not -collect or report multiple failures. - -For B entries, matching follows the byte/label algorithm of -RFC 5280 section 4.2.1.10, which RFC 5280 mandates when no -protocol-specific matching rules apply. Because this match is performed -without awareness of any specific higher-level protocol, additional -matching rules defined by later or more specific protocols must be -applied independently of this function to the certificate chain. - -NAME_CONSTRAINTS_check() performs only the constraint match for a single -certificate against a single constraint set. It does B perform the -chain-wide enforcement of RFC 5280 section 6.1.4(g)-(j): callers wishing to -enforce name constraints across an entire certification path must walk the -chain themselves and apply each ancestor's constraint set to certificates -lower in the chain, observing the usual exceptions (for example, -self-issued intermediate certificates are exempt from constraints imposed -by certificates above them, except when they are the leaf of the chain). -For full RFC 5280 name-constraint enforcement integrated with chain -validation, applications should use L, which performs -this internally. - -NAME_CONSTRAINTS_check() enforces an implementation limit on the product -of the certificate's name count and the constraint set's subtree count, to -prevent computationally expensive matching on pathological input. If that -limit is exceeded the function returns B without -performing any matching. The current limit is 2**20 (1,048,576) on the -product of the name count (subject DN entries plus B -entries) and the subtree count (B plus -B). - -=head1 RETURN VALUES - -NAME_CONSTRAINTS_check() returns B if every name considered -satisfies the constraints. Otherwise it returns one of the following -B codes: - -=over 4 - -=item B - -A name of a type for which I contains at least one permitted subtree -failed to match any of those subtrees. - -=item B - -A name matched an excluded subtree. - -=item B - -A subtree in I specified a B other than 0 or a B at -all. RFC 5280 requires that these B fields not be used, -and a constraint set that uses them cannot be processed. - -=item B - -A general-name type for which matching is not implemented was encountered. -The list of supported types is given in the DESCRIPTION above. - -=item B - -A name in the certificate is encoded in a way that cannot be matched (for -example, an B attribute in the subject that is not encoded -as an B). - -=item B - -The product of the certificate's name count and the constraint set's -subtree count exceeded the implementation limit; no matching was -performed. - -=back - -Other B codes may be returned by deeper name-matching -helpers (for example, codes arising from individual general-name type -comparisons). Callers should treat the return value as the authoritative -success/failure signal and treat any value other than B as a -failure, rather than enumerating the specific codes above. - -=head1 NOTES - -NAME_CONSTRAINTS_check() does not match the certificate's commonName -against B name constraints; that check is provided by a separate -function, B(). The commonName-as-DNS-identity -practice is a legacy concern: modern certificates assert DNS identities -through B entries in the subject alternative name extension, -which NAME_CONSTRAINTS_check() already covers. NAME_CONSTRAINTS_check_CN() -is required only for older certificates that express a DNS identity -through their commonName instead of, or in addition to, the SAN; for -certificates conforming to modern profiles a call to NAME_CONSTRAINTS_check() -alone is generally sufficient. - -=head1 BUGS - -RFC 9525's wildcard semantics apply only to presented-identifier -matching for TLS service identity, and explicitly call out they are not -valid for any other purpose; they do not define wildcard handling -for name-constraint matching. NAME_CONSTRAINTS_check() therefore -follows RFC 5280's requirements for when this is undefined, and treats -the B<*> character in a B as a literal label component, per -the RFC 5280 algorithm, which is often contrary to caller expectation. - -Even if specified in the future, due to the "fallback implementation" -nature of matching wildcards in SAN B entries specified by -RFC 5280, name constraint behaviour in the presence of wildcards -should not be strictly relied upon across implementations and -protocols. This matters most for the use of B -constraints, which should not be relied upon to reliably constrain -signing certificates for a PKI in a security dependent manner unless -the consumers of these certificates are themselves known to be -constrained by other means to only use implementations that provide -different semantics, or the PKI can be constrained by other means to -ensure that wildcards are never issued from such signing -certificates. - -=head1 SEE ALSO - -L, -L - -=head1 HISTORY - -NAME_CONSTRAINTS_check() was added in OpenSSL 1.0.0. - -NAME_CONSTRAINTS_check_CN() was added in OpenSSL 1.1.0. - -=head1 COPYRIGHT - -Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index 9e4cd0c22a..ce8a0b7fc9 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -846,7 +846,7 @@ Perform a Certification Request transaction, making use of the new credentials: OSSL_CMP_CTX_set1_cert(cmp_ctx, initialCert); OSSL_CMP_CTX_set1_pkey(cmp_ctx, initialKey); - OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, currentKey); + OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, curentKey); currentCert = OSSL_CMP_exec_CR_ses(cmp_ctx); Perform a Key Update Request, signed using the cert (and key) to be updated: diff --git a/doc/man3/SSL_CIPHER_get_name.pod b/doc/man3/SSL_CIPHER_get_name.pod index d0cee8adf1..4a159a68b8 100644 --- a/doc/man3/SSL_CIPHER_get_name.pod +++ b/doc/man3/SSL_CIPHER_get_name.pod @@ -46,11 +46,13 @@ B is NULL, it returns "(NONE)". SSL_CIPHER_standard_name() returns a pointer to the standard RFC name of B. If the B is NULL, it returns "(NONE)". If the B -has no standard name, it returns B. +has no standard name, it returns B. If B was defined in both +SSLv3 and TLS, it returns the TLS name. OPENSSL_cipher_name() returns a pointer to the OpenSSL name of B. If the B is NULL, or B has no corresponding OpenSSL name, -it returns "(NONE)". +it returns "(NONE)". Where both exist, B should be the TLS name rather +than the SSLv3 name. SSL_CIPHER_get_bits() returns the number of secret bits used for B. If B is NULL, 0 is returned. diff --git a/doc/man3/SSL_COMP_add_compression_method.pod b/doc/man3/SSL_COMP_add_compression_method.pod index 56f708ca88..4b32023959 100644 --- a/doc/man3/SSL_COMP_add_compression_method.pod +++ b/doc/man3/SSL_COMP_add_compression_method.pod @@ -40,7 +40,7 @@ maintain the internal table of compression methods. =head1 NOTES -The TLS standard allows the integration of compression methods +The TLS standard (or SSLv3) allows the integration of compression methods into the communication. The TLS RFC does however not specify compression methods or their corresponding identifiers, so there is currently no compatible way to integrate compression with unknown peers. It is therefore currently not @@ -48,7 +48,7 @@ recommended to integrate compression into applications. Applications for non-public use may agree on certain compression methods. Using different compression methods with the same identifier will lead to connection failure. -An OpenSSL client speaking a protocol that allows compression (TLSv1) +An OpenSSL client speaking a protocol that allows compression (SSLv3, TLSv1) will unconditionally send the list of all compression methods enabled with SSL_COMP_add_compression_method() to the server during the handshake. Unlike the mechanisms to set a cipher list, there is no method available to diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod index 15f969eb61..ed15a784fa 100644 --- a/doc/man3/SSL_CONF_cmd.pod +++ b/doc/man3/SSL_CONF_cmd.pod @@ -246,7 +246,7 @@ See L for more information. =item B<-min_protocol> I, B<-max_protocol> I Sets the minimum and maximum supported protocol. -Currently supported protocol values are B, B, +Currently supported protocol values are B, B, B, B, B for TLS; B, B for DTLS, and B for no limit. If either the lower or upper bound is not specified then only the other bound @@ -309,15 +309,12 @@ operations are permitted. =item B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3> -Disables protocol support for TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3 by -setting the corresponding options B, +Disables protocol support for SSLv3, TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3 by +setting the corresponding options B, B, B, B and B respectively. These options are deprecated, use B<-min_protocol> and B<-max_protocol> instead. -Note that B<-no_ssl3> is a no-op since support for SSLv3 was removed in OpenSSL -4.0. - =item B<-anti_replay>, B<-no_anti_replay> Switches replay protection, on or off respectively. With replay protection on, @@ -496,7 +493,7 @@ This is a synonym for the "Groups" command. This sets the minimum supported SSL, TLS or DTLS version. -Currently supported protocol values are B, B, +Currently supported protocol values are B, B, B, B, B, B and B. The SSL and TLS bounds apply only to TLS-based contexts, while the DTLS bounds apply only to DTLS-based contexts. @@ -508,7 +505,7 @@ The value B applies to both types of contexts and disables the limits. This sets the maximum supported SSL, TLS or DTLS version. -Currently supported protocol values are B, B, +Currently supported protocol values are B, B, B, B, B, B and B. The SSL and TLS bounds apply only to TLS-based contexts, while the DTLS bounds apply only to DTLS-based contexts. @@ -531,7 +528,7 @@ effect. Only enabling some protocol versions does not disable the other protocol versions. -Currently supported protocol values are B, B, +Currently supported protocol values are B, B, B, B, B, B and B. The special value B refers to all supported versions. @@ -563,7 +560,7 @@ B: SSL/TLS compression support, disabled by default. Inverse of B. B: use empty fragments as a countermeasure against a -TLS 1.0 protocol vulnerability affecting CBC ciphers. It +SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. It is set by default. Inverse of B. B: enable various bug workarounds. Same as B. @@ -731,15 +728,16 @@ argument. The order of operations is significant. This can be used to set either defaults or values which cannot be overridden. For example if an application calls: - SSL_CONF_cmd(ctx, "Protocol", "-TLSv1"); + SSL_CONF_cmd(ctx, "Protocol", "-SSLv3"); SSL_CONF_cmd(ctx, userparam, uservalue); -it will disable TLSv1 support by default but the user can override it. If +it will disable SSLv3 support by default but the user can override it. If however the call sequence is: SSL_CONF_cmd(ctx, userparam, uservalue); - SSL_CONF_cmd(ctx, "Protocol", "-TLSv1"); -TLSv1 is B disabled and attempt to override this by the user are + SSL_CONF_cmd(ctx, "Protocol", "-SSLv3"); + +SSLv3 is B disabled and attempt to override this by the user are ignored. By checking the return code of SSL_CONF_cmd() it is possible to query if a @@ -794,22 +792,22 @@ Set supported signature algorithms: There are various ways to select the supported protocols. -This sets the minimum protocol version to TLSv1.1, and so disables TLSv1. +This set the minimum protocol version to TLSv1, and so disables SSLv3. This is the recommended way to disable protocols. - SSL_CONF_cmd(ctx, "MinProtocol", "TLSv1.1"); + SSL_CONF_cmd(ctx, "MinProtocol", "TLSv1"); -The following also disables TLSv1: +The following also disables SSLv3: - SSL_CONF_cmd(ctx, "Protocol", "-TLSv1"); + SSL_CONF_cmd(ctx, "Protocol", "-SSLv3"); The following will first enable all protocols, and then disable -TLSv1. +SSLv3. If no protocol versions were disabled before this has the same effect as -"-TLSv1", but if some versions were disables this will re-enable them before -disabling TLSv1. +"-SSLv3", but if some versions were disables this will re-enable them before +disabling SSLv3. - SSL_CONF_cmd(ctx, "Protocol", "ALL,-TLSv1"); + SSL_CONF_cmd(ctx, "Protocol", "ALL,-SSLv3"); Only enable TLSv1.2: diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod index f791c28682..02a6e6ea10 100755 --- a/doc/man3/SSL_CTX_set1_curves.pod +++ b/doc/man3/SSL_CTX_set1_curves.pod @@ -4,8 +4,7 @@ SSL_CTX_set1_groups, SSL_CTX_set1_groups_list, SSL_set1_groups, SSL_set1_groups_list, SSL_get1_groups, SSL_get0_iana_groups, -SSL_get0_ec_point_formats, SSL_get_shared_group, SSL_get_negotiated_group, -SSL_CTX_set1_curves, +SSL_get_shared_group, SSL_get_negotiated_group, SSL_CTX_set1_curves, SSL_CTX_set1_curves_list, SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve, SSL_CTX_get0_implemented_groups - EC supported curve functions @@ -22,7 +21,6 @@ SSL_get1_curves, SSL_get_shared_curve, SSL_CTX_get0_implemented_groups int SSL_get1_groups(SSL *ssl, int *groups); int SSL_get0_iana_groups(SSL *ssl, uint16_t **out); - int SSL_get0_ec_point_formats(SSL *ssl, const unsigned char **plst); int SSL_get_shared_group(SSL *s, int n); int SSL_get_negotiated_group(SSL *s); @@ -115,7 +113,7 @@ levels, and can specify which predicted key shares should be sent by a client. Group tuples are used by OpenSSL TLS servers to decide whether to request a stronger keyshare than those predicted by sending a Hello Retry Request (B) even if some of the predicted groups are supported. -OpenSSL clients largely ignore tuple boundaries, and pay attention only to the +OpenSSL clients largely ignore tuple boundaries, and pay attenion only to the overall order of I elements and which groups are selected as predicted keyshares as described below. Tuple boundaries do however affect the behaviour of keyshare predictions @@ -248,19 +246,6 @@ identifiers, as assigned by IANA. The group list is returned in the same order that was received in the ClientHello. The return value is the number of groups, not the number of bytes written. -SSL_get0_ec_point_formats() retrieves the peer's B -extension as a byte array of B values in the -order received. If the peer sent the extension, B<*plst> is set to an -internal buffer holding the list and its length is returned; otherwise -the return value is 0 and B<*plst> is left unchanged. The returned -pointer is owned by the B connection and must not be freed. The -point format no longer affects certificate selection or acceptance. - -The B extension applies only to TLS 1.2 and below, but -the peer's list is recorded even when TLS 1.3 is ultimately negotiated, -since a TLS 1.3 B may still carry the extension for -backward compatibility. - SSL_get_shared_group() returns the NID of the shared group B for a server-side SSL B. If B is -1 then the total number of shared groups is returned, which may be zero. Other than for diagnostic purposes, @@ -319,10 +304,6 @@ SSL_get1_groups() returns the number of groups, which may be zero. SSL_get0_iana_groups() returns the number of (uint16_t) groups, which may be zero. -SSL_get0_ec_point_formats() returns the number of point formats sent by -the peer in its B extension, or 0 if no such extension -was received. - SSL_get_shared_group() returns the NID of shared group B or NID_undef if there is no shared group B; or the total number of shared groups if B is -1. @@ -402,10 +383,6 @@ SSL_set1_groups_list() was added in OpenSSL 3.3. Support for B was added in OpenSSL 3.5. -OpenSSL 3.5 also introduced support for group tuples, the C<*> keyshare -prediction prefix, the C tuple separator, the C pseudo-group, -and the C<-> prefix. - OpenSSL 3.5 also introduced support for three I ECDH PQ key exchange TLS groups: B, B and B. diff --git a/doc/man3/SSL_CTX_set_min_proto_version.pod b/doc/man3/SSL_CTX_set_min_proto_version.pod index c1bf21ac42..d9b61dcce9 100644 --- a/doc/man3/SSL_CTX_set_min_proto_version.pod +++ b/doc/man3/SSL_CTX_set_min_proto_version.pod @@ -39,7 +39,7 @@ controlled by system configuration. Getters return 0 in case B or B have been configured to automatically use the lowest or highest version supported by the library. -Currently supported versions are B, +Currently supported versions are B, B, B, B, B for TLS and B, B for DTLS. diff --git a/doc/man3/SSL_CTX_set_msg_callback.pod b/doc/man3/SSL_CTX_set_msg_callback.pod index 7acc796a24..f046c77b53 100644 --- a/doc/man3/SSL_CTX_set_msg_callback.pod +++ b/doc/man3/SSL_CTX_set_msg_callback.pod @@ -92,7 +92,7 @@ The SSL_trace() function can be used as a pre-written callback in a call to SSL_CTX_set_msg_callback() or SSL_set_msg_callback(). It requires a BIO to be set as the callback argument via SSL_CTX_set_msg_callback_arg() or SSL_set_msg_callback_arg(). Setting this callback will cause human readable -diagnostic tracing information about an SSL/TLS/QUIC connection to be written to +diagostic tracing information about an SSL/TLS/QUIC connection to be written to the BIO. =head1 NOTES @@ -108,8 +108,8 @@ processed. Due to automatic protocol version negotiation, I is not necessarily the protocol version used by the sender of the message: If -a TLS 1.1 ClientHello message is received by an TLS 1-only server, -I will be B. +a TLS 1.0 ClientHello message is received by an SSL 3.0-only server, +I will be B. Pseudo content type values may be sent at various points during the processing of data. The following pseudo content types are currently defined: diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod index 400e492f3a..ae6f11cd54 100644 --- a/doc/man3/SSL_CTX_set_options.pod +++ b/doc/man3/SSL_CTX_set_options.pod @@ -71,7 +71,7 @@ CSP 3.x. =item SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS -Disables a countermeasure against an TLS 1.0 protocol +Disables a countermeasure against an SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers, which cannot be handled by some broken SSL implementations. This option has no effect for connections using other ciphers. diff --git a/doc/man3/SSL_CTX_set_security_level.pod b/doc/man3/SSL_CTX_set_security_level.pod index 38bd87b5f0..b490c74039 100644 --- a/doc/man3/SSL_CTX_set_security_level.pod +++ b/doc/man3/SSL_CTX_set_security_level.pod @@ -78,7 +78,7 @@ DSA and DH keys shorter than 1024 bits and ECC keys shorter than 160 bits are prohibited. Any cipher suite using MD5 for the MAC is also prohibited. Any cipher suites using CCM with a 64 bit authentication tag are prohibited. Note that signatures using SHA1 and MD5 are also forbidden at this level as they -have less than 80 security bits. Additionally, TLS 1.0, TLS 1.1 and +have less than 80 security bits. Additionally, SSLv3, TLS 1.0, TLS 1.1 and DTLS 1.0 are all disabled at this level. =item B diff --git a/doc/man3/SSL_CTX_set_split_send_fragment.pod b/doc/man3/SSL_CTX_set_split_send_fragment.pod index d26b41fcfe..22433e5e37 100644 --- a/doc/man3/SSL_CTX_set_split_send_fragment.pod +++ b/doc/man3/SSL_CTX_set_split_send_fragment.pod @@ -38,7 +38,7 @@ able to process multiple simultaneous crypto operations. This capability could be utilised to parallelise the processing of a single connection. For example a single write can be split into multiple records and each one encrypted independently and in parallel. Note: this would only work in -TLS1.1+. There was no support in TLSv1.0 or DTLS (any version). This +TLS1.1+. There was no support in SSLv3, TLSv1.0 or DTLS (any version). This capability is known as "pipelining" within OpenSSL. In order to benefit from the pipelining capability, you would need to have an diff --git a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod index 4176bc467b..e4871590f7 100644 --- a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod +++ b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod @@ -29,7 +29,8 @@ see L: SSL_CTX_set_tlsext_ticket_key_evp_cb() sets a callback function I for handling session tickets for the ssl context I. Session tickets, defined in RFC5077 provide an enhanced session resumption capability where the server -implementation is not required to maintain per session state. +implementation is not required to maintain per session state. It only applies +to TLS and there is no SSLv3 implementation. The callback function I will be called for every client instigated TLS session when session ticket extension is presented in the TLS hello diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod index 1a9ef7d83e..58774796cd 100644 --- a/doc/man3/SSL_CTX_set_verify.pod +++ b/doc/man3/SSL_CTX_set_verify.pod @@ -74,9 +74,7 @@ SSL_CTX_set_client_cert_cb() if no certificate is provided at initialization. SSL_verify_client_post_handshake() causes a CertificateRequest message to be sent by a server on the given B connection. The SSL_VERIFY_PEER flag must -be set; the SSL_VERIFY_POST_HANDSHAKE flag is optional. The -SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag is also applicable and has the same -effect as with the client authentication during the handshake. +be set; the SSL_VERIFY_POST_HANDSHAKE flag is optional. =head1 NOTES diff --git a/doc/man3/SSL_get_version.pod b/doc/man3/SSL_get_version.pod index 2d9fd78cfc..b7c2d8156b 100644 --- a/doc/man3/SSL_get_version.pod +++ b/doc/man3/SSL_get_version.pod @@ -100,6 +100,10 @@ of the following: =over 4 +=item SSL3_VERSION + +The connection uses the SSLv3 protocol. + =item TLS1_VERSION The connection uses the TLSv1.0 protocol. diff --git a/doc/man3/X509_get_default_cert_file.pod b/doc/man3/X509_get_default_cert_file.pod index a604cf5571..1e65b22700 100644 --- a/doc/man3/X509_get_default_cert_file.pod +++ b/doc/man3/X509_get_default_cert_file.pod @@ -24,7 +24,7 @@ the default path when it is asked to load trusted CA certificates from a file and no other path is specified. If the file exists, CA certificates are loaded from the file. -The X509_get_default_cert_dir() function returns a default delimiter-separated +The X509_get_default_cert_dir() function returns a default delimeter-separated list of paths to a directories containing trusted CA certificates named in the hashed format. OpenSSL will use this as the default list of paths when it is asked to load trusted CA certificates from a directory and no other path is diff --git a/doc/man3/X509_verify_cert.pod b/doc/man3/X509_verify_cert.pod index aaaaace4d6..5beb41f560 100644 --- a/doc/man3/X509_verify_cert.pod +++ b/doc/man3/X509_verify_cert.pod @@ -104,9 +104,7 @@ terminator. =item 7. -B per RFC 5280 section 4.2.1.10; see -L for details of the matching primitive and -the general-name types it covers. +B per RFC 5280 section 4.2.1.10. =item 8. @@ -452,17 +450,8 @@ above it. Callers should nevertheless be aware that the chain returned in this mode does not necessarily terminate at an RFC 5280-style trust anchor. -L caps each per-pair check at 2**20 -comparisons, but the chain orchestrator issues B(B-1)/2 such -checks for an B-certificate chain. An adversary submitting a -maximally constructed chain can therefore force up to approximately -6.3 million name-constraint comparisons in a four-certificate chain -(one leaf and three name-constrained signers), or approximately 5.2 -billion at the default chain-depth limit of 100. - =head1 SEE ALSO -L, L, L, L, diff --git a/doc/man7/EVP_CIPHER-AES.pod b/doc/man7/EVP_CIPHER-AES.pod index 0cb6d20829..6da3f96a2d 100644 --- a/doc/man7/EVP_CIPHER-AES.pod +++ b/doc/man7/EVP_CIPHER-AES.pod @@ -65,10 +65,9 @@ L. =head1 NOTES -The AES-SIV, AES-WRAP, and GCM-SIV mode implementations do not support -streaming. That means to obtain correct results there can be only one -L or L call on the payload after -the initialization of the context. +The AES-SIV and AES-WRAP mode implementations do not support streaming. That +means to obtain correct results there can be only one L +or L call after the initialization of the context. When wrapping with AES-WRAP-PAD ciphers, the output buffer must be at least I rounded up to the cipher block size (8 bytes) plus the block size. diff --git a/doc/man7/EVP_KDF-SNMPKDF.pod b/doc/man7/EVP_KDF-SNMPKDF.pod index 9a2973722b..c0bcb70dee 100644 --- a/doc/man7/EVP_KDF-SNMPKDF.pod +++ b/doc/man7/EVP_KDF-SNMPKDF.pod @@ -29,9 +29,9 @@ The supported parameters are: =item "digest" (B) -=item "pass" (B) +=item "pass" (B) -These parameters work as described in L. +These parameters works as described in L. =item "eid" (B) @@ -70,7 +70,7 @@ This example derives an 8 byte IV using SHA1 with a 1K "key" and appropriate *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, SN_sha1, strlen(SN_sha1)); - *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASS, pass, sizeof(pass)); *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SNMPKDF_EID, eid, sizeof(eid)); @@ -100,7 +100,7 @@ This functionality was added in OpenSSL 4.0. =head1 COPYRIGHT -Copyright 2025-2026 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-EC.pod b/doc/man7/EVP_PKEY-EC.pod index 714b5c3b60..78ac13f332 100644 --- a/doc/man7/EVP_PKEY-EC.pod +++ b/doc/man7/EVP_PKEY-EC.pod @@ -94,18 +94,6 @@ Sets or gets the point_conversion_form for the I. For a description of point_conversion_forms please see L. Valid values are "uncompressed" or "compressed". The default value is "uncompressed". -At key generation time the public point is emitted in uncompressed -form. Any B supplied via -B(3) or B<-pkeyopt point-format:EformE> -is validated -- an invalid value is rejected -- but is otherwise -ignored on the generated key. - -On EC parameter generation the B setting selects the -encoding of the group's generator. On an existing key the setting -is honoured normally, so imported keys retain their original form -through B(3), B(3), -B(3) and PEM/DER encoding and decoding. - =item "group-check" (B) Sets or Gets the type of group check done when EVP_PKEY_param_check() is called. diff --git a/doc/man7/openssl-core_dispatch.h.pod b/doc/man7/openssl-core_dispatch.h.pod index 7f99fe2a81..a19e1331fa 100644 --- a/doc/man7/openssl-core_dispatch.h.pod +++ b/doc/man7/openssl-core_dispatch.h.pod @@ -24,7 +24,7 @@ are named as follows: These macros have the form C>. -=item dispatch numbers +=item dipatch numbers These macros have the form C_I>, where C> is the same as in the macro for the operation this diff --git a/doc/man7/ossl-guide-migration.pod b/doc/man7/ossl-guide-migration.pod index bf5c57d617..2c690dc48e 100644 --- a/doc/man7/ossl-guide-migration.pod +++ b/doc/man7/ossl-guide-migration.pod @@ -38,12 +38,6 @@ ASN1_BIT_STRING_set1(). The new functions in addition to what ASN1_BIT_STRING_set() does, validates the function arguments and sets unused bits after setting the BIT STRING value. -=head3 Deprecation of EVP_KDF_CTX_kdf() - -This function is deprecated in favour of EVP_KDF_CTX_get0_ctx(), to align -with the naming of functions that provide similar functionality for other kinds -of EVP context oobjects. - =head1 OPENSSL 4.0 =head2 Main Changes from OpenSSL 3.6 diff --git a/doc/man7/ossl-guide-quic-client-non-block.pod b/doc/man7/ossl-guide-quic-client-non-block.pod index c7f66079d7..06a13e36b6 100644 --- a/doc/man7/ossl-guide-quic-client-non-block.pod +++ b/doc/man7/ossl-guide-quic-client-non-block.pod @@ -173,7 +173,7 @@ stream but no data has not yet arrived from the peer for that stream). L and L will return 0 to indicate an error and L and L will return 0 or a negative value to indicate -an error. L will return a negative value to indicate an error. +an error. L will return a negative value to incidate an error. In the event of an error an application should call L to find out what type of error has occurred. If the error is non-fatal and can be diff --git a/doc/man7/ossl-guide-tls-client-non-block.pod b/doc/man7/ossl-guide-tls-client-non-block.pod index a45086caf6..ee03f6624b 100644 --- a/doc/man7/ossl-guide-tls-client-non-block.pod +++ b/doc/man7/ossl-guide-tls-client-non-block.pod @@ -140,7 +140,7 @@ from the underlying socket but the data has not yet arrived from the peer). L and L will return 0 to indicate an error and L and L will return 0 or a negative value to indicate -an error. L will return a negative value to indicate an error. +an error. L will return a negative value to incidate an error. In the event of an error an application should call L to find out what type of error has occurred. If the error is non-fatal and can be diff --git a/doc/man7/ossl-guide-tls-server-block.pod b/doc/man7/ossl-guide-tls-server-block.pod index f445492282..44ca2d7d8b 100644 --- a/doc/man7/ossl-guide-tls-server-block.pod +++ b/doc/man7/ossl-guide-tls-server-block.pod @@ -170,7 +170,7 @@ key agreement, but the certificate exchange is avoided. Most servers, including this one, do not solicit client certificates. We therefore do not need a "trust store" and allow the handshake to complete even when the client does not present a certificate. Note: Even if a client did -present a trusted certificate, for it to be useful, the server application +present a trusted ceritificate, for it to be useful, the server application would still need custom code to use the verified identity to grant nondefault access to that particular client. Some servers grant access to all clients with certificates from a private CA, this then requires processing of diff --git a/fuzz/acert.c b/fuzz/acert.c index 3af3c3e87a..14c2f657ee 100644 --- a/fuzz/acert.c +++ b/fuzz/acert.c @@ -26,16 +26,13 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) { const unsigned char *p = buf; unsigned char *der = NULL; - X509_ACERT *acert; - acert = d2i_X509_ACERT(NULL, &p, (long)len); + X509_ACERT *acert = d2i_X509_ACERT(NULL, &p, (long)len); if (acert != NULL) { BIO *bio = BIO_new(BIO_s_null()); - if (bio != NULL) { - X509_ACERT_print(bio, acert); - BIO_free(bio); - } + X509_ACERT_print(bio, acert); + BIO_free(bio); i2d_X509_ACERT(acert, &der); OPENSSL_free(der); diff --git a/fuzz/asn1.c b/fuzz/asn1.c index 12ba8a13d4..934e1447e9 100644 --- a/fuzz/asn1.c +++ b/fuzz/asn1.c @@ -277,6 +277,9 @@ static ASN1_PCTX *pctx; TYPE *type = D2I(NULL, &p, (long)len); \ \ if (type != NULL) { \ + BIO *bio = BIO_new(BIO_s_null()); \ + \ + BIO_free(bio); \ I2D(type, &der); \ OPENSSL_free(der); \ TYPE##_free(type); \ @@ -287,8 +290,6 @@ int FuzzerInitialize(int *argc, char ***argv) { FuzzerSetRand(); pctx = ASN1_PCTX_new(); - if (pctx == NULL) - return 0; ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT | ASN1_PCTX_FLAGS_SHOW_SEQUENCE | ASN1_PCTX_FLAGS_SHOW_SSOF | ASN1_PCTX_FLAGS_SHOW_TYPE | ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME); ASN1_PCTX_set_str_flags(pctx, ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_SHOW_TYPE | ASN1_STRFLGS_DUMP_ALL); diff --git a/fuzz/bignum.c b/fuzz/bignum.c index eec776e7b3..b9dcb49ebe 100644 --- a/fuzz/bignum.c +++ b/fuzz/bignum.c @@ -28,6 +28,7 @@ int FuzzerInitialize(int *argc, char ***argv) int FuzzerTestOneInput(const uint8_t *buf, size_t len) { + int success = 0; size_t l1 = 0, l2 = 0, l3 = 0; int s1 = 0, s3 = 0; BN_CTX *ctx; @@ -44,10 +45,6 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) b5 = BN_new(); ctx = BN_CTX_new(); - if (b1 == NULL || b2 == NULL || b3 == NULL || b4 == NULL || b5 == NULL - || ctx == NULL) - goto done; - /* Divide the input into three parts, using the values of the first two * bytes to choose lengths, which generate b1, b2 and b3. Use three bits * of the third byte to choose signs for the three numbers. @@ -65,25 +62,23 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) s3 = buf[0] & 4; ++buf; } - if (BN_bin2bn(buf, (int)l1, b1) != b1) - goto done; + OPENSSL_assert(BN_bin2bn(buf, (int)l1, b1) == b1); BN_set_negative(b1, s1); - if (BN_bin2bn(buf + l1, (int)l2, b2) != b2) - goto done; - if (BN_bin2bn(buf + l1 + l2, (int)l3, b3) != b3) - goto done; + OPENSSL_assert(BN_bin2bn(buf + l1, (int)l2, b2) == b2); + OPENSSL_assert(BN_bin2bn(buf + l1 + l2, (int)l3, b3) == b3); BN_set_negative(b3, s3); /* mod 0 is undefined */ - if (BN_is_zero(b3)) + if (BN_is_zero(b3)) { + success = 1; goto done; + } - if (!BN_mod_exp(b4, b1, b2, b3, ctx)) - goto done; - if (!BN_mod_exp_simple(b5, b1, b2, b3, ctx)) - goto done; + OPENSSL_assert(BN_mod_exp(b4, b1, b2, b3, ctx)); + OPENSSL_assert(BN_mod_exp_simple(b5, b1, b2, b3, ctx)); - if (BN_cmp(b4, b5) != 0) { + success = BN_cmp(b4, b5) == 0; + if (!success) { BN_print_fp(stdout, b1); putchar('\n'); BN_print_fp(stdout, b2); @@ -97,6 +92,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) } done: + OPENSSL_assert(success); BN_free(b1); BN_free(b2); BN_free(b3); diff --git a/fuzz/bndiv.c b/fuzz/bndiv.c index c3a2d2f305..a52f7b598b 100644 --- a/fuzz/bndiv.c +++ b/fuzz/bndiv.c @@ -37,19 +37,6 @@ int FuzzerInitialize(int *argc, char ***argv) b5 = BN_new(); ctx = BN_CTX_new(); - if (b1 == NULL || b2 == NULL || b3 == NULL || b4 == NULL || b5 == NULL - || ctx == NULL) { - BN_free(b1); - BN_free(b2); - BN_free(b3); - BN_free(b4); - BN_free(b5); - BN_CTX_free(ctx); - b1 = b2 = b3 = b4 = b5 = NULL; - ctx = NULL; - return 0; - } - OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); ERR_clear_error(); @@ -82,19 +69,18 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) ++buf; l2 = len - l1; } - if (BN_bin2bn(buf, (int)l1, b1) != b1) - goto done; + OPENSSL_assert(BN_bin2bn(buf, (int)l1, b1) == b1); BN_set_negative(b1, s1); - if (BN_bin2bn(buf + l1, (int)l2, b2) != b2) - goto done; + OPENSSL_assert(BN_bin2bn(buf + l1, (int)l2, b2) == b2); BN_set_negative(b2, s2); /* divide by 0 is an error */ - if (BN_is_zero(b2)) + if (BN_is_zero(b2)) { + success = 1; goto done; + } - if (!BN_div(b3, b4, b1, b2, ctx)) - goto done; + OPENSSL_assert(BN_div(b3, b4, b1, b2, ctx)); if (BN_is_zero(b1)) success = BN_is_zero(b3) && BN_is_zero(b4); else if (BN_is_negative(b1)) @@ -103,10 +89,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) else success = (BN_is_negative(b3) == BN_is_negative(b2) || BN_is_zero(b3)) && (!BN_is_negative(b4) || BN_is_zero(b4)); - if (!BN_mul(b5, b3, b2, ctx)) - goto done; - if (!BN_add(b5, b5, b4)) - goto done; + OPENSSL_assert(BN_mul(b5, b3, b2, ctx)); + OPENSSL_assert(BN_add(b5, b5, b4)); success = success && BN_cmp(b5, b1) == 0; if (!success) { @@ -130,6 +114,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) } done: + OPENSSL_assert(success); ERR_clear_error(); return 0; diff --git a/fuzz/build.info b/fuzz/build.info index fcbb76234c..3770c2df7e 100644 --- a/fuzz/build.info +++ b/fuzz/build.info @@ -50,10 +50,6 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}] PROGRAMS{noinst}=dtlsclient dtlsserver ENDIF - IF[{- !$disabled{"ech"} -}] - PROGRAMS{noinst}=echconfiglist_parser - ENDIF - SOURCE[asn1]=asn1.c driver.c fuzz_rand.c INCLUDE[asn1]=../include {- $ex_inc -} DEPEND[asn1]=../libcrypto ../libssl {- $ex_lib -} @@ -110,10 +106,6 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}] INCLUDE[dtlsserver]=../include {- $ex_inc -} DEPEND[dtlsserver]=../libcrypto ../libssl {- $ex_lib -} - SOURCE[echconfiglist_parser]=echconfiglist_parser.c driver.c - INCLUDE[echconfiglist_parser]=../include {- $ex_inc -} - DEPEND[echconfiglist_parser]=../libcrypto ../libssl {- $ex_lib -} - SOURCE[pem]=pem.c driver.c INCLUDE[pem]=../include {- $ex_inc -} DEPEND[pem]=../libcrypto.a {- $ex_lib -} @@ -184,8 +176,6 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}] ENDIF IF[{- !$disabled{tests} -}] - $FUZZTESTSRC=test-corpus.c ../test/mfail/mfail.c - PROGRAMS{noinst}=asn1-test asn1parse-test bignum-test bndiv-test client-test conf-test crl-test server-test smime-test PROGRAMS{noinst}=pkcs12-test punycode-test pem-test decoder-test hashtable-test acert-test PROGRAMS{noinst}=v3name-test @@ -228,139 +218,131 @@ IF[{- !$disabled{tests} -}] PROGRAMS{noinst}=dtlsclient-test dtlsserver-test ENDIF - IF[{- !$disabled{"ech"} -}] - PROGRAMS{noinst}=echconfiglist_parser-test - ENDIF + SOURCE[asn1-test]=asn1.c test-corpus.c fuzz_rand.c + INCLUDE[asn1-test]=../include + DEPEND[asn1-test]=../libcrypto ../libssl - SOURCE[asn1-test]=asn1.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[asn1-test]=../include ../test/mfail - DEPEND[asn1-test]=../libcrypto.a ../libssl.a + SOURCE[asn1parse-test]=asn1parse.c test-corpus.c + INCLUDE[asn1parse-test]=../include + DEPEND[asn1parse-test]=../libcrypto - SOURCE[asn1parse-test]=asn1parse.c $FUZZTESTSRC - INCLUDE[asn1parse-test]=../include ../test/mfail - DEPEND[asn1parse-test]=../libcrypto.a + SOURCE[bignum-test]=bignum.c test-corpus.c + INCLUDE[bignum-test]=../include + DEPEND[bignum-test]=../libcrypto - SOURCE[bignum-test]=bignum.c $FUZZTESTSRC - INCLUDE[bignum-test]=../include ../test/mfail - DEPEND[bignum-test]=../libcrypto.a + SOURCE[bndiv-test]=bndiv.c test-corpus.c + INCLUDE[bndiv-test]=../include + DEPEND[bndiv-test]=../libcrypto - SOURCE[bndiv-test]=bndiv.c $FUZZTESTSRC - INCLUDE[bndiv-test]=../include ../test/mfail - DEPEND[bndiv-test]=../libcrypto.a + SOURCE[client-test]=client.c test-corpus.c fuzz_rand.c + INCLUDE[client-test]=../include + DEPEND[client-test]=../libcrypto ../libssl - SOURCE[client-test]=client.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[client-test]=../include ../test/mfail - DEPEND[client-test]=../libcrypto.a ../libssl.a - - SOURCE[cmp-test]=cmp.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[cmp-test]=../include ../test/mfail + SOURCE[cmp-test]=cmp.c test-corpus.c fuzz_rand.c + INCLUDE[cmp-test]=../include DEPEND[cmp-test]=../libcrypto.a # referring to static lib allows using non-exported functions - SOURCE[ml-kem-test]=ml-kem.c $FUZZTESTSRC - INCLUDE[ml-kem-test]=../include ../test/mfail + SOURCE[ml-kem-test]=ml-kem.c test-corpus.c fuzz_rand.c + INCLUDE[ml-kem-test]=../include DEPEND[ml-kem-test]=../libcrypto.a # referring to static lib allows using non-exported functions - SOURCE[ml-dsa-test]=ml-dsa.c $FUZZTESTSRC - INCLUDE[ml-dsa-test]=../include ../test/mfail + SOURCE[ml-dsa-test]=ml-dsa.c test-corpus.c fuzz_rand.c + INCLUDE[ml-dsa-test]=../include DEPEND[ml-dsa-test]=../libcrypto.a # referring to static lib allows using non-exported functions - SOURCE[slh-dsa-test]=slh-dsa.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[slh-dsa-test]=../include ../test/mfail + SOURCE[slh-dsa-test]=slh-dsa.c test-corpus.c fuzz_rand.c + INCLUDE[slh-dsa-test]=../include DEPEND[slh-dsa-test]=../libcrypto.a # referring to static lib allows using non-exported functions - SOURCE[cms-test]=cms.c $FUZZTESTSRC - INCLUDE[cms-test]=../include ../test/mfail - DEPEND[cms-test]=../libcrypto.a + SOURCE[cms-test]=cms.c test-corpus.c + INCLUDE[cms-test]=../include + DEPEND[cms-test]=../libcrypto - SOURCE[pkcs12-test]=pkcs12.c $FUZZTESTSRC - INCLUDE[pkcs12-test]=../include ../test/mfail - DEPEND[pkcs12-test]=../libcrypto.a + SOURCE[pkcs12-test]=pkcs12.c test-corpus.c + INCLUDE[pkcs12-test]=../include + DEPEND[pkcs12-test]=../libcrypto - SOURCE[conf-test]=conf.c $FUZZTESTSRC - INCLUDE[conf-test]=../include ../test/mfail - DEPEND[conf-test]=../libcrypto.a + SOURCE[conf-test]=conf.c test-corpus.c + INCLUDE[conf-test]=../include + DEPEND[conf-test]=../libcrypto - SOURCE[crl-test]=crl.c $FUZZTESTSRC - INCLUDE[crl-test]=../include ../test/mfail - DEPEND[crl-test]=../libcrypto.a + SOURCE[crl-test]=crl.c test-corpus.c + INCLUDE[crl-test]=../include + DEPEND[crl-test]=../libcrypto - SOURCE[ct-test]=ct.c $FUZZTESTSRC - INCLUDE[ct-test]=../include ../test/mfail - DEPEND[ct-test]=../libcrypto.a + SOURCE[ct-test]=ct.c test-corpus.c + INCLUDE[ct-test]=../include + DEPEND[ct-test]=../libcrypto - SOURCE[dtlsclient-test]=dtlsclient.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[dtlsclient-test]=../include ../test/mfail - DEPEND[dtlsclient-test]=../libcrypto.a ../libssl.a + SOURCE[dtlsclient-test]=dtlsclient.c test-corpus.c fuzz_rand.c + INCLUDE[dtlsclient-test]=../include + DEPEND[dtlsclient-test]=../libcrypto ../libssl - SOURCE[dtlsserver-test]=dtlsserver.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[dtlsserver-test]=../include ../test/mfail - DEPEND[dtlsserver-test]=../libcrypto.a ../libssl.a + SOURCE[dtlsserver-test]=dtlsserver.c test-corpus.c fuzz_rand.c + INCLUDE[dtlsserver-test]=../include + DEPEND[dtlsserver-test]=../libcrypto ../libssl - SOURCE[echconfiglist_parser-test]=echconfiglist_parser.c $FUZZTESTSRC - INCLUDE[echconfiglist_parser-test]=../include ../test/mfail - DEPEND[echconfiglist_parser-test]=../libcrypto.a ../libssl.a - - SOURCE[pem-test]=pem.c $FUZZTESTSRC - INCLUDE[pem-test]=../include ../test/mfail + SOURCE[pem-test]=pem.c test-corpus.c + INCLUDE[pem-test]=../include DEPEND[pem-test]=../libcrypto.a - SOURCE[decoder-test]=decoder.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[decoder-test]=../include ../test/mfail - DEPEND[decoder-test]=../libcrypto.a + SOURCE[decoder-test]=decoder.c test-corpus.c fuzz_rand.c + INCLUDE[decoder-test]=../include + DEPEND[decoder-test]=../libcrypto - SOURCE[hashtable-test]=hashtable.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[hashtable-test]=../include ../test/mfail + SOURCE[hashtable-test]=hashtable.c test-corpus.c fuzz_rand.c + INCLUDE[hashtable-test]=../include DEPEND[hashtable-test]=../libcrypto.a - SOURCE[acert-test]=acert.c $FUZZTESTSRC - INCLUDE[acert-test]=../include ../test/mfail - DEPEND[acert-test]=../libcrypto.a + SOURCE[acert-test]=acert.c test-corpus.c + INCLUDE[acert-test]=../include + DEPEND[acert-test]=../libcrypto - SOURCE[punycode-test]=punycode.c $FUZZTESTSRC - INCLUDE[punycode-test]=../include ../test/mfail + SOURCE[punycode-test]=punycode.c test-corpus.c + INCLUDE[punycode-test]=../include DEPEND[punycode-test]=../libcrypto.a - SOURCE[smime-test]=smime.c $FUZZTESTSRC - INCLUDE[smime-test]=../include ../test/mfail - DEPEND[smime-test]=../libcrypto.a ../libssl.a + SOURCE[smime-test]=smime.c test-corpus.c + INCLUDE[smime-test]=../include + DEPEND[smime-test]=../libcrypto ../libssl - SOURCE[v3name-test]=v3name.c $FUZZTESTSRC - INCLUDE[v3name-test]=../include ../test/mfail + SOURCE[v3name-test]=v3name.c test-corpus.c + INCLUDE[v3name-test]=../include DEPEND[v3name-test]=../libcrypto.a - SOURCE[quic-client-test]=quic-client.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[quic-client-test]=../include ../test/mfail + SOURCE[quic-client-test]=quic-client.c test-corpus.c fuzz_rand.c + INCLUDE[quic-client-test]=../include DEPEND[quic-client-test]=../libcrypto.a ../libssl.a - SOURCE[quic-server-test]=quic-server.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[quic-server-test]=../include ../test/mfail + SOURCE[quic-server-test]=quic-server.c test-corpus.c fuzz_rand.c + INCLUDE[quic-server-test]=../include DEPEND[quic-server-test]=../libcrypto.a ../libssl.a - SOURCE[quic-srtm-test]=quic-srtm.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[quic-srtm-test]=../include ../test/mfail + SOURCE[quic-srtm-test]=quic-srtm.c test-corpus.c fuzz_rand.c + INCLUDE[quic-srtm-test]=../include DEPEND[quic-srtm-test]=../libcrypto.a ../libssl.a - SOURCE[quic-lcidm-test]=quic-lcidm.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[quic-lcidm-test]=../include ../test/mfail + SOURCE[quic-lcidm-test]=quic-lcidm.c test-corpus.c fuzz_rand.c + INCLUDE[quic-lcidm-test]=../include DEPEND[quic-lcidm-test]=../libcrypto.a ../libssl.a - SOURCE[quic-rcidm-test]=quic-rcidm.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[quic-rcidm-test]=../include ../test/mfail + SOURCE[quic-rcidm-test]=quic-rcidm.c test-corpus.c fuzz_rand.c + INCLUDE[quic-rcidm-test]=../include DEPEND[quic-rcidm-test]=../libcrypto.a ../libssl.a - SOURCE[server-test]=server.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[server-test]=../include ../test/mfail - DEPEND[server-test]=../libcrypto.a ../libssl.a + SOURCE[server-test]=server.c test-corpus.c fuzz_rand.c + INCLUDE[server-test]=../include + DEPEND[server-test]=../libcrypto ../libssl - SOURCE[x509-test]=x509.c $FUZZTESTSRC fuzz_rand.c - INCLUDE[x509-test]=../include ../test/mfail - DEPEND[x509-test]=../libcrypto.a + SOURCE[x509-test]=x509.c test-corpus.c fuzz_rand.c + INCLUDE[x509-test]=../include + DEPEND[x509-test]=../libcrypto - SOURCE[provider-test]=provider.c $FUZZTESTSRC - INCLUDE[provider-test]=../include ../test/mfail - DEPEND[provider-test]=../libcrypto.a + SOURCE[provider-test]=provider.c test-corpus.c + INCLUDE[provider-test]=../include + DEPEND[provider-test]=../libcrypto ENDIF diff --git a/fuzz/client.c b/fuzz/client.c index 64d30dd09e..86cec0cd43 100644 --- a/fuzz/client.c +++ b/fuzz/client.c @@ -76,10 +76,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) client = SSL_new(ctx); if (client == NULL) goto end; - if (SSL_set_min_proto_version(client, 0) != 1) - goto end; - if (SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") != 1) - goto end; + OPENSSL_assert(SSL_set_min_proto_version(client, 0) == 1); + OPENSSL_assert(SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") == 1); SSL_set_tlsext_host_name(client, "localhost"); in = BIO_new(BIO_s_mem()); if (in == NULL) @@ -91,8 +89,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) } SSL_set_bio(client, in, out); SSL_set_connect_state(client); - if ((size_t)BIO_write(in, buf, (int)len) != len) - goto end; + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); if (SSL_do_handshake(client) == 1) { /* Keep reading application data until error or EOF. */ uint8_t tmp[1024]; diff --git a/fuzz/cmp.c b/fuzz/cmp.c index ae4dcc033d..c86d390f8b 100644 --- a/fuzz/cmp.c +++ b/fuzz/cmp.c @@ -176,13 +176,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) return 0; in = BIO_new(BIO_s_mem()); - if (in == NULL) { - ERR_clear_error(); - return 0; - } if ((size_t)BIO_write(in, buf, (int)len) != len) { BIO_free(in); - ERR_clear_error(); return 0; } diff --git a/fuzz/cms.c b/fuzz/cms.c index d45bf1b63c..0cd8ea9551 100644 --- a/fuzz/cms.c +++ b/fuzz/cms.c @@ -34,23 +34,13 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) return 0; in = BIO_new(BIO_s_mem()); - if (in == NULL) { - ERR_clear_error(); - return 0; - } - if ((size_t)BIO_write(in, buf, (int)len) != len) { - BIO_free(in); - ERR_clear_error(); - return 0; - } + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); cms = d2i_CMS_bio(in, NULL); if (cms != NULL) { BIO *out = BIO_new(BIO_s_null()); - if (out != NULL) { - i2d_CMS_bio(out, cms); - BIO_free(out); - } + i2d_CMS_bio(out, cms); + BIO_free(out); CMS_ContentInfo_free(cms); } diff --git a/fuzz/conf.c b/fuzz/conf.c index 116759a0a1..9c5353868b 100644 --- a/fuzz/conf.c +++ b/fuzz/conf.c @@ -33,15 +33,9 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) return 0; conf = NCONF_new(NULL); - if (conf == NULL) - return 0; in = BIO_new(BIO_s_mem()); - if (in == NULL) - goto end; - if ((size_t)BIO_write(in, buf, (int)len) != len) - goto end; + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); NCONF_load_bio(conf, in, &eline); -end: NCONF_free(conf); BIO_free(in); ERR_clear_error(); diff --git a/fuzz/crl.c b/fuzz/crl.c index f704321ac5..c22f5d55e2 100644 --- a/fuzz/crl.c +++ b/fuzz/crl.c @@ -29,11 +29,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) X509_CRL *crl = d2i_X509_CRL(NULL, &p, (long)len); if (crl != NULL) { BIO *bio = BIO_new(BIO_s_null()); - - if (bio != NULL) { - X509_CRL_print(bio, crl); - BIO_free(bio); - } + X509_CRL_print(bio, crl); + BIO_free(bio); i2d_X509_CRL(crl, &der); OPENSSL_free(der); diff --git a/fuzz/ct.c b/fuzz/ct.c index 74fbf66c04..e46574d8eb 100644 --- a/fuzz/ct.c +++ b/fuzz/ct.c @@ -32,11 +32,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) STACK_OF(SCT) *scts = d2i_SCT_LIST(NULL, pp, (long)len); if (scts != NULL) { BIO *bio = BIO_new(BIO_s_null()); - - if (bio != NULL) { - SCT_LIST_print(scts, bio, 4, "\n", NULL); - BIO_free(bio); - } + SCT_LIST_print(scts, bio, 4, "\n", NULL); + BIO_free(bio); if (i2d_SCT_LIST(scts, &der)) { /* Silence unused result warning */ diff --git a/fuzz/decoder.c b/fuzz/decoder.c index 227c24fd71..3a9a48ad21 100644 --- a/fuzz/decoder.c +++ b/fuzz/decoder.c @@ -25,8 +25,6 @@ int FuzzerInitialize(int *argc, char ***argv) NULL); pctx = ASN1_PCTX_new(); - if (pctx == NULL) - return 0; ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT | ASN1_PCTX_FLAGS_SHOW_SEQUENCE | ASN1_PCTX_FLAGS_SHOW_SSOF | ASN1_PCTX_FLAGS_SHOW_TYPE | ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME); ASN1_PCTX_set_str_flags(pctx, ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_SHOW_TYPE | ASN1_STRFLGS_DUMP_ALL); @@ -43,15 +41,9 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) BIO *bio; bio = BIO_new(BIO_s_null()); - if (bio == NULL) { - ERR_clear_error(); - return 0; - } dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, NULL, NULL, NULL, 0, NULL, NULL); if (dctx == NULL) { - BIO_free(bio); - ERR_clear_error(); return 0; } if (OSSL_DECODER_from_data(dctx, &buf, &len)) { @@ -62,29 +54,27 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) EVP_PKEY_print_params(bio, pkey, 1, pctx); pkey2 = EVP_PKEY_dup(pkey); - if (pkey2 != NULL) { - EVP_PKEY_eq(pkey, pkey2); - EVP_PKEY_free(pkey2); - } + OPENSSL_assert(pkey2 != NULL); + EVP_PKEY_eq(pkey, pkey2); + EVP_PKEY_free(pkey2); ctx = EVP_PKEY_CTX_new(pkey, NULL); - if (ctx != NULL) { - /* - * Param check will take too long time on large DH parameters. - * Skip it. - */ - if ((!EVP_PKEY_is_a(pkey, "DH") && !EVP_PKEY_is_a(pkey, "DHX")) - || EVP_PKEY_get_bits(pkey) <= 2048) - EVP_PKEY_param_check(ctx); + /* + * Param check will take too long time on large DH parameters. + * Skip it. + */ + if ((!EVP_PKEY_is_a(pkey, "DH") && !EVP_PKEY_is_a(pkey, "DHX")) + || EVP_PKEY_get_bits(pkey) <= 2048) + EVP_PKEY_param_check(ctx); - EVP_PKEY_public_check(ctx); - /* Private and pairwise checks are unbounded, skip for large keys. */ - if (EVP_PKEY_get_bits(pkey) <= 4096) { - EVP_PKEY_private_check(ctx); - EVP_PKEY_pairwise_check(ctx); - } - EVP_PKEY_CTX_free(ctx); + EVP_PKEY_public_check(ctx); + /* Private and pairwise checks are unbounded, skip for large keys. */ + if (EVP_PKEY_get_bits(pkey) <= 4096) { + EVP_PKEY_private_check(ctx); + EVP_PKEY_pairwise_check(ctx); } + OPENSSL_assert(ctx != NULL); + EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); } OSSL_DECODER_CTX_free(dctx); diff --git a/fuzz/dtlsclient.c b/fuzz/dtlsclient.c index 2dc5ed709c..f07bc6ed67 100644 --- a/fuzz/dtlsclient.c +++ b/fuzz/dtlsclient.c @@ -76,10 +76,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) client = SSL_new(ctx); if (client == NULL) goto end; - if (SSL_set_min_proto_version(client, 0) != 1) - goto end; - if (SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") != 1) - goto end; + OPENSSL_assert(SSL_set_min_proto_version(client, 0) == 1); + OPENSSL_assert(SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") == 1); SSL_set_tlsext_host_name(client, "localhost"); in = BIO_new(BIO_s_mem()); if (in == NULL) @@ -91,8 +89,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) } SSL_set_bio(client, in, out); SSL_set_connect_state(client); - if ((size_t)BIO_write(in, buf, (int)len) != len) - goto end; + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); if (SSL_do_handshake(client) == 1) { /* Keep reading application data until error or EOF. */ uint8_t tmp[1024]; diff --git a/fuzz/dtlsserver.c b/fuzz/dtlsserver.c index 84ded9a4df..15c6c8bb57 100644 --- a/fuzz/dtlsserver.c +++ b/fuzz/dtlsserver.c @@ -218,6 +218,7 @@ static const uint8_t RSACertificatePEM[] = { 0x2d, 0x0a }; +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC1mQfTLWrNFfUs @@ -463,8 +464,10 @@ static const uint8_t RSAPrivateKeyPEM[] = { 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a }; +#endif #ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* -----BEGIN EC PRIVATE KEY----- MHcCAQEEIJLyl7hJjpQL/RhP1x2zS79xdiPJQB683gWeqcqHPeZkoAoGCCqGSM49 @@ -493,6 +496,7 @@ static const char ECDSAPrivateKeyPEM[] = { 0x4e, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a }; +#endif /* -----BEGIN CERTIFICATE----- @@ -555,7 +559,7 @@ static const char ECDSACertPEM[] = { }; #endif -#ifndef OPENSSL_NO_DSA +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0) /* -----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQDdkFKzNABLOha7Eqj7004+p5fhtR6bxpujToMmSZTYi8igVVXP @@ -775,109 +779,121 @@ time_t time(time_t *t) TIME_IMPL(t) return 1; } -static int use_pem_privkey(SSL_CTX *ctx, const void *pem, size_t pem_len) -{ - BIO *bio_buf; - EVP_PKEY *pkey; - int rv = 0; - - bio_buf = BIO_new(BIO_s_mem()); - if (bio_buf == NULL) - return 0; - if ((size_t)BIO_write(bio_buf, pem, (int)pem_len) != pem_len) { - BIO_free(bio_buf); - return 0; - } - pkey = PEM_read_bio_PrivateKey(bio_buf, NULL, NULL, NULL); - BIO_free(bio_buf); - if (pkey == NULL) - return 0; - if (SSL_CTX_use_PrivateKey(ctx, pkey) == 1) - rv = 1; - EVP_PKEY_free(pkey); - return rv; -} - -static int use_pem_cert(SSL_CTX *ctx, const void *pem, size_t pem_len) -{ - BIO *bio_buf; - X509 *cert; - int rv = 0; - - bio_buf = BIO_new(BIO_s_mem()); - if (bio_buf == NULL) - return 0; - if ((size_t)BIO_write(bio_buf, pem, (int)pem_len) != pem_len) { - BIO_free(bio_buf); - return 0; - } - cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); - BIO_free(bio_buf); - if (cert == NULL) - return 0; - if (SSL_CTX_use_certificate(ctx, cert) == 1) - rv = 1; - X509_free(cert); - return rv; -} - int FuzzerTestOneInput(const uint8_t *buf, size_t len) { - SSL *server = NULL; + SSL *server; BIO *in; BIO *out; + BIO *bio_buf; SSL_CTX *ctx; + int ret; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + RSA *privkey; +#endif +#if !defined(OPENSSL_NO_DEPRECATED_3_0) + EVP_PKEY *pkey; +#endif + X509 *cert; +#ifndef OPENSSL_NO_DEPRECATED_3_0 +#ifndef OPENSSL_NO_EC + EC_KEY *ecdsakey = NULL; +#endif +#endif +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0) + DSA *dsakey = NULL; +#endif if (len < 2 || len > INT_MAX) return 0; + /* This only fuzzes the initial flow from the client so far. */ ctx = SSL_CTX_new(DTLS_server_method()); - if (ctx == NULL) - return 0; - if (SSL_CTX_set_min_proto_version(ctx, 0) != 1) - goto end; - if (SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:@SECLEVEL=0") != 1) - goto end; + ret = SSL_CTX_set_min_proto_version(ctx, 0); + OPENSSL_assert(ret == 1); + ret = SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:@SECLEVEL=0"); + OPENSSL_assert(ret == 1); +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* RSA */ - if (!use_pem_privkey(ctx, RSAPrivateKeyPEM, sizeof(RSAPrivateKeyPEM))) - goto end; - if (!use_pem_cert(ctx, RSACertificatePEM, sizeof(RSACertificatePEM))) - goto end; - -#ifndef OPENSSL_NO_EC - /* ECDSA */ - if (!use_pem_privkey(ctx, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM))) - goto end; - if (!use_pem_cert(ctx, ECDSACertPEM, sizeof(ECDSACertPEM))) - goto end; + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, RSAPrivateKeyPEM, sizeof(RSAPrivateKeyPEM)) == sizeof(RSAPrivateKeyPEM)); + privkey = PEM_read_bio_RSAPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(privkey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(pkey, privkey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); #endif -#ifndef OPENSSL_NO_DSA + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, RSACertificatePEM, sizeof(RSACertificatePEM)) == sizeof(RSACertificatePEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + BIO_free(bio_buf); + OPENSSL_assert(cert != NULL); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); + +#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_DEPRECATED_3_0 + /* ECDSA */ + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM)) == sizeof(ECDSAPrivateKeyPEM)); + ecdsakey = PEM_read_bio_ECPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(ecdsakey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_EC_KEY(pkey, ecdsakey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); +#endif + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSACertPEM, sizeof(ECDSACertPEM)) == sizeof(ECDSACertPEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + OPENSSL_assert(cert != NULL); + BIO_free(bio_buf); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); +#endif + +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0) /* DSA */ - if (!use_pem_privkey(ctx, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM))) - goto end; - if (!use_pem_cert(ctx, DSACertPEM, sizeof(DSACertPEM))) - goto end; + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM)) == sizeof(DSAPrivateKeyPEM)); + dsakey = PEM_read_bio_DSAPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(dsakey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(pkey, dsakey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); + + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, DSACertPEM, sizeof(DSACertPEM)) == sizeof(DSACertPEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + OPENSSL_assert(cert != NULL); + BIO_free(bio_buf); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); #endif server = SSL_new(ctx); - if (server == NULL) - goto end; in = BIO_new(BIO_s_mem()); - if (in == NULL) - goto end; out = BIO_new(BIO_s_mem()); - if (out == NULL) { - BIO_free(in); - goto end; - } SSL_set_bio(server, in, out); SSL_set_accept_state(server); - if ((size_t)BIO_write(in, buf, (int)len) != len) - goto end; + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); if (SSL_do_handshake(server) == 1) { /* Keep reading application data until error or EOF. */ @@ -888,7 +904,6 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) } } } -end: SSL_free(server); ERR_clear_error(); SSL_CTX_free(ctx); diff --git a/fuzz/echconfiglist_parser.c b/fuzz/echconfiglist_parser.c deleted file mode 100644 index fce416ec4d..0000000000 --- a/fuzz/echconfiglist_parser.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.openssl.org/source/license.html - * or in the file LICENSE in the source distribution. - */ -#include -#include -#include -#include -#include -#include -#include -#include "fuzzer.h" - -static void parse_one(const uint8_t *buf, int len) -{ - OSSL_ECHSTORE *es; - BIO *in; - - es = OSSL_ECHSTORE_new(NULL, NULL); - if (es == NULL) - return; - - in = BIO_new_mem_buf(buf, len); - if (in == NULL) { - OSSL_ECHSTORE_free(es); - return; - } - - OSSL_ECHSTORE_read_echconfiglist(es, in); - - OSSL_ECHSTORE_free(es); - BIO_free(in); -} - -int FuzzerInitialize(int *argc, char ***argv) -{ - return 1; -} - -int FuzzerTestOneInput(const uint8_t *buf, size_t len) -{ - uint8_t *fixed_buf = NULL; - int bio_len; - uint16_t outer_len, inner_len; - - if (len > INT_MAX) - return 0; - bio_len = (int)len; - - /* Target raw without any fixup */ - parse_one(buf, bio_len); - - /* - * ech_decode_and_flatten has a strict size check: - * OSSL_ECH_MIN_ECHCONFIG_LEN = 32 - * OSSL_ECH_MAX_ECHCONFIG_LEN = 1500 - */ - if (len < OSSL_ECH_MIN_ECHCONFIG_LEN || len >= OSSL_ECH_MAX_ECHCONFIG_LEN) - goto end; - outer_len = (uint16_t)(len - 2); - inner_len = (uint16_t)(len - 6); - - fixed_buf = OPENSSL_memdup(buf, len); - if (fixed_buf == NULL) - goto end; - - /* Fix up to pass initial checks*/ - OPENSSL_store_u16_be(fixed_buf, outer_len); - OPENSSL_store_u16_be(fixed_buf + 2, OSSL_ECH_RFC9849_VERSION); - OPENSSL_store_u16_be(fixed_buf + 4, inner_len); - - parse_one(fixed_buf, bio_len); - -end: - OPENSSL_free(fixed_buf); - ERR_clear_error(); - - return 0; -} - -void FuzzerCleanup(void) -{ -} diff --git a/fuzz/hashtable.c b/fuzz/hashtable.c index 9eb81c0a9e..9e9519b865 100644 --- a/fuzz/hashtable.c +++ b/fuzz/hashtable.c @@ -162,11 +162,22 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) /* set the proper key value */ HT_SET_KEY_FIELD(&key, fuzzkey, keyval); - memcpy(&valptr->value, &buf[3], sizeof(uint64_t)); - /* lock the table */ ossl_ht_write_lock(fuzzer_table); + /* + * If the value to insert is already allocated + * then we expect a conflict in the insert + * i.e. we predict a return code of 0 instead + * of 1. On replacement, we expect it to succeed + * always + */ + if (valptr->flags & FZ_FLAG_ALLOCATED) { + if (!IS_REPLACE(op_flags)) + rc_prediction = 0; + } + + memcpy(&valptr->value, &buf[3], sizeof(uint64_t)); /* * do the insert/replace */ @@ -177,18 +188,30 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) rc = ossl_ht_fz_FUZZER_VALUE_insert(fuzzer_table, TO_HT_KEY(&key), valptr, NULL); + if (rc == -1) + /* failed to grow the hash table due to too many collisions */ + break; + + /* + * mark the entry as being allocated + */ + valptr->flags |= FZ_FLAG_ALLOCATED; + /* * unlock the table */ ossl_ht_write_unlock(fuzzer_table); /* - * mark the entry as being allocated + * Now check to make sure we did the right thing */ - if (rc == 1) { - valptr->flags |= FZ_FLAG_ALLOCATED; + OPENSSL_assert(rc == rc_prediction); + + /* + * successful insertion if there wasn't a conflict + */ + if (rc_prediction == 1) IS_REPLACE(op_flags) ? replacements++ : inserts++; - } break; case OP_DELETE: @@ -203,6 +226,15 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) /* lock the table */ ossl_ht_write_lock(fuzzer_table); + /* + * If the value to delete is not already allocated + * then we expect a miss in the delete + * i.e. we predict a return code of 0 instead + * of 1 + */ + if (!(valptr->flags & FZ_FLAG_ALLOCATED)) + rc_prediction = 0; + /* * do the delete */ @@ -213,10 +245,22 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) */ ossl_ht_write_unlock(fuzzer_table); + /* + * Now check to make sure we did the right thing + */ + OPENSSL_assert(rc == rc_prediction); + + /* + * once the unlock is done, the table rcu will have synced + * meaning the free function has run, so we can confirm now + * that the valptr is no longer allocated + */ + OPENSSL_assert(!(valptr->flags & FZ_FLAG_ALLOCATED)); + /* * successful deletion if there wasn't a conflict */ - if (rc == 1) + if (rc_prediction == 1) deletes++; break; @@ -257,23 +301,25 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) /* * Now check to make sure we did the right thing */ - if (valptr == NULL) - OPENSSL_assert(lval == NULL); - else - OPENSSL_assert(lval == NULL || lval == valptr); + OPENSSL_assert(lval == valptr); /* * if we expect a positive lookup, make sure that * we can use the _type and to_value functions */ - if (valptr != NULL && lval != NULL) { + if (valptr != NULL) { OPENSSL_assert(ossl_ht_fz_FUZZER_VALUE_type(v) == 1); v = ossl_ht_fz_FUZZER_VALUE_to_value(lval, &tv); OPENSSL_assert(v->value == lval); - lookups++; } + /* + * successful lookup if we didn't expect a miss + */ + if (valptr != NULL) + lookups++; + break; case OP_FLUSH: @@ -290,17 +336,17 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) * lock the table */ ossl_ht_write_lock(fuzzer_table); - rc = ossl_ht_flush(fuzzer_table); + ossl_ht_flush(fuzzer_table); ossl_ht_write_unlock(fuzzer_table); /* * now check to make sure everything is free */ - if (rc == 1) { - for (i = 0; i < USHRT_MAX; i++) - OPENSSL_assert((prediction_table[i].flags & FZ_FLAG_ALLOCATED) == 0); - flushes++; - } + for (i = 0; i < USHRT_MAX; i++) + OPENSSL_assert((prediction_table[i].flags & FZ_FLAG_ALLOCATED) == 0); + + /* good flush */ + flushes++; break; case OP_FOREACH: @@ -326,11 +372,11 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) rc_prediction = 1; htvlist = ossl_ht_filter(fuzzer_table, 1, filter_iterator, &keyval); - if (htvlist != NULL) { - OPENSSL_assert(htvlist->list_len == (size_t)rc_prediction); - ossl_ht_value_list_free(htvlist); - filters++; - } + + OPENSSL_assert(htvlist->list_len == (size_t)rc_prediction); + + ossl_ht_value_list_free(htvlist); + filters++; break; default: diff --git a/fuzz/ml-dsa.c b/fuzz/ml-dsa.c index e56a023e46..094af9096a 100644 --- a/fuzz/ml-dsa.c +++ b/fuzz/ml-dsa.c @@ -254,10 +254,6 @@ static int keygen_ml_dsa_real_key_helper(uint8_t **buf, size_t *len, ret = 1; err: - if (!ret) { - EVP_PKEY_free(*key); - *key = NULL; - } EVP_PKEY_CTX_free(ctx); return ret; } @@ -663,7 +659,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) /* And run our setup/doit/cleanup sequence */ if (ops[operation].setup != NULL) ops[operation].setup(&buffer_cursor, &len, &in1, &in2); - if (ops[operation].doit != NULL && in1 != NULL) + if (ops[operation].doit != NULL) ops[operation].doit(&buffer_cursor, &len, in1, in2, &out1, &out2); if (ops[operation].cleanup != NULL) ops[operation].cleanup(in1, in2, out1, out2); diff --git a/fuzz/ml-kem.c b/fuzz/ml-kem.c index dfd4faf6dc..6e3aed8b23 100644 --- a/fuzz/ml-kem.c +++ b/fuzz/ml-kem.c @@ -650,7 +650,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) */ if (ops[operation].setup != NULL) ops[operation].setup(&buffer_cursor, &len, &in1, &in2); - if (ops[operation].doit != NULL && in1 != NULL) + if (ops[operation].doit != NULL) ops[operation].doit(&buffer_cursor, &len, in1, in2, &out1, &out2); if (ops[operation].cleanup != NULL) ops[operation].cleanup(in1, in2, out1, out2); diff --git a/fuzz/pem.c b/fuzz/pem.c index a2da9820a7..a8a1d810f0 100644 --- a/fuzz/pem.c +++ b/fuzz/pem.c @@ -31,15 +31,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) return 0; in = BIO_new(BIO_s_mem()); - if (in == NULL) { - ERR_clear_error(); - return 0; - } - if ((size_t)BIO_write(in, buf + 1, (int)(len - 1)) != len - 1) { - BIO_free(in); - ERR_clear_error(); - return 0; - } + OPENSSL_assert((size_t)BIO_write(in, buf + 1, (int)(len - 1)) == len - 1); if (PEM_read_bio_ex(in, &name, &header, &data, &outlen, buf[0]) == 1) { /* Try to read all the data we get to see if allocated properly. */ BIO_write(in, name, (int)strlen(name)); diff --git a/fuzz/pkcs12.c b/fuzz/pkcs12.c index 74e2b6dd8a..3bc9b5f7d7 100644 --- a/fuzz/pkcs12.c +++ b/fuzz/pkcs12.c @@ -39,15 +39,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) return 0; in = BIO_new(BIO_s_mem()); - if (in == NULL) { - ERR_clear_error(); - return 0; - } - if ((size_t)BIO_write(in, buf, (int)len) != len) { - BIO_free(in); - ERR_clear_error(); - return 0; - } + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); p12 = d2i_PKCS12_bio(in, NULL); if (p12 != NULL) { PKCS12_verify_mac(p12, NULL, 0); diff --git a/fuzz/provider.c b/fuzz/provider.c index bc45489a2f..981be0690d 100644 --- a/fuzz/provider.c +++ b/fuzz/provider.c @@ -32,11 +32,8 @@ { \ STACK_OF(evp) *obj_stack = stack; \ \ - if (!evp##_up_ref(obj)) \ - return; \ - \ - if (sk_##evp##_push(obj_stack, obj) <= 0) \ - evp##_free(obj); \ + if (sk_##evp##_push(obj_stack, obj) > 0) \ + evp##_up_ref(obj); \ } \ static void init_##name(OSSL_LIB_CTX *libctx) \ { \ @@ -304,7 +301,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l if (!read_int(buf, len, &use_param)) { use_param = OPENSSL_malloc(sizeof(uint64_t)); if (use_param == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); return NULL; } @@ -316,7 +312,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l if (strcmp(param->key, OSSL_KDF_PARAM_ITER) == 0) { p_value_int = OPENSSL_malloc(sizeof(ITERS)); if (p_value_int == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -325,7 +320,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_N) == 0) { p_value_int = OPENSSL_malloc(sizeof(ITERS)); if (p_value_int == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -334,7 +328,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_R) == 0) { p_value_int = OPENSSL_malloc(sizeof(BLOCKSIZE)); if (p_value_int == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -343,7 +336,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_P) == 0) { p_value_int = OPENSSL_malloc(sizeof(BLOCKSIZE)); if (p_value_int == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -352,7 +344,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (!*use_param || !read_int(buf, len, &p_value_int)) { p_value_int = OPENSSL_malloc(sizeof(int64_t)); if (p_value_int == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -368,7 +359,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l if (strcmp(param->key, OSSL_KDF_PARAM_ITER) == 0) { p_value_uint = OPENSSL_malloc(sizeof(UITERS)); if (p_value_uint == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -377,7 +367,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_N) == 0) { p_value_uint = OPENSSL_malloc(sizeof(UITERS)); if (p_value_uint == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -386,7 +375,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_R) == 0) { p_value_uint = OPENSSL_malloc(sizeof(UBLOCKSIZE)); if (p_value_uint == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -395,7 +383,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_P) == 0) { p_value_uint = OPENSSL_malloc(sizeof(UBLOCKSIZE)); if (p_value_uint == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -404,7 +391,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l } else if (!*use_param || !read_uint(buf, len, &p_value_uint)) { p_value_uint = OPENSSL_malloc(sizeof(uint64_t)); if (p_value_uint == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; @@ -420,7 +406,6 @@ static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *l if (!*use_param || !read_double(buf, len, &p_value_double)) { p_value_double = OPENSSL_malloc(sizeof(double)); if (p_value_double == NULL) { - free_params(fuzzed_parameters); OPENSSL_free(fuzzed_parameters); OPENSSL_free(use_param); return NULL; diff --git a/fuzz/quic-client.c b/fuzz/quic-client.c index e75390ad60..851ecc5cc9 100644 --- a/fuzz/quic-client.c +++ b/fuzz/quic-client.c @@ -77,8 +77,6 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) if (client == NULL) goto end; - allstreams[0] = stream = client; - fake_now = ossl_ms2time(1); if (!ossl_quic_set_override_now_cb(client, fake_now_cb, NULL)) goto end; @@ -92,8 +90,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) if (!BIO_ADDR_rawmake(peer_addr, AF_INET, &ina, sizeof(ina), htons(4433))) goto end; - if (SSL_set_tlsext_host_name(client, "localhost") != 1) - goto end; + SSL_set_tlsext_host_name(client, "localhost"); in = BIO_new(BIO_s_dgram_mem()); if (in == NULL) goto end; @@ -119,6 +116,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) 0)) goto end; + allstreams[0] = stream = client; for (;;) { size_t size; uint64_t nxtpktms = 0; diff --git a/fuzz/quic-srtm.c b/fuzz/quic-srtm.c index 9eb4117adc..a7897da710 100644 --- a/fuzz/quic-srtm.c +++ b/fuzz/quic-srtm.c @@ -77,9 +77,9 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) sizeof(arg_token.token))) continue; /* just stop */ - if (ossl_quic_srtm_add(srtm, (void *)(uintptr_t)arg_opaque, - arg_seq_num, &arg_token)) - ossl_quic_srtm_check(srtm); + ossl_quic_srtm_add(srtm, (void *)(uintptr_t)arg_opaque, + arg_seq_num, &arg_token); + ossl_quic_srtm_check(srtm); break; case CMD_REMOVE: @@ -87,17 +87,17 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) || !PACKET_get_net_8(&pkt, &arg_seq_num)) continue; /* just stop */ - if (ossl_quic_srtm_remove(srtm, (void *)(uintptr_t)arg_opaque, - arg_seq_num, NULL)) - ossl_quic_srtm_check(srtm); + ossl_quic_srtm_remove(srtm, (void *)(uintptr_t)arg_opaque, + arg_seq_num); + ossl_quic_srtm_check(srtm); break; case CMD_CULL: if (!PACKET_get_net_8(&pkt, &arg_opaque)) continue; /* just stop */ - if (ossl_quic_srtm_cull(srtm, (void *)(uintptr_t)arg_opaque)) - ossl_quic_srtm_check(srtm); + ossl_quic_srtm_cull(srtm, (void *)(uintptr_t)arg_opaque); + ossl_quic_srtm_check(srtm); break; case CMD_LOOKUP: @@ -106,9 +106,9 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) || !PACKET_get_net_8(&pkt, &arg_idx)) continue; /* just stop */ - if (ossl_quic_srtm_lookup(srtm, &arg_token, (size_t)arg_idx, - NULL, NULL)) - ossl_quic_srtm_check(srtm); + ossl_quic_srtm_lookup(srtm, &arg_token, (size_t)arg_idx, + NULL, NULL); + ossl_quic_srtm_check(srtm); break; default: diff --git a/fuzz/server.c b/fuzz/server.c index 740ade8513..1723cecda5 100644 --- a/fuzz/server.c +++ b/fuzz/server.c @@ -25,7 +25,6 @@ #include #include "fuzzer.h" -#ifndef OPENSSL_NO_DEPRECATED_3_0 static const uint8_t kCertificateDER[] = { 0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, @@ -126,6 +125,7 @@ static const uint8_t kCertificateDER[] = { 0x76, 0x8a, 0xbb }; +#ifndef OPENSSL_NO_DEPRECATED_3_0 static const uint8_t kRSAPrivateKeyDER[] = { 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce, 0x47, 0xcb, 0x11, @@ -281,6 +281,7 @@ static const uint8_t kRSAPrivateKeyDER[] = { #endif #ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* * -----BEGIN EC PRIVATE KEY----- * MHcCAQEEIJLyl7hJjpQL/RhP1x2zS79xdiPJQB683gWeqcqHPeZkoAoGCCqGSM49 @@ -309,6 +310,7 @@ static const char ECDSAPrivateKeyPEM[] = { 0x4e, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a }; +#endif /* * -----BEGIN CERTIFICATE----- @@ -371,7 +373,7 @@ static const char ECDSACertPEM[] = { }; #endif -#ifndef OPENSSL_NO_DSA +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0) /* * -----BEGIN DSA PRIVATE KEY----- * MIIBuwIBAAKBgQDdkFKzNABLOha7Eqj7004+p5fhtR6bxpujToMmSZTYi8igVVXP @@ -591,155 +593,139 @@ time_t time(time_t *t) TIME_IMPL(t) return 1; } -#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DSA) -static int use_pem_privkey(SSL_CTX *ctx, const void *pem, size_t pem_len) -{ - BIO *bio_buf; - EVP_PKEY *pkey; - int rv = 0; - - bio_buf = BIO_new(BIO_s_mem()); - if (bio_buf == NULL) - return 0; - if ((size_t)BIO_write(bio_buf, pem, (int)pem_len) != pem_len) { - BIO_free(bio_buf); - return 0; - } - pkey = PEM_read_bio_PrivateKey(bio_buf, NULL, NULL, NULL); - BIO_free(bio_buf); - if (pkey == NULL) - return 0; - if (SSL_CTX_use_PrivateKey(ctx, pkey) == 1) - rv = 1; - EVP_PKEY_free(pkey); - return rv; -} - -static int use_pem_cert(SSL_CTX *ctx, const void *pem, size_t pem_len) -{ - BIO *bio_buf; - X509 *cert; - int rv = 0; - - bio_buf = BIO_new(BIO_s_mem()); - if (bio_buf == NULL) - return 0; - if ((size_t)BIO_write(bio_buf, pem, (int)pem_len) != pem_len) { - BIO_free(bio_buf); - return 0; - } - cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); - BIO_free(bio_buf); - if (cert == NULL) - return 0; - if (SSL_CTX_use_certificate(ctx, cert) == 1) - rv = 1; - X509_free(cert); - return rv; -} -#endif - int FuzzerTestOneInput(const uint8_t *buf, size_t len) { - SSL *server = NULL; + SSL *server; BIO *in; BIO *out; +#if !defined(OPENSSL_NO_EC) \ + || (!defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)) + BIO *bio_buf; +#endif SSL_CTX *ctx; + int ret; #ifndef OPENSSL_NO_DEPRECATED_3_0 + RSA *privkey; +#endif const uint8_t *bufp; - RSA *privkey = NULL; - EVP_PKEY *pkey = NULL; - X509 *cert = NULL; +#if !defined(OPENSSL_NO_DEPRECATED_3_0) + EVP_PKEY *pkey; +#endif + X509 *cert; +#ifndef OPENSSL_NO_DEPRECATED_3_0 +#ifndef OPENSSL_NO_EC + EC_KEY *ecdsakey = NULL; +#endif +#endif +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0) + DSA *dsakey = NULL; #endif uint8_t opt; - int ret; if (len < 2 || len > INT_MAX) return 0; + /* This only fuzzes the initial flow from the client so far. */ ctx = SSL_CTX_new(TLS_method()); - if (ctx == NULL) - return 0; - if (SSL_CTX_set_min_proto_version(ctx, 0) != 1) - goto end; - if (SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:@SECLEVEL=0") != 1) - goto end; + OPENSSL_assert(ctx != NULL); + ret = SSL_CTX_set_min_proto_version(ctx, 0); + OPENSSL_assert(ret == 1); + ret = SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:@SECLEVEL=0"); + OPENSSL_assert(ret == 1); #ifndef OPENSSL_NO_DEPRECATED_3_0 /* RSA */ bufp = kRSAPrivateKeyDER; privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER)); - if (privkey == NULL) - goto end; + OPENSSL_assert(privkey != NULL); pkey = EVP_PKEY_new(); - if (pkey == NULL) { - RSA_free(privkey); - goto end; - } - if (!EVP_PKEY_assign_RSA(pkey, privkey)) { - /* assignment failed; pkey doesn't own privkey, clean both */ - RSA_free(privkey); - EVP_PKEY_free(pkey); - goto end; - } + OPENSSL_assert(pkey != NULL); + EVP_PKEY_assign_RSA(pkey, privkey); ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); EVP_PKEY_free(pkey); - if (ret != 1) - goto end; +#endif bufp = kCertificateDER; cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER)); - if (cert == NULL) - goto end; + OPENSSL_assert(cert != NULL); ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); X509_free(cert); - if (ret != 1) - goto end; -#endif #ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* ECDSA */ - if (!use_pem_privkey(ctx, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM))) - goto end; - if (!use_pem_cert(ctx, ECDSACertPEM, sizeof(ECDSACertPEM))) - goto end; + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert(bio_buf != NULL); + OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM)) == sizeof(ECDSAPrivateKeyPEM)); + ecdsakey = PEM_read_bio_ECPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(ecdsakey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + OPENSSL_assert(pkey != NULL); + EVP_PKEY_assign_EC_KEY(pkey, ecdsakey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); +#endif + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert(bio_buf != NULL); + OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSACertPEM, sizeof(ECDSACertPEM)) == sizeof(ECDSACertPEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + OPENSSL_assert(cert != NULL); + BIO_free(bio_buf); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); #endif -#ifndef OPENSSL_NO_DSA +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0) /* DSA */ - if (!use_pem_privkey(ctx, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM))) - goto end; - if (!use_pem_cert(ctx, DSACertPEM, sizeof(DSACertPEM))) - goto end; + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert(bio_buf != NULL); + OPENSSL_assert((size_t)BIO_write(bio_buf, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM)) == sizeof(DSAPrivateKeyPEM)); + dsakey = PEM_read_bio_DSAPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(dsakey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + OPENSSL_assert(pkey != NULL); + EVP_PKEY_assign_DSA(pkey, dsakey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); + + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert(bio_buf != NULL); + OPENSSL_assert((size_t)BIO_write(bio_buf, DSACertPEM, sizeof(DSACertPEM)) == sizeof(DSACertPEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + OPENSSL_assert(cert != NULL); + BIO_free(bio_buf); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); #endif server = SSL_new(ctx); - if (server == NULL) - goto end; in = BIO_new(BIO_s_mem()); - if (in == NULL) - goto end; + OPENSSL_assert(in != NULL); out = BIO_new(BIO_s_mem()); - if (out == NULL) { - BIO_free(in); - goto end; - } + OPENSSL_assert(out != NULL); SSL_set_bio(server, in, out); SSL_set_accept_state(server); opt = (uint8_t)buf[len - 1]; len--; - if ((size_t)BIO_write(in, buf, (int)len) != len) - goto end; + OPENSSL_assert((size_t)BIO_write(in, buf, (int)len) == len); if ((opt & 0x01) != 0) { do { char early_buf[16384]; size_t early_len; - - ret = SSL_read_early_data(server, early_buf, sizeof(early_buf), - &early_len); + ret = SSL_read_early_data(server, early_buf, sizeof(early_buf), &early_len); if (ret != SSL_READ_EARLY_DATA_SUCCESS) break; @@ -755,7 +741,6 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) } } } -end: SSL_free(server); ERR_clear_error(); SSL_CTX_free(ctx); diff --git a/fuzz/slh-dsa.c b/fuzz/slh-dsa.c index 0f78a01da8..17238bcf8b 100644 --- a/fuzz/slh-dsa.c +++ b/fuzz/slh-dsa.c @@ -63,32 +63,26 @@ static EVP_PKEY *slh_dsa_gen_key(const char *name, uint32_t keysize, { EVP_PKEY_CTX *ctx; EVP_PKEY *new = NULL; + int rc; ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); - if (ctx == NULL) - return NULL; + OPENSSL_assert(ctx != NULL); if (params != NULL) { new = EVP_PKEY_new(); - if (new == NULL) - goto out; - if (!EVP_PKEY_fromdata_init(ctx)) { - EVP_PKEY_free(new); - new = NULL; - goto out; - } - if (EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) != 1) { + OPENSSL_assert(EVP_PKEY_fromdata_init(ctx)); + if (*param_broken) { + rc = EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params); + OPENSSL_assert(rc == 0); EVP_PKEY_free(new); new = NULL; + } else { + OPENSSL_assert(EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) == 1); } goto out; } - if (!EVP_PKEY_keygen_init(ctx)) - goto out; - if (!EVP_PKEY_generate(ctx, &new)) { - EVP_PKEY_free(new); - new = NULL; - } + OPENSSL_assert(EVP_PKEY_keygen_init(ctx)); + OPENSSL_assert(EVP_PKEY_generate(ctx, &new)); out: EVP_PKEY_CTX_free(ctx); @@ -227,10 +221,9 @@ static void slh_dsa_gen_key_with_params(uint8_t **buf, size_t *len, *buf = consume_uint8t(*buf, len, &selector); keytype = select_keytype(selector, &keysize); - if (!RAND_bytes(pubbuf, PARAM_BUF_SZ) - || !RAND_bytes(prvbuf, PARAM_BUF_SZ) - || !RAND_bytes(sdbuf, PARAM_BUF_SZ)) - return; + RAND_bytes(pubbuf, PARAM_BUF_SZ); + RAND_bytes(prvbuf, PARAM_BUF_SZ); + RAND_bytes(sdbuf, PARAM_BUF_SZ); /* * select an invalid length if the buffer 0th bit is one @@ -267,6 +260,11 @@ static void slh_dsa_gen_key_with_params(uint8_t **buf, size_t *len, params[2] = OSSL_PARAM_construct_end(); *out1 = (void *)slh_dsa_gen_key(keytype, keysize, params, &broken); + + if (broken) + OPENSSL_assert(*out1 == NULL); + else + OPENSSL_assert(*out1 != NULL); return; } @@ -321,6 +319,7 @@ static void slh_dsa_sign_verify(uint8_t **buf, size_t *len, void *key1, OSSL_PARAM params[4]; int paramidx = 0; int intval1, intval2; + int expect_init_rc = 1; *buf = consume_uint8t(*buf, len, &selector); if (*buf == NULL) @@ -341,6 +340,10 @@ static void slh_dsa_sign_verify(uint8_t **buf, size_t *len, void *key1, msg = (unsigned char *)*buf; msg_len = *len; + /* if msg_len > 255, sign_message_init will fail */ + if (msg_len > 255 && (selector & 0x1) != 0) + expect_init_rc = 0; + *len = 0; if (selector & 0x1) @@ -362,39 +365,33 @@ static void slh_dsa_sign_verify(uint8_t **buf, size_t *len, void *key1, params[paramidx] = OSSL_PARAM_construct_end(); key = (void *)slh_dsa_gen_key(keytype, keylen, NULL, 0); - if (key == NULL) - return; + OPENSSL_assert(key != NULL); *out1 = key; /* for cleanup */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, key, NULL); - if (ctx == NULL) - goto out; + OPENSSL_assert(ctx != NULL); sig_alg = EVP_SIGNATURE_fetch(NULL, keytype, NULL); - if (sig_alg == NULL) - goto out; + OPENSSL_assert(sig_alg != NULL); + OPENSSL_assert(EVP_PKEY_sign_message_init(ctx, sig_alg, params) == expect_init_rc); /* * the context_string parameter can be no more than 255 bytes, so if - * our random input buffer is greater than that, sign_message_init will - * fail, in which case there's nothing more we can do here so bail out + * our random input buffer is greater than that, we expect failure above, + * which we check for. In that event, there's nothing more we can do here + * so bail out */ - if (EVP_PKEY_sign_message_init(ctx, sig_alg, params) != 1) + if (expect_init_rc == 0) goto out; - if (EVP_PKEY_sign(ctx, NULL, &sig_len, msg, msg_len) != 1) - goto out; + OPENSSL_assert(EVP_PKEY_sign(ctx, NULL, &sig_len, msg, msg_len)); sig = OPENSSL_zalloc(sig_len); - if (sig == NULL) - goto out; + OPENSSL_assert(sig != NULL); - if (EVP_PKEY_sign(ctx, sig, &sig_len, msg, msg_len) != 1) - goto out; + OPENSSL_assert(EVP_PKEY_sign(ctx, sig, &sig_len, msg, msg_len)); - if (EVP_PKEY_verify_message_init(ctx, sig_alg, params) != 1) - goto out; - if (EVP_PKEY_verify(ctx, sig, sig_len, msg, msg_len) != 1) - fprintf(stderr, "Failed to verify message\n"); + OPENSSL_assert(EVP_PKEY_verify_message_init(ctx, sig_alg, params)); + OPENSSL_assert(EVP_PKEY_verify(ctx, sig, sig_len, msg, msg_len)); out: OPENSSL_free(sig); @@ -420,34 +417,32 @@ out: static void slh_dsa_export_import(uint8_t **buf, size_t *len, void *key1, void *key2, void **out1, void **out2) { + int rc; EVP_PKEY *alice = (EVP_PKEY *)key1; EVP_PKEY *bob = (EVP_PKEY *)key2; EVP_PKEY *new = NULL; EVP_PKEY_CTX *ctx = NULL; OSSL_PARAM *params = NULL; - if (alice == NULL || bob == NULL) - return; - - if (!EVP_PKEY_todata(alice, EVP_PKEY_KEYPAIR, ¶ms)) - goto alice_done; + OPENSSL_assert(EVP_PKEY_todata(alice, EVP_PKEY_KEYPAIR, ¶ms) == 1); ctx = EVP_PKEY_CTX_new_from_pkey(NULL, alice, NULL); - if (ctx == NULL) - goto alice_done; + OPENSSL_assert(ctx != NULL); - if (!EVP_PKEY_fromdata_init(ctx)) - goto alice_done; + OPENSSL_assert(EVP_PKEY_fromdata_init(ctx)); new = EVP_PKEY_new(); - if (new == NULL) - goto alice_done; - if (EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) != 1) - goto alice_done; + OPENSSL_assert(new != NULL); + OPENSSL_assert(EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) == 1); - (void)EVP_PKEY_eq(alice, new); - -alice_done: + /* + * EVP_PKEY returns: + * 1 if the keys are equivalent + * 0 if the keys are not equivalent + * -1 if the key types are different + * -2 if the operation is not supported + */ + OPENSSL_assert(EVP_PKEY_eq(alice, new) == 1); EVP_PKEY_free(new); EVP_PKEY_CTX_free(ctx); OSSL_PARAM_free(params); @@ -455,26 +450,26 @@ alice_done: ctx = NULL; new = NULL; - if (!EVP_PKEY_todata(bob, EVP_PKEY_KEYPAIR, ¶ms)) - goto bob_done; + OPENSSL_assert(EVP_PKEY_todata(bob, EVP_PKEY_KEYPAIR, ¶ms) == 1); ctx = EVP_PKEY_CTX_new_from_pkey(NULL, bob, NULL); - if (ctx == NULL) - goto bob_done; + OPENSSL_assert(ctx != NULL); - if (!EVP_PKEY_fromdata_init(ctx)) - goto bob_done; + OPENSSL_assert(EVP_PKEY_fromdata_init(ctx)); new = EVP_PKEY_new(); - if (new == NULL) - goto bob_done; - if (EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) != 1) - goto bob_done; + OPENSSL_assert(new != NULL); + OPENSSL_assert(EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) == 1); - (void)EVP_PKEY_eq(bob, new); - (void)EVP_PKEY_eq(alice, new); + OPENSSL_assert(EVP_PKEY_eq(bob, new) == 1); + + /* + * Depending on the types of eys that get generated + * we might get a simple non-equivalence or a type mismatch here + */ + rc = EVP_PKEY_eq(alice, new); + OPENSSL_assert(rc == 0 || rc == -1); -bob_done: EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(new); OSSL_PARAM_free(params); @@ -594,7 +589,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) */ if (ops[operation].setup != NULL) ops[operation].setup(&buffer_cursor, &len, &in1, &in2); - if (ops[operation].doit != NULL && in1 != NULL) + if (ops[operation].doit != NULL) ops[operation].doit(&buffer_cursor, &len, in1, in2, &out1, &out2); if (ops[operation].cleanup != NULL) ops[operation].cleanup(in1, in2, out1, out2); diff --git a/fuzz/smime.c b/fuzz/smime.c index ab68cb0165..b55a1ef74b 100644 --- a/fuzz/smime.c +++ b/fuzz/smime.c @@ -21,18 +21,8 @@ int FuzzerInitialize(int *argc, char ***argv) int FuzzerTestOneInput(const uint8_t *buf, size_t len) { - BIO *b; - PKCS7 *p7; - - if (len > INT_MAX) - return 0; - - b = BIO_new_mem_buf(buf, (int)len); - if (b == NULL) { - ERR_clear_error(); - return 0; - } - p7 = SMIME_read_PKCS7(b, NULL); + BIO *b = BIO_new_mem_buf(buf, (int)len); + PKCS7 *p7 = SMIME_read_PKCS7(b, NULL); if (p7 != NULL) { STACK_OF(PKCS7_SIGNER_INFO) *p7si = PKCS7_get_signer_info(p7); diff --git a/fuzz/test-corpus.c b/fuzz/test-corpus.c index a908f69644..783df1a076 100644 --- a/fuzz/test-corpus.c +++ b/fuzz/test-corpus.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,13 +17,10 @@ #include #include #include -#include #include #include -#include #include "fuzzer.h" #include "internal/o_dir.h" -#include "mfail.h" #if defined(_WIN32) && defined(_MAX_PATH) && !defined(PATH_MAX) #define PATH_MAX _MAX_PATH @@ -37,45 +34,7 @@ #define S_ISREG(m) ((m) & S_IFREG) #endif -static double secs_since(clock_t start) -{ - return (double)(clock() - start) / CLOCKS_PER_SEC; -} - -static void run_baseline(const unsigned char *buf, size_t s) -{ - FuzzerTestOneInput(buf, s); -} - -static void run_mfail(const unsigned char *buf, size_t s, - const char *path, int file_idx) -{ - mfail_init(file_idx, MFAIL_FLAG_COUNT); - while (mfail_has_next()) { - if (mfail_get_phase() == MFAIL_PHASE_COUNTING) - fprintf(stderr, - "# MFAIL_BEGIN file_idx=%d phase=count\n", file_idx); - else - fprintf(stderr, - "# MFAIL_BEGIN file_idx=%d point=%d/%d\n", - file_idx, mfail_get_point(), mfail_get_total()); - - mfail_start(); - FuzzerTestOneInput(buf, s); - mfail_end(); - - if (mfail_get_phase() == MFAIL_PHASE_COUNTING) { - fprintf(stderr, "# %s: %d allocations\n", path, mfail_get_count()); - } else { - fprintf(stderr, "# %s: point %d/%d %s\n", path, - mfail_get_point(), mfail_get_total(), - mfail_was_triggered() ? "hit" : "unreached"); - } - ERR_clear_error(); - } -} - -static void testfile(const char *pathname, int file_idx) +static void testfile(const char *pathname) { struct stat st; FILE *f; @@ -84,52 +43,26 @@ static void testfile(const char *pathname, int file_idx) if (stat(pathname, &st) < 0 || !S_ISREG(st.st_mode)) return; - - fprintf(stderr, "# CORPUS_FILE file_idx=%d size=%lld path=%s\n", - file_idx, (long long)st.st_size, pathname); + printf("# %s\n", pathname); + fflush(stdout); f = fopen(pathname, "rb"); if (f == NULL) return; buf = malloc(st.st_size); - if (buf == NULL) { - fclose(f); - return; + if (buf != NULL) { + s = fread(buf, 1, st.st_size, f); + OPENSSL_assert(s == (size_t)st.st_size); + FuzzerTestOneInput(buf, s); + free(buf); } - s = fread(buf, 1, st.st_size, f); - OPENSSL_assert(s == (size_t)st.st_size); - - if (mfail_is_installed()) - run_mfail(buf, s, pathname, file_idx); - else - run_baseline(buf, s); - - free(buf); fclose(f); } int main(int argc, char **argv) { - int n, mfi_rc; - int file_idx = 0; - clock_t corpus_start; + int n; - mfi_rc = mfail_install(1); - if (mfi_rc < 0) { - fprintf(stderr, "mfail: failed to install allocator hooks\n"); - return 1; - } else if (mfi_rc > 0) { - /* Disable buffering for better crash analysis */ - setvbuf(stdout, NULL, _IOLBF, 0); - setvbuf(stderr, NULL, _IOLBF, 0); - } - - if (FuzzerInitialize(&argc, &argv) < 0) { - if (mfail_is_installed()) - return 0; /* init failure under mfail is expected */ - return 1; - } - - corpus_start = clock(); + FuzzerInitialize(&argc, &argv); for (n = 1; n < argc; ++n) { size_t dirname_len = strlen(argv[n]); @@ -155,20 +88,18 @@ int main(int argc, char **argv) pathname[dirname_len] = '\0'; } strcpy(pathname + dirname_len, filename); - testfile(pathname, file_idx++); + testfile(pathname); } OPENSSL_DIR_end(&ctx); /* If it wasn't a directory, treat it as a file instead */ if (!wasdir) - testfile(argv[n], file_idx++); + testfile(argv[n]); free(pathname); } - if (!mfail_is_installed() || mfail_is_count_only()) - fprintf(stderr, "# corpus_time: %.6f\n", secs_since(corpus_start)); - FuzzerCleanup(); + return 0; } diff --git a/fuzz/v3name.c b/fuzz/v3name.c index 87fd8c1471..9a525e6f48 100644 --- a/fuzz/v3name.c +++ b/fuzz/v3name.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include "internal/nelem.h" @@ -24,11 +23,8 @@ int FuzzerTestOneInput(const uint8_t *data, size_t size) { GENERAL_NAME *namesa; GENERAL_NAME *namesb; + const unsigned char *derp = data; - - if (size > LONG_MAX) - return 0; - /* * We create two versions of each GENERAL_NAME so that we ensure when * we compare them they are always different pointers. @@ -36,11 +32,11 @@ int FuzzerTestOneInput(const uint8_t *data, size_t size) namesa = d2i_GENERAL_NAME(NULL, &derp, (long)size); derp = data; namesb = d2i_GENERAL_NAME(NULL, &derp, (long)size); - if (namesa != NULL && namesb != NULL) - GENERAL_NAME_cmp(namesa, namesb); - GENERAL_NAME_free(namesa); - GENERAL_NAME_free(namesb); - ERR_clear_error(); + GENERAL_NAME_cmp(namesa, namesb); + if (namesa != NULL) + GENERAL_NAME_free(namesa); + if (namesb != NULL) + GENERAL_NAME_free(namesb); return 0; } diff --git a/fuzz/x509.c b/fuzz/x509.c index a10e8c0067..68249b48db 100644 --- a/fuzz/x509.c +++ b/fuzz/x509.c @@ -99,8 +99,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) if (ctx == NULL) goto err; - if (!X509_STORE_CTX_init(ctx, store, x509_1, NULL)) - goto err; + X509_STORE_CTX_init(ctx, store, x509_1, NULL); if (crl != NULL) { crls = sk_X509_CRL_new_null(); diff --git a/include/crypto/aes_platform.h b/include/crypto/aes_platform.h index 36ba2665ee..13a31c5708 100644 --- a/include/crypto/aes_platform.h +++ b/include/crypto/aes_platform.h @@ -13,12 +13,6 @@ #include -typedef int (*aes_set_encrypt_key_fn)(const unsigned char *key, - int bits, AES_KEY *ks); - -typedef void (*aes_block128_f)(const unsigned char in[16], - unsigned char out[16], const AES_KEY *key); - #ifdef VPAES_ASM int vpaes_set_encrypt_key(const unsigned char *userKey, int bits, AES_KEY *key); diff --git a/include/crypto/bn.h b/include/crypto/bn.h index d2caade6a4..8e63b3a844 100644 --- a/include/crypto/bn.h +++ b/include/crypto/bn.h @@ -13,12 +13,58 @@ #include #include +#include "types.h" BIGNUM *bn_wexpand(BIGNUM *a, int words); BIGNUM *bn_expand2(BIGNUM *a, int words); void bn_correct_top(BIGNUM *a); +/* + * bn_acquire_ossl_fn() and bn_release() work in tandem, and are + * most useful at call sites that temporarily operate on a BIGNUM's + * fixed-width OSSL_FN representation. + */ + +/** + * Acquire the OSSL_FN from a BIGNUM. The BIGNUM should no longer be + * used until bn_release() is called. + * + * @param[in] b The BIGNUM instance to get an OSSL_FN from + * @param[in] limbs The minimum number of limbs 'b' should be expanded to. + * Note that this doesn't set 'top', that's done by + * bn_release(). + * @returns the OSSL_FN instance of the BIGNUM, if there is one + * @pre b must not be NULL + */ +OSSL_FN *bn_acquire_ossl_fn(BIGNUM *b, int limbs); + +/** + * Release the BIGNUM from which the OSSL_FN was acquired. This will + * adjust the BIGNUM to what was done with its OSSL_FN, and the BIGNUM + * can again be used with BN_ functions. + * + * @param[in] b The BIGNUM instance to release + * @param[in] limbs The maximum number of significant limbs. This sets + * 'top'. + * @pre b and b->data must not be NULL + */ +void bn_release(BIGNUM *b, int limbs); + +/** + * Get the OSSL_FN from a BIGNUM for read-only access. Unlike + * bn_acquire_ossl_fn(), this does not acquire or resize the BIGNUM: + * the BIGNUM remains fully usable with BN_ functions, no bn_release() + * call is needed, and the returned OSSL_FN keeps the BIGNUM's current + * allocated width without any expansion. Use this for read-only + * operands; use bn_acquire_ossl_fn() for writable results. + * + * @param[in] bn The BIGNUM instance to get an OSSL_FN from + * @returns the OSSL_FN instance of the BIGNUM, or NULL if it has none + * @pre bn must not be NULL + */ +OSSL_FN *bn_get_ossl_fn(const BIGNUM *bn); + /* * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. * This is an array r[] of values that are either zero or odd with an diff --git a/include/crypto/cryptlib.h b/include/crypto/cryptlib.h index 242de6fc2f..823cbbcf2c 100644 --- a/include/crypto/cryptlib.h +++ b/include/crypto/cryptlib.h @@ -36,4 +36,6 @@ void ossl_malloc_setup_failures(void); int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj, CRYPTO_EX_DATA *ad, int idx); +size_t ossl_num_bits(size_t value); + #endif /* OSSL_CRYPTO_CRYPTLIB_H */ diff --git a/include/crypto/decoder.h b/include/crypto/decoder.h index dafb143593..fcb914faeb 100644 --- a/include/crypto/decoder.h +++ b/include/crypto/decoder.h @@ -20,7 +20,7 @@ * (provider-object(7)). */ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, int no_store); + OSSL_PROVIDER *prov); OSSL_DECODER_INSTANCE * ossl_decoder_instance_new_forprov(OSSL_DECODER *decoder, void *provctx, diff --git a/include/crypto/evp.h b/include/crypto/evp.h index eca29a7438..aec23fb013 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -141,7 +141,6 @@ void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx); struct evp_mac_st { OSSL_PROVIDER *prov; int name_id; - int no_store; char *type_name; const char *description; @@ -165,7 +164,6 @@ struct evp_mac_st { struct evp_kdf_st { OSSL_PROVIDER *prov; int name_id; - int no_store; char *type_name; const char *description; CRYPTO_REF_COUNT refcnt; diff --git a/include/crypto/fn.h b/include/crypto/fn.h new file mode 100644 index 0000000000..76f71b4f1e --- /dev/null +++ b/include/crypto/fn.h @@ -0,0 +1,992 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OPENSSL_FN_H +#define OPENSSL_FN_H +#pragma once + +#include +#include +#include +#include +#include "crypto/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @type OSSL_FN_ULONG is the type for the OSSL_FN limb. It's made to be + * compatible with BN_ULONG (quite literally). + * + * @def OSSL_FN_BYTES is defined with the size of OSSL_FN_ULONG, measured in + * bytes. This is mainly useful where 'sizeof(OSSL_FN_ULONG)' isn't suitable, + * such as the C pre-processor. + */ + +#ifdef BN_BYTES +typedef BN_ULONG OSSL_FN_ULONG; +#define OSSL_FN_BYTES BN_BYTES +#endif + +#ifndef OSSL_FN_BYTES +#error "OpenSSL doesn't support large numbers on this platform" +#endif + +/* + * For practical reasons, we allow allocating OSSL_FNs in terms of limbs (what + * the BIGNUM library calls "words"), bytes and bits. The number of bytes and + * bits are rounded up to the number of limbs that can fit them. + */ + +/** + * Allocate an OSSL_FN in memory. + * + * @param[in] size The number of limbs for the number itself. + * There's an additional few bytes allocated for bookkeeping. + * @returns an OSSL_FN instance. + * @retval NULL on error. + */ +OSSL_FN *OSSL_FN_new_limbs(size_t size); + +/** + * Allocate an OSSL_FN in secure memory. + * + * @param[in] size The number of limbs for the number itself. + * There's an additional few bytes allocated for bookkeeping. + * @returns an OSSL_FN instance. + * @retval NULL on error. + */ +OSSL_FN *OSSL_FN_secure_new_limbs(size_t size); + +/** + * Allocate an OSSL_FN in memory. + * + * @param[in] size The number of bytes for the number itself. + * There's an additional few bytes allocated for bookkeeping. + * @returns an OSSL_FN instance. + * @retval NULL on error. + */ +OSSL_FN *OSSL_FN_new_bytes(size_t size); + +/** + * Allocate an OSSL_FN in secure memory. + * + * @param[in] size The number of bytes for the number itself. + * There's an additional few bytes allocated for bookkeeping. + * @returns an OSSL_FN instance. + * @retval NULL on error. + */ +OSSL_FN *OSSL_FN_secure_new_bytes(size_t size); + +/** + * Allocate an OSSL_FN in memory. + * + * @param[in] size The number of bits for the number itself. + * There's an additional few bytes allocated for bookkeeping. + * @returns an OSSL_FN instance. + * @retval NULL on error. + */ +OSSL_FN *OSSL_FN_new_bits(size_t size); + +/** + * Allocate an OSSL_FN in secure memory. + * + * @param[in] size The number of bits for the number itself. + * There's an additional few bytes allocated for bookkeeping. + * @returns an OSSL_FN instance. + * @retval NULL on error. + */ +OSSL_FN *OSSL_FN_secure_new_bits(size_t size); + +/** + * Free an OSSL_FN instance if it was dynamically allocated. + * Free it securely if it was allocated securely. + * + * @param[in] f The OSSL_FN instance to be freed. + */ +void OSSL_FN_free(OSSL_FN *f); + +/** + * Cleanse and free an OSSL_FN instance if it was dynamically allocated. + * Cleanse and free it securely if it was allocated securely. + * Merely cleanse it if it was not dynamically allocated. + * + * @param[in] f The OSSL_FN instance to be freed. + */ +void OSSL_FN_clear_free(OSSL_FN *f); + +/** + * Cleanse the data of an OSSL_FN instance, effectively making it zero. + * + * @param[in] f The OSSL_FN instance to be cleared. + */ +void OSSL_FN_clear(OSSL_FN *f); + +/** + * Set an OSSL_FN to a single-limb word value. + * + * @param[out] a The destination OSSL_FN + * @param[in] w The OSSL_FN_ULONG word + * @returns 1 on success, 0 on error + * + * @note Sets a->d[0] to @p w and zeroes the remaining limbs, so the full + * dsize array reflects the value @p w. If a->dsize is 0 there is no + * limb to write and the call fails with + * OSSL_FN_R_RESULT_ARG_TOO_SMALL (OSSL_FN is fixed-size, so the + * destination cannot be grown). The operation is constant-time with + * respect to @p w's value; the only branch is on the operand's public + * width (dsize). + */ +int OSSL_FN_set_word(OSSL_FN *a, OSSL_FN_ULONG w); + +/** + * Set an OSSL_FN to one. + * + * @param[out] a The destination OSSL_FN + * @returns 1 on success, 0 on error + * + * @note Equivalent to OSSL_FN_set_word(a, 1), provided as a named function + * for readability at call sites. Leak profile as for + * OSSL_FN_set_word(). + */ +int OSSL_FN_one(OSSL_FN *a); + +/** + * Set an OSSL_FN to zero. + * + * @param[out] a The destination OSSL_FN + * @returns 1 on success, 0 on error + * + * @note This is a plain value assignment, not a secure wipe; use + * OSSL_FN_clear() when the limbs may hold secret data and must be wiped + * irreversibly. Equivalent to OSSL_FN_set_word(a, 0). Leak profile as + * for OSSL_FN_set_word(). + */ +int OSSL_FN_zero(OSSL_FN *a); + +/** + * Copy the contents of one OSSL_FN instance to another. + * + * @param[out] a The destination OSSL_FN + * @param[in] b The source OSSL_FN + * @returns The destination on success, NULL on error. + * + * @note The destination must be at least as large as the source. + * Any limbs beyond the source size are zeroed. + */ +OSSL_FN *OSSL_FN_copy(OSSL_FN *a, const OSSL_FN *b); + +/** + * Copy the contents of one OSSL_FN instance to another, + * normally the shorter one, truncating the high bytes. + * + * @param[out] a The destination OSSL_FN + * @param[in] b The source OSSL_FN + * @returns the destination. + */ +OSSL_FN *OSSL_FN_copy_truncate(OSSL_FN *a, const OSSL_FN *b); + +/** + * Calculate the arena payload size for an OSSL_FN_CTX. + * + * @param[in] max_n_frames Maximum number of simultaneously active frames. + * This indicates the expected depth of call stack + * that the resulting OSSL_FN_CTX will be used in. + * Must be at least 1. + * @param[in] max_n_numbers Maximum number of simultaneously active OSSL_FN. + * Must be 0 if and only if @p max_n_limbs is 0. + * @param[in] max_n_limbs Maximum number of simultaneously active OSSL_FN + * limbs. Must be 0 if and only if + * @p max_n_numbers is 0. + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid argument. + * + * The returned size is the value to pass to OSSL_FN_CTX_new_size() or + * OSSL_FN_CTX_secure_new_size(). It does not include sizeof(OSSL_FN_CTX). + */ +size_t OSSL_FN_CTX_size(size_t max_n_frames, size_t max_n_numbers, + size_t max_n_limbs); + +/** + * Allocate a new OSSL_FN_CTX, given a set of input numbers. + * + * @param[in] libctx OpenSSL library context (currently unused) + * @param[in] max_n_frames Maximum number of simultaneously active frames. + * This indicates the expected depth of call stack + * that the resulting OSSL_FN_CTX will be used in. + * @param[in] max_n_numbers Maximum number of simultaneously active OSSL_FN. + * @param[in] max_n_limbs Maximum number of simultaneously active OSSL_FN + * limbs. + * @returns An allocated OSSL_FN_CTX, or NULL on error. + */ +OSSL_FN_CTX *OSSL_FN_CTX_new(OSSL_LIB_CTX *libctx, size_t max_n_frames, + size_t max_n_numbers, size_t max_n_limbs); + +/** + * Allocate a new OSSL_FN_CTX with a given arena payload size. + * + * @param[in] libctx OpenSSL library context (currently unused) + * @param[in] size Arena payload size in bytes, typically from + * OSSL_FN_CTX_size(). A size of 0 is the error + * return of OSSL_FN_CTX_size() and is treated as + * an error here too. + * @returns An allocated OSSL_FN_CTX, or NULL on error. + */ +OSSL_FN_CTX *OSSL_FN_CTX_new_size(OSSL_LIB_CTX *libctx, size_t size); + +/** + * Allocate a new OSSL_FN_CTX in secure memory, given a set of input numbers. + * Other than allocating in secure memory, this function does exactly the same + * thing as OSSL_FN_CTX_new(). + */ +OSSL_FN_CTX *OSSL_FN_CTX_secure_new(OSSL_LIB_CTX *libctx, size_t max_n_frames, + size_t max_n_numbers, size_t max_n_limbs); + +/** + * Allocate a new OSSL_FN_CTX in secure memory with a given arena payload size. + * + * @param[in] libctx OpenSSL library context (currently unused) + * @param[in] size Arena payload size in bytes, typically from + * OSSL_FN_CTX_size(). A size of 0 is treated as + * an error, as in OSSL_FN_CTX_new_size(). + * @returns An allocated OSSL_FN_CTX, or NULL on error. + */ +OSSL_FN_CTX *OSSL_FN_CTX_secure_new_size(OSSL_LIB_CTX *libctx, size_t size); + +/** + * Report the peak number of frames, numbers, and limbs that were + * simultaneously active during the lifetime of the OSSL_FN_CTX. + * This can be used to determine suitable arena parameters for a + * given workload. + * + * @param[in] ctx The OSSL_FN_CTX to query. This may be NULL. + * @param[out] peak_n_frames Peak number of simultaneously active frames + * @param[out] peak_n_numbers Peak number of simultaneously active OSSL_FNs + * @param[out] peak_n_limbs Peak total limbs across all active OSSL_FNs + * + * Any of the out parameters may be NULL. If ctx is NULL, all out + * parameters that are non-NULL are set to 0. + */ +void OSSL_FN_CTX_peak_usage(const OSSL_FN_CTX *ctx, size_t *peak_n_frames, + size_t *peak_n_numbers, size_t *peak_n_limbs); + +/** + * Free an OSSL_FN_CTX. + * + * @param[in] ctx The OSSL_FN_CTX to be freed. This may be NULL. + */ +void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx); + +/** + * Start a new OSSL_FN_CTX frame. This *must* be called by any function + * that wants to get a temporary OSSL_FN from the OSSL_FN_CTX. The function + * call this must also clean up with a OSSL_FN_CTX_end() call. + * + * @param[in] ctx The OSSL_FN_CTX to start the frame in. + * @returns Ownership token of the started frame, NULL on error. + * This token must be passed to OSSL_FN_CTX_end(). + */ +const void *OSSL_FN_CTX_start(OSSL_FN_CTX *ctx); + +/** + * End the last OSSL_FN_CTX frame, resetting back to the previous + * frame. If a function called OSSL_FN_CTX_start(), it *must* call + * this function before returning. + * + * @param[in] ctx The OSSL_FN_CTX to start the frame in. + * @param[in] token Ownership token returned by OSSL_FN_CTX_start(). + * @returns 1 on success, 0 on error. + * + * @note The token parameter is validated but not used for choosing a + * frame; only the most recent frame can be ended. Passing an incorrect + * token indicates a programming error and the function will fail. + * If NULL is passed, nothing will be done but the function will return 1. + */ +int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx, const void *token); + +/** + * Get a suitably sized OSSL_FN from an OSSL_FN_CTX. + * + * @param[in] ctx The OSSL_FN_CTX + * @param[in] limbs The desired size of the resulting OSSL_FN, + * in number of limbs. + * @returns an OSSL_FN pointer on success, NULL on error. + */ +OSSL_FN *OSSL_FN_CTX_get_limbs(OSSL_FN_CTX *ctx, size_t limbs); + +/** + * Get a suitably sized OSSL_FN from an OSSL_FN_CTX. + * + * @param[in] ctx The OSSL_FN_CTX + * @param[in] limbs The desired size of the resulting OSSL_FN, + * in number of bytes. + * @returns an OSSL_FN pointer on success, NULL on error. + */ +OSSL_FN *OSSL_FN_CTX_get_bytes(OSSL_FN_CTX *ctx, size_t bytes); + +/** + * Get a suitably sized OSSL_FN from an OSSL_FN_CTX. + * + * @param[in] ctx The OSSL_FN_CTX + * @param[in] limbs The desired size of the resulting OSSL_FN, + * in number of bits. + * @returns an OSSL_FN pointer on success, NULL on error. + */ +OSSL_FN *OSSL_FN_CTX_get_bits(OSSL_FN_CTX *ctx, size_t bits); + +/* + * Arithmetic functions treat the OSSL_FN 'd' array as a large 2's complement + * unsigned integer, least significant limb first. All carrys or borrows are + * extended in the result and otherwise ignored. This makes OSSL_FN functions + * act just like operations on C unsigned integer types, but at a larger scale. + */ + +/** + * Return the number of significant bits in an OSSL_FN number. + * + * @param[in] a The operand + * @returns The number of significant bits, or zero if a is zero + */ +size_t OSSL_FN_num_bits(const OSSL_FN *a); + +/** + * Compare two OSSL_FN numbers as unsigned integers. + * + * @param[in] a The first operand + * @param[in] b The second operand + * @returns 1 if a > b, -1 if a < b, 0 if a == b + */ +int OSSL_FN_cmp(const OSSL_FN *a, const OSSL_FN *b); + +/** + * Test whether bit @p n is set in @p a. + * + * @param[in] a The operand + * @param[in] n The bit index (0 = least significant) + * @returns 1 if bit @p n of @p a is set, 0 otherwise. + * + * @note An out-of-range index (n < 0 or n >= the operand's width in bits) + * reads as 0. The only control flow branches on the operand's public + * width (its dsize), not on limb values; the returned value is the bit + * itself, which is the information the caller asked for. + */ +int OSSL_FN_is_bit_set(const OSSL_FN *a, int n); + +/** + * Test whether the unsigned value of @p a equals the single-limb word @p w. + * + * @param[in] a The operand + * @param[in] w The OSSL_FN_ULONG word to compare against + * @returns 1 if the unsigned value of @p a equals @p w, 0 otherwise + * + * @note Control flow branches only on the operand's public width (its dsize), + * not on limb values; the returned value is the equality test the caller + * asked for. + */ +int OSSL_FN_is_word(const OSSL_FN *a, OSSL_FN_ULONG w); + +/** + * Test whether @p a is zero. + * + * @param[in] a The operand + * @returns 1 if @p a is zero, 0 otherwise + * + * @note Equivalent to OSSL_FN_is_word(a, 0), provided as a named predicate for + * readability at call sites. Leak profile as for OSSL_FN_is_word(): + * branches only on the operand's public width (its dsize). + */ +int OSSL_FN_is_zero(const OSSL_FN *a); + +/** + * Test whether @p a is one. + * + * @param[in] a The operand + * @returns 1 if @p a is one, 0 otherwise + * + * @note Equivalent to OSSL_FN_is_word(a, 1), provided as a named predicate for + * readability at call sites. Leak profile as for OSSL_FN_is_word(): + * branches only on the operand's public width (its dsize). + */ +int OSSL_FN_is_one(const OSSL_FN *a); + +/** + * Test whether @p a is odd. + * + * @param[in] a The operand + * @returns the least significant bit of @p a (1 if odd, 0 if even) + * + * @note The only control flow branches on the operand's public width (its + * dsize), not on limb values; the returned value is the bit itself, + * which is the information the caller asked for. + */ +int OSSL_FN_is_odd(const OSSL_FN *a); + +/*- + * Top/bottom selectors for OSSL_FN_rand() / OSSL_FN_priv_rand(). These are + * caller-chosen public parameters (not secrets); OSSL_FN_rand() branches on + * them to shape the top and bottom bits of the result. Each TOP_* value is + * the number of high bits to force to 1 (0 = unconstrained, 1, 2), matching + * the BOTTOM_* numbering (0 = unconstrained, 1 = force the low bit). + */ +#define OSSL_FN_RAND_TOP_ANY 0 +#define OSSL_FN_RAND_TOP_ONE 1 +#define OSSL_FN_RAND_TOP_TWO 2 +#define OSSL_FN_RAND_BOTTOM_ANY 0 +#define OSSL_FN_RAND_BOTTOM_ODD 1 + +/** + * Fill @p rnd with @p bits random bits. + * + * @param[out] rnd The OSSL_FN for the result + * @param[in] bits The number of random bits to generate + * @param[in] top Top-bit selector (OSSL_FN_RAND_TOP_*) + * @param[in] bottom Bottom-bit selector (OSSL_FN_RAND_BOTTOM_*) + * @param[in] strength The private strength of the generated bytes + * @param[in] libctx The OpenSSL library context (for the DRBG) + * @returns 1 on success, 0 on error + * + * Draws from the public DRBG pool via RAND_bytes_ex(). The library context + * is taken directly as @p libctx. The random bytes are drawn straight into + * rnd->d (no intermediate buffer) and the top/bottom/mask constraints are + * applied as limb value operations; a @p rnd too small for @p bits is + * reported as OSSL_FN_R_RESULT_ARG_TOO_SMALL rather than grown. Leak + * profile as for OSSL_FN_priv_rand(). + */ +int OSSL_FN_rand(OSSL_FN *rnd, size_t bits, int top, int bottom, + size_t strength, OSSL_LIB_CTX *libctx); + +/** + * Fill @p rnd with @p bits random bits from the private DRBG pool. + * + * @param[out] rnd The OSSL_FN for the result + * @param[in] bits The number of random bits to generate + * @param[in] top Top-bit selector (OSSL_FN_RAND_TOP_*) + * @param[in] bottom Bottom-bit selector (OSSL_FN_RAND_BOTTOM_*) + * @param[in] strength The private strength of the generated bytes + * @param[in] libctx The OpenSSL library context (for the DRBG) + * @returns 1 on success, 0 on error + * + * Draws from the private (non-forward-linkable) DRBG pool via + * RAND_priv_bytes_ex(). This is the private counterpart of OSSL_FN_rand(); + * the public/private pool selection is exposed as separate functions rather + * than a flag argument. Control flow branches only on @p bits, @p top, + * @p bottom (all caller-chosen, public) and on the byte-draw return value, + * never on the random bytes themselves; the returned value is the random + * number the caller asked for. + * + * @note See ossl_fn_rand() in crypto/fn/fn_rand.c for the byte-to-limb + * shaping mechanics. + */ +int OSSL_FN_priv_rand(OSSL_FN *rnd, size_t bits, int top, int bottom, + size_t strength, OSSL_LIB_CTX *libctx); + +/** + * Generate 0 <= r < range. + * + * @param[out] r The OSSL_FN for the result + * @param[in] range The exclusive upper bound (must be non-zero) + * @param[in] strength The private strength of the generated bytes + * @param[in] libctx The OpenSSL library context (for the DRBG) + * @returns 1 on success, 0 on error + * + * Draws from the public DRBG pool. OSSL_FN is unsigned, so no sign + * rejection is performed. The loop iteration count leaks the magnitude of + * @p range via OSSL_FN_num_bits() and the rejection probability. + * + * The destination @p r must be sized to hold at least + * OSSL_FN_num_bits(@p range) bits. Sizing @p r to hold one extra bit + * (OSSL_FN_num_bits(@p range) + 1) additionally enables the optimized + * "range = 100..._2" path, which draws n + 1 bits; an exactly-sized @p r + * (room for exactly OSSL_FN_num_bits(@p range) bits) uses standard n-bit + * rejection sampling instead. An @p r too small for + * OSSL_FN_num_bits(@p range) bits fails with OSSL_FN_R_RESULT_ARG_TOO_SMALL. + */ +int OSSL_FN_rand_range(OSSL_FN *r, const OSSL_FN *range, size_t strength, + OSSL_LIB_CTX *libctx); + +/** + * Generate 0 <= r < range from the private DRBG pool. + * + * @param[out] r The OSSL_FN for the result + * @param[in] range The exclusive upper bound (must be non-zero) + * @param[in] strength The private strength of the generated bytes + * @param[in] libctx The OpenSSL library context (for the DRBG) + * @returns 1 on success, 0 on error + * + * Draws from the private DRBG pool. Leak profile and destination sizing + * as for OSSL_FN_rand_range(). + */ +int OSSL_FN_priv_rand_range(OSSL_FN *r, const OSSL_FN *range, + size_t strength, OSSL_LIB_CTX *libctx); + +/** + * Shift an OSSL_FN number left by n bits. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] n The number of bits to shift + * @returns 1 on success, 0 on error + */ +int OSSL_FN_lshift(OSSL_FN *r, const OSSL_FN *a, int n); + +/** + * Shift an OSSL_FN number left by one bit. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @returns 1 on success, 0 on error + */ +int OSSL_FN_lshift1(OSSL_FN *r, const OSSL_FN *a); + +/** + * Shift an OSSL_FN number right by n bits. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] n The number of bits to shift + * @returns 1 on success, 0 on error + */ +int OSSL_FN_rshift(OSSL_FN *r, const OSSL_FN *a, int n); + +/** + * Shift an OSSL_FN number right by one bit. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @returns 1 on success, 0 on error + */ +int OSSL_FN_rshift1(OSSL_FN *r, const OSSL_FN *a); + +/** + * Add two OSSL_FN numbers. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @returns 1 on success, 0 on error + */ +int OSSL_FN_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b); + +/** + * Add an OSSL_FN_ULONG word to an OSSL_FN numbers. + * + * @param[in,out] a The OSSL_FN to add the word to + * @param[in] w The OSSL_FN_ULONG word + * @returns 1 on success, 0 on error + */ +int OSSL_FN_add_word(OSSL_FN *a, OSSL_FN_ULONG w); + +/** + * Subtract two OSSL_FN numbers. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @returns 1 on success, 0 on error + */ +int OSSL_FN_sub(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b); + +/** + * Subtract an OSSL_FN_ULONG word from an OSSL_FN numbers. + * + * @param[in,out] a The OSSL_FN to subtract the word from + * @param[in] w The OSSL_FN_ULONG word + * @returns 1 on success, 0 on error + */ +int OSSL_FN_sub_word(OSSL_FN *a, OSSL_FN_ULONG w); + +/** + * Multiply two OSSL_FN numbers. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for one temporary OSSL_FN with res->dsize limbs, plus one frame + * (currently 32 bytes). + */ +int OSSL_FN_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mul() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mul(). + */ +size_t OSSL_FN_mul_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b); + +/** + * Divide two OSSL_FN numbers. Truncates the result to fit in q and r. + * + * @param[out] q The OSSL_FN for the quotient + * @param[out] r The OSSL_FN for the remainder + * @param[in] n The first operand (numerator) + * @param[in] d The second operand (denominator) + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for 1 frame, 4 numbers, and 4 * max(n->dsize, d->dsize) + 2 limbs. + * Note that this provides an upper bound. Actual use of the arena may be + * smaller - see OSSL_FN_div_ctx_size() for an exact, conditional value. + */ +int OSSL_FN_div(OSSL_FN *q, OSSL_FN *r, const OSSL_FN *n, const OSSL_FN *d, + OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_div() needs. + * + * @param[in] q The OSSL_FN for the quotient, or NULL when + * only the remainder is of interest. + * @param[in] r The OSSL_FN for the remainder + * @param[in] n The first operand (numerator) + * @param[in] d The second operand (denominator) + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_div(). + * When q is NULL, the size is computed for the modulo case, i.e. as if + * only the remainder is produced. + */ +size_t OSSL_FN_div_ctx_size(const OSSL_FN *q, const OSSL_FN *r, + const OSSL_FN *n, const OSSL_FN *d); + +/** + * Add two OSSL_FN numbers modulo m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for one temporary OSSL_FN with max(a->dsize, b->dsize) + 1 + * limbs, plus the requirements of OSSL_FN_mod(), plus one frame + * (currently 32 bytes). + */ +int OSSL_FN_mod_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m, OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mod_add() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mod_add(). + */ +size_t OSSL_FN_mod_add_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b, const OSSL_FN *m); + +/** + * Add two OSSL_FN numbers modulo m. This is a quick variant that may be + * used if both a and b are less than m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @returns 1 on success, 0 on error + */ +int OSSL_FN_mod_add_quick(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m); + +/** + * Subtract two OSSL_FN numbers modulo m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for two temporary OSSL_FNs with m->dsize limbs each, plus an + * additional temporary OSSL_FN with m->dsize limbs if r == m, plus the + * requirements of OSSL_FN_mod(), plus one frame (currently 32 bytes). + */ +int OSSL_FN_mod_sub(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m, OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mod_sub() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mod_sub(). + */ +size_t OSSL_FN_mod_sub_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b, const OSSL_FN *m); + +/** + * Subtract two OSSL_FN numbers modulo m. This is a quick variant that may + * be used if a is less than m and b is of the same bit width as m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @returns 1 on success, 0 on error + */ +int OSSL_FN_mod_sub_quick(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m); + +/** + * Multiply two OSSL_FN numbers modulo m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for one temporary OSSL_FN with a->dsize + b->dsize limbs + * (or 2 * a->dsize limbs if a == b), plus the largest of the + * requirements of OSSL_FN_mul(), OSSL_FN_sqr(), and OSSL_FN_mod(), + * plus one frame (currently 32 bytes). + */ +int OSSL_FN_mod_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, + const OSSL_FN *m, OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mod_mul() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The first operand + * @param[in] b The second operand + * @param[in] m The modulus + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mod_mul(). + */ +size_t OSSL_FN_mod_mul_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *b, const OSSL_FN *m); + +/** + * Square an OSSL_FN number modulo m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] m The modulus + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for one temporary OSSL_FN with 2 * a->dsize limbs, plus the + * larger of the requirements of OSSL_FN_sqr() and OSSL_FN_mod(), + * plus one frame (currently 32 bytes). + */ +int OSSL_FN_mod_sqr(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *m, + OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mod_sqr() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] m The modulus + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mod_sqr(). + */ +size_t OSSL_FN_mod_sqr_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *m); + +/** + * Left shift an OSSL_FN number by 1 bit, modulo m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] m The modulus + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for one temporary OSSL_FN with m->dsize + 1 limbs, plus the + * requirements of OSSL_FN_mod(), plus one frame (currently 32 bytes). + */ +int OSSL_FN_mod_lshift1(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *m, + OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mod_lshift1() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] m The modulus + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by + * OSSL_FN_mod_lshift1(). + */ +size_t OSSL_FN_mod_lshift1_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + const OSSL_FN *m); + +/** + * Left shift an OSSL_FN number by 1 bit, modulo m. This is a quick + * variant that may be used if a is less than m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] m The modulus + * @returns 1 on success, 0 on error + */ +int OSSL_FN_mod_lshift1_quick(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *m); + +/** + * Left shift an OSSL_FN number by n bits, modulo m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] n The number of bits to shift + * @param[in] m The modulus + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for one temporary OSSL_FN with m->dsize limbs, plus the + * requirements of OSSL_FN_mod(), plus one frame (currently 32 bytes). + */ +int OSSL_FN_mod_lshift(OSSL_FN *r, const OSSL_FN *a, int n, const OSSL_FN *m, + OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_mod_lshift() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] n The number of bits to shift + * @param[in] m The modulus + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mod_lshift(). + */ +size_t OSSL_FN_mod_lshift_ctx_size(const OSSL_FN *r, const OSSL_FN *a, + int n, const OSSL_FN *m); + +/** + * Left shift an OSSL_FN number by n bits, modulo m. This is a quick + * variant that may be used if a is less than m. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] n The number of bits to shift + * @param[in] m The modulus + * @returns 1 on success, 0 on error + */ +int OSSL_FN_mod_lshift_quick(OSSL_FN *r, const OSSL_FN *a, int n, + const OSSL_FN *m); + +/** + * Calculate modulo of two OSSL_FN numbers. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the remainder + * @param[in] n The first operand (numerator) + * @param[in] d The second operand (denominator) + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function has the same requirements on ctx as OSSL_FN_div(). + * It is equivalent to OSSL_FN_div(NULL, r, n, d, ctx). + */ +static inline int OSSL_FN_mod(OSSL_FN *r, const OSSL_FN *n, const OSSL_FN *d, + OSSL_FN_CTX *ctx) +{ + return OSSL_FN_div(NULL, r, n, d, ctx); +} + +/** + * Calculate the arena payload size that OSSL_FN_mod() needs. + * + * @param[in] r The OSSL_FN for the remainder + * @param[in] n The numerator + * @param[in] d The denominator + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_mod(). + * This is a thin wrapper around OSSL_FN_div_ctx_size() with a NULL + * quotient, since OSSL_FN_mod() is itself a wrapper around OSSL_FN_div(). + */ +static inline size_t OSSL_FN_mod_ctx_size(const OSSL_FN *r, + const OSSL_FN *n, const OSSL_FN *d) +{ + return OSSL_FN_div_ctx_size(NULL, r, n, d); +} + +/** + * Calculate the square of one OSSL_FN number. Truncates the result to fit in r. + * + * @param[out] r The OSSL_FN for the result + * @param[in] a The operand + * @param[in] ctx A context to get temporary OSSL_FN + * instances from. + * @returns 1 on success, 0 on error + * + * @note This function currently requires that the OSSL_FN_CTX has free + * space for two temporary OSSL_FNs, a->dsize * 2 limbs each, plus one + * frame (currently 32 bytes). + */ +int OSSL_FN_sqr(OSSL_FN *r, const OSSL_FN *a, OSSL_FN_CTX *ctx); + +/** + * Calculate the arena payload size that OSSL_FN_sqr() needs. + * + * @param[in] r The OSSL_FN for the result + * @param[in] a The operand + * @returns The arena payload size, in bytes. + * @retval 0 on arithmetic overflow or invalid input. + * + * The returned size includes any frame budget needed by OSSL_FN_sqr(). + */ +size_t OSSL_FN_sqr_ctx_size(const OSSL_FN *r, const OSSL_FN *a); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crypto/fn_intern.h b/include/crypto/fn_intern.h new file mode 100644 index 0000000000..29bb6e5a0f --- /dev/null +++ b/include/crypto/fn_intern.h @@ -0,0 +1,60 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * @file A set of internal functions to manipulate the OSSL_FN d array, and + * for introspection. + */ + +#ifndef OPENSSL_FN_INTERN_H +#define OPENSSL_FN_INTERN_H +#pragma once + +#include +#include "crypto/fn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if OSSL_FN_BYTES == 4 +/* 32-bit systems */ +#define OSSL_FN_ULONG_C(n) UINT32_C(n) +#define OSSL_FN_ULONG64_C(hi32, lo32) OSSL_FN_ULONG_C(lo32), OSSL_FN_ULONG_C(hi32) +#elif OSSL_FN_BYTES == 8 +/* 64-bit systems */ +#define OSSL_FN_ULONG_C(n) UINT64_C(n) +#define OSSL_FN_ULONG64_C(hi32, lo32) (OSSL_FN_ULONG_C(hi32) << 32 | OSSL_FN_ULONG_C(lo32)) +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif + +int ossl_fn_set_words(OSSL_FN *f, const OSSL_FN_ULONG *words, size_t limbs); +const OSSL_FN_ULONG *ossl_fn_get_words(const OSSL_FN *f); + +size_t ossl_fn_get_dsize(const OSSL_FN *f); + +void ossl_fn_set_negative(OSSL_FN *f, bool neg); + +bool ossl_fn_is_negative(const OSSL_FN *f); +bool ossl_fn_is_dynamically_allocated(const OSSL_FN *f); +bool ossl_fn_is_securely_allocated(const OSSL_FN *f); + +OSSL_FN_ULONG ossl_fn_add_words(OSSL_FN_ULONG *r, size_t rl, + const OSSL_FN_ULONG *a, size_t al, + const OSSL_FN_ULONG *b, size_t bl); +OSSL_FN_ULONG ossl_fn_sub_words(OSSL_FN_ULONG *r, size_t rl, + const OSSL_FN_ULONG *a, size_t al, + const OSSL_FN_ULONG *b, size_t bl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crypto/fnerr.h b/include/crypto/fnerr.h new file mode 100644 index 0000000000..e1741ccdc3 --- /dev/null +++ b/include/crypto/fnerr.h @@ -0,0 +1,38 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 2020-2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_CRYPTO_FNERR_H +#define OSSL_CRYPTO_FNERR_H +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int ossl_err_load_OSSL_FN_strings(void); + +/* + * OSSL_FN reason codes. + */ +#define OSSL_FN_R_DIV_BY_ZERO 101 +#define OSSL_FN_R_INPUT_NOT_REDUCED 103 +#define OSSL_FN_R_BITS_TOO_SMALL 105 +#define OSSL_FN_R_INVALID_RANGE 106 +#define OSSL_FN_R_INVALID_SHIFT 102 +#define OSSL_FN_R_RESULT_ARG_TOO_SMALL 100 +#define OSSL_FN_R_TOO_MANY_ITERATIONS 107 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/crypto/md32_common.inc b/include/crypto/md32_common.inc index 3dea481c56..06293681b4 100644 --- a/include/crypto/md32_common.inc +++ b/include/crypto/md32_common.inc @@ -104,7 +104,7 @@ #define ROTATE(a, n) (((a) << (n)) | (((a) & 0xffffffff) >> (32 - (n)))) #ifndef PEDANTIC -#if defined(__GNUC__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) #if defined(__riscv_zbb) || defined(__riscv_zbkb) #if __riscv_xlen == 64 #undef ROTATE diff --git a/include/crypto/modes.h b/include/crypto/modes.h index baa0f3a6c1..d749eed77d 100644 --- a/include/crypto/modes.h +++ b/include/crypto/modes.h @@ -31,7 +31,7 @@ #endif #if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 2 #if defined(__x86_64) || defined(__x86_64__) #define BSWAP8(x) ({ uint64_t ret_=(x); \ asm ("bswapq %0" \ diff --git a/include/crypto/rand.h b/include/crypto/rand.h index 357ce885b7..4845c84a94 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -39,16 +39,6 @@ /* * Defines related to seed sources */ - -/* Name of the seed source used to seed the primary DRBG. */ -#ifndef OPENSSL_NO_FIPS_JITTER -#define OPENSSL_SEED_SRC_NAME "JITTER" -#elif defined(OPENSSL_DEFAULT_SEED_SRC) -#define OPENSSL_SEED_SRC_NAME OPENSSL_MSTR(OPENSSL_DEFAULT_SEED_SRC) -#else -#define OPENSSL_SEED_SRC_NAME "SEED-SRC" -#endif - #ifndef DEVRANDOM /* * set this to a comma-separated list of 'random' device files to try out. By diff --git a/include/crypto/types.h b/include/crypto/types.h index 8a9d0029d4..32a7517ee6 100644 --- a/include/crypto/types.h +++ b/include/crypto/types.h @@ -13,6 +13,10 @@ #define OSSL_CRYPTO_TYPES_H #pragma once +/* At some point in the future, this may move to include/openssl/types.h */ +typedef struct ossl_fn_st OSSL_FN; +typedef struct ossl_fn_ctx_st OSSL_FN_CTX; + #ifdef OPENSSL_NO_DEPRECATED_3_0 typedef struct rsa_st RSA; typedef struct rsa_meth_st RSA_METHOD; diff --git a/include/internal/core.h b/include/internal/core.h index 33a16395e2..5c9ffc657b 100644 --- a/include/internal/core.h +++ b/include/internal/core.h @@ -44,7 +44,7 @@ typedef struct ossl_method_construct_method_st { const char *name, const char *propdef, void *data); /* Construct a new method */ void *(*construct)(const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov, - void *data, int no_store); + void *data); /* Destruct a method */ void (*destruct)(void *method, void *data); } OSSL_METHOD_CONSTRUCT_METHOD; diff --git a/include/internal/e_os.h b/include/internal/e_os.h index 444f888674..3ea75209cf 100644 --- a/include/internal/e_os.h +++ b/include/internal/e_os.h @@ -83,7 +83,7 @@ #endif #ifdef WINDOWS -#if !defined(_WIN32_WINNT) +#if !defined(_WIN32_WCE) && !defined(_WIN32_WINNT) /* * The _WIN32_WINNT is described here: * https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 @@ -109,15 +109,18 @@ * 0x0603 // Windows 8.1 * 0x0A00 // Windows 10 */ -#define _WIN32_WINNT 0x0600 +#define _WIN32_WINNT 0x0501 #endif #include #include #include #include +#if defined(_WIN32_WCE) && !defined(EACCES) +#define EACCES 13 +#endif #include #include -#if defined(_MSC_VER) && !defined(_DLL) && defined(stdin) +#if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(_DLL) && defined(stdin) #if _MSC_VER >= 1300 && _MSC_VER < 1600 #undef stdin #undef stdout @@ -133,6 +136,10 @@ FILE *__iob_func(void); #include #include +#ifdef OPENSSL_SYS_WINCE +#define OPENSSL_NO_POSIX_IO +#endif + #define EXIT(n) exit(n) #define LIST_SEPARATOR_CHAR ';' #ifndef W_OK @@ -141,7 +148,11 @@ FILE *__iob_func(void); #ifndef R_OK #define R_OK 4 #endif +#ifdef OPENSSL_SYS_WINCE +#define DEFAULT_HOME "" +#else #define DEFAULT_HOME "C:" +#endif /* Avoid Visual Studio 13 GetVersion deprecated problems */ #if defined(_MSC_VER) && _MSC_VER >= 1800 @@ -221,7 +232,7 @@ FILE *__iob_func(void); /***********************************************/ #if defined(OPENSSL_SYS_WINDOWS) -#if defined(_MSC_VER) && (_MSC_VER >= 1310) +#if defined(_MSC_VER) && (_MSC_VER >= 1310) && !defined(_WIN32_WCE) #define open _open #define fdopen _fdopen #define close _close diff --git a/include/internal/e_winsock.h b/include/internal/e_winsock.h index 1ea7383348..6fe7fd0fae 100644 --- a/include/internal/e_winsock.h +++ b/include/internal/e_winsock.h @@ -12,7 +12,7 @@ #pragma once #ifdef WINDOWS -#if !defined(_WIN32_WINNT) +#if !defined(_WIN32_WCE) && !defined(_WIN32_WINNT) /* * The _WIN32_WINNT is described here: * https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 @@ -40,7 +40,7 @@ */ #define _WIN32_WINNT 0x0501 #endif -#if defined(_WIN32_WINNT) +#if defined(_WIN32_WINNT) || defined(_WIN32_WCE) /* * Just like defining _WIN32_WINNT including winsock2.h implies * certain "discipline" for maintaining [broad] binary compatibility. diff --git a/include/internal/hashtable.h b/include/internal/hashtable.h index 9aad653097..7c4150ba28 100644 --- a/include/internal/hashtable.h +++ b/include/internal/hashtable.h @@ -357,7 +357,7 @@ static ossl_inline ossl_unused void ossl_ht_strcase(HT_KEY *key, char *tgt, cons if (key != NULL && key->keysize + len > key->bufsize) len = (size_t)(key->bufsize - key->keysize); - for (i = 0; i < len && src[i] != '\0'; i++) + for (i = 0; src[i] != '\0' && i < len; i++) tgt[i] = case_adjust & src[i]; } diff --git a/include/internal/quic_lcidm.h b/include/internal/quic_lcidm.h index 079dacd597..66421e8ac1 100644 --- a/include/internal/quic_lcidm.h +++ b/include/internal/quic_lcidm.h @@ -254,7 +254,7 @@ int ossl_quic_lcidm_debug_add(QUIC_LCIDM *lcidm, void *opaque, /* * Obtain a local connection id which is not used yet. - * Returns 1 on success, 0 on failure. + * Returns 1 on succes, 0 on failure. */ int ossl_quic_lcidm_get_unused_cid(QUIC_LCIDM *lcidm, QUIC_CONN_ID *cid); diff --git a/include/internal/quic_srtm.h b/include/internal/quic_srtm.h index 77c0af6ac4..1a8f55da5d 100644 --- a/include/internal/quic_srtm.h +++ b/include/internal/quic_srtm.h @@ -11,7 +11,6 @@ #define OSSL_INTERNAL_QUIC_SRTM_H #pragma once -#include #include "internal/e_os.h" #include "internal/time.h" #include "internal/quic_types.h" @@ -70,22 +69,11 @@ void ossl_quic_srtm_free(QUIC_SRTM *srtm); int ossl_quic_srtm_add(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num, const QUIC_STATELESS_RESET_TOKEN *token); -/** - * \brief Removes an entry identified by its (opaque, seq_num) tuple. - * - * The absence of a matching entry is not an error. - * - * \param srtm SRTM instance to remove the entry from. - * \param opaque Opaque pointer identifying the entry. - * \param seq_num Sequence number identifying the entry. - * \param match If non-NULL, \c *match is set to 1 if a matching entry was - * found or to 0 if not. May be NULL if this information is not - * required. - * - * \return 1 on success and 0 on internal error. +/* + * Removes an entry by identifying it via its (opaque, seq_num) tuple. + * Returns 1 if the entry was found and removed, and 0 if it was not found. */ -int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num, - uint8_t *match); +int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num); /* * Removes all entries (opaque, *) with the given opaque pointer. diff --git a/include/internal/quic_vlint.h b/include/internal/quic_vlint.h index c8b056909d..ff015eb127 100644 --- a/include/internal/quic_vlint.h +++ b/include/internal/quic_vlint.h @@ -54,7 +54,7 @@ static ossl_unused ossl_inline size_t ossl_quic_vlint_encode_len(uint64_t v) } /* - * This function writes a QUIC variable-length encoded integer to buf. + * This function writes a QUIC varable-length encoded integer to buf. * The smallest usable representation is used. * * It is the caller's responsibility to ensure that the buffer is big enough by diff --git a/include/internal/quic_wire.h b/include/internal/quic_wire.h index 06ae9ca677..f2efabaeba 100644 --- a/include/internal/quic_wire.h +++ b/include/internal/quic_wire.h @@ -424,7 +424,7 @@ int ossl_quic_wire_encode_frame_conn_close(WPACKET *pkt, /* * Encodes a QUIC HANDSHAKE_DONE frame to the packet writer. This frame type - * takes no arguments. + * takes no arguiments. */ int ossl_quic_wire_encode_frame_handshake_done(WPACKET *pkt); diff --git a/include/internal/refcount.h b/include/internal/refcount.h index 8bbb11e3fc..61eb78ae41 100644 --- a/include/internal/refcount.h +++ b/include/internal/refcount.h @@ -14,8 +14,6 @@ #include #include -#include - #if defined(OPENSSL_THREADS) && !defined(OPENSSL_DEV_NO_ATOMICS) #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ && !defined(__STDC_NO_ATOMICS__) @@ -38,10 +36,10 @@ typedef struct { _Atomic int val; } CRYPTO_REF_COUNT; -static inline bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +static inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { *ret = atomic_fetch_add_explicit(&refcnt->val, 1, memory_order_relaxed) + 1; - return true; + return 1; } /* @@ -70,6 +68,12 @@ static inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) return 1; } +static inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +{ + *ret = atomic_load_explicit(&refcnt->val, memory_order_acquire); + return 1; +} + #elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 #define HAVE_ATOMICS 1 @@ -78,10 +82,10 @@ typedef struct { int val; } CRYPTO_REF_COUNT; -static __inline__ bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +static __inline__ int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { *ret = __atomic_fetch_add(&refcnt->val, 1, __ATOMIC_RELAXED) + 1; - return true; + return 1; } static __inline__ int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) @@ -92,6 +96,12 @@ static __inline__ int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) return 1; } +static __inline__ int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +{ + *ret = __atomic_load_n(&refcnt->val, __ATOMIC_RELAXED); + return 1; +} + #elif defined(__ICL) && defined(_WIN32) #define HAVE_ATOMICS 1 @@ -99,10 +109,10 @@ typedef struct { volatile int val; } CRYPTO_REF_COUNT; -static __inline bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +static __inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { *ret = _InterlockedExchangeAdd((void *)&refcnt->val, 1) + 1; - return true; + return 1; } static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) @@ -111,6 +121,12 @@ static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) return 1; } +static __inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +{ + *ret = _InterlockedExchangeAdd((void *)&refcnt->val, 0); + return 1; +} + #elif defined(_MSC_VER) && _MSC_VER >= 1200 #define HAVE_ATOMICS 1 @@ -119,16 +135,16 @@ typedef struct { volatile int val; } CRYPTO_REF_COUNT; -#if (defined(_M_ARM) && _M_ARM >= 7) || defined(_M_ARM64) +#if (defined(_M_ARM) && _M_ARM >= 7 && !defined(_WIN32_WCE)) || defined(_M_ARM64) #include #if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH) #define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH #endif -static __inline bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +static __inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { *ret = _InterlockedExchangeAdd_nf(&refcnt->val, 1) + 1; - return true; + return 1; } static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) @@ -137,13 +153,29 @@ static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) return 1; } -#else -#pragma intrinsic(_InterlockedExchangeAdd) +static __inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +{ + *ret = _InterlockedExchangeAdd_acq((void *)&refcnt->val, 0); + return 1; +} -static __inline bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +#else +#if !defined(_WIN32_WCE) +#pragma intrinsic(_InterlockedExchangeAdd) +#else +#if _WIN32_WCE >= 0x600 +extern long __cdecl _InterlockedExchangeAdd(long volatile *, long); +#else +/* under Windows CE we still have old-style Interlocked* functions */ +extern long __cdecl InterlockedExchangeAdd(long volatile *, long); +#define _InterlockedExchangeAdd InterlockedExchangeAdd +#endif +#endif + +static __inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { *ret = _InterlockedExchangeAdd(&refcnt->val, 1) + 1; - return true; + return 1; } static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) @@ -152,6 +184,12 @@ static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret) return 1; } +static __inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret) +{ + *ret = _InterlockedExchangeAdd(&refcnt->val, 0); + return 1; +} + #endif #endif @@ -173,10 +211,10 @@ typedef struct { #ifdef OPENSSL_THREADS -static ossl_unused ossl_inline bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, +static ossl_unused ossl_inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { - return CRYPTO_atomic_add(&refcnt->val, 1, ret, refcnt->lock) ? true : false; + return CRYPTO_atomic_add(&refcnt->val, 1, ret, refcnt->lock); } static ossl_unused ossl_inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, @@ -185,6 +223,12 @@ static ossl_unused ossl_inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, return CRYPTO_atomic_add(&refcnt->val, -1, ret, refcnt->lock); } +static ossl_unused ossl_inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, + int *ret) +{ + return CRYPTO_atomic_load_int(&refcnt->val, ret, refcnt->lock); +} + #define CRYPTO_NEW_FREE_DEFINED 1 static ossl_unused ossl_inline int CRYPTO_NEW_REF(CRYPTO_REF_COUNT *refcnt, int n) { @@ -205,12 +249,12 @@ static ossl_unused ossl_inline void CRYPTO_FREE_REF(CRYPTO_REF_COUNT *refcnt) #else /* OPENSSL_THREADS */ -static ossl_unused ossl_inline bool CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, +static ossl_unused ossl_inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret) { refcnt->val++; *ret = refcnt->val; - return true; + return 1; } static ossl_unused ossl_inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, @@ -221,6 +265,13 @@ static ossl_unused ossl_inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, return 1; } +static ossl_unused ossl_inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, + int *ret) +{ + *ret = refcnt->val; + return 1; +} + #endif /* OPENSSL_THREADS */ #endif diff --git a/include/internal/sha3.h b/include/internal/sha3.h index 0e0ab76fb5..f91d00a74f 100644 --- a/include/internal/sha3.h +++ b/include/internal/sha3.h @@ -65,75 +65,4 @@ int ossl_shake_squeeze_default(KECCAK1600_CTX *ctx, unsigned char *out, size_t o size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, size_t r); -/* Multi-buffer (x4) Keccak-f[1600] context and API */ -#if defined(KECCAK1600_ASM) \ - && (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \ - && !defined(OPENSSL_NO_ASM) - -/* Runtime capability check for AVX512VL */ -int SHA3_avx512vl_capable(void); - -/* Context for 4-way parallel SHAKE operations */ -typedef struct { - /* 4 interleaved Keccak states (800 bytes) - plus 8 bytes to store the number of - already absorbed or not yet squeezed bytes */ - uint64_t A[(25 * 4) + 1]; - size_t rate; /* Rate in bytes: 168 (SHAKE-128) or 136 (SHAKE-256) */ - unsigned finalized; /* Has finalize been called? 0=no, 1=yes */ -} KECCAK1600_X4_AVX512VL_CTX; - -/* SHAKE-128 x4 incremental API */ -void ossl_sha3_shake128_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx); - -void ossl_sha3_shake128_x4_inc_absorb_avx512vl( - KECCAK1600_X4_AVX512VL_CTX *ctx, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -void ossl_sha3_shake128_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx); - -void ossl_sha3_shake128_x4_inc_squeeze_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - KECCAK1600_X4_AVX512VL_CTX *ctx); - -/* SHAKE-256 x4 incremental API */ -void ossl_sha3_shake256_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx); - -void ossl_sha3_shake256_x4_inc_absorb_avx512vl( - KECCAK1600_X4_AVX512VL_CTX *ctx, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -void ossl_sha3_shake256_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx); - -void ossl_sha3_shake256_x4_inc_squeeze_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - KECCAK1600_X4_AVX512VL_CTX *ctx); - -/* Single-call SHAKE x4 APIs (wrapper functions) */ -void ossl_sha3_shake128_x4_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -void ossl_sha3_shake256_x4_avx512vl( - void *out0, void *out1, - void *out2, void *out3, - size_t outlen, - const void *in0, const void *in1, - const void *in2, const void *in3, - size_t inlen); - -#endif /* KECCAK1600_ASM && x86_64 && !OPENSSL_NO_ASM */ - #endif /* OSSL_INTERNAL_SHA3_H */ diff --git a/include/internal/sockets.h b/include/internal/sockets.h index 1da34aa7b0..ba8432c0a5 100644 --- a/include/internal/sockets.h +++ b/include/internal/sockets.h @@ -37,11 +37,18 @@ #include #include #include +#elif defined(_WIN32_WCE) && _WIN32_WCE < 410 +#define getservbyname _masked_declaration_getservbyname #endif #if !defined(IPPROTO_IP) /* winsock[2].h was included already? */ #include "internal/e_winsock.h" #endif +#ifdef getservbyname +/* this is used to be wcecompat/include/winsock_extras.h */ +#undef getservbyname +struct servent *PASCAL getservbyname(const char *, const char *); +#endif #ifdef _WIN64 /* @@ -223,7 +230,7 @@ static ossl_inline int writesocket_ex(int s, const void *b, int n, int f) #endif /* also in apps/include/apps.h */ -#if defined(OPENSSL_SYS_WIN32) +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE) #define openssl_fdset(a, b) FD_SET((unsigned int)(a), b) #else #define openssl_fdset(a, b) FD_SET(a, b) diff --git a/include/internal/ssl3_cbc.h b/include/internal/ssl3_cbc.h index 84c2ccb813..89a3efa25d 100644 --- a/include/internal/ssl3_cbc.h +++ b/include/internal/ssl3_cbc.h @@ -13,6 +13,13 @@ #include /* tls_pad.c */ +int ssl3_cbc_remove_padding_and_mac(size_t *reclen, + size_t origreclen, + unsigned char *recdata, + unsigned char **mac, + int *alloced, + size_t block_size, size_t mac_size, + OSSL_LIB_CTX *libctx); int tls1_cbc_remove_padding_and_mac(size_t *reclen, size_t origreclen, @@ -33,6 +40,6 @@ __owur int ssl3_cbc_digest_record(const EVP_MD *md, size_t data_size, size_t data_plus_mac_plus_padding_size, const unsigned char *mac_secret, - size_t mac_secret_length); + size_t mac_secret_length, char is_sslv3); #endif /* !defined(OSSL_INTERNAL_SSL3_CBC_H) */ diff --git a/include/internal/thread_arch.h b/include/internal/thread_arch.h index 73e6e0d1e7..d7fc08a8af 100644 --- a/include/internal/thread_arch.h +++ b/include/internal/thread_arch.h @@ -11,9 +11,12 @@ #define OSSL_INTERNAL_THREAD_ARCH_H #include #include -#include "internal/e_os.h" #include "internal/time.h" +#if defined(_WIN32) +#include +#endif + #if defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_UNIX) #define OPENSSL_THREADS_POSIX #elif defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_VMS) diff --git a/include/internal/threads_common.h b/include/internal/threads_common.h index e32257d630..b6dea47ab9 100644 --- a/include/internal/threads_common.h +++ b/include/internal/threads_common.h @@ -88,7 +88,7 @@ void CRYPTO_THREAD_clean_local(void); #endif /* Allow us to know if atomics will be implemented with a fallback lock or not. */ -#if defined(OSSL_USE_GCC_ATOMICS) || defined(OSSL_USE_SOLARIS_ATOMICS) || defined(OSSL_USE_INTERLOCKEDOR64) +#if defined(OSSL_USE_GCC_ATOMICS) || defined(OSSL_USE_SOLARIS_ATOMICS) || defined(USE_INTERLOCKEDOR64) #define OSSL_ATOMICS_LOCKLESS #endif diff --git a/include/internal/tlssigalgs.h b/include/internal/tlssigalgs.h index f5aea80f64..1d6c9df49f 100644 --- a/include/internal/tlssigalgs.h +++ b/include/internal/tlssigalgs.h @@ -49,19 +49,6 @@ #define TLSEXT_SIGALG_mldsa65 0x0905 #define TLSEXT_SIGALG_mldsa87 0x0906 -#define TLSEXT_SIGALG_slhdsa_sha2_128s 0x0911 -#define TLSEXT_SIGALG_slhdsa_sha2_128f 0x0912 -#define TLSEXT_SIGALG_slhdsa_sha2_192s 0x0913 -#define TLSEXT_SIGALG_slhdsa_sha2_192f 0x0914 -#define TLSEXT_SIGALG_slhdsa_sha2_256s 0x0915 -#define TLSEXT_SIGALG_slhdsa_sha2_256f 0x0916 -#define TLSEXT_SIGALG_slhdsa_shake_128s 0x0917 -#define TLSEXT_SIGALG_slhdsa_shake_128f 0x0918 -#define TLSEXT_SIGALG_slhdsa_shake_192s 0x0919 -#define TLSEXT_SIGALG_slhdsa_shake_192f 0x091a -#define TLSEXT_SIGALG_slhdsa_shake_256s 0x091b -#define TLSEXT_SIGALG_slhdsa_shake_256f 0x091c - /* Sigalgs names */ #define TLSEXT_SIGALG_ecdsa_secp256r1_sha256_name "ecdsa_secp256r1_sha256" #define TLSEXT_SIGALG_ecdsa_secp384r1_sha384_name "ecdsa_secp384r1_sha384" @@ -105,17 +92,4 @@ #define TLSEXT_SIGALG_mldsa65_name "mldsa65" #define TLSEXT_SIGALG_mldsa87_name "mldsa87" -#define TLSEXT_SIGALG_slhdsa_sha2_128s_name "slhdsa_sha2_128s" -#define TLSEXT_SIGALG_slhdsa_sha2_128f_name "slhdsa_sha2_128f" -#define TLSEXT_SIGALG_slhdsa_sha2_192s_name "slhdsa_sha2_192s" -#define TLSEXT_SIGALG_slhdsa_sha2_192f_name "slhdsa_sha2_192f" -#define TLSEXT_SIGALG_slhdsa_sha2_256s_name "slhdsa_sha2_256s" -#define TLSEXT_SIGALG_slhdsa_sha2_256f_name "slhdsa_sha2_256f" -#define TLSEXT_SIGALG_slhdsa_shake_128s_name "slhdsa_shake_128s" -#define TLSEXT_SIGALG_slhdsa_shake_128f_name "slhdsa_shake_128f" -#define TLSEXT_SIGALG_slhdsa_shake_192s_name "slhdsa_shake_192s" -#define TLSEXT_SIGALG_slhdsa_shake_192f_name "slhdsa_shake_192f" -#define TLSEXT_SIGALG_slhdsa_shake_256s_name "slhdsa_shake_256s" -#define TLSEXT_SIGALG_slhdsa_shake_256f_name "slhdsa_shake_256f" - #endif diff --git a/include/internal/tsan_assist.h b/include/internal/tsan_assist.h index a4e87504a1..db011f19f0 100644 --- a/include/internal/tsan_assist.h +++ b/include/internal/tsan_assist.h @@ -78,7 +78,7 @@ #endif #elif defined(_MSC_VER) && _MSC_VER >= 1200 \ - && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7)) + && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7 && !defined(_WIN32_WCE))) /* * There is subtle dependency on /volatile: command-line option. * "ms" implies same semantic as memory_order_acquire for loads and diff --git a/include/internal/zeroization.h b/include/internal/zeroization.h index d30baa869a..be8e18d638 100644 --- a/include/internal/zeroization.h +++ b/include/internal/zeroization.h @@ -11,7 +11,7 @@ * Utility functions for handling OPENSSL_PEDANTIC_ZEROIZATION. * * ISO 19790:2012/Cor.1:2015 7.9 requires cryptographic module to provide - * methods to zeroise all unprotected security sensitive parameters + * methods to zeroise all unproctected security sensitive parameters * (which includes both Critical/Private and Public security parameters). * * To comply with these (arguably, unnecessarily onerous) requirements, diff --git a/include/openssl/asn1.h.in b/include/openssl/asn1.h.in index 440a6b3766..21d9e772c6 100644 --- a/include/openssl/asn1.h.in +++ b/include/openssl/asn1.h.in @@ -199,10 +199,7 @@ struct asn1_string_table_st { */ typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; typedef struct ASN1_TLC_st ASN1_TLC; -/* - * This is deliberately used as an opaque pointer to a structure that - * is never defined. In other words it will behave like void * - */ +/* This is just an opaque pointer */ typedef struct ASN1_VALUE_st ASN1_VALUE; /* Declare ASN1 functions: the implement macro is in asn1t.h */ @@ -540,16 +537,9 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); * Since this is used to store all sorts of things, via macros, for now, * make its data void * */ -#if !defined(OPENSSL_NO_DEPRECATED_4_1) -OSSL_DEPRECATEDIN_4_1_FOR(" Use ASN1_STRING_set_data() or ASN1_STRING_set_string() instead.") int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); -OSSL_DEPRECATEDIN_4_1_FOR(" Use ASN1_STRING_length_ex() instead.") -int ASN1_STRING_length(const ASN1_STRING *x); -#endif /* !defined(OPENSSL_NO_DEPRECATED_4_1) */ void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); -int ASN1_STRING_set_data(ASN1_STRING *str, const uint8_t *data, size_t len); -int ASN1_STRING_set_string(ASN1_STRING *str, const char *cstring); -size_t ASN1_STRING_length_ex(const ASN1_STRING *x); +int ASN1_STRING_length(const ASN1_STRING *x); #ifndef OPENSSL_NO_DEPRECATED_3_0 OSSL_DEPRECATEDIN_3_0 void ASN1_STRING_length_set(ASN1_STRING *x, int n); #endif diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index c2990efde4..7912dcaa82 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -932,20 +932,33 @@ void BIO_copy_next_retry(BIO *b); */ #define ossl_bio__attr__(x) -#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__MINGW64__) \ +#if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__MINGW32__) && !defined(__MINGW64__) \ && !defined(__APPLE__) +/* + * Because we support the 'z' modifier, which made its appearance in C99, + * we can't use __attribute__ with pre C99 dialects. + */ +#if __STDC_VERSION__ >= 199901L #undef ossl_bio__attr__ #define ossl_bio__attr__ __attribute__ +#if __GNUC__ * 10 + __GNUC_MINOR__ >= 44 +#define ossl_bio__printf__ __gnu_printf__ +#else +#define ossl_bio__printf__ __printf__ +#endif +#endif #endif int BIO_printf(BIO *bio, const char *format, ...) - ossl_bio__attr__((__format__(__printf__, 2, 3))); + ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 3))); int BIO_vprintf(BIO *bio, const char *format, va_list args) - ossl_bio__attr__((__format__(__printf__, 2, 0))); + ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 0))); int BIO_snprintf(char *buf, size_t n, const char *format, ...) - ossl_bio__attr__((__format__(__printf__, 3, 4))); + ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 4))); int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) - ossl_bio__attr__((__format__(__printf__, 3, 0))); + ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 0))); #undef ossl_bio__attr__ +#undef ossl_bio__printf__ BIO_METHOD *BIO_meth_new(int type, const char *name); void BIO_meth_free(BIO_METHOD *biom); diff --git a/include/openssl/bn.h b/include/openssl/bn.h index 5d7e5ce83f..d7eaa22736 100644 --- a/include/openssl/bn.h +++ b/include/openssl/bn.h @@ -21,36 +21,15 @@ #ifndef OPENSSL_NO_STDIO #include #endif -#include #include #include #include +#include #ifdef __cplusplus extern "C" { #endif -/* - * 64-bit processor with LP64 ABI - */ -#ifdef SIXTY_FOUR_BIT_LONG -typedef unsigned long BN_ULONG; -#define BN_BYTES 8 -#endif - -/* - * 64-bit processor other than LP64 ABI - */ -#ifdef SIXTY_FOUR_BIT -typedef unsigned long long BN_ULONG; -#define BN_BYTES 8 -#endif - -#ifdef THIRTY_TWO_BIT -typedef unsigned int BN_ULONG; -#define BN_BYTES 4 -#endif - #define BN_BITS2 (BN_BYTES * 8) #define BN_BITS (BN_BITS2 * 2) #define BN_TBIT ((BN_ULONG)1 << (BN_BITS2 - 1)) diff --git a/include/openssl/bn_limbs.h b/include/openssl/bn_limbs.h new file mode 100644 index 0000000000..ed440d95ba --- /dev/null +++ b/include/openssl/bn_limbs.h @@ -0,0 +1,48 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * @file Defines the type of large integer limbs. + * + * The large number is composed of words, the size of which is assumed to + * be optimal for the platform it's built for. In many large number texts, + * these words are called "limb". The BIGNUM library also calls this "word". + * + * In OpenSSL code, the BIGNUM "limb" is represented with the type macro + * BN_ULONG. + */ + +#ifndef OPENSSL_BN_LIMBS_H +#define OPENSSL_BN_LIMBS_H +#pragma once + +#include + +/* + * 64-bit processor with LP64 ABI + */ +#ifdef SIXTY_FOUR_BIT_LONG +typedef unsigned long BN_ULONG; +#define BN_BYTES 8 +#endif + +/* + * 64-bit processor other than LP64 ABI + */ +#ifdef SIXTY_FOUR_BIT +typedef unsigned long long BN_ULONG; +#define BN_BYTES 8 +#endif + +#ifdef THIRTY_TWO_BIT +typedef unsigned int BN_ULONG; +#define BN_BYTES 4 +#endif + +#endif diff --git a/include/openssl/e_os2.h b/include/openssl/e_os2.h index f3cda73da1..bacc161bd6 100644 --- a/include/openssl/e_os2.h +++ b/include/openssl/e_os2.h @@ -72,11 +72,14 @@ extern "C" { #if defined(OPENSSL_SYS_WINNT) #undef OPENSSL_SYS_UNIX #endif +#if defined(OPENSSL_SYS_WINCE) +#undef OPENSSL_SYS_UNIX +#endif #endif #endif /* Anything that tries to look like Microsoft is "Windows" */ -#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE) #undef OPENSSL_SYS_UNIX #define OPENSSL_SYS_WINDOWS #ifndef OPENSSL_SYS_MSDOS @@ -253,7 +256,7 @@ typedef uint64_t ossl_uintmax_t; #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* just use inline */ #define ossl_inline inline -#elif defined(__GNUC__) +#elif defined(__GNUC__) && __GNUC__ >= 2 #define ossl_inline __inline__ #elif defined(_MSC_VER) /* @@ -271,7 +274,7 @@ typedef uint64_t ossl_uintmax_t; #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus) #define ossl_noreturn _Noreturn -#elif defined(__GNUC__) +#elif defined(__GNUC__) && __GNUC__ >= 2 #define ossl_noreturn __attribute__((noreturn)) #else #define ossl_noreturn diff --git a/include/openssl/err.h.in b/include/openssl/err.h.in index de27183c00..e99d5954be 100644 --- a/include/openssl/err.h.in +++ b/include/openssl/err.h.in @@ -105,6 +105,7 @@ extern "C" { #define ERR_LIB_OSSL_ENCODER 59 #define ERR_LIB_OSSL_DECODER 60 #define ERR_LIB_HTTP 61 +#define ERR_LIB_OSSL_FN 62 #define ERR_LIB_USER 128 diff --git a/include/openssl/evp.h b/include/openssl/evp.h index dcbc5b26d3..6ab3f556cd 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -155,8 +155,6 @@ int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable); /* Note if suitable for use in FIPS mode */ #define EVP_MD_FLAG_FIPS 0x0400 -#define EVP_MD_FLAG_NO_STORE 0x0800 - /* Digest ctrls */ #define EVP_MD_CTRL_DIGALGID 0x1 @@ -269,8 +267,6 @@ int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable); #define EVP_CIPH_FLAG_GET_WRAP_CIPHER 0x4000000 #define EVP_CIPH_FLAG_INVERSE_CIPHER 0x8000000 #define EVP_CIPH_FLAG_ENC_THEN_MAC 0x10000000 -/* flag to indicate that this cipher isn't cached, and so should be refcounted*/ -#define EVP_CIPH_FLAG_NO_STORE 0x20000000 /* * Cipher context flag to indicate we can handle wrap mode: if allowed in diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h index d49b22373e..ab79e02e04 100644 --- a/include/openssl/kdf.h +++ b/include/openssl/kdf.h @@ -37,13 +37,7 @@ const char *EVP_KDF_get0_description(const EVP_KDF *kdf); int EVP_KDF_is_a(const EVP_KDF *kdf, const char *name); const char *EVP_KDF_get0_name(const EVP_KDF *kdf); const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf); -const EVP_KDF *EVP_KDF_CTX_get0_kdf(const EVP_KDF_CTX *ctx); -EVP_KDF *EVP_KDF_CTX_get1_kdf(const EVP_KDF_CTX *ctx); - -#if !defined(OPENSSL_NO_DEPRECATED_4_1) -OSSL_DEPRECATEDIN_4_1_FOR("Use EVP_KDF_CTX_get0_kdf") -const EVP_KDF *EVP_KDF_CTX_kdf(const EVP_KDF_CTX *ctx); -#endif /* !OPENSSL_NO_DEPRECATED_4_1 */ +const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx); void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx); size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx); diff --git a/include/openssl/macros.h b/include/openssl/macros.h index 7e820875e2..40f067c8ab 100644 --- a/include/openssl/macros.h +++ b/include/openssl/macros.h @@ -53,11 +53,21 @@ __pragma(warning(push)) __pragma(warning(disable : 4996)) #define OSSL_END_ALLOW_DEPRECATED __pragma(warning(pop)) #elif defined(__GNUC__) +/* + * According to GCC documentation, deprecations with message appeared in + * GCC 4.5.0 + */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #define OSSL_DEPRECATED(since) \ __attribute__((deprecated("Since OpenSSL " #since))) #define OSSL_DEPRECATED_FOR(since, message) \ __attribute__((deprecated("Since OpenSSL " #since ";" message))) #define OSSL_DEPRECATED_MESSAGE(message) __attribute__((deprecated(message))) +#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) +#define OSSL_DEPRECATED(since) __attribute__((deprecated)) +#define OSSL_DEPRECATED_FOR(since, message) __attribute__((deprecated)) +#define OSSL_DEPRECATED_MESSAGE(message) __attribute__((deprecated)) +#endif #define OSSL_BEGIN_ALLOW_DEPRECATED \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") @@ -366,7 +376,7 @@ #if defined(__STDC_VERSION__) #if __STDC_VERSION__ >= 199901L #define OPENSSL_FUNC __func__ -#elif defined(__GNUC__) +#elif defined(__GNUC__) && __GNUC__ >= 2 #define OPENSSL_FUNC __FUNCTION__ #endif #elif defined(_MSC_VER) diff --git a/include/openssl/ocsp.h.in b/include/openssl/ocsp.h.in index ce33a4d8fc..86ed7f5869 100644 --- a/include/openssl/ocsp.h.in +++ b/include/openssl/ocsp.h.in @@ -144,13 +144,9 @@ typedef struct ocsp_service_locator_st OCSP_SERVICELOC; #define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" #define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" -#define d2i_OCSP_REQUEST_bio(bp, p) \ - ((OCSP_REQUEST *)ASN1_item_d2i_bio(ASN1_ITEM_rptr(OCSP_REQUEST), \ - (bp), CHECKED_PPTR_OF(OCSP_REQUEST, p))) +#define d2i_OCSP_REQUEST_bio(bp, p) ASN1_d2i_bio_of(OCSP_REQUEST, OCSP_REQUEST_new, d2i_OCSP_REQUEST, bp, p) -#define d2i_OCSP_RESPONSE_bio(bp, p) \ - ((OCSP_RESPONSE *)ASN1_item_d2i_bio(ASN1_ITEM_rptr(OCSP_RESPONSE), \ - (bp), CHECKED_PPTR_OF(OCSP_RESPONSE, p))) +#define d2i_OCSP_RESPONSE_bio(bp, p) ASN1_d2i_bio_of(OCSP_RESPONSE, OCSP_RESPONSE_new, d2i_OCSP_RESPONSE, bp, p) #define PEM_read_bio_OCSP_REQUEST(bp, x, cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \ (d2i_of_void *)d2i_OCSP_REQUEST, PEM_STRING_OCSP_REQUEST, \ @@ -168,13 +164,9 @@ typedef struct ocsp_service_locator_st OCSP_SERVICELOC; PEM_ASN1_write_bio((i2d_of_void *)i2d_OCSP_RESPONSE, PEM_STRING_OCSP_RESPONSE, \ bp, (char *)(o), NULL, NULL, 0, NULL, NULL) -#define i2d_OCSP_RESPONSE_bio(bp, o) \ - ASN1_item_i2d_bio(ASN1_ITEM_rptr(OCSP_RESPONSE), \ - (bp), CHECKED_PTR_OF(const OCSP_RESPONSE, o)) +#define i2d_OCSP_RESPONSE_bio(bp, o) ASN1_i2d_bio_of(OCSP_RESPONSE, i2d_OCSP_RESPONSE, bp, o) -#define i2d_OCSP_REQUEST_bio(bp, o) \ - ASN1_item_i2d_bio(ASN1_ITEM_rptr(OCSP_REQUEST), \ - (bp), CHECKED_PTR_OF(const OCSP_REQUEST, o)) +#define i2d_OCSP_REQUEST_bio(bp, o) ASN1_i2d_bio_of(OCSP_REQUEST, i2d_OCSP_REQUEST, bp, o) #define ASN1_BIT_STRING_digest(data, type, md, len) \ ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING), type, data, md, len) diff --git a/include/openssl/pem.h b/include/openssl/pem.h index 115c8f2733..ccde1b93d5 100644 --- a/include/openssl/pem.h +++ b/include/openssl/pem.h @@ -117,26 +117,8 @@ extern "C" { #define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u) \ { \ - BIO *b; \ - const unsigned char *p = NULL; \ - unsigned char *data = NULL; \ - long len; \ - type *ret = NULL; \ - \ - if ((b = BIO_new(BIO_s_file())) == NULL) { \ - ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); \ - return NULL; \ - } \ - BIO_set_fp(b, fp, BIO_NOCLOSE); \ - if (PEM_bytes_read_bio(&data, &len, NULL, str, b, cb, u)) { \ - p = data; \ - ret = d2i_##asn1(x, &p, len); \ - if (ret == NULL) \ - ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); \ - } \ - BIO_free(b); \ - OPENSSL_free(data); \ - return ret; \ + return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str, fp, \ + (void **)x, cb, u); \ } #define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ @@ -164,24 +146,12 @@ extern "C" { #endif #endif -#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ - type *PEM_read_bio_##name(BIO *bp, type **x, \ - pem_password_cb *cb, void *u) \ - { \ - const unsigned char *p = NULL; \ - unsigned char *data = NULL; \ - long len; \ - type *ret = NULL; \ - \ - if (!PEM_bytes_read_bio(&data, &len, NULL, str, \ - bp, cb, u)) \ - return NULL; \ - p = data; \ - ret = d2i_##asn1(x, &p, len); \ - if (ret == NULL) \ - ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); \ - OPENSSL_free(data); \ - return ret; \ +#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + type *PEM_read_bio_##name(BIO *bp, type **x, \ + pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str, bp, \ + (void **)x, cb, u); \ } #define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h index 0db3a82b47..79bbc6628e 100644 --- a/include/openssl/proverr.h +++ b/include/openssl/proverr.h @@ -97,7 +97,6 @@ #define PROV_R_INVALID_UKM_LENGTH 200 #define PROV_R_INVALID_X931_DIGEST 170 #define PROV_R_IN_ERROR_STATE 192 -#define PROV_R_KEY_IMMUTABLE_ONCE_SET 266 #define PROV_R_KEY_SETUP_FAILED 101 #define PROV_R_KEY_SIZE_TOO_SMALL 171 #define PROV_R_LENGTH_TOO_LARGE 202 diff --git a/include/openssl/safestack.h.in b/include/openssl/safestack.h.in index 64ac28be04..a4c178d189 100644 --- a/include/openssl/safestack.h.in +++ b/include/openssl/safestack.h.in @@ -222,27 +222,15 @@ extern "C" { } \ static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_dup(const STACK_OF(t1) *sk) \ { \ - OPENSSL_STACK *ret = OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \ - OPENSSL_sk_freefunc_thunk f_thunk; \ - \ - f_thunk = (OPENSSL_sk_freefunc_thunk)sk_##t1##_freefunc_thunk; \ - OPENSSL_sk_set_cmp_thunks(ret, sk_##t1##_cmpfunc_thunk); \ - OPENSSL_sk_set_copy_thunks(ret, sk_##t1##_copyfunc_thunk); \ - return (STACK_OF(t1) *)OPENSSL_sk_set_thunks(ret, f_thunk); \ + return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \ } \ static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \ sk_##t1##_copyfunc copyfunc, \ sk_##t1##_freefunc freefunc) \ { \ - OPENSSL_STACK *ret = OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \ + return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \ (OPENSSL_sk_copyfunc)copyfunc, \ (OPENSSL_sk_freefunc)freefunc); \ - OPENSSL_sk_freefunc_thunk f_thunk; \ - \ - f_thunk = (OPENSSL_sk_freefunc_thunk)sk_##t1##_freefunc_thunk; \ - OPENSSL_sk_set_cmp_thunks(ret, sk_##t1##_cmpfunc_thunk); \ - OPENSSL_sk_set_copy_thunks(ret, sk_##t1##_copyfunc_thunk); \ - return (STACK_OF(t1) *)OPENSSL_sk_set_thunks(ret, f_thunk); \ } \ static ossl_unused ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \ { \ diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index b010a6e677..f92937e951 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -346,7 +346,7 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg); /* In TLSv1.3 allow a non-(ec)dhe based kex_mode */ #define SSL_OP_ALLOW_NO_DHE_KEX SSL_OP_BIT(10) /* - * Disable TLS 1.0 CBC vulnerability workaround that was added + * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added * in OpenSSL 0.9.6d. Usually (depending on the application protocol) * the workaround is not needed. Unfortunately some broken SSL/TLS * implementations cannot handle it at all, which is why we include it @@ -2695,18 +2695,8 @@ const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx); #define SSL_SECOP_OTHER_SIGALG (5 << 16) #define SSL_SECOP_OTHER_CERT (6 << 16) -/* - * Unused values - these do nothing and are never set. - * They are retained because of API. They should - * be removed next major - */ +/* Indicated operation refers to peer key or certificate */ #define SSL_SECOP_PEER 0x1000 -/* Peer EE key in certificate */ -#define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) -/* Peer CA key in certificate */ -#define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) -/* Peer CA digest algorithm in certificate */ -#define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) /* Values for "op" parameter in security callback */ @@ -2745,6 +2735,12 @@ const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx); #define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT) /* CA digest algorithm in certificate */ #define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT) +/* Peer EE key in certificate */ +#define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) +/* Peer CA key in certificate */ +#define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) +/* Peer CA digest algorithm in certificate */ +#define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) void SSL_set_security_level(SSL *s, int level); __owur int SSL_get_security_level(const SSL *s); @@ -2784,11 +2780,8 @@ __owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx); int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); #ifndef OPENSSL_NO_UNIT_TEST -#ifndef OPENSSL_NO_DEPRECATED_4_1 -OSSL_DEPRECATEDIN_4_1 __owur const struct openssl_ssl_test_functions *SSL_test_functions(void); #endif -#endif __owur int SSL_free_buffers(SSL *ssl); __owur int SSL_alloc_buffers(SSL *ssl); diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index 6ae701dba0..28e3886169 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -269,6 +269,21 @@ #define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362 #define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363 #define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364 +#define SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH 232 +#define SSL_R_TLS_EXT_INVALID_SERVERNAME 319 +#define SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE 320 +#define SSL_R_TLS_SESSION_ID_TOO_LONG 300 +#define SSL_R_TLS_ALERT_BAD_CERTIFICATE 1042 +#define SSL_R_TLS_ALERT_BAD_RECORD_MAC 1020 +#define SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED 1045 +#define SSL_R_TLS_ALERT_CERTIFICATE_REVOKED 1044 +#define SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN 1046 +#define SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE 1030 +#define SSL_R_TLS_ALERT_HANDSHAKE_FAILURE 1040 +#define SSL_R_TLS_ALERT_ILLEGAL_PARAMETER 1047 +#define SSL_R_TLS_ALERT_NO_CERTIFICATE 1041 +#define SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE 1010 +#define SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE 1043 #define SSL_R_SSL_COMMAND_SECTION_EMPTY 117 #define SSL_R_SSL_COMMAND_SECTION_NOT_FOUND 125 #define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 @@ -311,23 +326,8 @@ #define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 #define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 #define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 -#define SSL_R_TLS_ALERT_BAD_CERTIFICATE 1042 -#define SSL_R_TLS_ALERT_BAD_RECORD_MAC 1020 -#define SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED 1045 -#define SSL_R_TLS_ALERT_CERTIFICATE_REVOKED 1044 -#define SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN 1046 -#define SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE 1030 -#define SSL_R_TLS_ALERT_HANDSHAKE_FAILURE 1040 -#define SSL_R_TLS_ALERT_ILLEGAL_PARAMETER 1047 -#define SSL_R_TLS_ALERT_NO_CERTIFICATE 1041 -#define SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE 1010 -#define SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE 1043 -#define SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH 232 -#define SSL_R_TLS_EXT_INVALID_SERVERNAME 319 -#define SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE 320 #define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157 -#define SSL_R_TLS_SESSION_ID_TOO_LONG 300 #define SSL_R_TOO_MANY_KEY_UPDATES 132 #define SSL_R_TOO_MANY_WARN_ALERTS 409 #define SSL_R_TOO_MUCH_EARLY_DATA 164 diff --git a/include/openssl/x509v3.h.in b/include/openssl/x509v3.h.in index 21def64b94..8e50d31144 100644 --- a/include/openssl/x509v3.h.in +++ b/include/openssl/x509v3.h.in @@ -933,7 +933,7 @@ DECLARE_ASN1_FUNCTIONS(IPAddressChoice) DECLARE_ASN1_FUNCTIONS(IPAddressFamily) /* - * API tag for elements of the ASIdentifier SEQUENCE. + * API tag for elements of the ASIdentifer SEQUENCE. */ #define V3_ASID_ASNUM 0 #define V3_ASID_RDI 1 diff --git a/ms/applink.c b/ms/applink.c index 242b0bed74..4777d2e361 100644 --- a/ms/applink.c +++ b/ms/applink.c @@ -103,14 +103,6 @@ static int app_fsetmod(FILE *fp, char mod) extern "C" { #endif -/* - * The AppLink table exposes the legacy CRT signatures used by ms/uplink.h. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) -#endif - __declspec(dllexport) void ** #if defined(__BORLANDC__) /* @@ -159,10 +151,6 @@ __declspec(dllexport) void ** return OPENSSL_ApplinkTable; } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/ms/uplink-ia64.pl b/ms/uplink-ia64.pl new file mode 100755 index 0000000000..757e77d29f --- /dev/null +++ b/ms/uplink-ia64.pl @@ -0,0 +1,60 @@ +#! /usr/bin/env perl +# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$output = pop and open STDOUT,">$output"; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}."); + +require "uplink-common.pl"; + +local $V=8; # max number of args uplink functions may accept... +my $loc0 = "r".(32+$V); +print <<___; +.text +.global OPENSSL_Uplink# +.type OPENSSL_Uplink#,\@function + +___ +for ($i=1;$i<=$N;$i++) { +print <<___; +.proc lazy$i# +lazy$i: + .prologue +{ .mii; .save ar.pfs,$loc0 + alloc loc0=ar.pfs,$V,3,2,0 + .save b0,loc1 + mov loc1=b0 + addl loc2=\@ltoff(OPENSSL_UplinkTable#),gp };; + .body +{ .mmi; ld8 out0=[loc2] + mov out1=$i };; +{ .mib; add loc2=8*$i,out0 + br.call.sptk.many b0=OPENSSL_Uplink# };; +{ .mmi; ld8 r31=[loc2];; + ld8 r30=[r31],8 };; +{ .mii; ld8 gp=[r31] + mov b6=r30 + mov b0=loc1 };; +{ .mib; mov ar.pfs=loc0 + br.many b6 };; +.endp lazy$i# + +___ +} +print <<___; +.data +.global OPENSSL_UplinkTable# +OPENSSL_UplinkTable: data8 $N // amount of following entries +___ +for ($i=1;$i<=$N;$i++) { print " data8 \@fptr(lazy$i#)\n"; } +print <<___; +.size OPENSSL_UplinkTable,.-OPENSSL_UplinkTable# +___ + +close STDOUT; diff --git a/ms/uplink.c b/ms/uplink.c index c2d1bef80a..56f525b7e4 100644 --- a/ms/uplink.c +++ b/ms/uplink.c @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#if defined(_WIN64) && !defined(UNICODE) +#if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE) #define UNICODE #endif #if defined(UNICODE) && !defined(_UNICODE) diff --git a/pkcs11-provider b/pkcs11-provider index 5dcc876263..64fc325ac0 160000 --- a/pkcs11-provider +++ b/pkcs11-provider @@ -1 +1 @@ -Subproject commit 5dcc876263c083d44944d84e6425497529f8ff54 +Subproject commit 64fc325ac0f91d03d76b3546df2998d3a38c525b diff --git a/providers/baseprov.c b/providers/baseprov.c index f517e5ae81..16d2f91bb1 100644 --- a/providers/baseprov.c +++ b/providers/baseprov.c @@ -29,6 +29,10 @@ static OSSL_FUNC_provider_gettable_params_fn base_gettable_params; static OSSL_FUNC_provider_get_params_fn base_get_params; static OSSL_FUNC_provider_query_operation_fn base_query; +/* Functions provided by the core */ +static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; +static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; + /* Parameters we provide to the core */ static const OSSL_PARAM base_param_types[] = { OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), @@ -135,13 +139,15 @@ int ossl_base_provider_init(const OSSL_CORE_HANDLE *handle, void **provctx) { OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; - OSSL_FUNC_core_get_params_fn *c_get_params = NULL; BIO_METHOD *corebiometh; if (!ossl_prov_bio_from_dispatch(in)) return 0; for (; in->function_id != 0; in++) { switch (in->function_id) { + case OSSL_FUNC_CORE_GETTABLE_PARAMS: + c_gettable_params = OSSL_FUNC_core_gettable_params(in); + break; case OSSL_FUNC_CORE_GET_PARAMS: c_get_params = OSSL_FUNC_core_get_params(in); break; diff --git a/providers/common/capabilities.c b/providers/common/capabilities.c index f461ec222a..b97d4d6bcd 100644 --- a/providers/common/capabilities.c +++ b/providers/common/capabilities.c @@ -281,7 +281,7 @@ static int tls_group_capability(OSSL_CALLBACK *cb, void *arg) /* --------------------------------------------------------------- */ -#if !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA) \ +#if !defined(OPENSSL_NO_ML_DSA) \ || (!defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2) && !defined(OPENSSL_NO_SM3)) typedef struct tls_sigalg_constants_st { @@ -297,18 +297,6 @@ static const TLS_SIGALG_CONSTANTS sigalg_constants_list[] = { { TLSEXT_SIGALG_mldsa44, 128, TLS1_3_VERSION, 0, -1, -1 }, { TLSEXT_SIGALG_mldsa65, 192, TLS1_3_VERSION, 0, -1, -1 }, { TLSEXT_SIGALG_mldsa87, 256, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_sha2_128s, 128, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_sha2_128f, 128, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_sha2_192s, 192, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_sha2_192f, 192, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_sha2_256s, 256, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_sha2_256f, 256, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_shake_128s, 128, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_shake_128f, 128, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_shake_192s, 192, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_shake_192f, 192, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_shake_256s, 256, TLS1_3_VERSION, 0, -1, -1 }, - { TLSEXT_SIGALG_slhdsa_shake_256f, 256, TLS1_3_VERSION, 0, -1, -1 }, { TLSEXT_SIGALG_sm2sig_sm3, 128, TLS1_3_VERSION, 0, -1, -1 }, }; @@ -341,22 +329,8 @@ static const OSSL_PARAM param_sigalg_list[][10] = { TLS_SIGALG_ENTRY("mldsa65", "ML-DSA-65", "2.16.840.1.101.3.4.3.18", 1), TLS_SIGALG_ENTRY("mldsa87", "ML-DSA-87", "2.16.840.1.101.3.4.3.19", 2), #endif -#ifndef OPENSSL_NO_SLH_DSA - TLS_SIGALG_ENTRY("slhdsa_sha2_128s", "SLH-DSA-SHA2-128s", "2.16.840.1.101.3.4.3.20", 3), - TLS_SIGALG_ENTRY("slhdsa_sha2_128f", "SLH-DSA-SHA2-128f", "2.16.840.1.101.3.4.3.21", 4), - TLS_SIGALG_ENTRY("slhdsa_sha2_192s", "SLH-DSA-SHA2-192s", "2.16.840.1.101.3.4.3.22", 5), - TLS_SIGALG_ENTRY("slhdsa_sha2_192f", "SLH-DSA-SHA2-192f", "2.16.840.1.101.3.4.3.23", 6), - TLS_SIGALG_ENTRY("slhdsa_sha2_256s", "SLH-DSA-SHA2-256s", "2.16.840.1.101.3.4.3.24", 7), - TLS_SIGALG_ENTRY("slhdsa_sha2_256f", "SLH-DSA-SHA2-256f", "2.16.840.1.101.3.4.3.25", 8), - TLS_SIGALG_ENTRY("slhdsa_shake_128s", "SLH-DSA-SHAKE-128s", "2.16.840.1.101.3.4.3.26", 9), - TLS_SIGALG_ENTRY("slhdsa_shake_128f", "SLH-DSA-SHAKE-128f", "2.16.840.1.101.3.4.3.27", 10), - TLS_SIGALG_ENTRY("slhdsa_shake_192s", "SLH-DSA-SHAKE-192s", "2.16.840.1.101.3.4.3.28", 11), - TLS_SIGALG_ENTRY("slhdsa_shake_192f", "SLH-DSA-SHAKE-192f", "2.16.840.1.101.3.4.3.29", 12), - TLS_SIGALG_ENTRY("slhdsa_shake_256s", "SLH-DSA-SHAKE-256s", "2.16.840.1.101.3.4.3.30", 13), - TLS_SIGALG_ENTRY("slhdsa_shake_256f", "SLH-DSA-SHAKE-256f", "2.16.840.1.101.3.4.3.31", 14), -#endif #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2) && !defined(OPENSSL_NO_SM3) - TLS_SIGALG_ENTRY("sm2sig_sm3", "SM2", "1.2.156.10197.1 501", 15), + TLS_SIGALG_ENTRY("sm2sig_sm3", "SM2", "1.2.156.10197.1 501", 3), #endif }; #endif diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 33e7edb454..7e3e189dd2 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -144,8 +144,6 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_X931_DIGEST), "invalid x931 digest" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_IN_ERROR_STATE), "in error state" }, - { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_IMMUTABLE_ONCE_SET), - "key immutable once set" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SETUP_FAILED), "key setup failed" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL), "key size too small" }, diff --git a/providers/defltprov.c b/providers/defltprov.c index 1f39b34d6e..c471cf8e7e 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -34,6 +34,10 @@ static OSSL_FUNC_provider_query_operation_fn deflt_query; #define ALGC(NAMES, FUNC, CHECK) { { NAMES, "provider=default", FUNC }, CHECK } #define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL) +/* Functions provided by the core */ +static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; +static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; + /* Parameters we provide to the core */ static const OSSL_PARAM deflt_param_types[] = { OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), @@ -795,7 +799,6 @@ int ossl_default_provider_init(const OSSL_CORE_HANDLE *handle, void **provctx) { OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; - OSSL_FUNC_core_get_params_fn *c_get_params = NULL; BIO_METHOD *corebiometh; if (!ossl_prov_bio_from_dispatch(in) @@ -803,6 +806,9 @@ int ossl_default_provider_init(const OSSL_CORE_HANDLE *handle, return 0; for (; in->function_id != 0; in++) { switch (in->function_id) { + case OSSL_FUNC_CORE_GETTABLE_PARAMS: + c_gettable_params = OSSL_FUNC_core_gettable_params(in); + break; case OSSL_FUNC_CORE_GET_PARAMS: c_get_params = OSSL_FUNC_core_get_params(in); break; diff --git a/providers/fips-sources.checksums b/providers/fips-sources.checksums index 598c3bb44d..527e124d76 100644 --- a/providers/fips-sources.checksums +++ b/providers/fips-sources.checksums @@ -270,7 +270,6 @@ ff65c82c56e341f47df03d0c74de7fb537de0e68a4fa23fa07a9fdb51c511f1c crypto/ml_dsa/ 3e0980e67842c4d8637fa449ac41e9d650c614c1074c29f1021605d229a4f73d crypto/ml_dsa/ml_dsa_params.c 10e37ab3ee09a45d99007665e073efb2b062c819f30af8694c6b0f411eb33822 crypto/ml_dsa/ml_dsa_poly.h 26be5266a9f1a33999a5a68c96cffc7932ba64521d9554dabe7397591611c852 crypto/ml_dsa/ml_dsa_sample.c -9e57d844f2acedb490b6e8f32e125240078ddab380a7faa533baa9c447dee262 crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc 2127303173eff12cb2b71f92179d10370b555c26e7a305e87ce7066580d57689 crypto/ml_dsa/ml_dsa_sign.c 5217ef237e21872205703b95577290c34898423466a465c7bd609b2eb4627964 crypto/ml_dsa/ml_dsa_sign.h e3ef4cf1598420c94eee4f53d13491ff0f9dc8cfb1fe1cacd3a1225e2073fa56 crypto/ml_dsa/ml_dsa_vector.h @@ -360,7 +359,6 @@ b7f1f4e69d41812dba39226aea0942fb2e3a638308c3130b0c83bb636a258ce6 crypto/sha/asm 82a84e6ae5ffe90e76530de560f6261c5004c23923fa9fd9aa2aae3852976426 crypto/sha/asm/keccak1600-s390x.pl e485942ed7f7bf1f376059ed2e5e194907348f44a4308dfc4bbc2d8be05fed99 crypto/sha/asm/keccak1600-x86_64.pl af173b53537e18453705a3843e0629334b37e8ca03483a2b164fd48252289da3 crypto/sha/asm/keccak1600p8-ppc.pl -d27078e0478f34536f596e037887ad673b05537d9cd4b79376e902774a4c8340 crypto/sha/asm/keccak1600x4-avx512vl.pl 3dd5e288f70b684d337f4054119935ab46af4042a40dffdca203868fe943bae0 crypto/sha/asm/sha1-586.pl 58378cb694b61022d70956ab344331d7577f9a26431acd00a60bed91229b29eb crypto/sha/asm/sha1-alpha.pl 8576b406e8596c8ac56a351a92175accfcf4121dd3dbffc59bae7d0ece0b0dab crypto/sha/asm/sha1-armv4-large.pl @@ -403,7 +401,6 @@ feb4283e1bb2a36f0a98d4cd7b43ac78c40b72efeab8d58b4f0aad8b65a1d2ba crypto/sha/asm f6021e6e5f4694579ba5a014e2aba44b6d436b2fd25c18ecd474a7383042b027 crypto/sha/sha256.c ed6049496d9786296d011a4582ffcfe0859a609b37f1f4ce57cee36136ee526c crypto/sha/sha3.c db0f16a4cb9c86f971b4defbee9dccd77345766f64efc45e0f1bc8d448bfb3e3 crypto/sha/sha3_encode.c -8def0b2e5996f2a2e187abcb7443e5e98edd4be0f71ff918a1b8c717cb97eb27 crypto/sha/sha3_x4_avx512vl.c 833e0990a4b8590a40990bfe1cfe59542ece6923fde37d3dd6faddfe1b9418fc crypto/sha/sha512.c 7b99b3c9fa26c5e58a56cbbb62b6e2bfe62542a662799f910387e76e5688a13a crypto/sha/sha_local.h dfd99e02830973ab349409ac6ba0ee901ba7736216030965bd7e5a54356abd7c crypto/slh_dsa/slh_adrs.c @@ -500,7 +497,7 @@ ee75ecd35b3ae90c51ace957ab7ce06de3c7d5064b97a878241ff65cc943a6db include/intern 3f476694478c1125574dfb2e75c4c0c0d04c7d3d763176686a4730028513fcd5 include/internal/rcu.h b6e33da6011b2b74d27e39f27cf98e6f123fe47826562b6479d0dbd5c758c4c2 include/internal/refcount.h f77c0844cc44bd92965647cd8cb6addb210f0300a8d1090da8c26e4382e87c2c include/internal/safe_math.h -17f6585bc81ad324d00aaacd558e0176dbe22cc7cbdb353c8c9072fa40000a58 include/internal/sha3.h +ea565ff98b36d3ae2d8eb709a52cba75720b30e2527cdfda3b90aa426291ac38 include/internal/sha3.h 8e672cc0620606b044f63b8446125f5233d64e3eea59df54c1fcca6bc90ba537 include/internal/sizes.h 188be736ff23a2202fe594e6d49a7ccf4c23a7baa86e2dac5d58360f21d9c986 include/internal/skey.h abf03dc8635f2925bdc2299feabe115f8d5d6eaa450b421172ded222872386ba include/internal/ssl3_cbc.h diff --git a/providers/fips.checksum b/providers/fips.checksum index 2c7bab5eab..b70425fb45 100644 --- a/providers/fips.checksum +++ b/providers/fips.checksum @@ -1 +1 @@ -864d3535e188440ca60b8268ce8137e0cffb870be990531fd9f68a23f0ffa898 providers/fips-sources.checksums +7e5428946b50e077e099dd7bd3891b854b37c623ede0cc8ace51c09b94871db7 providers/fips-sources.checksums diff --git a/providers/fips.module.sources b/providers/fips.module.sources index 5358458573..f9a12d7105 100644 --- a/providers/fips.module.sources +++ b/providers/fips.module.sources @@ -270,7 +270,6 @@ crypto/ml_dsa/ml_dsa_ntt.c crypto/ml_dsa/ml_dsa_params.c crypto/ml_dsa/ml_dsa_poly.h crypto/ml_dsa/ml_dsa_sample.c -crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc crypto/ml_dsa/ml_dsa_sign.c crypto/ml_dsa/ml_dsa_sign.h crypto/ml_dsa/ml_dsa_vector.h @@ -360,7 +359,6 @@ crypto/sha/asm/keccak1600-ppc64.pl crypto/sha/asm/keccak1600-s390x.pl crypto/sha/asm/keccak1600-x86_64.pl crypto/sha/asm/keccak1600p8-ppc.pl -crypto/sha/asm/keccak1600x4-avx512vl.pl crypto/sha/asm/sha1-586.pl crypto/sha/asm/sha1-alpha.pl crypto/sha/asm/sha1-armv4-large.pl @@ -403,7 +401,6 @@ crypto/sha/sha1dgst.c crypto/sha/sha256.c crypto/sha/sha3.c crypto/sha/sha3_encode.c -crypto/sha/sha3_x4_avx512vl.c crypto/sha/sha512.c crypto/sha/sha_local.h crypto/slh_dsa/slh_adrs.c @@ -663,24 +660,18 @@ providers/implementations/ciphers/cipher_aes_cbc_hmac_sha_etm.h providers/implementations/ciphers/cipher_aes_ccm.c providers/implementations/ciphers/cipher_aes_ccm.h providers/implementations/ciphers/cipher_aes_ccm_hw.c +providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc +providers/implementations/ciphers/cipher_aes_cfb.h +providers/implementations/ciphers/cipher_aes_cfb_hw.c +providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc providers/implementations/ciphers/cipher_aes_cts.inc providers/implementations/ciphers/cipher_aes_gcm.c providers/implementations/ciphers/cipher_aes_gcm.h providers/implementations/ciphers/cipher_aes_gcm_hw.c -providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.c -providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.c -providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.c -providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.c -providers/implementations/ciphers/cipher_aes_gcm_hw_rv32i.c -providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.c -providers/implementations/ciphers/cipher_aes_gcm_hw_t4.c -providers/implementations/ciphers/cipher_aes_hw_aesni.c -providers/implementations/ciphers/cipher_aes_hw_armv8.c -providers/implementations/ciphers/cipher_aes_hw_rv32i.c -providers/implementations/ciphers/cipher_aes_hw_rv64i.c -providers/implementations/ciphers/cipher_aes_hw_s390x.c -providers/implementations/ciphers/cipher_aes_hw_t4.c +providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc +providers/implementations/ciphers/cipher_aes_gcm_hw_vaes_avx512.inc providers/implementations/ciphers/cipher_aes_hw.c +providers/implementations/ciphers/cipher_aes_hw_aesni.inc providers/implementations/ciphers/cipher_aes_ocb.c providers/implementations/ciphers/cipher_aes_ocb.h providers/implementations/ciphers/cipher_aes_ocb.inc.in diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 5f331920ba..3292dce334 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -63,6 +63,7 @@ extern OSSL_FUNC_core_thread_start_fn *c_thread_start; */ /* Functions provided by the core */ +static OSSL_FUNC_core_gettable_params_fn *c_gettable_params; static OSSL_FUNC_core_get_params_fn *c_get_params; OSSL_FUNC_core_thread_start_fn *c_thread_start; static OSSL_FUNC_core_new_error_fn *c_new_error; @@ -839,6 +840,9 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, case OSSL_FUNC_CORE_GET_LIBCTX: set_func(c_get_libctx, OSSL_FUNC_core_get_libctx(in)); break; + case OSSL_FUNC_CORE_GETTABLE_PARAMS: + set_func(c_gettable_params, OSSL_FUNC_core_gettable_params(in)); + break; case OSSL_FUNC_CORE_GET_PARAMS: set_func(c_get_params, OSSL_FUNC_core_get_params(in)); break; diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c index 364fd0ef65..6024395aa0 100644 --- a/providers/fips/self_test.c +++ b/providers/fips/self_test.c @@ -344,7 +344,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, void *fips_global, bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb"); /* This section can be called on demand and that could race with deferred - * tests being executed in another thread, so we use helpers to get + * tests being executed in another thread, so we use use helpers to get * proper locking around this critical section */ if (SELF_TEST_lock_deferred(fips_global)) { diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c index f2d5c439d9..17f79b9d0c 100644 --- a/providers/fips/self_test_kats.c +++ b/providers/fips/self_test_kats.c @@ -213,7 +213,7 @@ err: return ret; } -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ >= 4 #define SENTINEL __attribute__((sentinel)) #endif diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info index 2460b0183d..dc43b8980c 100644 --- a/providers/implementations/ciphers/build.info +++ b/providers/implementations/ciphers/build.info @@ -103,12 +103,10 @@ SOURCE[$NULL_GOAL]=\ cipher_null.c SOURCE[$AES_GOAL]=\ - cipher_aes.c cipher_aes_hw.c cipher_aes_hw_aesni.c \ - cipher_aes_hw_armv8.c cipher_aes_hw_rv32i.c cipher_aes_hw_rv64i.c \ - cipher_aes_hw_s390x.c cipher_aes_hw_t4.c \ + cipher_aes.c cipher_aes_hw.c \ cipher_aes_xts.c cipher_aes_xts_hw.c \ + cipher_aes_cfb_hw.c \ cipher_aes_gcm.c cipher_aes_gcm_hw.c \ - cipher_aes_gcm_hw_ppc.c \ cipher_aes_ccm.c cipher_aes_ccm_hw.c \ cipher_aes_wrp.c \ cipher_aes_cbc_hmac_sha.c \ diff --git a/providers/implementations/ciphers/cipher_aes.c b/providers/implementations/ciphers/cipher_aes.c index 3638919aeb..3444888082 100644 --- a/providers/implementations/ciphers/cipher_aes.c +++ b/providers/implementations/ciphers/cipher_aes.c @@ -19,6 +19,7 @@ #include "cipher_aes.h" #include "prov/implementations.h" #include "prov/providercommon.h" +#include "cipher_aes_cfb.h" static OSSL_FUNC_cipher_freectx_fn aes_freectx; static OSSL_FUNC_cipher_dupctx_fn aes_dupctx; diff --git a/providers/implementations/ciphers/cipher_aes.h b/providers/implementations/ciphers/cipher_aes.h index 4e71678fd1..48235f32d8 100644 --- a/providers/implementations/ciphers/cipher_aes.h +++ b/providers/implementations/ciphers/cipher_aes.h @@ -53,51 +53,10 @@ typedef struct prov_aes_ctx_st { } PROV_AES_CTX; -/* Note that XTS, CCM and GCM modes are handled with separate abstractions - * so they are not listed here */ -enum aes_modes { - AES_MODE_ECB = 1, - AES_MODE_CBC, - AES_MODE_CFB128, - AES_MODE_CFB8, - AES_MODE_CFB1, - AES_MODE_OFB128, - AES_MODE_CTR, -}; - +#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128 const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ecb(size_t keybits); const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cbc(size_t keybits); -#define ossl_prov_cipher_hw_aes_cfb ossl_prov_cipher_hw_aes_cfb128 -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits); -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits); -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits); -#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128 const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ofb128(size_t keybits); const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ctr(size_t keybits); -int ossl_cipher_set_aes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen, - aes_set_encrypt_key_fn fn_set_key, aes_block128_f fn_block, - ecb128_f fn_ecb, cbc128_f fn_cbc, ctr128_f fn_ctr); - -int ossl_cipher_hw_aes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen); - -void ossl_cipher_aes_copyctx(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src); - -#if defined(AESNI_CAPABLE) -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aesni(enum aes_modes mode); -#elif defined(ARMv8_HWAES_CAPABLE) -const PROV_CIPHER_HW *ossl_prov_cipher_hw_arm(enum aes_modes mode); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 -const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv32i(enum aes_modes mode); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 -const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode); -#elif defined(S390X_aes_128_CAPABLE) -const PROV_CIPHER_HW *ossl_prov_cipher_hw_s390x(enum aes_modes mode, - size_t keybits); -#elif defined(SPARC_AES_CAPABLE) -const PROV_CIPHER_HW *ossl_prov_cipher_hw_t4(enum aes_modes mode); -#endif - #endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_H) */ diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c index 747a30f287..b1041b5550 100644 --- a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c +++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c @@ -176,7 +176,8 @@ static int aes_set_ctx_params(void *vctx, const OSSL_PARAM params[]) ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return 0; } - if (ctx->base.tlsversion == TLS1_VERSION) { + if (ctx->base.tlsversion == SSL3_VERSION + || ctx->base.tlsversion == TLS1_VERSION) { if (!ossl_assert(ctx->base.removetlsfixed >= AES_BLOCK_SIZE)) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return 0; diff --git a/providers/implementations/ciphers/cipher_aes_ccm.h b/providers/implementations/ciphers/cipher_aes_ccm.h index 9fe8ba2e07..6e4599fdbf 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm.h +++ b/providers/implementations/ciphers/cipher_aes_ccm.h @@ -48,27 +48,6 @@ typedef struct prov_aes_ccm_ctx_st { } ccm; } PROV_AES_CCM_CTX; -int ossl_cipher_set_ccm_aes_initkey(PROV_CCM_CTX *ctx, - const unsigned char *key, size_t keylen, - aes_set_encrypt_key_fn fn_set_key, aes_block128_f fn_block, - ccm128_f fn_ccm_enc, ccm128_f fn_ccm_dec); - const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keylen); -#if defined(AESNI_CAPABLE) -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_aesni(void); -#endif -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv32i(void); -#endif -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv64i(void); -#endif -#if defined(S390X_aes_128_CAPABLE) -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_s390x(size_t keybits); -#endif -#if defined(SPARC_AES_CAPABLE) -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_t4(void); -#endif - #endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CCM_H) */ diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw.c b/providers/implementations/ciphers/cipher_aes_ccm_hw.c index 6387157740..8bc7586adc 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm_hw.c +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw.c @@ -14,50 +14,37 @@ * non-internal use) in order to implement provider AES ciphers. */ #include "internal/deprecated.h" -#include + #include "cipher_aes_ccm.h" -int ossl_cipher_set_ccm_aes_initkey(PROV_CCM_CTX *ctx, - const unsigned char *key, size_t keylen, - aes_set_encrypt_key_fn fn_set_key, aes_block128_f fn_block, - ccm128_f fn_ccm_enc, ccm128_f fn_ccm_dec) -{ - PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; - AES_KEY *ks = &actx->ccm.ks.ks; - - int ret = fn_set_key(key, (int)(keylen * 8), ks); - if (ret < 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); - return 0; - } - CRYPTO_ccm128_init(&ctx->ccm_ctx, (unsigned int)ctx->m, - (unsigned int)ctx->l, ks, (block128_f)fn_block); - - ctx->str = ctx->enc ? fn_ccm_enc : fn_ccm_dec; +#define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec) \ + fn_set_enc_key(key, (int)(keylen * 8), &actx->ccm.ks.ks); \ + CRYPTO_ccm128_init(&ctx->ccm_ctx, (unsigned int)ctx->m, \ + (unsigned int)ctx->l, &actx->ccm.ks.ks, \ + (block128_f)fn_blk); \ + ctx->str = ctx->enc ? (ccm128_f)fn_ccm_enc : (ccm128_f)fn_ccm_dec; \ ctx->key_set = 1; - return 1; -} - static int ccm_generic_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, size_t keylen) { + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL); - } -#endif + AES_HW_CCM_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL); + } else +#endif /* HWAES_CAPABLE */ #ifdef VPAES_CAPABLE - if (VPAES_CAPABLE) { - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL); - } + if (VPAES_CAPABLE) { + AES_HW_CCM_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL); + } else #endif - - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_encrypt, NULL, NULL); + { + AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, AES_encrypt, NULL, NULL) + } + return 1; } static const PROV_CCM_HW aes_ccm = { @@ -69,21 +56,19 @@ static const PROV_CCM_HW aes_ccm = { ossl_ccm_generic_gettag }; +#if defined(S390X_aes_128_CAPABLE) +#include "cipher_aes_ccm_hw_s390x.inc" +#elif defined(AESNI_CAPABLE) +#include "cipher_aes_ccm_hw_aesni.inc" +#elif defined(SPARC_AES_CAPABLE) +#include "cipher_aes_ccm_hw_t4.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 +#include "cipher_aes_ccm_hw_rv64i.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 +#include "cipher_aes_ccm_hw_rv32i.inc" +#else const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits) { - const PROV_CCM_HW *aes_ccm_hw = NULL; -#if defined(AESNI_CAPABLE) - aes_ccm_hw = ossl_prov_aes_hw_ccm_aesni(); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 - aes_ccm_hw = ossl_prov_aes_hw_ccm_rv32i(); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 - aes_ccm_hw = ossl_prov_aes_hw_ccm_rv64i(); -#elif defined(S390X_aes_128_CAPABLE) - aes_ccm_hw = ossl_prov_aes_hw_ccm_s390x(keybits); -#elif defined(SPARC_AES_CAPABLE) - aes_ccm_hw = ossl_prov_aes_hw_ccm_t4(); -#endif - if (aes_ccm_hw != NULL) - return aes_ccm_hw; return &aes_ccm; } +#endif diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc new file mode 100644 index 0000000000..579e5a3d4f --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc @@ -0,0 +1,38 @@ +/* + * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI support for AES CCM. + * This file is included by cipher_aes_ccm_hw.c + */ + +static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(aesni_set_encrypt_key, aesni_encrypt, + aesni_ccm64_encrypt_blocks, + aesni_ccm64_decrypt_blocks); + return 1; +} + +static const PROV_CCM_HW aesni_ccm = { + ccm_aesni_initkey, + ossl_ccm_generic_setiv, + ossl_ccm_generic_setaad, + ossl_ccm_generic_auth_encrypt, + ossl_ccm_generic_auth_decrypt, + ossl_ccm_generic_gettag +}; + +const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits) +{ + return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_rv32i.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_rv32i.inc new file mode 100644 index 0000000000..7cfe0fc4ce --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_rv32i.inc @@ -0,0 +1,60 @@ +/* + * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * RISC-V 32 ZKND ZKNE support for AES CCM. + * This file is included by cipher_aes_ccm_hw.c + */ + +static int ccm_rv32i_zknd_zkne_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt, + NULL, NULL); + return 1; +} + +static int ccm_rv32i_zbkb_zknd_zkne_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt, + NULL, NULL); + return 1; +} + +static const PROV_CCM_HW rv32i_zknd_zkne_ccm = { + ccm_rv32i_zknd_zkne_initkey, + ossl_ccm_generic_setiv, + ossl_ccm_generic_setaad, + ossl_ccm_generic_auth_encrypt, + ossl_ccm_generic_auth_decrypt, + ossl_ccm_generic_gettag +}; + +static const PROV_CCM_HW rv32i_zbkb_zknd_zkne_ccm = { + ccm_rv32i_zbkb_zknd_zkne_initkey, + ossl_ccm_generic_setiv, + ossl_ccm_generic_setaad, + ossl_ccm_generic_auth_encrypt, + ossl_ccm_generic_auth_decrypt, + ossl_ccm_generic_gettag +}; + +const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits) +{ + if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) + return &rv32i_zbkb_zknd_zkne_ccm; + if (RISCV_HAS_ZKND_AND_ZKNE()) + return &rv32i_zknd_zkne_ccm; + return &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_rv64i.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_rv64i.inc new file mode 100644 index 0000000000..f2353bb3b8 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_rv64i.inc @@ -0,0 +1,71 @@ +/* + * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * RISC-V 64 ZKND ZKNE support for AES CCM. + * This file is included by cipher_aes_ccm_hw.c + */ + +static int ccm_rv64i_zknd_zkne_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, + NULL, NULL); + return 1; +} + +static const PROV_CCM_HW rv64i_zknd_zkne_ccm = { + ccm_rv64i_zknd_zkne_initkey, + ossl_ccm_generic_setiv, + ossl_ccm_generic_setaad, + ossl_ccm_generic_auth_encrypt, + ossl_ccm_generic_auth_decrypt, + ossl_ccm_generic_gettag +}; + +/*- + * RISC-V RV64 ZVKNED support for AES CCM. + * This file is included by cipher_aes_ccm_hw.c + */ + +static int ccm_rv64i_zvkned_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + /* Zvkned only supports 128 and 256 bit keys for key schedule generation. */ + if (keylen * 8 == 128 || keylen * 8 == 256) { + AES_HW_CCM_SET_KEY_FN(rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, + NULL, NULL); + } else { + AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL) + } + return 1; +} + +static const PROV_CCM_HW rv64i_zvkned_ccm = { + ccm_rv64i_zvkned_initkey, + ossl_ccm_generic_setiv, + ossl_ccm_generic_setaad, + ossl_ccm_generic_auth_encrypt, + ossl_ccm_generic_auth_decrypt, + ossl_ccm_generic_gettag +}; + +const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits) +{ + if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) + return &rv64i_zvkned_ccm; + else if (RISCV_HAS_ZKND_AND_ZKNE()) + return &rv64i_zknd_zkne_ccm; + else + return &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc new file mode 100644 index 0000000000..7253f03a7e --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc @@ -0,0 +1,268 @@ +/* + * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * S390X support for AES CCM. + * This file is included by cipher_aes_ccm_hw.c + */ + +#define S390X_CCM_AAD_FLAG 0x40 + +static int s390x_aes_ccm_initkey(PROV_CCM_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + sctx->ccm.s390x.fc = S390X_AES_FC(keylen); + memcpy(&sctx->ccm.s390x.kmac.k, key, keylen); + /* Store encoded m and l. */ + sctx->ccm.s390x.nonce.b[0] = ((ctx->l - 1) & 0x7) + | (((ctx->m - 2) >> 1) & 0x7) << 3; + memset(sctx->ccm.s390x.nonce.b + 1, 0, sizeof(sctx->ccm.s390x.nonce.b)); + sctx->ccm.s390x.blocks = 0; + ctx->key_set = 1; + return 1; +} + +static int s390x_aes_ccm_setiv(PROV_CCM_CTX *ctx, + const unsigned char *nonce, size_t noncelen, + size_t mlen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + sctx->ccm.s390x.nonce.b[0] &= ~S390X_CCM_AAD_FLAG; + sctx->ccm.s390x.nonce.g[1] = mlen; + memcpy(sctx->ccm.s390x.nonce.b + 1, nonce, 15 - ctx->l); + return 1; +} + +/*- + * Process additional authenticated data. Code is big-endian. + */ +static int s390x_aes_ccm_setaad(PROV_CCM_CTX *ctx, + const unsigned char *aad, size_t alen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + unsigned char *ptr; + int i, rem; + + if (!alen) + return 1; + + sctx->ccm.s390x.nonce.b[0] |= S390X_CCM_AAD_FLAG; + + /* Suppress 'type-punned pointer dereference' warning. */ + ptr = sctx->ccm.s390x.buf.b; + + if (alen < ((1 << 16) - (1 << 8))) { + *(uint16_t *)ptr = alen; + i = 2; + } else if (sizeof(alen) == 8 + && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { + *(uint16_t *)ptr = 0xffff; + *(uint64_t *)(ptr + 2) = alen; + i = 10; + } else { + *(uint16_t *)ptr = 0xfffe; + *(uint32_t *)(ptr + 2) = alen; + i = 6; + } + + while (i < 16 && alen) { + sctx->ccm.s390x.buf.b[i] = *aad; + ++aad; + --alen; + ++i; + } + while (i < 16) { + sctx->ccm.s390x.buf.b[i] = 0; + ++i; + } + + sctx->ccm.s390x.kmac.icv.g[0] = 0; + sctx->ccm.s390x.kmac.icv.g[1] = 0; + s390x_kmac(sctx->ccm.s390x.nonce.b, 32, sctx->ccm.s390x.fc, + &sctx->ccm.s390x.kmac); + sctx->ccm.s390x.blocks += 2; + + rem = alen & 0xf; + alen &= ~(size_t)0xf; + if (alen) { + s390x_kmac(aad, alen, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); + sctx->ccm.s390x.blocks += alen >> 4; + aad += alen; + } + if (rem) { + for (i = 0; i < rem; i++) + sctx->ccm.s390x.kmac.icv.b[i] ^= aad[i]; + + s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, + sctx->ccm.s390x.kmac.icv.b, sctx->ccm.s390x.fc, + sctx->ccm.s390x.kmac.k); + sctx->ccm.s390x.blocks++; + } + return 1; +} + +/*- + * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for + * success. + */ +static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len, int enc) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + size_t n, rem; + unsigned int i, l, num; + unsigned char flags; + + flags = sctx->ccm.s390x.nonce.b[0]; + if (!(flags & S390X_CCM_AAD_FLAG)) { + s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.kmac.icv.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + sctx->ccm.s390x.blocks++; + } + l = flags & 0x7; + sctx->ccm.s390x.nonce.b[0] = l; + + /*- + * Reconstruct length from encoded length field + * and initialize it with counter value. + */ + n = 0; + for (i = 15 - l; i < 15; i++) { + n |= sctx->ccm.s390x.nonce.b[i]; + sctx->ccm.s390x.nonce.b[i] = 0; + n <<= 8; + } + n |= sctx->ccm.s390x.nonce.b[15]; + sctx->ccm.s390x.nonce.b[15] = 1; + + if (n != len) + return 0; /* length mismatch */ + + if (enc) { + /* Two operations per block plus one for tag encryption */ + sctx->ccm.s390x.blocks += (((len + 15) >> 4) << 1) + 1; + if (sctx->ccm.s390x.blocks > (1ULL << 61)) + return 0; /* too much data */ + } + + num = 0; + rem = len & 0xf; + len &= ~(size_t)0xf; + + if (enc) { + /* mac-then-encrypt */ + if (len) + s390x_kmac(in, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); + if (rem) { + for (i = 0; i < rem; i++) + sctx->ccm.s390x.kmac.icv.b[i] ^= in[len + i]; + + s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, + sctx->ccm.s390x.kmac.icv.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + } + + CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks, + sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b, + &num, (ctr128_f)AES_ctr32_encrypt); + } else { + /* decrypt-then-mac */ + CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks, + sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b, + &num, (ctr128_f)AES_ctr32_encrypt); + + if (len) + s390x_kmac(out, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); + if (rem) { + for (i = 0; i < rem; i++) + sctx->ccm.s390x.kmac.icv.b[i] ^= out[len + i]; + + s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, + sctx->ccm.s390x.kmac.icv.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + } + } + /* encrypt tag */ + for (i = 15 - l; i < 16; i++) + sctx->ccm.s390x.nonce.b[i] = 0; + + s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.buf.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + sctx->ccm.s390x.kmac.icv.g[0] ^= sctx->ccm.s390x.buf.g[0]; + sctx->ccm.s390x.kmac.icv.g[1] ^= sctx->ccm.s390x.buf.g[1]; + + sctx->ccm.s390x.nonce.b[0] = flags; /* restore flags field */ + return 1; +} + + +static int s390x_aes_ccm_gettag(PROV_CCM_CTX *ctx, + unsigned char *tag, size_t tlen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + if (tlen > ctx->m) + return 0; + memcpy(tag, sctx->ccm.s390x.kmac.icv.b, tlen); + return 1; +} + +static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *tag, size_t taglen) +{ + int rv; + + rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 1); + if (rv && tag != NULL) + rv = s390x_aes_ccm_gettag(ctx, tag, taglen); + return rv; +} + +static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *expected_tag, + size_t taglen) +{ + int rv = 0; + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 0); + if (rv) { + if (CRYPTO_memcmp(sctx->ccm.s390x.kmac.icv.b, expected_tag, ctx->m) != 0) + rv = 0; + } + if (rv == 0) + OPENSSL_cleanse(out, len); + return rv; +} + +static const PROV_CCM_HW s390x_aes_ccm = { + s390x_aes_ccm_initkey, + s390x_aes_ccm_setiv, + s390x_aes_ccm_setaad, + s390x_aes_ccm_auth_encrypt, + s390x_aes_ccm_auth_decrypt, + s390x_aes_ccm_gettag +}; + +const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits) +{ + if ((keybits == 128 && S390X_aes_128_ccm_CAPABLE) + || (keybits == 192 && S390X_aes_192_ccm_CAPABLE) + || (keybits == 256 && S390X_aes_256_ccm_CAPABLE)) + return &s390x_aes_ccm; + return &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc new file mode 100644 index 0000000000..a676d411b5 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc @@ -0,0 +1,36 @@ +/* + * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Fujitsu SPARC64 X support for AES CCM. + * This file is included by cipher_aes_ccm_hw.c + */ + +static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL); + return 1; +} + +static const PROV_CCM_HW t4_aes_ccm = { + ccm_t4_aes_initkey, + ossl_ccm_generic_setiv, + ossl_ccm_generic_setaad, + ossl_ccm_generic_auth_encrypt, + ossl_ccm_generic_auth_decrypt, + ossl_ccm_generic_gettag +}; + +const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits) +{ + return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_cfb.h b/providers/implementations/ciphers/cipher_aes_cfb.h new file mode 100644 index 0000000000..416ba585fc --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cfb.h @@ -0,0 +1,21 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CFB_H) +#define OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CFB_H + +#include "prov/ciphercommon.h" + +#define ossl_prov_cipher_hw_aes_cfb ossl_prov_cipher_hw_aes_cfb128 + +const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits); +const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits); +const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits); + +#endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CFB_H) */ diff --git a/providers/implementations/ciphers/cipher_aes_cfb_hw.c b/providers/implementations/ciphers/cipher_aes_cfb_hw.c new file mode 100644 index 0000000000..a0399bcdc2 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cfb_hw.c @@ -0,0 +1,98 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file uses the low level AES functions (which are deprecated for + * non-internal use) in order to implement provider AES ciphers. + */ +#include "internal/deprecated.h" + +#include +#include "cipher_aes.h" +#include "cipher_aes_cfb.h" + +static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)HWAES_encrypt; + dat->stream.cbc = NULL; + } else { +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)vpaes_encrypt; + dat->stream.cbc = NULL; + } else { +#endif + { + ret = AES_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.cbc = NULL; + } +#ifdef VPAES_CAPABLE + } +#endif +#ifdef HWAES_CAPABLE + } +#endif + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aes_copyctx, PROV_AES_CTX) + +#define PROV_CIPHER_HW_aes_mode(mode) \ + static const PROV_CIPHER_HW aes_##mode = { \ + cipher_hw_aes_initkey, \ + ossl_cipher_hw_generic_##mode, \ + cipher_hw_aes_copyctx \ + }; \ + PROV_CIPHER_HW_declare(mode) \ + const PROV_CIPHER_HW * \ + ossl_prov_cipher_hw_aes_##mode(size_t keybits) \ + { \ + PROV_CIPHER_HW_select(mode) return &aes_##mode; \ + } + +#if defined(AESNI_CAPABLE) +#include "cipher_aes_cfb_hw_aesni.inc" +#elif defined(SPARC_AES_CAPABLE) +#include "cipher_aes_hw_t4.inc" +#elif defined(S390X_aes_128_CAPABLE) +#include "cipher_aes_cfb_hw_s390x.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 +#include "cipher_aes_hw_rv64i.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 +#include "cipher_aes_hw_rv32i.inc" +#elif defined(ARMv8_HWAES_CAPABLE) +#include "cipher_aes_hw_armv8.inc" +#else +/* The generic case */ +#define PROV_CIPHER_HW_declare(mode) +#define PROV_CIPHER_HW_select(mode) +#endif + +PROV_CIPHER_HW_aes_mode(cfb128) + PROV_CIPHER_HW_aes_mode(cfb1) + PROV_CIPHER_HW_aes_mode(cfb8) diff --git a/providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc new file mode 100644 index 0000000000..eb8e0164ac --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc @@ -0,0 +1,101 @@ +/* + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI and VAES support for AES CFB mode. + * This file is included by cipher_aes_cfb_hw.c + */ + +#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) + #define cipher_hw_vaes_cfb128 aes_cfb128_vaes_encdec_wrapper +#else + #define cipher_hw_vaes_cfb128 ossl_cipher_hw_generic_cfb128 + int ossl_aes_cfb128_vaes_eligible() { + return 0; + } +#endif +#define cipher_hw_vaes_cfb8 ossl_cipher_hw_generic_cfb8 +#define cipher_hw_vaes_cfb1 ossl_cipher_hw_generic_cfb1 + +#define cipher_hw_aesni_cfb128 ossl_cipher_hw_generic_cfb128 +#define cipher_hw_aesni_cfb8 ossl_cipher_hw_generic_cfb8 +#define cipher_hw_aesni_cfb1 ossl_cipher_hw_generic_cfb1 + +static int ossl_aes_cfb8_vaes_eligible(void) { return 0; } +static int ossl_aes_cfb1_vaes_eligible(void) { return 0; } + +#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) +/* active in 64-bit builds when AES-NI, AVX512F, and VAES are detected */ +static int aes_cfb128_vaes_encdec_wrapper( + PROV_CIPHER_CTX* dat, + unsigned char *out, + const unsigned char *in, + size_t len) +{ + ossl_ssize_t num; + + num = (ossl_ssize_t)dat->num; + + if (num < 0) { + /* behavior from CRYPTO_cfb128_encrypt */ + dat->num = -1; + return 1; + } + + if (dat->enc) + ossl_aes_cfb128_vaes_enc(in, out, len, dat->ks, dat->iv, &num); + else + ossl_aes_cfb128_vaes_dec(in, out, len, dat->ks, dat->iv, &num); + + dat->num = (int)num; + + return 1; +} +#endif + +/* generates AES round keys for AES-NI and VAES implementations */ +static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + ret = aesni_set_encrypt_key(key, (int)(keylen * 8), ks); + + dat->block = (block128_f) aesni_encrypt; + dat->stream.cbc = NULL; + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW aesni_##mode = { \ + cipher_hw_aesni_initkey, \ + cipher_hw_aesni_##mode, \ + cipher_hw_aes_copyctx \ +}; \ +static const PROV_CIPHER_HW vaes_##mode = { \ + cipher_hw_aesni_initkey, \ + cipher_hw_vaes_##mode, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (AESNI_CAPABLE) { \ + if (ossl_aes_##mode##_vaes_eligible()) \ + return &vaes_##mode; \ + return &aesni_##mode; \ +} diff --git a/providers/implementations/ciphers/cipher_aes_cfb_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_cfb_hw_s390x.inc new file mode 100644 index 0000000000..113c1de6a9 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cfb_hw_s390x.inc @@ -0,0 +1,122 @@ +/* + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * IBM S390X support for AES mode cfb. + * This file is included by cipher_aes_cfb_hw.c + */ + +#include "arch/s390x_arch.h" + +#include + +#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey +#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1 + +#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE +#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE +#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE + +static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + adat->plat.s390x.fc = S390X_AES_FC(keylen); + adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */ + memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); + return 1; +} + +static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; + int n = dat->num; + int rem; + unsigned char tmp; + + memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); + while (n && len) { + tmp = *in; + *out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; + adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier, + &adat->plat.s390x.param.kmo_kmf); + + out += len; + in += len; + } + + if (rem) { + s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, + adat->plat.s390x.param.kmo_kmf.cv, + S390X_AES_FC(dat->keylen), + adat->plat.s390x.param.kmo_kmf.k); + + while (rem--) { + tmp = in[n]; + out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; + adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp; + ++n; + } + } + + memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); + dat->num = n; + return 1; +} + +static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + adat->plat.s390x.fc = S390X_AES_FC(keylen); + adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */ + memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); + return 1; +} + +static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; + + memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); + s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier, + &adat->plat.s390x.param.kmo_kmf); + memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW s390x_aes_##mode = { \ + s390x_aes_##mode##_initkey, \ + s390x_aes_##mode##_cipher_hw, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \ + || (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \ + || (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \ + return &s390x_aes_##mode; + diff --git a/providers/implementations/ciphers/cipher_aes_gcm.h b/providers/implementations/ciphers/cipher_aes_gcm.h index b041248b3c..33819705de 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm.h +++ b/providers/implementations/ciphers/cipher_aes_gcm.h @@ -45,34 +45,6 @@ typedef struct prov_aes_gcm_ctx_st { } plat; } PROV_AES_GCM_CTX; -int ossl_aes_gcm_hw_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen, aes_set_encrypt_key_fn fn_set_key, - aes_block128_f fn_block, ctr128_f fn_ctr); - -int ossl_generic_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, - const unsigned char *in, size_t len, unsigned char *out); - const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits); -#if defined(AESNI_CAPABLE) -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_aesni(void); -#endif -#if defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM) -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_armv8(void); -#endif -#if defined(PPC_AES_GCM_CAPABLE) && defined(_ARCH_PPC64) -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_ppc(size_t keybits); -#endif -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv32i(void); -#endif -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv64i(void); -#endif -#if defined(S390X_aes_128_CAPABLE) -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_s390x(size_t keybits); -#endif -#if defined(SPARC_AES_CAPABLE) -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_t4(void); -#endif #endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_GCM_H) */ diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_hw.c index bbb7e21c31..d2b7437cde 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw.c @@ -14,71 +14,52 @@ * non-internal use) in order to implement provider AES ciphers. */ #include "internal/deprecated.h" -#include + #include "cipher_aes_gcm.h" -int ossl_aes_gcm_hw_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen, aes_set_encrypt_key_fn fn_set_key, - aes_block128_f fn_block, ctr128_f fn_ctr) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - AES_KEY *ks = &actx->ks.ks; - - int ret = fn_set_key(key, (int)(keylen * 8), ks); - if (ret < 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); - return 0; - } - - CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); - ctx->ctr = fn_ctr; - ctx->key_set = 1; - - return 1; -} - static int aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, size_t keylen) { + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { #ifdef HWAES_ctr32_encrypt_blocks - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, HWAES_set_encrypt_key, - HWAES_encrypt, HWAES_ctr32_encrypt_blocks); + GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, + HWAES_ctr32_encrypt_blocks); #else - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, HWAES_set_encrypt_key, - HWAES_encrypt, NULL); + GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, NULL); #endif /* HWAES_ctr32_encrypt_blocks */ } else #endif /* HWAES_CAPABLE */ #ifdef BSAES_CAPABLE if (BSAES_CAPABLE) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, AES_set_encrypt_key, - AES_encrypt, (ctr128_f)ossl_bsaes_ctr32_encrypt_blocks); + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, + ossl_bsaes_ctr32_encrypt_blocks); } else #endif /* BSAES_CAPABLE */ #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, vpaes_set_encrypt_key, - vpaes_encrypt, NULL); + GCM_HW_SET_KEY_CTR_FN(ks, vpaes_set_encrypt_key, vpaes_encrypt, NULL); } else #endif /* VPAES_CAPABLE */ { #ifdef AES_CTR_ASM - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, AES_set_encrypt_key, - AES_encrypt, (ctr128_f)AES_ctr32_encrypt); + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, + AES_ctr32_encrypt); #else - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, AES_set_encrypt_key, - AES_encrypt, NULL); + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, NULL); #endif /* AES_CTR_ASM */ } + return 1; } -int ossl_generic_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, - const unsigned char *in, size_t len, unsigned char *out) +static int generic_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, + size_t len, unsigned char *out) { if (ctx->enc) { if (ctx->ctr != NULL) { @@ -146,33 +127,28 @@ static const PROV_GCM_HW aes_gcm = { aes_gcm_initkey, ossl_gcm_setiv, ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, + generic_aes_gcm_cipher_update, ossl_gcm_cipher_final, ossl_gcm_one_shot }; +#if defined(S390X_aes_128_CAPABLE) +#include "cipher_aes_gcm_hw_s390x.inc" +#elif defined(AESNI_CAPABLE) +#include "cipher_aes_gcm_hw_aesni.inc" +#elif defined(SPARC_AES_CAPABLE) +#include "cipher_aes_gcm_hw_t4.inc" +#elif defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM) +#include "cipher_aes_gcm_hw_armv8.inc" +#elif defined(PPC_AES_GCM_CAPABLE) && defined(_ARCH_PPC64) +#include "cipher_aes_gcm_hw_ppc.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 +#include "cipher_aes_gcm_hw_rv64i.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 +#include "cipher_aes_gcm_hw_rv32i.inc" +#else const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) { - const PROV_GCM_HW *aes_gcm_hw = NULL; - -#if defined(AESNI_CAPABLE) - aes_gcm_hw = ossl_prov_aes_hw_gcm_aesni(); -#elif defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM) - aes_gcm_hw = ossl_prov_aes_hw_gcm_armv8(); -#elif defined(PPC_AES_GCM_CAPABLE) && defined(_ARCH_PPC64) - aes_gcm_hw = ossl_prov_aes_hw_gcm_ppc(keybits); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 - aes_gcm_hw = ossl_prov_aes_hw_gcm_rv32i(); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 - aes_gcm_hw = ossl_prov_aes_hw_gcm_rv64i(); -#elif defined(S390X_aes_128_CAPABLE) - aes_gcm_hw = ossl_prov_aes_hw_gcm_s390x(keybits); -#elif defined(SPARC_AES_CAPABLE) - aes_gcm_hw = ossl_prov_aes_hw_gcm_t4(); -#endif - - if (aes_gcm_hw == NULL) - aes_gcm_hw = &aes_gcm; - - return aes_gcm_hw; + return &aes_gcm; } +#endif diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc new file mode 100644 index 0000000000..92f41b8cd6 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc @@ -0,0 +1,47 @@ +/* + * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI support for AES GCM. + * This file is included by cipher_aes_gcm_hw.c + */ + +static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + GCM_HW_SET_KEY_CTR_FN(ks, aesni_set_encrypt_key, aesni_encrypt, + aesni_ctr32_encrypt_blocks); + return 1; +} + +static const PROV_GCM_HW aesni_gcm = { + aesni_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +#include "cipher_aes_gcm_hw_vaes_avx512.inc" + +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) +{ +#ifdef VAES_GCM_ENABLED + if (ossl_vaes_vpclmulqdq_capable()) + return &vaes_gcm; + else +#endif + if (AESNI_CAPABLE) + return &aesni_gcm; + else + return &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc new file mode 100644 index 0000000000..42a305a00d --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc @@ -0,0 +1,108 @@ +/* + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Crypto extension support for AES GCM. + * This file is included by cipher_aes_gcm_hw.c + */ + +size_t armv8_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], uint64_t *Xi) +{ + AES_KEY *aes_key = (AES_KEY *)key; + size_t align_bytes = len - len % 16; + + switch(aes_key->rounds) { + case 10: + if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { + unroll8_eor3_aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } else { + aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } + break; + case 12: + if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { + unroll8_eor3_aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } else { + aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } + break; + case 14: + if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { + unroll8_eor3_aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } else { + aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } + break; + } + return align_bytes; +} + +size_t armv8_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], uint64_t *Xi) +{ + AES_KEY *aes_key = (AES_KEY *)key; + size_t align_bytes = len - len % 16; + + switch(aes_key->rounds) { + case 10: + if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { + unroll8_eor3_aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } else { + aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } + break; + case 12: + if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { + unroll8_eor3_aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } else { + aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } + break; + case 14: + if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { + unroll8_eor3_aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } else { + aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); + } + break; + } + return align_bytes; +} + +static int armv8_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + if (AES_UNROLL12_EOR3_CAPABLE) { + GCM_HW_SET_KEY_CTR_FN(ks, aes_v8_set_encrypt_key, aes_v8_encrypt, + aes_v8_ctr32_encrypt_blocks_unroll12_eor3); + } else { + GCM_HW_SET_KEY_CTR_FN(ks, aes_v8_set_encrypt_key, aes_v8_encrypt, + aes_v8_ctr32_encrypt_blocks); + } + return 1; +} + + +static const PROV_GCM_HW armv8_aes_gcm = { + armv8_aes_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) +{ + return AES_PMULL_CAPABLE ? &armv8_aes_gcm : &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.c b/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc similarity index 69% rename from providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.c rename to providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc index c5d8d27c94..4d1238a744 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc @@ -9,23 +9,23 @@ /*- * PPC support for AES GCM. - * This file is used by cipher_aes_gcm_hw.c + * This file is included by cipher_aes_gcm_hw.c */ -#include "internal/deprecated.h" -#include "cipher_aes_gcm.h" - -#if defined(PPC_AES_GCM_CAPABLE) && defined(_ARCH_PPC64) static int aes_ppc_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) + size_t keylen) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, aes_p8_set_encrypt_key, - aes_p8_encrypt, aes_p8_ctr32_encrypt_blocks); + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + GCM_HW_SET_KEY_CTR_FN(ks, aes_p8_set_encrypt_key, aes_p8_encrypt, + aes_p8_ctr32_encrypt_blocks); + return 1; } static inline uint32_t UTO32(unsigned char *buf) { - return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]); + return ((uint32_t) buf[0] << 24) | ((uint32_t) buf[1] << 16) | ((uint32_t) buf[2] << 8) | ((uint32_t) buf[3]); } static inline uint32_t add32TOU(unsigned char buf[4], uint32_t n) @@ -34,15 +34,15 @@ static inline uint32_t add32TOU(unsigned char buf[4], uint32_t n) r = UTO32(buf); r += n; - buf[0] = (unsigned char)(r >> 24) & 0xFF; - buf[1] = (unsigned char)(r >> 16) & 0xFF; - buf[2] = (unsigned char)(r >> 8) & 0xFF; - buf[3] = (unsigned char)r & 0xFF; + buf[0] = (unsigned char) (r >> 24) & 0xFF; + buf[1] = (unsigned char) (r >> 16) & 0xFF; + buf[2] = (unsigned char) (r >> 8) & 0xFF; + buf[3] = (unsigned char) r & 0xFF; return r; } static size_t ppc_aes_gcm_crypt(const unsigned char *in, unsigned char *out, size_t len, - const void *key, unsigned char ivec[16], uint64_t *Xi, int encrypt) + const void *key, unsigned char ivec[16], uint64_t *Xi, int encrypt) { size_t s = 0; size_t ndone = 0; @@ -55,7 +55,7 @@ static size_t ppc_aes_gcm_crypt(const unsigned char *in, unsigned char *out, siz memcpy(ctr_saved, ivec, 12); while (nb) { - blocks_unused = (uint64_t)0xffffffffU + 1 - (uint64_t)UTO32(ivec + 12); + blocks_unused = (uint64_t) 0xffffffffU + 1 - (uint64_t) UTO32 (ivec + 12); if (nb > blocks_unused) { len = blocks_unused * 16; nb -= blocks_unused; @@ -71,7 +71,7 @@ static size_t ppc_aes_gcm_crypt(const unsigned char *in, unsigned char *out, siz : ppc_aes_gcm_decrypt(in, out, len, key, ivec, Xi); /* add counter to ivec */ - add32TOU(ivec + 12, (uint32_t)next_ctr); + add32TOU(ivec + 12, (uint32_t) next_ctr); if (ctr_reset) { ctr_reset = 0; in += len; @@ -85,7 +85,7 @@ static size_t ppc_aes_gcm_crypt(const unsigned char *in, unsigned char *out, siz } static int ppc_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, - size_t len, unsigned char *out) + size_t len, unsigned char *out) { if (ctx->enc) { if (ctx->ctr != NULL) { @@ -98,14 +98,14 @@ static int ppc_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, return 0; bulk = ppc_aes_gcm_crypt(in + res, out + res, len - res, - ctx->gcm.key, - ctx->gcm.Yi.c, ctx->gcm.Xi.u, 1); + ctx->gcm.key, + ctx->gcm.Yi.c, ctx->gcm.Xi.u, 1); ctx->gcm.len.u[1] += bulk; bulk += res; } if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk, - len - bulk, ctx->ctr)) + len - bulk, ctx->ctr)) return 0; } else { if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len)) @@ -122,14 +122,14 @@ static int ppc_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, return 0; bulk = ppc_aes_gcm_crypt(in + res, out + res, len - res, - ctx->gcm.key, - ctx->gcm.Yi.c, ctx->gcm.Xi.u, 0); + ctx->gcm.key, + ctx->gcm.Yi.c, ctx->gcm.Xi.u, 0); ctx->gcm.len.u[1] += bulk; bulk += res; } if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk, - len - bulk, ctx->ctr)) + len - bulk, ctx->ctr)) return 0; } else { if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len)) @@ -148,9 +148,8 @@ static const PROV_GCM_HW aes_ppc_gcm = { ossl_gcm_one_shot }; -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_ppc(size_t keybits) +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) { - return PPC_AES_GCM_CAPABLE ? &aes_ppc_gcm : NULL; + return PPC_AES_GCM_CAPABLE ? &aes_ppc_gcm : &aes_gcm; } -#endif diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_rv32i.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_rv32i.inc new file mode 100644 index 0000000000..bf3f98df16 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_rv32i.inc @@ -0,0 +1,63 @@ +/* + * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * RISC-V 32 ZKND ZKNE support for AES GCM. + * This file is included by cipher_aes_gcm_hw.c + */ + +static int rv32i_zknd_zkne_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + GCM_HW_SET_KEY_CTR_FN(ks, rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt, + NULL); + return 1; +} + +static int rv32i_zbkb_zknd_zkne_gcm_initkey(PROV_GCM_CTX *ctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + GCM_HW_SET_KEY_CTR_FN(ks, rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt, + NULL); + return 1; +} + +static const PROV_GCM_HW rv32i_zknd_zkne_gcm = { + rv32i_zknd_zkne_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +static const PROV_GCM_HW rv32i_zbkb_zknd_zkne_gcm = { + rv32i_zbkb_zknd_zkne_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) +{ + if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) + return &rv32i_zbkb_zknd_zkne_gcm; + if (RISCV_HAS_ZKND_AND_ZKNE()) + return &rv32i_zknd_zkne_gcm; + return &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.inc new file mode 100644 index 0000000000..dae9beae07 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.inc @@ -0,0 +1,117 @@ +/* + * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * RISC-V 64 support for AES GCM. + * This file is included by cipher_aes_gcm_hw.c + */ + +/*- + * RISC-V 64 ZKND and ZKNE support for AES GCM. + */ +static int rv64i_zknd_zkne_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + GCM_HW_SET_KEY_CTR_FN(ks, rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, + NULL); + return 1; +} + +static const PROV_GCM_HW rv64i_zknd_zkne_gcm = { + rv64i_zknd_zkne_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +/*- + * RISC-V RV64 ZVKNED support for AES GCM. + */ +static int rv64i_zvkned_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + /* + * Zvkned only supports 128 and 256 bit keys for key schedule generation. + * For AES-192 case, we could fallback to `AES_set_encrypt_key`. + */ + if (keylen * 8 == 128 || keylen * 8 == 256) { + GCM_HW_SET_KEY_CTR_FN(ks, rv64i_zvkned_set_encrypt_key, + rv64i_zvkned_encrypt, NULL); + } else { + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, + rv64i_zvkned_encrypt, NULL); + } + + return 1; +} + +static const PROV_GCM_HW rv64i_zvkned_gcm = { + rv64i_zvkned_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +/*- + * RISC-V RV64 ZVKB, ZVKG and ZVKNED support for AES GCM. + */ +static int rv64i_zvkb_zvkg_zvkned_gcm_initkey(PROV_GCM_CTX *ctx, + const unsigned char *key, + size_t keylen) { + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + /* + * Zvkned only supports 128 and 256 bit keys for key schedule generation. + * For AES-192 case, we could fallback to `AES_set_encrypt_key`. + */ + if (keylen * 8 == 128 || keylen * 8 == 256) { + GCM_HW_SET_KEY_CTR_FN(ks, rv64i_zvkned_set_encrypt_key, + rv64i_zvkned_encrypt, + rv64i_zvkb_zvkned_ctr32_encrypt_blocks); + } else { + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, + rv64i_zvkned_encrypt, + rv64i_zvkb_zvkned_ctr32_encrypt_blocks); + } + + return 1; +} + +static const PROV_GCM_HW rv64i_zvkb_zvkg_zvkned_gcm = { + rv64i_zvkb_zvkg_zvkned_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; + +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) { + if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) { + if (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKG()) + return &rv64i_zvkb_zvkg_zvkned_gcm; + return &rv64i_zvkned_gcm; + } + + if (RISCV_HAS_ZKND_AND_ZKNE()) { + return &rv64i_zknd_zkne_gcm; + } + + return &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc new file mode 100644 index 0000000000..a36c48e3ec --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc @@ -0,0 +1,312 @@ +/* + * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * IBM S390X support for AES GCM. + * This file is included by cipher_aes_gcm_hw.c + */ + +/* iv + padding length for iv lengths != 12 */ +#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16) + +/* Additional flag or'ed to fc for decryption */ +#define S390X_gcm_decrypt_flag(ctx) (((ctx)->enc) ? 0 : S390X_DECRYPT) + +#define S390X_gcm_fc(A,C) ((A)->plat.s390x.fc | (A)->plat.s390x.hsflag |\ + S390X_gcm_decrypt_flag((C))) + +static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + + ctx->key_set = 1; + memcpy(&actx->plat.s390x.param.kma.k, key, keylen); + actx->plat.s390x.fc = S390X_AES_FC(keylen); + return 1; +} + +static int s390x_aes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, + size_t ivlen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + + kma->t.g[0] = 0; + kma->t.g[1] = 0; + kma->tpcl = 0; + kma->taadl = 0; + actx->plat.s390x.mreslen = 0; + actx->plat.s390x.areslen = 0; + actx->plat.s390x.kreslen = 0; + + if (ivlen == GCM_IV_DEFAULT_SIZE) { + memcpy(&kma->j0, iv, ivlen); + kma->j0.w[3] = 1; + kma->cv.w = 1; + actx->plat.s390x.hsflag = 0; + } else { + unsigned long long ivbits = ivlen << 3; + size_t len = S390X_gcm_ivpadlen(ivlen); + unsigned char iv_zero_pad[S390X_gcm_ivpadlen(GCM_IV_MAX_SIZE)]; + /* + * The IV length needs to be zero padded to be a multiple of 16 bytes + * followed by 8 bytes of zeros and 8 bytes for the IV length. + * The GHASH of this value can then be calculated. + */ + memcpy(iv_zero_pad, iv, ivlen); + memset(iv_zero_pad + ivlen, 0, len - ivlen); + memcpy(iv_zero_pad + len - sizeof(ivbits), &ivbits, sizeof(ivbits)); + /* + * Calculate the ghash of the iv - the result is stored into the tag + * param. + */ + s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma); + actx->plat.s390x.hsflag = S390X_KMA_HS; /* The hash subkey is set */ + + /* Copy the 128 bit GHASH result into J0 and clear the tag */ + kma->j0.g[0] = kma->t.g[0]; + kma->j0.g[1] = kma->t.g[1]; + kma->t.g[0] = 0; + kma->t.g[1] = 0; + /* Set the 32 bit counter */ + kma->cv.w = kma->j0.w[3]; + } + return 1; +} + +static int s390x_aes_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + unsigned char out[AES_BLOCK_SIZE]; + unsigned int fc; + int rc; + + kma->taadl <<= 3; + kma->tpcl <<= 3; + fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC; + s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, + actx->plat.s390x.mres, actx->plat.s390x.mreslen, out, + fc, kma); + + /* gctx->mres already returned to the caller */ + OPENSSL_cleanse(out, actx->plat.s390x.mreslen); + + if (ctx->enc) { + ctx->taglen = GCM_TAG_MAX_SIZE; + memcpy(tag, kma->t.b, ctx->taglen); + rc = 1; + } else { + rc = (CRYPTO_memcmp(tag, kma->t.b, ctx->taglen) == 0); + } + return rc; +} + +static int s390x_aes_gcm_one_shot(PROV_GCM_CTX *ctx, + unsigned char *aad, size_t aad_len, + const unsigned char *in, size_t in_len, + unsigned char *out, + unsigned char *tag, size_t taglen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + unsigned int fc; + int rc; + + kma->taadl = aad_len << 3; + kma->tpcl = in_len << 3; + fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC; + s390x_kma(aad, aad_len, in, in_len, out, fc, kma); + + if (ctx->enc) { + memcpy(tag, kma->t.b, taglen); + rc = 1; + } else { + rc = (CRYPTO_memcmp(tag, kma->t.b, taglen) == 0); + } + return rc; +} + +/* + * Process additional authenticated data. Returns 1 on success. Code is + * big-endian. + */ +static int s390x_aes_gcm_aad_update(PROV_GCM_CTX *ctx, + const unsigned char *aad, size_t len) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + unsigned long long alen; + unsigned int fc; + int n, rem; + + /* If already processed pt/ct then error */ + if (kma->tpcl != 0) + return 0; + + /* update the total aad length */ + alen = kma->taadl + len; + if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len)) + return 0; + kma->taadl = alen; + + /* check if there is any existing aad data from a previous add */ + n = actx->plat.s390x.areslen; + if (n) { + /* add additional data to a buffer until it has 16 bytes */ + while (n && len) { + actx->plat.s390x.ares[n] = *aad; + ++aad; + --len; + n = (n + 1) & 0xf; + } + /* ctx->ares contains a complete block if offset has wrapped around */ + if (!n) { + fc = S390X_gcm_fc(actx, ctx); + s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL, fc, kma); + actx->plat.s390x.hsflag = S390X_KMA_HS; + } + actx->plat.s390x.areslen = n; + } + + /* If there are leftover bytes (< 128 bits) save them for next time */ + rem = len & 0xf; + /* Add any remaining 16 byte blocks (128 bit each) */ + len &= ~(size_t)0xf; + if (len) { + fc = S390X_gcm_fc(actx, ctx); + s390x_kma(aad, len, NULL, 0, NULL, fc, kma); + actx->plat.s390x.hsflag = S390X_KMA_HS; + aad += len; + } + + if (rem) { + actx->plat.s390x.areslen = rem; + + do { + --rem; + actx->plat.s390x.ares[rem] = aad[rem]; + } while (rem); + } + return 1; +} + +/*- + * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 1 for + * success. Code is big-endian. + */ +static int s390x_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, + const unsigned char *in, size_t len, + unsigned char *out) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + const unsigned char *inptr; + unsigned long long mlen; + unsigned int fc; + union { + unsigned int w[4]; + unsigned char b[16]; + } buf; + size_t inlen; + int n, rem, i; + + mlen = kma->tpcl + len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return 0; + kma->tpcl = mlen; + + fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD; + n = actx->plat.s390x.mreslen; + if (n) { + inptr = in; + inlen = len; + while (n && inlen) { + actx->plat.s390x.mres[n] = *inptr; + n = (n + 1) & 0xf; + ++inptr; + --inlen; + } + /* ctx->mres contains a complete block if offset has wrapped around */ + if (!n) { + s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, + actx->plat.s390x.mres, 16, buf.b, fc, kma); + actx->plat.s390x.hsflag = S390X_KMA_HS; + fc |= S390X_KMA_HS; + actx->plat.s390x.areslen = 0; + + /* previous call already encrypted/decrypted its remainder, + * see comment below */ + n = actx->plat.s390x.mreslen; + while (n) { + *out = buf.b[n]; + n = (n + 1) & 0xf; + ++out; + ++in; + --len; + } + actx->plat.s390x.mreslen = 0; + } + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out, + fc, kma); + in += len; + out += len; + actx->plat.s390x.hsflag = S390X_KMA_HS; + actx->plat.s390x.areslen = 0; + } + + /*- + * If there is a remainder, it has to be saved such that it can be + * processed by kma later. However, we also have to do the for-now + * unauthenticated encryption/decryption part here and now... + */ + if (rem) { + if (!actx->plat.s390x.mreslen) { + buf.w[0] = kma->j0.w[0]; + buf.w[1] = kma->j0.w[1]; + buf.w[2] = kma->j0.w[2]; + buf.w[3] = kma->cv.w + 1; + s390x_km(buf.b, 16, actx->plat.s390x.kres, + fc & 0x1f, &kma->k); + } + + n = actx->plat.s390x.mreslen; + for (i = 0; i < rem; i++) { + actx->plat.s390x.mres[n + i] = in[i]; + out[i] = in[i] ^ actx->plat.s390x.kres[n + i]; + } + actx->plat.s390x.mreslen += rem; + } + return 1; +} + +static const PROV_GCM_HW s390x_aes_gcm = { + s390x_aes_gcm_initkey, + s390x_aes_gcm_setiv, + s390x_aes_gcm_aad_update, + s390x_aes_gcm_cipher_update, + s390x_aes_gcm_cipher_final, + s390x_aes_gcm_one_shot +}; + +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) +{ + if ((keybits == 128 && S390X_aes_128_gcm_CAPABLE) + || (keybits == 192 && S390X_aes_192_gcm_CAPABLE) + || (keybits == 256 && S390X_aes_256_gcm_CAPABLE)) + return &s390x_aes_gcm; + return &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc new file mode 100644 index 0000000000..2b3a6d1d5e --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc @@ -0,0 +1,52 @@ +/* + * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Fujitsu SPARC64 X support for AES GCM. + * This file is included by cipher_aes_gcm_hw.c + */ + +static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + ctr128_f ctr; + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + + switch (keylen) { + case 16: + ctr = (ctr128_f)aes128_t4_ctr32_encrypt; + break; + case 24: + ctr = (ctr128_f)aes192_t4_ctr32_encrypt; + break; + case 32: + ctr = (ctr128_f)aes256_t4_ctr32_encrypt; + break; + default: + return 0; + } + + GCM_HW_SET_KEY_CTR_FN(ks, aes_t4_set_encrypt_key, aes_t4_encrypt, ctr); + return 1; +} + +static const PROV_GCM_HW t4_aes_gcm = { + t4_aes_gcm_initkey, + ossl_gcm_setiv, + ossl_gcm_aad_update, + generic_aes_gcm_cipher_update, + ossl_gcm_cipher_final, + ossl_gcm_one_shot +}; +const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) +{ + return SPARC_AES_CAPABLE ? &t4_aes_gcm : &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_vaes_avx512.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_vaes_avx512.inc new file mode 100644 index 0000000000..5406548f3e --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_vaes_avx512.inc @@ -0,0 +1,204 @@ +/* + * Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2021, Intel Corporation. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AVX512 VAES + VPCLMULDQD support for AES GCM. + * This file is included by cipher_aes_gcm_hw_aesni.inc + */ + +#undef VAES_GCM_ENABLED +#if (defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64)) +# define VAES_GCM_ENABLED + +/* Returns non-zero when AVX512F + VAES + VPCLMULDQD combination is available */ +int ossl_vaes_vpclmulqdq_capable(void); + +# define OSSL_AES_GCM_UPDATE(direction) \ + void ossl_aes_gcm_ ## direction ## _avx512(const void *ks, \ + void *gcm128ctx, \ + unsigned int *pblocklen, \ + const unsigned char *in, \ + size_t len, \ + unsigned char *out); + +OSSL_AES_GCM_UPDATE(encrypt) +OSSL_AES_GCM_UPDATE(decrypt) + +void ossl_aes_gcm_init_avx512(const void *ks, void *gcm128ctx); +void ossl_aes_gcm_setiv_avx512(const void *ks, void *gcm128ctx, + const unsigned char *iv, size_t ivlen); +void ossl_aes_gcm_update_aad_avx512(void *gcm128ctx, const unsigned char *aad, + size_t aadlen); +void ossl_aes_gcm_finalize_avx512(void *gcm128ctx, unsigned int pblocklen); + +void ossl_gcm_gmult_avx512(uint64_t Xi[2], const void *gcm128ctx); + +static int vaes_gcm_setkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + GCM128_CONTEXT *gcmctx = &ctx->gcm; + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + aesni_set_encrypt_key(key, (int)(keylen * 8), ks); + memset(gcmctx, 0, sizeof(*gcmctx)); + gcmctx->key = ks; + ctx->key_set = 1; + + ossl_aes_gcm_init_avx512(ks, gcmctx); + + return 1; +} + +static int vaes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, + size_t ivlen) +{ + GCM128_CONTEXT *gcmctx = &ctx->gcm; + + gcmctx->Yi.u[0] = 0; /* Current counter */ + gcmctx->Yi.u[1] = 0; + gcmctx->Xi.u[0] = 0; /* AAD hash */ + gcmctx->Xi.u[1] = 0; + gcmctx->len.u[0] = 0; /* AAD length */ + gcmctx->len.u[1] = 0; /* Message length */ + gcmctx->ares = 0; + gcmctx->mres = 0; + + /* IV is limited by 2^64 bits, thus 2^61 bytes */ + if (ivlen > (U64(1) << 61)) + return 0; + + ossl_aes_gcm_setiv_avx512(gcmctx->key, gcmctx, iv, ivlen); + + return 1; +} + +static int vaes_gcm_aadupdate(PROV_GCM_CTX *ctx, + const unsigned char *aad, + size_t aad_len) +{ + GCM128_CONTEXT *gcmctx = &ctx->gcm; + uint64_t alen = gcmctx->len.u[0]; + unsigned int ares; + size_t i, lenBlks; + + /* Bad sequence: call of AAD update after message processing */ + if (gcmctx->len.u[1] > 0) + return 0; + + alen += aad_len; + /* AAD is limited by 2^64 bits, thus 2^61 bytes */ + if ((alen > (U64(1) << 61)) || (alen < aad_len)) + return 0; + + gcmctx->len.u[0] = alen; + + ares = gcmctx->ares; + /* Partial AAD block left from previous AAD update calls */ + if (ares > 0) { + /* + * Fill partial block buffer till full block + * (note, the hash is stored reflected) + */ + while (ares > 0 && aad_len > 0) { + gcmctx->Xi.c[15 - ares] ^= *(aad++); + --aad_len; + ares = (ares + 1) % AES_BLOCK_SIZE; + } + /* Full block gathered */ + if (ares == 0) { + ossl_gcm_gmult_avx512(gcmctx->Xi.u, gcmctx); + } else { /* no more AAD */ + gcmctx->ares = ares; + return 1; + } + } + + /* Bulk AAD processing */ + lenBlks = aad_len & ((size_t)(-AES_BLOCK_SIZE)); + if (lenBlks > 0) { + ossl_aes_gcm_update_aad_avx512(gcmctx, aad, lenBlks); + aad += lenBlks; + aad_len -= lenBlks; + } + + /* Add remaining AAD to the hash (note, the hash is stored reflected) */ + if (aad_len > 0) { + ares = (unsigned int)aad_len; + for (i = 0; i < aad_len; i++) + gcmctx->Xi.c[15 - i] ^= aad[i]; + } + + gcmctx->ares = ares; + + return 1; +} + +static int vaes_gcm_cipherupdate(PROV_GCM_CTX *ctx, const unsigned char *in, + size_t len, unsigned char *out) +{ + GCM128_CONTEXT *gcmctx = &ctx->gcm; + uint64_t mlen = gcmctx->len.u[1]; + + mlen += len; + if (mlen > ((U64(1) << 36) - 32) || (mlen < len)) + return 0; + + gcmctx->len.u[1] = mlen; + + /* Finalize GHASH(AAD) if AAD partial blocks left unprocessed */ + if (gcmctx->ares > 0) { + ossl_gcm_gmult_avx512(gcmctx->Xi.u, gcmctx); + gcmctx->ares = 0; + } + + if (ctx->enc) + ossl_aes_gcm_encrypt_avx512(gcmctx->key, gcmctx, &gcmctx->mres, in, len, out); + else + ossl_aes_gcm_decrypt_avx512(gcmctx->key, gcmctx, &gcmctx->mres, in, len, out); + + return 1; +} + +static int vaes_gcm_cipherfinal(PROV_GCM_CTX *ctx, unsigned char *tag) +{ + GCM128_CONTEXT *gcmctx = &ctx->gcm; + unsigned int *res = &gcmctx->mres; + + /* Finalize AAD processing */ + if (gcmctx->ares > 0) + res = &gcmctx->ares; + + ossl_aes_gcm_finalize_avx512(gcmctx, *res); + + if (ctx->enc) { + ctx->taglen = GCM_TAG_MAX_SIZE; + memcpy(tag, gcmctx->Xi.c, + ctx->taglen <= sizeof(gcmctx->Xi.c) ? ctx->taglen : + sizeof(gcmctx->Xi.c)); + *res = 0; + } else { + return !CRYPTO_memcmp(gcmctx->Xi.c, tag, ctx->taglen); + } + + return 1; +} + +static const PROV_GCM_HW vaes_gcm = { + vaes_gcm_setkey, + vaes_gcm_setiv, + vaes_gcm_aadupdate, + vaes_gcm_cipherupdate, + vaes_gcm_cipherfinal, + ossl_gcm_one_shot +}; + +#endif diff --git a/providers/implementations/ciphers/cipher_aes_gcm_siv.c b/providers/implementations/ciphers/cipher_aes_gcm_siv.c index 2f4a86dc56..1fd97fe3d1 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_siv.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_siv.c @@ -182,11 +182,8 @@ static int ossl_aes_gcm_siv_get_ctx_params(void *vctx, OSSL_PARAM params[]) return 0; if (p.tag != NULL && p.tag->data_type == OSSL_PARAM_OCTET_STRING) { - if (!ctx->enc || !ctx->generated_tag) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET); - return 0; - } - if (p.tag->data_size != sizeof(ctx->tag) + if (!ctx->enc || !ctx->generated_tag + || p.tag->data_size != sizeof(ctx->tag) || !OSSL_PARAM_set_octet_string(p.tag, ctx->tag, sizeof(ctx->tag))) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -230,9 +227,6 @@ static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[] if (!ctx->enc) { memcpy(ctx->user_tag, p.tag->data, sizeof(ctx->tag)); ctx->have_user_tag = 1; - } else if (p.tag->data != NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED); - return 0; } } diff --git a/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c index 9622c2dcca..452c9f00fe 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c @@ -15,7 +15,6 @@ #include "internal/deprecated.h" #include -#include #include #include #include "cipher_aes_gcm_siv.h" @@ -152,6 +151,8 @@ static int aes_gcm_siv_encrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *i DECLARE_IS_ENDIAN; ctx->generated_tag = 0; + if (!ctx->speed && ctx->used_enc) + return 0; /* need to check the size of the input! */ if (len64 > ((int64_t)1 << 36)) return 0; @@ -211,6 +212,8 @@ static int aes_gcm_siv_decrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *i DECLARE_IS_ENDIAN; ctx->generated_tag = 0; + if (!ctx->speed && ctx->used_dec) + return 0; /* need to check the size of the input! */ if (len64 > ((int64_t)1 << 36)) return 0; @@ -282,18 +285,6 @@ static int aes_gcm_siv_cipher(void *vctx, unsigned char *out, if (in == NULL) return aes_gcm_siv_finish(ctx); - /* - * SIV derives the CTR IV from the tag, which depends on the whole plaintext, - * so the payload cannot be streamed. - * Payload must arrive in a single update, after which the tag is fixed. - * Any later AAD or payload update is therefore out of order and errors out. - * The speed benchmark test is exempt. - */ - if (!ctx->speed && (ctx->used_enc || ctx->used_dec)) { - ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); - return 0; - } - /* Deal with associated data */ if (out == NULL) return aes_gcm_siv_aad(ctx, in, len); diff --git a/providers/implementations/ciphers/cipher_aes_hw.c b/providers/implementations/ciphers/cipher_aes_hw.c index 03ddb46947..da9a6729d0 100644 --- a/providers/implementations/ciphers/cipher_aes_hw.c +++ b/providers/implementations/ciphers/cipher_aes_hw.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,273 +16,149 @@ #include #include "cipher_aes.h" -int ossl_cipher_set_aes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen, - aes_set_encrypt_key_fn fn_set_key, aes_block128_f fn_block, - ecb128_f fn_ecb, cbc128_f fn_cbc, ctr128_f fn_ctr) +static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) { - PROV_AES_CTX *actx = (PROV_AES_CTX *)ctx; - AES_KEY *ks = &actx->ks.ks; + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)HWAES_decrypt; + dat->stream.cbc = NULL; +#ifdef HWAES_cbc_encrypt + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt; +#endif +#ifdef HWAES_ecb_encrypt + if (dat->mode == EVP_CIPH_ECB_MODE) + dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt; +#endif + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) { + ret = AES_set_decrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)AES_decrypt; + dat->stream.cbc = (cbc128_f)ossl_bsaes_cbc_encrypt; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_decrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)vpaes_decrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)vpaes_cbc_encrypt + : NULL; + } else +#endif + { + ret = AES_set_decrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)AES_decrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)AES_cbc_encrypt + : NULL; + } + } else +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)HWAES_encrypt; + dat->stream.cbc = NULL; +#ifdef HWAES_cbc_encrypt + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt; + else +#endif +#ifdef HWAES_ecb_encrypt + if (dat->mode == EVP_CIPH_ECB_MODE) + dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt; + else +#endif +#ifdef HWAES_ctr32_encrypt_blocks + if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks; + else +#endif + (void)0; /* terminate potentially open 'else' */ + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) { + ret = AES_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.ctr = (ctr128_f)ossl_bsaes_ctr32_encrypt_blocks; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)vpaes_encrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)vpaes_cbc_encrypt + : NULL; + } else +#endif + { + ret = AES_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)AES_cbc_encrypt + : NULL; +#ifdef AES_CTR_ASM + if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt; +#endif + } - int ret = fn_set_key(key, (int)(keylen * 8), ks); if (ret < 0) { ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); return 0; } - ctx->ks = ks; - - ctx->block = (block128_f)fn_block; - - switch (ctx->mode) { - case EVP_CIPH_ECB_MODE: - ctx->stream.ecb = fn_ecb; - break; - case EVP_CIPH_CBC_MODE: - ctx->stream.cbc = fn_cbc; - break; - case EVP_CIPH_CTR_MODE: - ctx->stream.ctr = fn_ctr; - break; - default: - memset(&ctx->stream, 0, sizeof(ctx->stream)); - break; - } return 1; } -#ifdef HWAES_CAPABLE -static int hwaes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (HWAES_CAPABLE) { - ecb128_f fn_ecb = NULL; - cbc128_f fn_cbc = NULL; - ctr128_f fn_ctr = NULL; -#ifdef HWAES_ecb_encrypt - fn_ecb = (ecb128_f)HWAES_ecb_encrypt; -#endif -#ifdef HWAES_cbc_encrypt - fn_cbc = (cbc128_f)HWAES_cbc_encrypt; -#endif -#ifdef HWAES_ctr32_encrypt_blocks - fn_ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks; -#endif - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - HWAES_set_decrypt_key, HWAES_decrypt, fn_ecb, fn_cbc, fn_ctr); - else - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - HWAES_set_encrypt_key, HWAES_encrypt, fn_ecb, fn_cbc, fn_ctr); +IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aes_copyctx, PROV_AES_CTX) + +#define PROV_CIPHER_HW_aes_mode(mode) \ + static const PROV_CIPHER_HW aes_##mode = { \ + cipher_hw_aes_initkey, \ + ossl_cipher_hw_generic_##mode, \ + cipher_hw_aes_copyctx \ + }; \ + PROV_CIPHER_HW_declare(mode) \ + const PROV_CIPHER_HW * \ + ossl_prov_cipher_hw_aes_##mode(size_t keybits) \ + { \ + PROV_CIPHER_HW_select(mode) return &aes_##mode; \ } - return -1; -} -#endif /* HWAES_CAPABLE */ - -#ifdef BSAES_CAPABLE -static int bsaes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (BSAES_CAPABLE) { - if (ctx->mode == EVP_CIPH_CBC_MODE && !ctx->enc) - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - AES_set_decrypt_key, AES_decrypt, NULL, - (cbc128_f)ossl_bsaes_cbc_encrypt, NULL); - else if (ctx->mode == EVP_CIPH_CTR_MODE) - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_encrypt, NULL, NULL, - (ctr128_f)ossl_bsaes_ctr32_encrypt_blocks); - } - return -1; -} -#endif /* BSAES_CAPABLE */ - -#ifdef VPAES_CAPABLE -static int vpaes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (VPAES_CAPABLE) { - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - vpaes_set_decrypt_key, vpaes_decrypt, NULL, - (cbc128_f)vpaes_cbc_encrypt, NULL); - } else { - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - vpaes_set_encrypt_key, vpaes_encrypt, NULL, - (cbc128_f)vpaes_cbc_encrypt, NULL); - } - } - return -1; -} -#endif /* VPAES_CAPABLE */ - -int ossl_cipher_hw_aes_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - int ret = 0; - -#ifdef HWAES_CAPABLE - ret = hwaes_initkey(ctx, key, keylen); - if (ret >= 0) - return ret; -#endif - -#ifdef BSAES_CAPABLE - ret = bsaes_initkey(ctx, key, keylen); - if (ret >= 0) - return ret; -#endif - -#ifdef VPAES_CAPABLE - ret = vpaes_initkey(ctx, key, keylen); - if (ret >= 0) - return ret; -#endif - - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - ret = ossl_cipher_set_aes_initkey(ctx, key, keylen, - AES_set_decrypt_key, AES_decrypt, NULL, (cbc128_f)AES_cbc_encrypt, - NULL); - } else { - ctr128_f fn_ctr = NULL; -#ifdef AES_CTR_ASM - fn_ctr = (ctr128_f)AES_ctr32_encrypt; -#endif - ret = ossl_cipher_set_aes_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_encrypt, NULL, (cbc128_f)AES_cbc_encrypt, - fn_ctr); - } - - return ret; -} - -void ossl_cipher_aes_copyctx(PROV_CIPHER_CTX *dst, - const PROV_CIPHER_CTX *src) -{ - PROV_AES_CTX *sctx = (PROV_AES_CTX *)src; - PROV_AES_CTX *dctx = (PROV_AES_CTX *)dst; - - *dctx = *sctx; - dst->ks = &dctx->ks.ks; -} - -static const PROV_CIPHER_HW aes_ecb = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_ecb, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_cbc = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_cbc, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_cfb128 = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_cfb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_cfb8 = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_cfb8, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_cfb1 = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_cfb1, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_ofb128 = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_ofb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_ctr = { - ossl_cipher_hw_aes_initkey, - ossl_cipher_hw_generic_ctr, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_mode(enum aes_modes mode, - size_t keybits) -{ - const PROV_CIPHER_HW *aes_hw_mode = NULL; #if defined(AESNI_CAPABLE) - aes_hw_mode = ossl_prov_cipher_hw_aesni(mode); -#elif defined(ARMv8_HWAES_CAPABLE) - aes_hw_mode = ossl_prov_cipher_hw_arm(mode); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 - aes_hw_mode = ossl_prov_cipher_hw_rv32i(mode); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 - aes_hw_mode = ossl_prov_cipher_hw_rv64i(mode); -#elif defined(S390X_aes_128_CAPABLE) - aes_hw_mode = ossl_prov_cipher_hw_s390x(mode, keybits); +#include "cipher_aes_hw_aesni.inc" #elif defined(SPARC_AES_CAPABLE) - aes_hw_mode = ossl_prov_cipher_hw_t4(mode); +#include "cipher_aes_hw_t4.inc" +#elif defined(S390X_aes_128_CAPABLE) +#include "cipher_aes_hw_s390x.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 +#include "cipher_aes_hw_rv64i.inc" +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 +#include "cipher_aes_hw_rv32i.inc" +#elif defined(ARMv8_HWAES_CAPABLE) +#include "cipher_aes_hw_armv8.inc" +#else +/* The generic case */ +#define PROV_CIPHER_HW_declare(mode) +#define PROV_CIPHER_HW_select(mode) #endif - if (aes_hw_mode == NULL) { - switch (mode) { - case AES_MODE_ECB: - return &aes_ecb; - case AES_MODE_CBC: - return &aes_cbc; - case AES_MODE_CFB128: - return &aes_cfb128; - case AES_MODE_CFB8: - return &aes_cfb8; - case AES_MODE_CFB1: - return &aes_cfb1; - case AES_MODE_OFB128: - return &aes_ofb128; - case AES_MODE_CTR: - return &aes_ctr; - } - } - - return aes_hw_mode; -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ecb(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_ECB, keybits); -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cbc(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_CBC, keybits); -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_CFB128, keybits); -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_CFB8, keybits); -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_CFB1, keybits); -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ofb128(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_OFB128, keybits); -} - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ctr(size_t keybits) -{ - return ossl_prov_cipher_hw_aes_mode(AES_MODE_CTR, keybits); -} +PROV_CIPHER_HW_aes_mode(cbc) + PROV_CIPHER_HW_aes_mode(ecb) + PROV_CIPHER_HW_aes_mode(ofb128) + PROV_CIPHER_HW_aes_mode(ctr) diff --git a/providers/implementations/ciphers/cipher_aes_hw_aesni.c b/providers/implementations/ciphers/cipher_aes_hw_aesni.c deleted file mode 100644 index f8ae45129b..0000000000 --- a/providers/implementations/ciphers/cipher_aes_hw_aesni.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright 2001-2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/*- - * AES-NI support for all hardware accelerated AES modes. - */ - -#include "internal/deprecated.h" -#include "cipher_aes.h" -#include "cipher_aes_gcm.h" -#include "cipher_aes_ccm.h" -#include "cipher_aes_xts.h" - -#if defined(AESNI_CAPABLE) - -/* MODES: ecb, cbc, cfb, ofb, ctr */ - -/* generates AES round keys for AES-NI and VAES implementations */ -static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - aesni_set_decrypt_key, aesni_decrypt, NULL, - (cbc128_f)aesni_cbc_encrypt, NULL); - } else { - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - aesni_set_encrypt_key, aesni_encrypt, NULL, - (cbc128_f)aesni_cbc_encrypt, (ctr128_f)aesni_ctr32_encrypt_blocks); - } -} - -static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t len) -{ - if (len < ctx->blocksize) - return 1; - - aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc); - - return 1; -} - -static const PROV_CIPHER_HW aesni_ecb = { - cipher_hw_aesni_initkey, - cipher_hw_aesni_ecb, - ossl_cipher_aes_copyctx -}; - -static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t len) -{ - aesni_cbc_encrypt(in, out, len, ctx->ks, ctx->iv, ctx->enc); - - return 1; -} - -static const PROV_CIPHER_HW aesni_cbc = { - cipher_hw_aesni_initkey, - cipher_hw_aesni_cbc, - ossl_cipher_aes_copyctx -}; - -#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) -/* active in 64-bit builds when AES-NI, AVX512F, and VAES are detected */ -#define VAES_CFB128_ELIGIBLE 1 -#else -#define VAES_CFB128_ELIGIBLE 0 -#endif - -#if VAES_CFB128_ELIGIBLE -static int aes_cfb128_vaes_encdec_wrapper( - PROV_CIPHER_CTX *ctx, - unsigned char *out, - const unsigned char *in, - size_t len) -{ - ossl_ssize_t num; - - num = (ossl_ssize_t)ctx->num; - - if (num < 0) { - /* behavior from CRYPTO_cfb128_encrypt */ - ctx->num = -1; - return 1; - } - - if (ctx->enc) - ossl_aes_cfb128_vaes_enc(in, out, len, ctx->ks, ctx->iv, &num); - else - ossl_aes_cfb128_vaes_dec(in, out, len, ctx->ks, ctx->iv, &num); - - ctx->num = (int)num; - - return 1; -} - -static const PROV_CIPHER_HW aesni_vaes_cfb128 = { - cipher_hw_aesni_initkey, - aes_cfb128_vaes_encdec_wrapper, - ossl_cipher_aes_copyctx -}; -#endif /* VAES_CFB128_ELIGIBLE */ - -static const PROV_CIPHER_HW aesni_cfb128 = { - cipher_hw_aesni_initkey, - ossl_cipher_hw_generic_cfb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aesni_cfb8 = { - cipher_hw_aesni_initkey, - ossl_cipher_hw_generic_cfb8, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aesni_cfb1 = { - cipher_hw_aesni_initkey, - ossl_cipher_hw_generic_cfb1, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aesni_ofb128 = { - cipher_hw_aesni_initkey, - ossl_cipher_hw_generic_ofb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aesni_ctr = { - cipher_hw_aesni_initkey, - ossl_cipher_hw_generic_ctr, - ossl_cipher_aes_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aesni(enum aes_modes mode) -{ - if (AESNI_CAPABLE) { - switch (mode) { - case AES_MODE_ECB: - return &aesni_ecb; - case AES_MODE_CBC: - return &aesni_cbc; - case AES_MODE_CFB128: -#if VAES_CFB128_ELIGIBLE - if (ossl_aes_cfb128_vaes_eligible()) - return &aesni_vaes_cfb128; -#endif - return &aesni_cfb128; - case AES_MODE_CFB8: - return &aesni_cfb8; - case AES_MODE_CFB1: - return &aesni_cfb1; - case AES_MODE_OFB128: - return &aesni_ofb128; - case AES_MODE_CTR: - return &aesni_ctr; - default: - return NULL; - } - } - return NULL; -} - -/* MODES: GCM */ - -static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, aesni_set_encrypt_key, - aesni_encrypt, aesni_ctr32_encrypt_blocks); -} - -static const PROV_GCM_HW aesni_gcm = { - aesni_gcm_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -/*- - * AVX512 VAES + VPCLMULDQD support for AES GCM. - */ - -#undef VAES_GCM_ENABLED -#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) -#define VAES_GCM_ENABLED - -/* Returns non-zero when AVX512F + VAES + VPCLMULDQD combination is available */ -int ossl_vaes_vpclmulqdq_capable(void); - -void ossl_aes_gcm_encrypt_avx512(const void *ks, void *gcm128ctx, - unsigned int *pblocklen, const unsigned char *in, size_t len, - unsigned char *out); -void ossl_aes_gcm_decrypt_avx512(const void *ks, void *gcm128ctx, - unsigned int *pblocklen, const unsigned char *in, size_t len, - unsigned char *out); - -void ossl_aes_gcm_init_avx512(const void *ks, void *gcm128ctx); -void ossl_aes_gcm_setiv_avx512(const void *ks, void *gcm128ctx, - const unsigned char *iv, size_t ivlen); -void ossl_aes_gcm_update_aad_avx512(void *gcm128ctx, const unsigned char *aad, - size_t aadlen); -void ossl_aes_gcm_finalize_avx512(void *gcm128ctx, unsigned int pblocklen); - -void ossl_gcm_gmult_avx512(uint64_t Xi[2], const void *gcm128ctx); - -static int vaes_gcm_setkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - GCM128_CONTEXT *gcmctx = &ctx->gcm; - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - AES_KEY *ks = &actx->ks.ks; - - aesni_set_encrypt_key(key, (int)(keylen * 8), ks); - memset(gcmctx, 0, sizeof(*gcmctx)); - gcmctx->key = ks; - ctx->key_set = 1; - - ossl_aes_gcm_init_avx512(ks, gcmctx); - - return 1; -} - -static int vaes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, - size_t ivlen) -{ - GCM128_CONTEXT *gcmctx = &ctx->gcm; - - gcmctx->Yi.u[0] = 0; /* Current counter */ - gcmctx->Yi.u[1] = 0; - gcmctx->Xi.u[0] = 0; /* AAD hash */ - gcmctx->Xi.u[1] = 0; - gcmctx->len.u[0] = 0; /* AAD length */ - gcmctx->len.u[1] = 0; /* Message length */ - gcmctx->ares = 0; - gcmctx->mres = 0; - - /* IV is limited by 2^64 bits, thus 2^61 bytes */ - if (ivlen > (U64(1) << 61)) - return 0; - - ossl_aes_gcm_setiv_avx512(gcmctx->key, gcmctx, iv, ivlen); - - return 1; -} - -static int vaes_gcm_aadupdate(PROV_GCM_CTX *ctx, - const unsigned char *aad, - size_t aad_len) -{ - GCM128_CONTEXT *gcmctx = &ctx->gcm; - uint64_t alen = gcmctx->len.u[0]; - unsigned int ares; - size_t i, lenBlks; - - /* Bad sequence: call of AAD update after message processing */ - if (gcmctx->len.u[1] > 0) - return 0; - - alen += aad_len; - /* AAD is limited by 2^64 bits, thus 2^61 bytes */ - if ((alen > (U64(1) << 61)) || (alen < aad_len)) - return 0; - - gcmctx->len.u[0] = alen; - - ares = gcmctx->ares; - /* Partial AAD block left from previous AAD update calls */ - if (ares > 0) { - /* - * Fill partial block buffer till full block - * (note, the hash is stored reflected) - */ - while (ares > 0 && aad_len > 0) { - gcmctx->Xi.c[15 - ares] ^= *(aad++); - --aad_len; - ares = (ares + 1) % AES_BLOCK_SIZE; - } - /* Full block gathered */ - if (ares == 0) { - ossl_gcm_gmult_avx512(gcmctx->Xi.u, gcmctx); - } else { /* no more AAD */ - gcmctx->ares = ares; - return 1; - } - } - - /* Bulk AAD processing */ - lenBlks = aad_len & ((size_t)(-AES_BLOCK_SIZE)); - if (lenBlks > 0) { - ossl_aes_gcm_update_aad_avx512(gcmctx, aad, lenBlks); - aad += lenBlks; - aad_len -= lenBlks; - } - - /* Add remaining AAD to the hash (note, the hash is stored reflected) */ - if (aad_len > 0) { - ares = (unsigned int)aad_len; - for (i = 0; i < aad_len; i++) - gcmctx->Xi.c[15 - i] ^= aad[i]; - } - - gcmctx->ares = ares; - - return 1; -} - -static int vaes_gcm_cipherupdate(PROV_GCM_CTX *ctx, const unsigned char *in, - size_t len, unsigned char *out) -{ - GCM128_CONTEXT *gcmctx = &ctx->gcm; - uint64_t mlen = gcmctx->len.u[1]; - - mlen += len; - if (mlen > ((U64(1) << 36) - 32) || (mlen < len)) - return 0; - - gcmctx->len.u[1] = mlen; - - /* Finalize GHASH(AAD) if AAD partial blocks left unprocessed */ - if (gcmctx->ares > 0) { - ossl_gcm_gmult_avx512(gcmctx->Xi.u, gcmctx); - gcmctx->ares = 0; - } - - if (ctx->enc) - ossl_aes_gcm_encrypt_avx512(gcmctx->key, gcmctx, &gcmctx->mres, in, len, out); - else - ossl_aes_gcm_decrypt_avx512(gcmctx->key, gcmctx, &gcmctx->mres, in, len, out); - - return 1; -} - -static int vaes_gcm_cipherfinal(PROV_GCM_CTX *ctx, unsigned char *tag) -{ - GCM128_CONTEXT *gcmctx = &ctx->gcm; - unsigned int *res = &gcmctx->mres; - - /* Finalize AAD processing */ - if (gcmctx->ares > 0) - res = &gcmctx->ares; - - ossl_aes_gcm_finalize_avx512(gcmctx, *res); - - if (ctx->enc) { - ctx->taglen = GCM_TAG_MAX_SIZE; - memcpy(tag, gcmctx->Xi.c, - ctx->taglen <= sizeof(gcmctx->Xi.c) ? ctx->taglen : sizeof(gcmctx->Xi.c)); - *res = 0; - } else { - return !CRYPTO_memcmp(gcmctx->Xi.c, tag, ctx->taglen); - } - - return 1; -} - -static const PROV_GCM_HW vaes_gcm = { - vaes_gcm_setkey, - vaes_gcm_setiv, - vaes_gcm_aadupdate, - vaes_gcm_cipherupdate, - vaes_gcm_cipherfinal, - ossl_gcm_one_shot -}; - -#endif - -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_aesni(void) -{ -#ifdef VAES_GCM_ENABLED - if (ossl_vaes_vpclmulqdq_capable()) - return &vaes_gcm; -#endif - if (AESNI_CAPABLE) - return &aesni_gcm; - - return NULL; -} - -/* MODES: CCM */ - -static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - aesni_set_encrypt_key, aesni_encrypt, aesni_ccm64_encrypt_blocks, - aesni_ccm64_decrypt_blocks); -} - -static const PROV_CCM_HW aesni_ccm = { - ccm_aesni_initkey, - ossl_ccm_generic_setiv, - ossl_ccm_generic_setaad, - ossl_ccm_generic_auth_encrypt, - ossl_ccm_generic_auth_decrypt, - ossl_ccm_generic_gettag -}; - -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_aesni(void) -{ - if (AESNI_CAPABLE) - return &aesni_ccm; - return NULL; -} - -/* MODES: XTS */ - -static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - void (*aesni_xts_enc)(const unsigned char *in, - unsigned char *out, - size_t length, - const AES_KEY *key1, const AES_KEY *key2, - const unsigned char iv[16]); - void (*aesni_xts_dec)(const unsigned char *in, - unsigned char *out, - size_t length, - const AES_KEY *key1, const AES_KEY *key2, - const unsigned char iv[16]); - - aesni_xts_enc = aesni_xts_encrypt; - aesni_xts_dec = aesni_xts_decrypt; - -#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) - if (aesni_xts_avx512_eligible()) { - if (keylen == 64) { - aesni_xts_enc = aesni_xts_256_encrypt_avx512; - aesni_xts_dec = aesni_xts_256_decrypt_avx512; - } else if (keylen == 32) { - aesni_xts_enc = aesni_xts_128_encrypt_avx512; - aesni_xts_dec = aesni_xts_128_decrypt_avx512; - } - } -#endif - - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - aesni_set_encrypt_key, aesni_set_decrypt_key, - aesni_encrypt, aesni_decrypt, aesni_xts_enc, aesni_xts_dec); -} - -static const PROV_CIPHER_HW aesni_xts = { - cipher_hw_aesni_xts_initkey, - NULL, - ossl_cipher_hw_aes_xts_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_aesni(void) -{ - if (AESNI_CAPABLE) - return &aesni_xts; - return NULL; -} - -#endif diff --git a/providers/implementations/ciphers/cipher_aes_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc new file mode 100644 index 0000000000..7b7084aea7 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc @@ -0,0 +1,81 @@ +/* + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI support for AES modes ecb, cbc, ofb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#define cipher_hw_aesni_ofb128 ossl_cipher_hw_generic_ofb128 +#define cipher_hw_aesni_ctr ossl_cipher_hw_generic_ctr + +static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = aesni_set_decrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f) aesni_decrypt; + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aesni_cbc_encrypt : NULL; + } else { + ret = aesni_set_encrypt_key(key, (int)(keylen * 8), ks); + dat->block = (block128_f) aesni_encrypt; + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; + else + dat->stream.cbc = NULL; + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + const AES_KEY *ks = ctx->ks; + + aesni_cbc_encrypt(in, out, len, ks, ctx->iv, ctx->enc); + + return 1; +} + +static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + if (len < ctx->blocksize) + return 1; + + aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc); + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW aesni_##mode = { \ + cipher_hw_aesni_initkey, \ + cipher_hw_aesni_##mode, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (AESNI_CAPABLE) \ + return &aesni_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_hw_armv8.c b/providers/implementations/ciphers/cipher_aes_hw_armv8.c deleted file mode 100644 index 673206b6d2..0000000000 --- a/providers/implementations/ciphers/cipher_aes_hw_armv8.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2019-2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * ARMv8 support for all hardware accelerated AES modes. - */ - -#include "internal/deprecated.h" -#include "cipher_aes.h" -#include "cipher_aes_gcm.h" - -#if defined(ARMv8_HWAES_CAPABLE) - -/* MODES: ctr */ - -static int cipher_hw_aes_arm_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (!ossl_cipher_hw_aes_initkey(ctx, key, keylen)) - return 0; - - if (AES_UNROLL12_EOR3_CAPABLE && ctx->mode == EVP_CIPH_CTR_MODE) - ctx->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks_unroll12_eor3; - - return 1; -} - -static const PROV_CIPHER_HW arm_ctr = { - cipher_hw_aes_arm_initkey, - ossl_cipher_hw_generic_ctr, - ossl_cipher_aes_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_arm(enum aes_modes mode) -{ - if (ARMv8_HWAES_CAPABLE && mode == AES_MODE_CTR) - return &arm_ctr; - return NULL; -} - -#endif - -/* MODES: GCM */ - -#if defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM) - -size_t armv8_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len, - const void *key, unsigned char ivec[16], uint64_t *Xi) -{ - AES_KEY *aes_key = (AES_KEY *)key; - size_t align_bytes = len - len % 16; - - switch (aes_key->rounds) { - case 10: - if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { - unroll8_eor3_aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } else { - aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } - break; - case 12: - if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { - unroll8_eor3_aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } else { - aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } - break; - case 14: - if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { - unroll8_eor3_aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } else { - aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } - break; - } - return align_bytes; -} - -size_t armv8_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len, - const void *key, unsigned char ivec[16], uint64_t *Xi) -{ - AES_KEY *aes_key = (AES_KEY *)key; - size_t align_bytes = len - len % 16; - - switch (aes_key->rounds) { - case 10: - if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { - unroll8_eor3_aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } else { - aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } - break; - case 12: - if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { - unroll8_eor3_aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } else { - aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } - break; - case 14: - if (IS_CPU_SUPPORT_UNROLL8_EOR3()) { - unroll8_eor3_aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } else { - aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key); - } - break; - } - return align_bytes; -} - -static int armv8_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - if (AES_UNROLL12_EOR3_CAPABLE) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - aes_v8_set_encrypt_key, aes_v8_encrypt, - aes_v8_ctr32_encrypt_blocks_unroll12_eor3); - } else { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - aes_v8_set_encrypt_key, aes_v8_encrypt, - aes_v8_ctr32_encrypt_blocks); - } -} - -static const PROV_GCM_HW armv8_aes_gcm = { - armv8_aes_gcm_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_armv8(void) -{ - return AES_PMULL_CAPABLE ? &armv8_aes_gcm : NULL; -} - -#endif diff --git a/providers/implementations/ciphers/cipher_aes_hw_armv8.inc b/providers/implementations/ciphers/cipher_aes_hw_armv8.inc new file mode 100644 index 0000000000..3f73c79290 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_armv8.inc @@ -0,0 +1,34 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Crypto extension support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +static int cipher_hw_aes_arm_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, + size_t keylen) +{ + int ret = cipher_hw_aes_initkey(dat, key, keylen); + if (AES_UNROLL12_EOR3_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks_unroll12_eor3; + + return ret; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW aes_arm_##mode = { \ + cipher_hw_aes_arm_initkey, \ + ossl_cipher_hw_generic_##mode, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (ARMv8_HWAES_CAPABLE) \ + return &aes_arm_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv32i.c b/providers/implementations/ciphers/cipher_aes_hw_rv32i.c deleted file mode 100644 index eeb26a8948..0000000000 --- a/providers/implementations/ciphers/cipher_aes_hw_rv32i.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2022-2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/*- - * RISC-V 32 ZKND ZKNE support for all hardware accelerated AES modes. - */ - -#include "internal/deprecated.h" -#include "cipher_aes.h" -#include "cipher_aes_gcm.h" -#include "cipher_aes_ccm.h" -#include "cipher_aes_xts.h" - -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 - -/* MODES: ecb, cbc, cfb, ofb, ctr */ - -static int cipher_hw_rv32i_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - rv32i_zbkb_zknd_zkne_set_decrypt_key, rv32i_zknd_decrypt, - NULL, NULL, NULL); - else - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - rv32i_zknd_zkne_set_decrypt_key, rv32i_zknd_decrypt, - NULL, NULL, NULL); - } else { - if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt, - NULL, NULL, NULL); - else - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt, - NULL, NULL, NULL); - } -} - -static const PROV_CIPHER_HW rv32i_ecb = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_ecb, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv32i_cbc = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_cbc, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv32i_cfb128 = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_cfb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv32i_cfb8 = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_cfb8, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv32i_cfb1 = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_cfb1, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv32i_ofb128 = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_ofb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv32i_ctr = { - cipher_hw_rv32i_initkey, - ossl_cipher_hw_generic_ctr, - ossl_cipher_aes_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv32i(enum aes_modes mode) -{ - if (RISCV_HAS_ZKND_AND_ZKNE()) { - switch (mode) { - case AES_MODE_ECB: - return &rv32i_ecb; - case AES_MODE_CBC: - return &rv32i_cbc; - case AES_MODE_CFB128: - return &rv32i_cfb128; - case AES_MODE_CFB8: - return &rv32i_cfb8; - case AES_MODE_CFB1: - return &rv32i_cfb1; - case AES_MODE_OFB128: - return &rv32i_ofb128; - case AES_MODE_CTR: - return &rv32i_ctr; - default: - return NULL; - } - } - return NULL; -} - -/* MODES: GCM */ - -static int aes_gcm_rv32i_initkey(PROV_GCM_CTX *ctx, - const unsigned char *key, - size_t keylen) -{ - if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt, NULL); - } else if (RISCV_HAS_ZKND_AND_ZKNE()) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt, NULL); - } - return 0; -} - -static const PROV_GCM_HW aes_gcm_rv32i = { - aes_gcm_rv32i_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv32i(void) -{ - if (RISCV_HAS_ZKND_AND_ZKNE()) - return &aes_gcm_rv32i; - return NULL; -} - -/* MODES: CCM */ - -static int aes_ccm_rv32i_initkey(PROV_CCM_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) { - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt, NULL, NULL); - } else if (RISCV_HAS_ZKND_AND_ZKNE()) { - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt, NULL, NULL); - } - return 0; -} - -static const PROV_CCM_HW aes_ccm_rv32i = { - aes_ccm_rv32i_initkey, - ossl_ccm_generic_setiv, - ossl_ccm_generic_setaad, - ossl_ccm_generic_auth_encrypt, - ossl_ccm_generic_auth_decrypt, - ossl_ccm_generic_gettag -}; - -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv32i(void) -{ - if (RISCV_HAS_ZKND_AND_ZKNE()) - return &aes_ccm_rv32i; - return NULL; -} - -/* MODES: XTS */ - -static int cipher_hw_aes_xts_rv32i_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - rv32i_zbkb_zkne_set_encrypt_key, - rv32i_zbkb_zknd_zkne_set_decrypt_key, - rv32i_zkne_encrypt, rv32i_zknd_decrypt, NULL, NULL); - - if (RISCV_HAS_ZKND_AND_ZKNE()) - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - rv32i_zkne_set_encrypt_key, rv32i_zknd_zkne_set_decrypt_key, - rv32i_zkne_encrypt, rv32i_zknd_decrypt, NULL, NULL); - - return 0; -} - -static const PROV_CIPHER_HW aes_xts_rv32i = { - cipher_hw_aes_xts_rv32i_initkey, - NULL, - ossl_cipher_hw_aes_xts_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv32i(void) -{ - if (RISCV_HAS_ZKND_AND_ZKNE()) - return &aes_xts_rv32i; - return NULL; -} - -#endif diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv32i.inc b/providers/implementations/ciphers/cipher_aes_hw_rv32i.inc new file mode 100644 index 0000000000..f6c652c32d --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_rv32i.inc @@ -0,0 +1,102 @@ +/* + * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * RISC-V 32 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#define cipher_hw_rv32i_zknd_zkne_cbc ossl_cipher_hw_generic_cbc +#define cipher_hw_rv32i_zknd_zkne_ecb ossl_cipher_hw_generic_ecb +#define cipher_hw_rv32i_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128 +#define cipher_hw_rv32i_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128 +#define cipher_hw_rv32i_zknd_zkne_cfb8 ossl_cipher_hw_generic_cfb8 +#define cipher_hw_rv32i_zknd_zkne_cfb1 ossl_cipher_hw_generic_cfb1 +#define cipher_hw_rv32i_zknd_zkne_ctr ossl_cipher_hw_generic_ctr + +#define cipher_hw_rv32i_zbkb_zknd_zkne_cbc ossl_cipher_hw_generic_cbc +#define cipher_hw_rv32i_zbkb_zknd_zkne_ecb ossl_cipher_hw_generic_ecb +#define cipher_hw_rv32i_zbkb_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128 +#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128 +#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb8 ossl_cipher_hw_generic_cfb8 +#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb1 ossl_cipher_hw_generic_cfb1 +#define cipher_hw_rv32i_zbkb_zknd_zkne_ctr ossl_cipher_hw_generic_ctr + +static int cipher_hw_rv32i_zknd_zkne_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = rv32i_zknd_zkne_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) rv32i_zknd_decrypt; + dat->stream.cbc = NULL; + } else { + ret = rv32i_zkne_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) rv32i_zkne_encrypt; + dat->stream.cbc = NULL; + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int cipher_hw_rv32i_zbkb_zknd_zkne_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = rv32i_zbkb_zknd_zkne_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) rv32i_zknd_decrypt; + dat->stream.cbc = NULL; + } else { + ret = rv32i_zbkb_zkne_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) rv32i_zkne_encrypt; + dat->stream.cbc = NULL; + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW rv32i_zknd_zkne_##mode = { \ + cipher_hw_rv32i_zknd_zkne_initkey, \ + cipher_hw_rv32i_zknd_zkne_##mode, \ + cipher_hw_aes_copyctx \ +}; \ +static const PROV_CIPHER_HW rv32i_zbkb_zknd_zkne_##mode = { \ + cipher_hw_rv32i_zbkb_zknd_zkne_initkey, \ + cipher_hw_rv32i_zbkb_zknd_zkne_##mode, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) \ + return &rv32i_zbkb_zknd_zkne_##mode; \ +if (RISCV_HAS_ZKND_AND_ZKNE()) \ + return &rv32i_zknd_zkne_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv64i.c b/providers/implementations/ciphers/cipher_aes_hw_rv64i.c deleted file mode 100644 index fa1e3f2b2a..0000000000 --- a/providers/implementations/ciphers/cipher_aes_hw_rv64i.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright 2022-2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/*- - * RISC-V 64 ZKND ZKNE / ZVKNED support for all hardware accelerated AES modes. - */ - -#include "internal/deprecated.h" -#include "cipher_aes.h" -#include "cipher_aes_gcm.h" -#include "cipher_aes_ccm.h" -#include "cipher_aes_xts.h" - -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 - -static int zvkned_key_schedule_supported(size_t keylen) -{ - if (keylen * 8 == 128 || keylen * 8 == 256) { - return 1; - } - return 0; -} - -/* MODES: ecb, cbc, cfb, ofb, ctr */ - -static int cipher_hw_rv64i_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) { - /* - * Zvkned only supports 128 and 256 bit keys for key schedule - * generation. For the AES-192 case, we fallback to the generic - * `AES_set_encrypt_key`. All Zvkned-based implementations use the - * same `encrypt-key` scheduling for both encryption and decryption. - */ - aes_set_encrypt_key_fn fn_set_key = AES_set_encrypt_key; - aes_block128_f fn_block = NULL; - - if (zvkned_key_schedule_supported(keylen)) { - fn_set_key = rv64i_zvkned_set_encrypt_key; - } - ecb128_f fn_ecb = ctx->enc ? (ecb128_f)rv64i_zvkned_ecb_encrypt : (ecb128_f)rv64i_zvkned_ecb_decrypt; - cbc128_f fn_cbc = ctx->enc ? (cbc128_f)rv64i_zvkned_cbc_encrypt : (cbc128_f)rv64i_zvkned_cbc_decrypt; - ctr128_f fn_ctr = RISCV_HAS_ZVKB() ? (ctr128_f)rv64i_zvkb_zvkned_ctr32_encrypt_blocks : NULL; - - /* Zvkned supports aes-128/192/256 encryption and decryption. */ - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - fn_block = rv64i_zvkned_decrypt; - } else { - fn_block = rv64i_zvkned_encrypt; - } - return ossl_cipher_set_aes_initkey(ctx, key, keylen, fn_set_key, - fn_block, fn_ecb, fn_cbc, fn_ctr); - } else if (RISCV_HAS_ZKND_AND_ZKNE()) { - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - rv64i_zknd_set_decrypt_key, rv64i_zknd_decrypt, - NULL, NULL, NULL); - } else { - return ossl_cipher_set_aes_initkey(ctx, key, keylen, - rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, - NULL, NULL, NULL); - } - } - return 0; -} - -static const PROV_CIPHER_HW rv64i_ecb = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_ecb, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv64i_cbc = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_cbc, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv64i_cfb128 = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_cfb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv64i_cfb8 = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_cfb8, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv64i_cfb1 = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_cfb1, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv64i_ofb128 = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_ofb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW rv64i_ctr = { - cipher_hw_rv64i_initkey, - ossl_cipher_hw_generic_ctr, - ossl_cipher_aes_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode) -{ - if ((RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) - || RISCV_HAS_ZKND_AND_ZKNE()) { - switch (mode) { - case AES_MODE_ECB: - return &rv64i_ecb; - case AES_MODE_CBC: - return &rv64i_cbc; - case AES_MODE_CFB128: - return &rv64i_cfb128; - case AES_MODE_CFB8: - return &rv64i_cfb8; - case AES_MODE_CFB1: - return &rv64i_cfb1; - case AES_MODE_OFB128: - return &rv64i_ofb128; - case AES_MODE_CTR: - return &rv64i_ctr; - default: - return NULL; - } - } - return NULL; -} - -/* MODES: GCM */ - -/*- - * RISC-V 64 ZKND and ZKNE support for AES GCM. - */ -static int rv64i_zknd_zkne_gcm_initkey(PROV_GCM_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, NULL); -} - -static const PROV_GCM_HW rv64i_zknd_zkne_gcm = { - rv64i_zknd_zkne_gcm_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -/*- - * RISC-V RV64 ZVKNED support for AES GCM. - */ -static int rv64i_zvkned_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - /* - * Zvkned only supports 128 and 256 bit keys for key schedule generation. - * For AES-192 case, we could fallback to `AES_set_encrypt_key`. - */ - if (zvkned_key_schedule_supported(keylen)) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, NULL); - } else { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL); - } -} - -static const PROV_GCM_HW rv64i_zvkned_gcm = { - rv64i_zvkned_gcm_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -/*- - * RISC-V RV64 ZVKB, ZVKG and ZVKNED support for AES GCM. - */ -static int rv64i_zvkb_zvkg_zvkned_gcm_initkey(PROV_GCM_CTX *ctx, - const unsigned char *key, - size_t keylen) -{ - /* - * Zvkned only supports 128 and 256 bit keys for key schedule generation. - * For AES-192 case, we could fallback to `AES_set_encrypt_key`. - */ - if (zvkned_key_schedule_supported(keylen)) { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, - rv64i_zvkb_zvkned_ctr32_encrypt_blocks); - } else { - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - AES_set_encrypt_key, rv64i_zvkned_encrypt, - rv64i_zvkb_zvkned_ctr32_encrypt_blocks); - } -} - -static const PROV_GCM_HW rv64i_zvkb_zvkg_zvkned_gcm = { - rv64i_zvkb_zvkg_zvkned_gcm_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv64i(void) -{ - if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) { - if (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKG()) - return &rv64i_zvkb_zvkg_zvkned_gcm; - return &rv64i_zvkned_gcm; - } - - if (RISCV_HAS_ZKND_AND_ZKNE()) { - return &rv64i_zknd_zkne_gcm; - } - - return NULL; -} - -/* MODES: CCM */ - -static int ccm_rv64i_zknd_zkne_initkey(PROV_CCM_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, NULL, NULL); -} - -static const PROV_CCM_HW rv64i_zknd_zkne_ccm = { - ccm_rv64i_zknd_zkne_initkey, - ossl_ccm_generic_setiv, - ossl_ccm_generic_setaad, - ossl_ccm_generic_auth_encrypt, - ossl_ccm_generic_auth_decrypt, - ossl_ccm_generic_gettag -}; - -/*- - * RISC-V RV64 ZVKNED support for AES CCM. - * This file is included by cipher_aes_ccm_hw.c - */ - -static int ccm_rv64i_zvkned_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - /* Zvkned only supports 128 and 256 bit keys for key schedule generation. */ - if (zvkned_key_schedule_supported(keylen)) { - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL); - } else { - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL); - } -} - -static const PROV_CCM_HW rv64i_zvkned_ccm = { - ccm_rv64i_zvkned_initkey, - ossl_ccm_generic_setiv, - ossl_ccm_generic_setaad, - ossl_ccm_generic_auth_encrypt, - ossl_ccm_generic_auth_decrypt, - ossl_ccm_generic_gettag -}; - -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv64i(void) -{ - if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) - return &rv64i_zvkned_ccm; - else if (RISCV_HAS_ZKND_AND_ZKNE()) - return &rv64i_zknd_zkne_ccm; - else - return NULL; -} - -/* MODES: XTS */ - -static int cipher_hw_aes_xts_rv64i_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - if (RISCV_HAS_ZVBB() && RISCV_HAS_ZVKG() && RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) { - /* Zvkned only supports 128 and 256 bit keys. */ - if (zvkned_key_schedule_supported(keylen / 2)) { - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - rv64i_zvkned_set_encrypt_key, rv64i_zvkned_set_decrypt_key, - rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, - rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt, - rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt); - } - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_set_encrypt_key, - rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL); - } - - if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) { - /* Zvkned only supports 128 and 256 bit keys. */ - if (zvkned_key_schedule_supported(keylen / 2)) { - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - rv64i_zvkned_set_encrypt_key, rv64i_zvkned_set_decrypt_key, - rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL); - } - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_set_encrypt_key, - rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL); - } - - if (RISCV_HAS_ZKND_AND_ZKNE()) { - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - rv64i_zkne_set_encrypt_key, rv64i_zknd_set_decrypt_key, - rv64i_zkne_encrypt, rv64i_zknd_decrypt, NULL, NULL); - } - - return 0; -} - -static const PROV_CIPHER_HW aes_xts_rv64i = { - cipher_hw_aes_xts_rv64i_initkey, - NULL, - ossl_cipher_hw_aes_xts_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv64i(void) -{ - if ((RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) - || RISCV_HAS_ZKND_AND_ZKNE()) - return &aes_xts_rv64i; - return NULL; -} - -#endif diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv64i.inc b/providers/implementations/ciphers/cipher_aes_hw_rv64i.inc new file mode 100644 index 0000000000..07d479303d --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_rv64i.inc @@ -0,0 +1,135 @@ +/* + * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * RISC-V 64 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#define cipher_hw_rv64i_zknd_zkne_cbc ossl_cipher_hw_generic_cbc +#define cipher_hw_rv64i_zknd_zkne_ecb ossl_cipher_hw_generic_ecb +#define cipher_hw_rv64i_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128 +#define cipher_hw_rv64i_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128 +#define cipher_hw_rv64i_zknd_zkne_cfb8 ossl_cipher_hw_generic_cfb8 +#define cipher_hw_rv64i_zknd_zkne_cfb1 ossl_cipher_hw_generic_cfb1 +#define cipher_hw_rv64i_zknd_zkne_ctr ossl_cipher_hw_generic_ctr + +static int cipher_hw_rv64i_zknd_zkne_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = rv64i_zknd_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) rv64i_zknd_decrypt; + dat->stream.cbc = NULL; + } else { + ret = rv64i_zkne_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) rv64i_zkne_encrypt; + dat->stream.cbc = NULL; + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +/*- + * RISC-V RV64 ZVKNED support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#define cipher_hw_rv64i_zvkned_cbc ossl_cipher_hw_generic_cbc +#define cipher_hw_rv64i_zvkned_ecb ossl_cipher_hw_generic_ecb +#define cipher_hw_rv64i_zvkned_ofb128 ossl_cipher_hw_generic_ofb128 +#define cipher_hw_rv64i_zvkned_cfb128 ossl_cipher_hw_generic_cfb128 +#define cipher_hw_rv64i_zvkned_cfb8 ossl_cipher_hw_generic_cfb8 +#define cipher_hw_rv64i_zvkned_cfb1 ossl_cipher_hw_generic_cfb1 +#define cipher_hw_rv64i_zvkned_ctr ossl_cipher_hw_generic_ctr + +static int cipher_hw_rv64i_zvkned_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, + size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + /* + * Zvkned only supports 128 and 256 bit keys for key schedule generation. + * For AES-192 case, we could fallback to `AES_set_encrypt_key`. + * All Zvkned-based implementations use the same `encrypt-key` scheduling + * for both encryption and decryption. + */ + if (keylen * 8 == 128 || keylen * 8 == 256) { + ret = rv64i_zvkned_set_encrypt_key(key, keylen * 8, ks); + } else { + ret = AES_set_encrypt_key(key, keylen * 8, ks); + } + + if (dat->mode == EVP_CIPH_CBC_MODE) { + if (dat->enc) { + dat->stream.cbc = (cbc128_f) rv64i_zvkned_cbc_encrypt; + } else { + dat->stream.cbc = (cbc128_f) rv64i_zvkned_cbc_decrypt; + } + } else if (dat->mode == EVP_CIPH_CTR_MODE) { + if (RISCV_HAS_ZVKB()) { + dat->stream.ctr = (ctr128_f) rv64i_zvkb_zvkned_ctr32_encrypt_blocks; + } + } else if (dat->mode == EVP_CIPH_ECB_MODE) { + if (dat->enc) { + dat->stream.ecb = (ecb128_f) rv64i_zvkned_ecb_encrypt; + } else { + dat->stream.ecb = (ecb128_f) rv64i_zvkned_ecb_decrypt; + } + } + + /* Zvkned supports aes-128/192/256 encryption and decryption. */ + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) && + !dat->enc) { + dat->block = (block128_f) rv64i_zvkned_decrypt; + } else { + dat->block = (block128_f) rv64i_zvkned_encrypt; + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW rv64i_zknd_zkne_##mode = { \ + cipher_hw_rv64i_zknd_zkne_initkey, \ + cipher_hw_rv64i_zknd_zkne_##mode, \ + cipher_hw_aes_copyctx \ +}; \ +static const PROV_CIPHER_HW rv64i_zvkned_##mode = { \ + cipher_hw_rv64i_zvkned_initkey, \ + cipher_hw_rv64i_zvkned_##mode, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) \ + return &rv64i_zvkned_##mode; \ +else if (RISCV_HAS_ZKND_AND_ZKNE()) \ + return &rv64i_zknd_zkne_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_hw_s390x.c b/providers/implementations/ciphers/cipher_aes_hw_s390x.c deleted file mode 100644 index e9e81f4746..0000000000 --- a/providers/implementations/ciphers/cipher_aes_hw_s390x.c +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Copyright 2001-2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * IBM S390X support for all hardware accelerated AES modes. - */ - -#include "internal/deprecated.h" -#include -#include "cipher_aes.h" -#include "cipher_aes_gcm.h" -#include "cipher_aes_ccm.h" -#include "cipher_aes_xts.h" -#include - -#if defined(S390X_aes_128_CAPABLE) - -/* MODES: ecb, cfb, ofb */ - -static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat, - const unsigned char *key, size_t keylen) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - - adat->plat.s390x.fc = S390X_AES_FC(keylen); - memcpy(adat->plat.s390x.param.km.k, key, keylen); - return 1; -} - -static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; - - s390x_km(in, len, out, adat->plat.s390x.fc | modifier, - &adat->plat.s390x.param.km); - return 1; -} - -static const PROV_CIPHER_HW s390x_aes_ecb = { - s390x_aes_ecb_initkey, - s390x_aes_ecb_cipher_hw, - ossl_cipher_aes_copyctx -}; - -static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat, - const unsigned char *key, size_t keylen) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - - memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); - adat->plat.s390x.fc = S390X_AES_FC(keylen); - return 1; -} - -static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - int n = dat->num; - int rem; - - memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); - while (n && len) { - *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n]; - n = (n + 1) & 0xf; - --len; - ++in; - ++out; - } - - rem = len & 0xf; - - len &= ~(size_t)0xf; - if (len) { - s390x_kmo(in, len, out, adat->plat.s390x.fc, - &adat->plat.s390x.param.kmo_kmf); - - out += len; - in += len; - } - - if (rem) { - s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, - adat->plat.s390x.param.kmo_kmf.cv, - adat->plat.s390x.fc, - adat->plat.s390x.param.kmo_kmf.k); - - while (rem--) { - out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n]; - ++n; - } - } - - memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); - dat->num = n; - return 1; -} - -static const PROV_CIPHER_HW s390x_aes_ofb128 = { - s390x_aes_ofb128_initkey, - s390x_aes_ofb128_cipher_hw, - ossl_cipher_aes_copyctx -}; - -static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat, - const unsigned char *key, size_t keylen) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - - adat->plat.s390x.fc = S390X_AES_FC(keylen); - adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */ - memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); - return 1; -} - -static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; - int n = dat->num; - int rem; - unsigned char tmp; - - memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); - while (n && len) { - tmp = *in; - *out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; - adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp; - n = (n + 1) & 0xf; - --len; - ++in; - ++out; - } - - rem = len & 0xf; - - len &= ~(size_t)0xf; - if (len) { - s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier, - &adat->plat.s390x.param.kmo_kmf); - - out += len; - in += len; - } - - if (rem) { - s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, - adat->plat.s390x.param.kmo_kmf.cv, - S390X_AES_FC(dat->keylen), - adat->plat.s390x.param.kmo_kmf.k); - - while (rem--) { - tmp = in[n]; - out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; - adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp; - ++n; - } - } - - memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); - dat->num = n; - return 1; -} - -static const PROV_CIPHER_HW s390x_aes_cfb128 = { - s390x_aes_cfb128_initkey, - s390x_aes_cfb128_cipher_hw, - ossl_cipher_aes_copyctx -}; - -static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat, - const unsigned char *key, size_t keylen) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - - adat->plat.s390x.fc = S390X_AES_FC(keylen); - adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */ - memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); - return 1; -} - -static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; - unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; - - memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); - s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier, - &adat->plat.s390x.param.kmo_kmf); - memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); - return 1; -} - -static const PROV_CIPHER_HW s390x_aes_cfb8 = { - s390x_aes_cfb8_initkey, - s390x_aes_cfb8_cipher_hw, - ossl_cipher_aes_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_s390x(enum aes_modes mode, - size_t keybits) -{ - switch (mode) { - case AES_MODE_ECB: - if ((keybits == 128 && S390X_aes_128_ecb_CAPABLE) - || (keybits == 192 && S390X_aes_192_ecb_CAPABLE) - || (keybits == 256 && S390X_aes_256_ecb_CAPABLE)) - return &s390x_aes_ecb; - break; - case AES_MODE_CFB128: - if ((keybits == 128 && S390X_aes_128_cfb_CAPABLE) - || (keybits == 192 && S390X_aes_192_cfb_CAPABLE) - || (keybits == 256 && S390X_aes_256_cfb_CAPABLE)) - return &s390x_aes_cfb128; - break; - case AES_MODE_CFB8: - if ((keybits == 128 && S390X_aes_128_cfb8_CAPABLE) - || (keybits == 192 && S390X_aes_192_cfb8_CAPABLE) - || (keybits == 256 && S390X_aes_256_cfb8_CAPABLE)) - return &s390x_aes_cfb8; - break; - case AES_MODE_OFB128: - if ((keybits == 128 && S390X_aes_128_ofb_CAPABLE) - || (keybits == 192 && S390X_aes_192_ofb_CAPABLE) - || (keybits == 256 && S390X_aes_256_ofb_CAPABLE)) - return &s390x_aes_ofb128; - break; - default: - break; - } - return NULL; -} - -/* MODES: GCM */ - -/* iv + padding length for iv lengths != 12 */ -#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16) - -/* Additional flag or'ed to fc for decryption */ -#define S390X_gcm_decrypt_flag(ctx) (((ctx)->enc) ? 0 : S390X_DECRYPT) - -#define S390X_gcm_fc(A, C) ((A)->plat.s390x.fc | (A)->plat.s390x.hsflag | S390X_gcm_decrypt_flag((C))) - -static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - - ctx->key_set = 1; - memcpy(&actx->plat.s390x.param.kma.k, key, keylen); - actx->plat.s390x.fc = S390X_AES_FC(keylen); - return 1; -} - -static int s390x_aes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, - size_t ivlen) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; - - kma->t.g[0] = 0; - kma->t.g[1] = 0; - kma->tpcl = 0; - kma->taadl = 0; - actx->plat.s390x.mreslen = 0; - actx->plat.s390x.areslen = 0; - actx->plat.s390x.kreslen = 0; - - if (ivlen == GCM_IV_DEFAULT_SIZE) { - memcpy(&kma->j0, iv, ivlen); - kma->j0.w[3] = 1; - kma->cv.w = 1; - actx->plat.s390x.hsflag = 0; - } else { - unsigned long long ivbits = ivlen << 3; - size_t len = S390X_gcm_ivpadlen(ivlen); - unsigned char iv_zero_pad[S390X_gcm_ivpadlen(GCM_IV_MAX_SIZE)]; - /* - * The IV length needs to be zero padded to be a multiple of 16 bytes - * followed by 8 bytes of zeros and 8 bytes for the IV length. - * The GHASH of this value can then be calculated. - */ - memcpy(iv_zero_pad, iv, ivlen); - memset(iv_zero_pad + ivlen, 0, len - ivlen); - memcpy(iv_zero_pad + len - sizeof(ivbits), &ivbits, sizeof(ivbits)); - /* - * Calculate the ghash of the iv - the result is stored into the tag - * param. - */ - s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma); - actx->plat.s390x.hsflag = S390X_KMA_HS; /* The hash subkey is set */ - - /* Copy the 128 bit GHASH result into J0 and clear the tag */ - kma->j0.g[0] = kma->t.g[0]; - kma->j0.g[1] = kma->t.g[1]; - kma->t.g[0] = 0; - kma->t.g[1] = 0; - /* Set the 32 bit counter */ - kma->cv.w = kma->j0.w[3]; - } - return 1; -} - -static int s390x_aes_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; - unsigned char out[AES_BLOCK_SIZE]; - unsigned int fc; - int rc; - - kma->taadl <<= 3; - kma->tpcl <<= 3; - fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC; - s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, - actx->plat.s390x.mres, actx->plat.s390x.mreslen, out, - fc, kma); - - /* gctx->mres already returned to the caller */ - OPENSSL_cleanse(out, actx->plat.s390x.mreslen); - - if (ctx->enc) { - ctx->taglen = GCM_TAG_MAX_SIZE; - memcpy(tag, kma->t.b, ctx->taglen); - rc = 1; - } else { - rc = (CRYPTO_memcmp(tag, kma->t.b, ctx->taglen) == 0); - } - return rc; -} - -static int s390x_aes_gcm_one_shot(PROV_GCM_CTX *ctx, - unsigned char *aad, size_t aad_len, - const unsigned char *in, size_t in_len, - unsigned char *out, - unsigned char *tag, size_t taglen) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; - unsigned int fc; - int rc; - - kma->taadl = aad_len << 3; - kma->tpcl = in_len << 3; - fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC; - s390x_kma(aad, aad_len, in, in_len, out, fc, kma); - - if (ctx->enc) { - memcpy(tag, kma->t.b, taglen); - rc = 1; - } else { - rc = (CRYPTO_memcmp(tag, kma->t.b, taglen) == 0); - } - return rc; -} - -/* - * Process additional authenticated data. Returns 1 on success. Code is - * big-endian. - */ -static int s390x_aes_gcm_aad_update(PROV_GCM_CTX *ctx, - const unsigned char *aad, size_t len) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; - unsigned long long alen; - unsigned int fc; - int n, rem; - - /* If already processed pt/ct then error */ - if (kma->tpcl != 0) - return 0; - - /* update the total aad length */ - alen = kma->taadl + len; - if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len)) - return 0; - kma->taadl = alen; - - /* check if there is any existing aad data from a previous add */ - n = actx->plat.s390x.areslen; - if (n) { - /* add additional data to a buffer until it has 16 bytes */ - while (n && len) { - actx->plat.s390x.ares[n] = *aad; - ++aad; - --len; - n = (n + 1) & 0xf; - } - /* ctx->ares contains a complete block if offset has wrapped around */ - if (!n) { - fc = S390X_gcm_fc(actx, ctx); - s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL, fc, kma); - actx->plat.s390x.hsflag = S390X_KMA_HS; - } - actx->plat.s390x.areslen = n; - } - - /* If there are leftover bytes (< 128 bits) save them for next time */ - rem = len & 0xf; - /* Add any remaining 16 byte blocks (128 bit each) */ - len &= ~(size_t)0xf; - if (len) { - fc = S390X_gcm_fc(actx, ctx); - s390x_kma(aad, len, NULL, 0, NULL, fc, kma); - actx->plat.s390x.hsflag = S390X_KMA_HS; - aad += len; - } - - if (rem) { - actx->plat.s390x.areslen = rem; - - do { - --rem; - actx->plat.s390x.ares[rem] = aad[rem]; - } while (rem); - } - return 1; -} - -/*- - * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 1 for - * success. Code is big-endian. - */ -static int s390x_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, - const unsigned char *in, size_t len, - unsigned char *out) -{ - PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; - S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; - const unsigned char *inptr; - unsigned long long mlen; - unsigned int fc; - union { - unsigned int w[4]; - unsigned char b[16]; - } buf; - size_t inlen; - int n, rem, i; - - mlen = kma->tpcl + len; - if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) - return 0; - kma->tpcl = mlen; - - fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD; - n = actx->plat.s390x.mreslen; - if (n) { - inptr = in; - inlen = len; - while (n && inlen) { - actx->plat.s390x.mres[n] = *inptr; - n = (n + 1) & 0xf; - ++inptr; - --inlen; - } - /* ctx->mres contains a complete block if offset has wrapped around */ - if (!n) { - s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, - actx->plat.s390x.mres, 16, buf.b, fc, kma); - actx->plat.s390x.hsflag = S390X_KMA_HS; - fc |= S390X_KMA_HS; - actx->plat.s390x.areslen = 0; - - /* previous call already encrypted/decrypted its remainder, - * see comment below */ - n = actx->plat.s390x.mreslen; - while (n) { - *out = buf.b[n]; - n = (n + 1) & 0xf; - ++out; - ++in; - --len; - } - actx->plat.s390x.mreslen = 0; - } - } - - rem = len & 0xf; - - len &= ~(size_t)0xf; - if (len) { - s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out, - fc, kma); - in += len; - out += len; - actx->plat.s390x.hsflag = S390X_KMA_HS; - actx->plat.s390x.areslen = 0; - } - - /*- - * If there is a remainder, it has to be saved such that it can be - * processed by kma later. However, we also have to do the for-now - * unauthenticated encryption/decryption part here and now... - */ - if (rem) { - if (!actx->plat.s390x.mreslen) { - buf.w[0] = kma->j0.w[0]; - buf.w[1] = kma->j0.w[1]; - buf.w[2] = kma->j0.w[2]; - buf.w[3] = kma->cv.w + 1; - s390x_km(buf.b, 16, actx->plat.s390x.kres, - fc & 0x1f, &kma->k); - } - - n = actx->plat.s390x.mreslen; - for (i = 0; i < rem; i++) { - actx->plat.s390x.mres[n + i] = in[i]; - out[i] = in[i] ^ actx->plat.s390x.kres[n + i]; - } - actx->plat.s390x.mreslen += rem; - } - return 1; -} - -static const PROV_GCM_HW s390x_aes_gcm = { - s390x_aes_gcm_initkey, - s390x_aes_gcm_setiv, - s390x_aes_gcm_aad_update, - s390x_aes_gcm_cipher_update, - s390x_aes_gcm_cipher_final, - s390x_aes_gcm_one_shot -}; - -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_s390x(size_t keybits) -{ - if ((keybits == 128 && S390X_aes_128_gcm_CAPABLE) - || (keybits == 192 && S390X_aes_192_gcm_CAPABLE) - || (keybits == 256 && S390X_aes_256_gcm_CAPABLE)) - return &s390x_aes_gcm; - return NULL; -} - -/* MODES: CCM */ - -#define S390X_CCM_AAD_FLAG 0x40 - -static int s390x_aes_ccm_initkey(PROV_CCM_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; - - sctx->ccm.s390x.fc = S390X_AES_FC(keylen); - memcpy(&sctx->ccm.s390x.kmac.k, key, keylen); - /* Store encoded m and l. */ - sctx->ccm.s390x.nonce.b[0] = ((ctx->l - 1) & 0x7) - | (((ctx->m - 2) >> 1) & 0x7) << 3; - memset(sctx->ccm.s390x.nonce.b + 1, 0, sizeof(sctx->ccm.s390x.nonce.b)); - sctx->ccm.s390x.blocks = 0; - ctx->key_set = 1; - return 1; -} - -static int s390x_aes_ccm_setiv(PROV_CCM_CTX *ctx, - const unsigned char *nonce, size_t noncelen, - size_t mlen) -{ - PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; - - sctx->ccm.s390x.nonce.b[0] &= ~S390X_CCM_AAD_FLAG; - sctx->ccm.s390x.nonce.g[1] = mlen; - memcpy(sctx->ccm.s390x.nonce.b + 1, nonce, 15 - ctx->l); - return 1; -} - -/*- - * Process additional authenticated data. Code is big-endian. - */ -static int s390x_aes_ccm_setaad(PROV_CCM_CTX *ctx, - const unsigned char *aad, size_t alen) -{ - PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; - unsigned char *ptr; - int i, rem; - - if (!alen) - return 1; - - sctx->ccm.s390x.nonce.b[0] |= S390X_CCM_AAD_FLAG; - - /* Suppress 'type-punned pointer dereference' warning. */ - ptr = sctx->ccm.s390x.buf.b; - - if (alen < ((1 << 16) - (1 << 8))) { - *(uint16_t *)ptr = alen; - i = 2; - } else if (sizeof(alen) == 8 - && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { - *(uint16_t *)ptr = 0xffff; - *(uint64_t *)(ptr + 2) = alen; - i = 10; - } else { - *(uint16_t *)ptr = 0xfffe; - *(uint32_t *)(ptr + 2) = alen; - i = 6; - } - - while (i < 16 && alen) { - sctx->ccm.s390x.buf.b[i] = *aad; - ++aad; - --alen; - ++i; - } - while (i < 16) { - sctx->ccm.s390x.buf.b[i] = 0; - ++i; - } - - sctx->ccm.s390x.kmac.icv.g[0] = 0; - sctx->ccm.s390x.kmac.icv.g[1] = 0; - s390x_kmac(sctx->ccm.s390x.nonce.b, 32, sctx->ccm.s390x.fc, - &sctx->ccm.s390x.kmac); - sctx->ccm.s390x.blocks += 2; - - rem = alen & 0xf; - alen &= ~(size_t)0xf; - if (alen) { - s390x_kmac(aad, alen, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); - sctx->ccm.s390x.blocks += alen >> 4; - aad += alen; - } - if (rem) { - for (i = 0; i < rem; i++) - sctx->ccm.s390x.kmac.icv.b[i] ^= aad[i]; - - s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, - sctx->ccm.s390x.kmac.icv.b, sctx->ccm.s390x.fc, - sctx->ccm.s390x.kmac.k); - sctx->ccm.s390x.blocks++; - } - return 1; -} - -/*- - * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for - * success. - */ -static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX *ctx, - const unsigned char *in, - unsigned char *out, size_t len, int enc) -{ - PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; - size_t n, rem; - unsigned int i, l, num; - unsigned char flags; - - flags = sctx->ccm.s390x.nonce.b[0]; - if (!(flags & S390X_CCM_AAD_FLAG)) { - s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.kmac.icv.b, - sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); - sctx->ccm.s390x.blocks++; - } - l = flags & 0x7; - sctx->ccm.s390x.nonce.b[0] = l; - - /*- - * Reconstruct length from encoded length field - * and initialize it with counter value. - */ - n = 0; - for (i = 15 - l; i < 15; i++) { - n |= sctx->ccm.s390x.nonce.b[i]; - sctx->ccm.s390x.nonce.b[i] = 0; - n <<= 8; - } - n |= sctx->ccm.s390x.nonce.b[15]; - sctx->ccm.s390x.nonce.b[15] = 1; - - if (n != len) - return 0; /* length mismatch */ - - if (enc) { - /* Two operations per block plus one for tag encryption */ - sctx->ccm.s390x.blocks += (((len + 15) >> 4) << 1) + 1; - if (sctx->ccm.s390x.blocks > (1ULL << 61)) - return 0; /* too much data */ - } - - num = 0; - rem = len & 0xf; - len &= ~(size_t)0xf; - - if (enc) { - /* mac-then-encrypt */ - if (len) - s390x_kmac(in, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); - if (rem) { - for (i = 0; i < rem; i++) - sctx->ccm.s390x.kmac.icv.b[i] ^= in[len + i]; - - s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, - sctx->ccm.s390x.kmac.icv.b, - sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); - } - - CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks, - sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b, - &num, (ctr128_f)AES_ctr32_encrypt); - } else { - /* decrypt-then-mac */ - CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks, - sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b, - &num, (ctr128_f)AES_ctr32_encrypt); - - if (len) - s390x_kmac(out, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); - if (rem) { - for (i = 0; i < rem; i++) - sctx->ccm.s390x.kmac.icv.b[i] ^= out[len + i]; - - s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, - sctx->ccm.s390x.kmac.icv.b, - sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); - } - } - /* encrypt tag */ - for (i = 15 - l; i < 16; i++) - sctx->ccm.s390x.nonce.b[i] = 0; - - s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.buf.b, - sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); - sctx->ccm.s390x.kmac.icv.g[0] ^= sctx->ccm.s390x.buf.g[0]; - sctx->ccm.s390x.kmac.icv.g[1] ^= sctx->ccm.s390x.buf.g[1]; - - sctx->ccm.s390x.nonce.b[0] = flags; /* restore flags field */ - return 1; -} - -static int s390x_aes_ccm_gettag(PROV_CCM_CTX *ctx, - unsigned char *tag, size_t tlen) -{ - PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; - - if (tlen > ctx->m) - return 0; - memcpy(tag, sctx->ccm.s390x.kmac.icv.b, tlen); - return 1; -} - -static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX *ctx, - const unsigned char *in, - unsigned char *out, size_t len, - unsigned char *tag, size_t taglen) -{ - int rv; - - rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 1); - if (rv && tag != NULL) - rv = s390x_aes_ccm_gettag(ctx, tag, taglen); - return rv; -} - -static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX *ctx, - const unsigned char *in, - unsigned char *out, size_t len, - unsigned char *expected_tag, - size_t taglen) -{ - int rv = 0; - PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; - - rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 0); - if (rv) { - if (CRYPTO_memcmp(sctx->ccm.s390x.kmac.icv.b, expected_tag, ctx->m) != 0) - rv = 0; - } - if (rv == 0) - OPENSSL_cleanse(out, len); - return rv; -} - -static const PROV_CCM_HW s390x_aes_ccm = { - s390x_aes_ccm_initkey, - s390x_aes_ccm_setiv, - s390x_aes_ccm_setaad, - s390x_aes_ccm_auth_encrypt, - s390x_aes_ccm_auth_decrypt, - s390x_aes_ccm_gettag -}; - -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_s390x(size_t keybits) -{ - if ((keybits == 128 && S390X_aes_128_ccm_CAPABLE) - || (keybits == 192 && S390X_aes_192_ccm_CAPABLE) - || (keybits == 256 && S390X_aes_256_ccm_CAPABLE)) - return &s390x_aes_ccm; - return NULL; -} - -#endif - -/* MODES: XTS */ - -#if defined(AES_XTS_S390X) - -int s390x_aes_xts_cipher_stream(PROV_AES_XTS_CTX *xctx, - unsigned char *out, size_t *outl, - const unsigned char *in, size_t inl) -{ - S390X_KM_XTS_PARAMS *km = &xctx->plat.s390x.param.km; - unsigned char *param = (unsigned char *)km + xctx->plat.s390x.offset; - unsigned int fc = xctx->plat.s390x.fc; - unsigned char tmp[2][AES_BLOCK_SIZE]; - unsigned char nap_n1[AES_BLOCK_SIZE]; - unsigned char drop[AES_BLOCK_SIZE]; - size_t len_incomplete, len_complete; - - len_incomplete = inl % AES_BLOCK_SIZE; - len_complete = (len_incomplete == 0) ? inl : (inl / AES_BLOCK_SIZE - 1) * AES_BLOCK_SIZE; - - if (len_complete > 0) - s390x_km(in, len_complete, out, fc, param); - if (len_incomplete == 0) - goto out; - - memcpy(tmp, in + len_complete, AES_BLOCK_SIZE + len_incomplete); - /* swap NAP for decrypt */ - if (fc & S390X_DECRYPT) { - memcpy(nap_n1, km->nap, AES_BLOCK_SIZE); - s390x_km(tmp[0], AES_BLOCK_SIZE, drop, fc, param); - } - s390x_km(tmp[0], AES_BLOCK_SIZE, tmp[0], fc, param); - if (fc & S390X_DECRYPT) - memcpy(km->nap, nap_n1, AES_BLOCK_SIZE); - - memcpy(tmp[1] + len_incomplete, tmp[0] + len_incomplete, - AES_BLOCK_SIZE - len_incomplete); - s390x_km(tmp[1], AES_BLOCK_SIZE, out + len_complete, fc, param); - memcpy(out + len_complete + AES_BLOCK_SIZE, tmp[0], len_incomplete); - - /* do not expose temporary data */ - OPENSSL_cleanse(tmp, sizeof(tmp)); -out: - memcpy(xctx->base.iv, km->tweak, AES_BLOCK_SIZE); - *outl = inl; - - return 1; -} - -static int cipher_hw_aes_xts_s390x_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; - S390X_KM_XTS_PARAMS *km = &xctx->plat.s390x.param.km; - unsigned int fc, offs; - unsigned int dec = 0; - int supported = 0; - - if (key != NULL) { - switch (keylen) { - case 128 / 8 * 2: - fc = S390X_XTS_AES_128_MSA10; - offs = 32; - break; - case 256 / 8 * 2: - fc = S390X_XTS_AES_256_MSA10; - offs = 0; - break; - default: - fc = 0; - break; - } - } else { - fc = xctx->plat.s390x.fc & ~S390X_DECRYPT; - offs = xctx->plat.s390x.offset; - } - - if (fc != 0) - supported = (OPENSSL_s390xcap_P.km[1] && S390X_CAPBIT(fc)); - if (!supported) { - xctx->plat.s390x.fc = 0; - xctx->plat.s390x.offset = 0; - return 0; - } - - if (xctx->base.iv_set) { - if (xctx->base.ivlen > sizeof(km->tweak)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); - return 0; - } - memcpy(km->tweak, xctx->base.iv, xctx->base.ivlen); - xctx->plat.s390x.iv_set = 1; - } - - if (key != NULL) { - memcpy(km->key + offs, key, keylen); - xctx->plat.s390x.key_set = 1; - } - - if (xctx->base.enc == 0) - dec = S390X_DECRYPT; - - xctx->plat.s390x.fc = fc | dec; - xctx->plat.s390x.offset = offs; - - memset(km->nap, 0, sizeof(km->nap)); - km->nap[0] = 0x1; - - return 1; -} - -static void cipher_hw_aes_xts_s390x_copyctx(PROV_CIPHER_CTX *dst, - const PROV_CIPHER_CTX *src) -{ - PROV_AES_XTS_CTX *sctx = (PROV_AES_XTS_CTX *)src; - PROV_AES_XTS_CTX *dctx = (PROV_AES_XTS_CTX *)dst; - - *dctx = *sctx; - dctx->xts.key1 = NULL; - dctx->xts.key2 = NULL; -} - -static const PROV_CIPHER_HW aes_xts_s390x = { - cipher_hw_aes_xts_s390x_initkey, - NULL, - cipher_hw_aes_xts_s390x_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_s390x(size_t keybits) -{ - switch (keybits) { - case (128 * 2): - if (OPENSSL_s390xcap_P.km[1] && S390X_CAPBIT(S390X_XTS_AES_128_MSA10)) - return &aes_xts_s390x; - break; - case (256 * 2): - if (OPENSSL_s390xcap_P.km[1] && S390X_CAPBIT(S390X_XTS_AES_256_MSA10)) - return &aes_xts_s390x; - break; - default: - break; - } - - return NULL; -} - -#endif diff --git a/providers/implementations/ciphers/cipher_aes_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc new file mode 100644 index 0000000000..be82d3be9b --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc @@ -0,0 +1,113 @@ +/* + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#include "arch/s390x_arch.h" + +#include + +#define s390x_aes_cbc_initkey cipher_hw_aes_initkey +#define s390x_aes_ctr_initkey cipher_hw_aes_initkey +#define s390x_aes_cbc_cipher_hw ossl_cipher_hw_generic_cbc +#define s390x_aes_ctr_cipher_hw ossl_cipher_hw_generic_ctr + +#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE +#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE +#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE + +static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + adat->plat.s390x.fc = S390X_AES_FC(keylen); + memcpy(adat->plat.s390x.param.km.k, key, keylen); + return 1; +} + +static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; + + s390x_km(in, len, out, adat->plat.s390x.fc | modifier, + &adat->plat.s390x.param.km); + return 1; +} + +static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); + adat->plat.s390x.fc = S390X_AES_FC(keylen); + return 1; +} + +static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + int n = dat->num; + int rem; + + memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); + while (n && len) { + *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n]; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmo(in, len, out, adat->plat.s390x.fc, + &adat->plat.s390x.param.kmo_kmf); + + out += len; + in += len; + } + + if (rem) { + s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, + adat->plat.s390x.param.kmo_kmf.cv, + adat->plat.s390x.fc, + adat->plat.s390x.param.kmo_kmf.k); + + while (rem--) { + out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n]; + ++n; + } + } + + memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); + dat->num = n; + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW s390x_aes_##mode = { \ + s390x_aes_##mode##_initkey, \ + s390x_aes_##mode##_cipher_hw, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \ + || (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \ + || (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \ + return &s390x_aes_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_hw_t4.c b/providers/implementations/ciphers/cipher_aes_hw_t4.c deleted file mode 100644 index 514a7a737f..0000000000 --- a/providers/implementations/ciphers/cipher_aes_hw_t4.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2001-2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/*- - * Sparc t4 support for all hardware accelerated AES modes. - */ - -#include "internal/deprecated.h" -#include -#include "cipher_aes.h" -#include "cipher_aes_gcm.h" -#include "cipher_aes_ccm.h" -#include "cipher_aes_xts.h" - -#if defined(SPARC_AES_CAPABLE) - -/* MODES: ecb, cbc, cfb, ofb, ctr */ - -static int t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks) -{ - aes_t4_set_encrypt_key(key, bits, ks); - return 0; -} - -static int t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks) -{ - aes_t4_set_decrypt_key(key, bits, ks); - return 0; -} - -static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - cbc128_f fn_cbc = NULL; - if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE) - && !ctx->enc) { - switch (keylen) { - case 16: - fn_cbc = (cbc128_f)aes128_t4_cbc_decrypt; - break; - case 24: - fn_cbc = (cbc128_f)aes192_t4_cbc_decrypt; - break; - case 32: - fn_cbc = (cbc128_f)aes256_t4_cbc_decrypt; - break; - default: - ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); - return 0; - } - return ossl_cipher_set_aes_initkey(ctx, key, keylen, t4_set_decrypt_key, - aes_t4_decrypt, NULL, fn_cbc, NULL); - } else { - ctr128_f fn_ctr = NULL; - switch (keylen) { - case 16: - fn_cbc = (cbc128_f)aes128_t4_cbc_encrypt; - fn_ctr = (ctr128_f)aes128_t4_ctr32_encrypt; - break; - case 24: - fn_cbc = (cbc128_f)aes192_t4_cbc_encrypt; - fn_ctr = (ctr128_f)aes192_t4_ctr32_encrypt; - break; - case 32: - fn_cbc = (cbc128_f)aes256_t4_cbc_encrypt; - fn_ctr = (ctr128_f)aes256_t4_ctr32_encrypt; - break; - default: - ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); - return 0; - } - return ossl_cipher_set_aes_initkey(ctx, key, keylen, t4_set_encrypt_key, - aes_t4_encrypt, NULL, fn_cbc, fn_ctr); - } -} - -static const PROV_CIPHER_HW aes_t4_ecb = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_ecb, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_t4_cbc = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_cbc, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_t4_cfb128 = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_cfb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_t4_cfb8 = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_cfb8, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_t4_cfb1 = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_cfb1, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_t4_ofb128 = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_ofb128, - ossl_cipher_aes_copyctx -}; - -static const PROV_CIPHER_HW aes_t4_ctr = { - cipher_hw_aes_t4_initkey, - ossl_cipher_hw_generic_ctr, - ossl_cipher_aes_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_t4(enum aes_modes mode) -{ - if (SPARC_AES_CAPABLE) { - switch (mode) { - case AES_MODE_ECB: - return &aes_t4_ecb; - case AES_MODE_CBC: - return &aes_t4_cbc; - case AES_MODE_CFB128: - return &aes_t4_cfb128; - case AES_MODE_CFB8: - return &aes_t4_cfb8; - case AES_MODE_CFB1: - return &aes_t4_cfb1; - case AES_MODE_OFB128: - return &aes_t4_ofb128; - case AES_MODE_CTR: - return &aes_t4_ctr; - default: - return NULL; - } - } - return NULL; -} - -/* MODES: GCM */ - -static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - switch (keylen) { - case 16: - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - t4_set_encrypt_key, aes_t4_encrypt, - (ctr128_f)aes128_t4_ctr32_encrypt); - case 24: - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - t4_set_encrypt_key, aes_t4_encrypt, - (ctr128_f)aes192_t4_ctr32_encrypt); - case 32: - return ossl_aes_gcm_hw_initkey(ctx, key, keylen, - t4_set_encrypt_key, aes_t4_encrypt, - (ctr128_f)aes256_t4_ctr32_encrypt); - default: - return 0; - } -} - -static const PROV_GCM_HW t4_aes_gcm = { - t4_aes_gcm_initkey, - ossl_gcm_setiv, - ossl_gcm_aad_update, - ossl_generic_aes_gcm_cipher_update, - ossl_gcm_cipher_final, - ossl_gcm_one_shot -}; - -const PROV_GCM_HW *ossl_prov_aes_hw_gcm_t4(void) -{ - return SPARC_AES_CAPABLE ? &t4_aes_gcm : NULL; -} - -/* MODES: CCM */ - -static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, - size_t keylen) -{ - return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen, - t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL); -} - -static const PROV_CCM_HW t4_aes_ccm = { - ccm_t4_aes_initkey, - ossl_ccm_generic_setiv, - ossl_ccm_generic_setaad, - ossl_ccm_generic_auth_encrypt, - ossl_ccm_generic_auth_decrypt, - ossl_ccm_generic_gettag -}; - -const PROV_CCM_HW *ossl_prov_aes_hw_ccm_t4(void) -{ - if (SPARC_AES_CAPABLE) - return &t4_aes_ccm; - return NULL; -} - -/* MODES: XTS */ - -static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen) -{ - OSSL_xts_stream_fn stream_enc = NULL; - OSSL_xts_stream_fn stream_dec = NULL; - - /* Note: keylen is the size of 2 keys */ - switch (keylen) { - case 32: - stream_enc = aes128_t4_xts_encrypt; - stream_dec = aes128_t4_xts_decrypt; - break; - case 64: - stream_enc = aes256_t4_xts_encrypt; - stream_dec = aes256_t4_xts_decrypt; - break; - default: - return 0; - } - - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - t4_set_encrypt_key, t4_set_decrypt_key, - aes_t4_encrypt, aes_t4_decrypt, stream_enc, stream_dec); -} - -static const PROV_CIPHER_HW aes_xts_t4 = { - cipher_hw_aes_xts_t4_initkey, - NULL, - ossl_cipher_hw_aes_xts_copyctx -}; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_t4(void) -{ - if (SPARC_AES_CAPABLE) - return &aes_xts_t4; - return NULL; -} - -#endif diff --git a/providers/implementations/ciphers/cipher_aes_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_hw_t4.inc new file mode 100644 index 0000000000..28454fc508 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_t4.inc @@ -0,0 +1,96 @@ +/* + * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret, bits; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = (const void *)ks; /* used by cipher_hw_generic_XXX */ + + bits = keylen * 8; + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = 0; + aes_t4_set_decrypt_key(key, bits, ks); + dat->block = (block128_f)aes_t4_decrypt; + switch (bits) { + case 128: + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f)aes128_t4_cbc_decrypt : NULL; + break; + case 192: + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f)aes192_t4_cbc_decrypt : NULL; + break; + case 256: + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f)aes256_t4_cbc_decrypt : NULL; + break; + default: + ret = -1; + } + } else { + ret = 0; + aes_t4_set_encrypt_key(key, bits, ks); + dat->block = (block128_f)aes_t4_encrypt; + switch (bits) { + case 128: + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 192: + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 256: + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + default: + ret = -1; + } + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW aes_t4_##mode = { \ + cipher_hw_aes_t4_initkey, \ + ossl_cipher_hw_generic_##mode, \ + cipher_hw_aes_copyctx \ +}; +#define PROV_CIPHER_HW_select(mode) \ + if (SPARC_AES_CAPABLE) \ + return &aes_t4_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_ocb.c b/providers/implementations/ciphers/cipher_aes_ocb.c index 1bd5281cc2..329d4bfa3e 100644 --- a/providers/implementations/ciphers/cipher_aes_ocb.c +++ b/providers/implementations/ciphers/cipher_aes_ocb.c @@ -376,7 +376,7 @@ static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[]) ctx->taglen = p.tag->data_size; } else { if (ctx->base.enc) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED); + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } if (p.tag->data_size != ctx->taglen) { @@ -476,11 +476,7 @@ static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[]) ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return 0; } - if (!ctx->base.enc) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET); - return 0; - } - if (p.tag->data_size != ctx->taglen) { + if (!ctx->base.enc || p.tag->data_size != ctx->taglen) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH); return 0; } diff --git a/providers/implementations/ciphers/cipher_aes_xts.c b/providers/implementations/ciphers/cipher_aes_xts.c index 54820469a9..a630b25eb3 100644 --- a/providers/implementations/ciphers/cipher_aes_xts.c +++ b/providers/implementations/ciphers/cipher_aes_xts.c @@ -63,6 +63,10 @@ static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes, return 1; } +#ifdef AES_XTS_S390X +#include "cipher_aes_xts_s390x.inc" +#endif + /*- * Provider dispatch functions */ @@ -92,13 +96,6 @@ static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen, if (!ctx->hw->init(ctx, key, keylen)) return 0; } -#ifdef AES_XTS_S390X - else if (xctx->plat.s390x.fc && ctx->iv_set) { - /* special handle iv-only update */ - if (!ctx->hw->init(ctx, NULL, 0)) - return 0; - } -#endif return aes_xts_set_ctx_params(ctx, params); } @@ -106,6 +103,10 @@ static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen, const unsigned char *iv, size_t ivlen, const OSSL_PARAM params[]) { +#ifdef AES_XTS_S390X + if (s390x_aes_xts_einit(vctx, key, keylen, iv, ivlen, params) == 1) + return 1; +#endif return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 1); } @@ -113,6 +114,10 @@ static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen, const unsigned char *iv, size_t ivlen, const OSSL_PARAM params[]) { +#ifdef AES_XTS_S390X + if (s390x_aes_xts_dinit(vctx, key, keylen, iv, ivlen, params) == 1) + return 1; +#endif return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 0); } @@ -147,6 +152,11 @@ static void *aes_xts_dupctx(void *vctx) if (!ossl_prov_is_running()) return NULL; +#ifdef AES_XTS_S390X + if (in->plat.s390x.fc) + return s390x_aes_xts_dupctx(vctx); +#endif + if (in->xts.key1 != NULL) { if (in->xts.key1 != &in->ks1) return NULL; @@ -167,23 +177,19 @@ static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl, { PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; - if (!ossl_prov_is_running() - || inl < AES_BLOCK_SIZE - || in == NULL - || out == NULL) - return 0; - #ifdef AES_XTS_S390X - if (ctx->plat.s390x.fc) { - if (!ctx->plat.s390x.iv_set || !ctx->plat.s390x.key_set) - return 0; - } else + if (ctx->plat.s390x.fc) + return s390x_aes_xts_cipher(vctx, out, outl, outsize, in, inl); #endif - { - if (ctx->xts.key1 == NULL || ctx->xts.key2 == NULL - || !ctx->base.iv_set) - return 0; - } + + if (!ossl_prov_is_running() + || ctx->xts.key1 == NULL + || ctx->xts.key2 == NULL + || !ctx->base.iv_set + || out == NULL + || in == NULL + || inl < AES_BLOCK_SIZE) + return 0; /* * Impose a limit of 2^20 blocks per data unit as specified by @@ -196,11 +202,6 @@ static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl, return 0; } -#ifdef AES_XTS_S390X - if (ctx->plat.s390x.fc) - return s390x_aes_xts_cipher_stream(ctx, out, outl, in, inl); -#endif - if (ctx->stream != NULL) (*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv); else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl, diff --git a/providers/implementations/ciphers/cipher_aes_xts.h b/providers/implementations/ciphers/cipher_aes_xts.h index 49ee66ac88..18dc295e47 100644 --- a/providers/implementations/ciphers/cipher_aes_xts.h +++ b/providers/implementations/ciphers/cipher_aes_xts.h @@ -60,39 +60,6 @@ typedef struct prov_aes_xts_ctx_st { } plat; } PROV_AES_XTS_CTX; -int ossl_cipher_set_aes_xts_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen, - aes_set_encrypt_key_fn fn_set_enc_key, - aes_set_encrypt_key_fn fn_set_dec_key, - aes_block128_f fn_block_enc, aes_block128_f fn_block_dec, - OSSL_xts_stream_fn fn_stream_enc, OSSL_xts_stream_fn fn_stream_dec); - -void ossl_cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst, - const PROV_CIPHER_CTX *src); - -#if defined(AESNI_CAPABLE) -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_aesni(void); -#endif - -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv32i(void); -#endif - -#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv64i(void); -#endif - -#ifdef AES_XTS_S390X -int s390x_aes_xts_cipher_stream(PROV_AES_XTS_CTX *xctx, - unsigned char *out, size_t *outl, - const unsigned char *in, size_t inl); -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_s390x(size_t keybits); -#endif - -#if defined(SPARC_AES_CAPABLE) -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_t4(void); -#endif - const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits); #endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_XTS_H) */ diff --git a/providers/implementations/ciphers/cipher_aes_xts_hw.c b/providers/implementations/ciphers/cipher_aes_xts_hw.c index 162f8e4593..022fbc7ff0 100644 --- a/providers/implementations/ciphers/cipher_aes_xts_hw.c +++ b/providers/implementations/ciphers/cipher_aes_xts_hw.c @@ -15,37 +15,32 @@ #include "cipher_aes_xts.h" -int ossl_cipher_set_aes_xts_initkey(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen, - aes_set_encrypt_key_fn fn_set_enc_key, - aes_set_encrypt_key_fn fn_set_dec_key, - aes_block128_f fn_block_enc, aes_block128_f fn_block_dec, - OSSL_xts_stream_fn fn_stream_enc, OSSL_xts_stream_fn fn_stream_dec) -{ - PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; - size_t bytes = keylen / 2; - size_t bits = bytes * 8; - - if (ctx->enc) { - fn_set_enc_key(key, (int)bits, &xctx->ks1.ks); - xctx->xts.block1 = (block128_f)fn_block_enc; - } else { - fn_set_dec_key(key, (int)bits, &xctx->ks1.ks); - xctx->xts.block1 = (block128_f)fn_block_dec; +#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \ + fn_block_enc, fn_block_dec, \ + fn_stream_enc, fn_stream_dec) \ + { \ + size_t bytes = keylen / 2; \ + size_t bits = bytes * 8; \ + \ + if (ctx->enc) { \ + fn_set_enc_key(key, (int)bits, &xctx->ks1.ks); \ + xctx->xts.block1 = (block128_f)fn_block_enc; \ + } else { \ + fn_set_dec_key(key, (int)bits, &xctx->ks1.ks); \ + xctx->xts.block1 = (block128_f)fn_block_dec; \ + } \ + fn_set_enc_key(key + bytes, (int)bits, &xctx->ks2.ks); \ + xctx->xts.block2 = (block128_f)fn_block_enc; \ + xctx->xts.key1 = &xctx->ks1; \ + xctx->xts.key2 = &xctx->ks2; \ + xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec; \ } - fn_set_enc_key(key + bytes, (int)bits, &xctx->ks2.ks); - xctx->xts.block2 = (block128_f)fn_block_enc; - xctx->xts.key1 = &xctx->ks1; - xctx->xts.key2 = &xctx->ks2; - xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec; - - return 1; -} static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx, const unsigned char *key, size_t keylen) { + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; OSSL_xts_stream_fn stream_enc = NULL; OSSL_xts_stream_fn stream_dec = NULL; @@ -62,36 +57,37 @@ static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx, #ifdef HWAES_xts_decrypt stream_dec = HWAES_xts_decrypt; #endif /* HWAES_xts_decrypt */ - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - HWAES_set_encrypt_key, HWAES_set_decrypt_key, - HWAES_encrypt, HWAES_decrypt, stream_enc, stream_dec); - } + XTS_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key, + HWAES_encrypt, HWAES_decrypt, + stream_enc, stream_dec); + return 1; + } else #endif /* HWAES_CAPABLE */ #ifdef BSAES_CAPABLE - if (BSAES_CAPABLE) { + if (BSAES_CAPABLE) { stream_enc = ossl_bsaes_xts_encrypt; stream_dec = ossl_bsaes_xts_decrypt; - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_set_decrypt_key, + } else +#endif /* BSAES_CAPABLE */ +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + XTS_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key, + vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec); + return 1; + } else +#endif /* VPAES_CAPABLE */ + { + (void)0; + } + { + XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key, AES_encrypt, AES_decrypt, stream_enc, stream_dec); } -#endif /* BSAES_CAPABLE */ - -#ifdef VPAES_CAPABLE - if (VPAES_CAPABLE) { - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - vpaes_set_encrypt_key, vpaes_set_decrypt_key, - vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec); - } -#endif /* VPAES_CAPABLE */ - - return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen, - AES_set_encrypt_key, AES_set_decrypt_key, - AES_encrypt, AES_decrypt, stream_enc, stream_dec); + return 1; } -void ossl_cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst, +static void cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) { PROV_AES_XTS_CTX *sctx = (PROV_AES_XTS_CTX *)src; @@ -102,30 +98,234 @@ void ossl_cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst, dctx->xts.key2 = &dctx->ks2.ks; } +#if defined(AESNI_CAPABLE) + +static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + + void (*aesni_xts_enc)(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); + void (*aesni_xts_dec)(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); + + aesni_xts_enc = aesni_xts_encrypt; + aesni_xts_dec = aesni_xts_decrypt; + +#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) + if (aesni_xts_avx512_eligible()) { + if (keylen == 64) { + aesni_xts_enc = aesni_xts_256_encrypt_avx512; + aesni_xts_dec = aesni_xts_256_decrypt_avx512; + } else if (keylen == 32) { + aesni_xts_enc = aesni_xts_128_encrypt_avx512; + aesni_xts_dec = aesni_xts_128_decrypt_avx512; + } + } +#endif + + XTS_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key, + aesni_encrypt, aesni_decrypt, + aesni_xts_enc, aesni_xts_dec); + return 1; +} + +#define PROV_CIPHER_HW_declare_xts() \ + static const PROV_CIPHER_HW aesni_xts = { \ + cipher_hw_aesni_xts_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; +#define PROV_CIPHER_HW_select_xts() \ + if (AESNI_CAPABLE) \ + return &aesni_xts; + +#elif defined(SPARC_AES_CAPABLE) + +static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + OSSL_xts_stream_fn stream_enc = NULL; + OSSL_xts_stream_fn stream_dec = NULL; + + /* Note: keylen is the size of 2 keys */ + switch (keylen) { + case 32: + stream_enc = aes128_t4_xts_encrypt; + stream_dec = aes128_t4_xts_decrypt; + break; + case 64: + stream_enc = aes256_t4_xts_encrypt; + stream_dec = aes256_t4_xts_decrypt; + break; + default: + return 0; + } + + XTS_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key, + aes_t4_encrypt, aes_t4_decrypt, + stream_enc, stream_dec); + return 1; +} + +#define PROV_CIPHER_HW_declare_xts() \ + static const PROV_CIPHER_HW aes_xts_t4 = { \ + cipher_hw_aes_xts_t4_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; +#define PROV_CIPHER_HW_select_xts() \ + if (SPARC_AES_CAPABLE) \ + return &aes_xts_t4; + +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 + +static int cipher_hw_aes_xts_rv64i_zknd_zkne_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + OSSL_xts_stream_fn stream_enc = NULL; + OSSL_xts_stream_fn stream_dec = NULL; + + XTS_SET_KEY_FN(rv64i_zkne_set_encrypt_key, rv64i_zknd_set_decrypt_key, + rv64i_zkne_encrypt, rv64i_zknd_decrypt, + stream_enc, stream_dec); + return 1; +} + +static int cipher_hw_aes_xts_rv64i_zvbb_zvkg_zvkned_initkey( + PROV_CIPHER_CTX *ctx, const unsigned char *key, size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + OSSL_xts_stream_fn stream_enc = NULL; + OSSL_xts_stream_fn stream_dec = NULL; + + /* Zvkned only supports 128 and 256 bit keys. */ + if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2) { + XTS_SET_KEY_FN(rv64i_zvkned_set_encrypt_key, + rv64i_zvkned_set_decrypt_key, rv64i_zvkned_encrypt, + rv64i_zvkned_decrypt, + rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt, + rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt); + } else { + XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_encrypt_key, + rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, + stream_enc, stream_dec); + } + return 1; +} + +static int cipher_hw_aes_xts_rv64i_zvkned_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + OSSL_xts_stream_fn stream_enc = NULL; + OSSL_xts_stream_fn stream_dec = NULL; + + /* Zvkned only supports 128 and 256 bit keys. */ + if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2) { + XTS_SET_KEY_FN(rv64i_zvkned_set_encrypt_key, + rv64i_zvkned_set_decrypt_key, + rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, + stream_enc, stream_dec); + } else { + XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_encrypt_key, + rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, + stream_enc, stream_dec); + } + return 1; +} + +#define PROV_CIPHER_HW_declare_xts() \ + static const PROV_CIPHER_HW aes_xts_rv64i_zknd_zkne = { \ + cipher_hw_aes_xts_rv64i_zknd_zkne_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; \ + static const PROV_CIPHER_HW aes_xts_rv64i_zvkned = { \ + cipher_hw_aes_xts_rv64i_zvkned_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; \ + static const PROV_CIPHER_HW aes_xts_rv64i_zvbb_zvkg_zvkned = { \ + cipher_hw_aes_xts_rv64i_zvbb_zvkg_zvkned_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; + +#define PROV_CIPHER_HW_select_xts() \ + if (RISCV_HAS_ZVBB() && RISCV_HAS_ZVKG() && RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) \ + return &aes_xts_rv64i_zvbb_zvkg_zvkned; \ + if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) \ + return &aes_xts_rv64i_zvkned; \ + else if (RISCV_HAS_ZKND_AND_ZKNE()) \ + return &aes_xts_rv64i_zknd_zkne; + +#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 + +static int cipher_hw_aes_xts_rv32i_zknd_zkne_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + + XTS_SET_KEY_FN(rv32i_zkne_set_encrypt_key, rv32i_zknd_zkne_set_decrypt_key, + rv32i_zkne_encrypt, rv32i_zknd_decrypt, + NULL, NULL); + return 1; +} + +static int cipher_hw_aes_xts_rv32i_zbkb_zknd_zkne_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + + XTS_SET_KEY_FN(rv32i_zbkb_zkne_set_encrypt_key, rv32i_zbkb_zknd_zkne_set_decrypt_key, + rv32i_zkne_encrypt, rv32i_zknd_decrypt, + NULL, NULL); + return 1; +} + +#define PROV_CIPHER_HW_declare_xts() \ + static const PROV_CIPHER_HW aes_xts_rv32i_zknd_zkne = { \ + cipher_hw_aes_xts_rv32i_zknd_zkne_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; \ + static const PROV_CIPHER_HW aes_xts_rv32i_zbkb_zknd_zkne = { \ + cipher_hw_aes_xts_rv32i_zbkb_zknd_zkne_initkey, \ + NULL, \ + cipher_hw_aes_xts_copyctx \ + }; +#define PROV_CIPHER_HW_select_xts() \ + if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) \ + return &aes_xts_rv32i_zbkb_zknd_zkne; \ + if (RISCV_HAS_ZKND_AND_ZKNE()) \ + return &aes_xts_rv32i_zknd_zkne; +#else +/* The generic case */ +#define PROV_CIPHER_HW_declare_xts() +#define PROV_CIPHER_HW_select_xts() +#endif + static const PROV_CIPHER_HW aes_generic_xts = { cipher_hw_aes_xts_generic_initkey, NULL, - ossl_cipher_hw_aes_xts_copyctx + cipher_hw_aes_xts_copyctx }; - -const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits) +PROV_CIPHER_HW_declare_xts() + const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits) { - const PROV_CIPHER_HW *aes_xts_hw = NULL; - -#if defined(AESNI_CAPABLE) - aes_xts_hw = ossl_prov_cipher_hw_aes_xts_aesni(); -#elif defined(SPARC_AES_CAPABLE) - aes_xts_hw = ossl_prov_cipher_hw_aes_xts_t4(); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32 - aes_xts_hw = ossl_prov_cipher_hw_aes_xts_rv32i(); -#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 - aes_xts_hw = ossl_prov_cipher_hw_aes_xts_rv64i(); -#elif defined(AES_XTS_S390X) - aes_xts_hw = ossl_prov_cipher_hw_aes_xts_s390x(keybits); -#endif - - if (aes_xts_hw == NULL) - return &aes_generic_xts; - - return aes_xts_hw; + PROV_CIPHER_HW_select_xts() return &aes_generic_xts; } diff --git a/providers/implementations/ciphers/cipher_aes_xts_s390x.inc b/providers/implementations/ciphers/cipher_aes_xts_s390x.inc new file mode 100644 index 0000000000..b13d23581c --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_xts_s390x.inc @@ -0,0 +1,167 @@ +/* + * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "arch/s390x_arch.h" + +static OSSL_FUNC_cipher_encrypt_init_fn s390x_aes_xts_einit; +static OSSL_FUNC_cipher_decrypt_init_fn s390x_aes_xts_dinit; +static OSSL_FUNC_cipher_cipher_fn s390x_aes_xts_cipher; +static OSSL_FUNC_cipher_dupctx_fn s390x_aes_xts_dupctx; + +static int s390x_aes_xts_init(void *vctx, const unsigned char *key, + size_t keylen, const unsigned char *iv, + size_t ivlen, const OSSL_PARAM params[], + unsigned int dec) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx; + S390X_KM_XTS_PARAMS *km = &xctx->plat.s390x.param.km; + unsigned int fc, offs; + + switch (xctx->base.keylen) { + case 128 / 8 * 2: + fc = S390X_XTS_AES_128_MSA10; + offs = 32; + break; + case 256 / 8 * 2: + fc = S390X_XTS_AES_256_MSA10; + offs = 0; + break; + default: + goto not_supported; + } + + if (!(OPENSSL_s390xcap_P.km[1] && S390X_CAPBIT(fc))) + goto not_supported; + + if (iv != NULL) { + if (ivlen != xctx->base.ivlen + || ivlen > sizeof(km->tweak)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return 0; + } + memcpy(km->tweak, iv, ivlen); + xctx->plat.s390x.iv_set = 1; + } + + if (key != NULL) { + if (keylen != xctx->base.keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + if (!aes_xts_check_keys_differ(key, keylen / 2, !dec)) + return 0; + + memcpy(km->key + offs, key, keylen); + xctx->plat.s390x.key_set = 1; + } + + xctx->plat.s390x.fc = fc | dec; + xctx->plat.s390x.offset = offs; + + memset(km->nap, 0, sizeof(km->nap)); + km->nap[0] = 0x1; + + return aes_xts_set_ctx_params(xctx, params); + +not_supported: + xctx->plat.s390x.fc = 0; + xctx->plat.s390x.offset = 0; + return 0; +} + +static int s390x_aes_xts_einit(void *vctx, const unsigned char *key, + size_t keylen, const unsigned char *iv, + size_t ivlen, const OSSL_PARAM params[]) +{ + return s390x_aes_xts_init(vctx, key, keylen, iv, ivlen, params, 0); +} + +static int s390x_aes_xts_dinit(void *vctx, const unsigned char *key, + size_t keylen, const unsigned char *iv, + size_t ivlen, const OSSL_PARAM params[]) +{ + return s390x_aes_xts_init(vctx, key, keylen, iv, ivlen, params, + S390X_DECRYPT); +} + +static void *s390x_aes_xts_dupctx(void *vctx) +{ + PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx; + PROV_AES_XTS_CTX *ret = OPENSSL_zalloc(sizeof(*in)); + + if (ret != NULL) + *ret = *in; + + return ret; +} + +static int s390x_aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx; + S390X_KM_XTS_PARAMS *km = &xctx->plat.s390x.param.km; + unsigned char *param = (unsigned char *)km + xctx->plat.s390x.offset; + unsigned int fc = xctx->plat.s390x.fc; + unsigned char tmp[2][AES_BLOCK_SIZE]; + unsigned char nap_n1[AES_BLOCK_SIZE]; + unsigned char drop[AES_BLOCK_SIZE]; + size_t len_incomplete, len_complete; + + if (!ossl_prov_is_running() + || inl < AES_BLOCK_SIZE + || in == NULL + || out == NULL + || !xctx->plat.s390x.iv_set + || !xctx->plat.s390x.key_set) + return 0; + + /* + * Impose a limit of 2^20 blocks per data unit as specified by + * IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007 + * indicated that this was a SHOULD NOT rather than a MUST NOT. + * NIST SP 800-38E mandates the same limit. + */ + if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) { + ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE); + return 0; + } + + len_incomplete = inl % AES_BLOCK_SIZE; + len_complete = (len_incomplete == 0) ? inl : + (inl / AES_BLOCK_SIZE - 1) * AES_BLOCK_SIZE; + + if (len_complete > 0) + s390x_km(in, len_complete, out, fc, param); + if (len_incomplete == 0) + goto out; + + memcpy(tmp, in + len_complete, AES_BLOCK_SIZE + len_incomplete); + /* swap NAP for decrypt */ + if (fc & S390X_DECRYPT) { + memcpy(nap_n1, km->nap, AES_BLOCK_SIZE); + s390x_km(tmp[0], AES_BLOCK_SIZE, drop, fc, param); + } + s390x_km(tmp[0], AES_BLOCK_SIZE, tmp[0], fc, param); + if (fc & S390X_DECRYPT) + memcpy(km->nap, nap_n1, AES_BLOCK_SIZE); + + memcpy(tmp[1] + len_incomplete, tmp[0] + len_incomplete, + AES_BLOCK_SIZE - len_incomplete); + s390x_km(tmp[1], AES_BLOCK_SIZE, out + len_complete, fc, param); + memcpy(out + len_complete + AES_BLOCK_SIZE, tmp[0], len_incomplete); + + /* do not expose temporary data */ + OPENSSL_cleanse(tmp, sizeof(tmp)); +out: + memcpy(xctx->base.iv, km->tweak, AES_BLOCK_SIZE); + *outl = inl; + + return 1; +} diff --git a/providers/implementations/ciphers/cipher_aria_gcm_hw.c b/providers/implementations/ciphers/cipher_aria_gcm_hw.c index 35f3257d89..f4c8646103 100644 --- a/providers/implementations/ciphers/cipher_aria_gcm_hw.c +++ b/providers/implementations/ciphers/cipher_aria_gcm_hw.c @@ -19,11 +19,7 @@ static int aria_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, PROV_ARIA_GCM_CTX *actx = (PROV_ARIA_GCM_CTX *)ctx; ARIA_KEY *ks = &actx->ks.ks; - ossl_aria_set_encrypt_key(key, (int)(keylen * 8), ks); - CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)ossl_aria_encrypt); - ctx->ctr = NULL; - ctx->key_set = 1; - + GCM_HW_SET_KEY_CTR_FN(ks, ossl_aria_set_encrypt_key, ossl_aria_encrypt, NULL); return 1; } diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c index 31a163e57e..47f4c3cb68 100644 --- a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c +++ b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c @@ -9,7 +9,6 @@ /* chacha20_poly1305 cipher implementation */ -#include #include "internal/endian.h" #include "cipher_chacha20_poly1305.h" @@ -302,10 +301,6 @@ static int chacha20_poly1305_aead_cipher(PROV_CIPHER_CTX *bctx, if (in != NULL) { /* aad or text */ if (out == NULL) { /* aad */ - if (ctx->len.text != 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); - goto err; - } Poly1305_Update(poly, in, inl); ctx->len.aad += inl; ctx->aad = 1; diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c index a6320d2d81..36c3864c9a 100644 --- a/providers/implementations/ciphers/ciphercommon.c +++ b/providers/implementations/ciphers/ciphercommon.c @@ -276,9 +276,15 @@ int ossl_cipher_generic_block_update(void *vctx, unsigned char *out, return 0; } padval = (unsigned char)(padnum - 1); - /* we need to add 'padnum' padding bytes of value padval */ - for (loop = inl; loop < inl + padnum; loop++) - out[loop] = padval; + if (ctx->tlsversion == SSL3_VERSION) { + if (padnum > 1) + memset(out + inl, 0, padnum - 1); + *(out + inl + padnum - 1) = padval; + } else { + /* we need to add 'padnum' padding bytes of value padval */ + for (loop = inl; loop < inl + padnum; loop++) + out[loop] = padval; + } inl += padnum; } diff --git a/providers/implementations/ciphers/ciphercommon_block.c b/providers/implementations/ciphers/ciphercommon_block.c index 8ce491ddca..634bae4c1c 100644 --- a/providers/implementations/ciphers/ciphercommon_block.c +++ b/providers/implementations/ciphers/ciphercommon_block.c @@ -123,7 +123,7 @@ int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize) * time. * * libctx: Our library context - * tlsversion: The TLS version in use, e.g. TLS1_VERSION, etc + * tlsversion: The TLS version in use, e.g. SSL3_VERSION, TLS1_VERSION, etc * buf: The decrypted TLS record data * buflen: The length of the decrypted TLS record data. Updated with the new * length after the padding is removed @@ -147,6 +147,11 @@ int ossl_cipher_tlsunpadblock(OSSL_LIB_CTX *libctx, unsigned int tlsversion, int ret; switch (tlsversion) { + case SSL3_VERSION: + return ssl3_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac, + alloced, blocksize, macsize, + libctx); + case TLS1_2_VERSION: case DTLS1_2_VERSION: case TLS1_1_VERSION: diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c index c93b0767b0..d9be50f513 100644 --- a/providers/implementations/ciphers/ciphercommon_gcm.c +++ b/providers/implementations/ciphers/ciphercommon_gcm.c @@ -215,7 +215,7 @@ int ossl_gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) if (p.tag != NULL) { sz = p.tag->data_size; if (!ctx->enc || ctx->taglen == UNINITIALISED_SIZET) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET); + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); return 0; } if (p.tag->data != NULL && (sz > EVP_GCM_TLS_TAG_LEN || sz == 0)) { @@ -263,11 +263,7 @@ int ossl_gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return 0; } - if (ctx->enc) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED); - return 0; - } - if (sz == 0) { + if (sz == 0 || ctx->enc) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); return 0; } diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c index 6ed99e68fa..964a86ff17 100644 --- a/providers/implementations/encode_decode/decode_der2key.c +++ b/providers/implementations/encode_decode/decode_der2key.c @@ -404,16 +404,11 @@ static int der2key_export_object(void *vctx, /* ---------------------------------------------------------------------- */ #ifndef OPENSSL_NO_DH -static void dh_free_key(void *key) -{ - DH_free(key); -} - #define dh_evp_type EVP_PKEY_DH #define dh_d2i_private_key NULL #define dh_d2i_public_key NULL #define dh_d2i_key_params (d2i_of_void *)d2i_DHparams -#define dh_free dh_free_key +#define dh_free (free_key_fn *)DH_free #define dh_check NULL static void *dh_d2i_PKCS8(const unsigned char **der, long der_len, @@ -436,7 +431,7 @@ static void dh_adjust(void *key, struct der2key_ctx_st *ctx) #define dhx_d2i_public_key NULL #define dhx_d2i_key_params (d2i_of_void *)d2i_DHxparams #define dhx_d2i_PKCS8 dh_d2i_PKCS8 -#define dhx_free dh_free_key +#define dhx_free (free_key_fn *)DH_free #define dhx_check NULL #define dhx_adjust dh_adjust #endif @@ -444,16 +439,11 @@ static void dh_adjust(void *key, struct der2key_ctx_st *ctx) /* ---------------------------------------------------------------------- */ #ifndef OPENSSL_NO_DSA -static void dsa_free_key(void *key) -{ - DSA_free(key); -} - #define dsa_evp_type EVP_PKEY_DSA #define dsa_d2i_private_key (d2i_of_void *)d2i_DSAPrivateKey #define dsa_d2i_public_key (d2i_of_void *)d2i_DSAPublicKey #define dsa_d2i_key_params (d2i_of_void *)d2i_DSAparams -#define dsa_free dsa_free_key +#define dsa_free (free_key_fn *)DSA_free #define dsa_check NULL static void *dsa_d2i_PKCS8(const unsigned char **der, long der_len, @@ -474,16 +464,11 @@ static void dsa_adjust(void *key, struct der2key_ctx_st *ctx) /* ---------------------------------------------------------------------- */ #ifndef OPENSSL_NO_EC -static void ec_free_key(void *key) -{ - EC_KEY_free(key); -} - #define ec_evp_type EVP_PKEY_EC #define ec_d2i_private_key (d2i_of_void *)d2i_ECPrivateKey #define ec_d2i_public_key NULL #define ec_d2i_key_params (d2i_of_void *)d2i_ECParameters -#define ec_free ec_free_key +#define ec_free (free_key_fn *)EC_KEY_free static void *ec_d2i_PKCS8(const unsigned char **der, long der_len, struct der2key_ctx_st *ctx) @@ -537,17 +522,12 @@ static void ecx_key_adjust(void *key, struct der2key_ctx_st *ctx) ossl_ecx_key_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx)); } -static void ecx_free_key(void *key) -{ - ossl_ecx_key_free(key); -} - #define ed25519_evp_type EVP_PKEY_ED25519 #define ed25519_d2i_private_key NULL #define ed25519_d2i_public_key NULL #define ed25519_d2i_key_params NULL #define ed25519_d2i_PKCS8 ecx_d2i_PKCS8 -#define ed25519_free ecx_free_key +#define ed25519_free (free_key_fn *)ossl_ecx_key_free #define ed25519_check NULL #define ed25519_adjust ecx_key_adjust @@ -556,7 +536,7 @@ static void ecx_free_key(void *key) #define ed448_d2i_public_key NULL #define ed448_d2i_key_params NULL #define ed448_d2i_PKCS8 ecx_d2i_PKCS8 -#define ed448_free ecx_free_key +#define ed448_free (free_key_fn *)ossl_ecx_key_free #define ed448_check NULL #define ed448_adjust ecx_key_adjust @@ -565,7 +545,7 @@ static void ecx_free_key(void *key) #define x25519_d2i_public_key NULL #define x25519_d2i_key_params NULL #define x25519_d2i_PKCS8 ecx_d2i_PKCS8 -#define x25519_free ecx_free_key +#define x25519_free (free_key_fn *)ossl_ecx_key_free #define x25519_check NULL #define x25519_adjust ecx_key_adjust @@ -574,7 +554,7 @@ static void ecx_free_key(void *key) #define x448_d2i_public_key NULL #define x448_d2i_key_params NULL #define x448_d2i_PKCS8 ecx_d2i_PKCS8 -#define x448_free ecx_free_key +#define x448_free (free_key_fn *)ossl_ecx_key_free #define x448_check NULL #define x448_adjust ecx_key_adjust #endif /* OPENSSL_NO_ECX */ @@ -585,7 +565,7 @@ static void ecx_free_key(void *key) #define sm2_d2i_public_key NULL #define sm2_d2i_key_params (d2i_of_void *)d2i_ECParameters #define sm2_d2i_PUBKEY ec_d2i_PUBKEY -#define sm2_free ec_free_key +#define sm2_free (free_key_fn *)EC_KEY_free #define sm2_check ec_check #define sm2_adjust ec_adjust @@ -627,18 +607,13 @@ ml_kem_d2i_PUBKEY(const uint8_t **der, long der_len, return key; } -static void ml_kem_free_key(void *key) -{ - ossl_ml_kem_key_free(key); -} - #define ml_kem_512_evp_type EVP_PKEY_ML_KEM_512 #define ml_kem_512_d2i_private_key NULL #define ml_kem_512_d2i_public_key NULL #define ml_kem_512_d2i_key_params NULL #define ml_kem_512_d2i_PUBKEY ml_kem_d2i_PUBKEY #define ml_kem_512_d2i_PKCS8 ml_kem_d2i_PKCS8 -#define ml_kem_512_free ml_kem_free_key +#define ml_kem_512_free (free_key_fn *)ossl_ml_kem_key_free #define ml_kem_512_check NULL #define ml_kem_512_adjust NULL @@ -648,7 +623,7 @@ static void ml_kem_free_key(void *key) #define ml_kem_768_d2i_key_params NULL #define ml_kem_768_d2i_PUBKEY ml_kem_d2i_PUBKEY #define ml_kem_768_d2i_PKCS8 ml_kem_d2i_PKCS8 -#define ml_kem_768_free ml_kem_free_key +#define ml_kem_768_free (free_key_fn *)ossl_ml_kem_key_free #define ml_kem_768_check NULL #define ml_kem_768_adjust NULL @@ -658,18 +633,13 @@ static void ml_kem_free_key(void *key) #define ml_kem_1024_d2i_PUBKEY ml_kem_d2i_PUBKEY #define ml_kem_1024_d2i_PKCS8 ml_kem_d2i_PKCS8 #define ml_kem_1024_d2i_key_params NULL -#define ml_kem_1024_free ml_kem_free_key +#define ml_kem_1024_free (free_key_fn *)ossl_ml_kem_key_free #define ml_kem_1024_check NULL #define ml_kem_1024_adjust NULL #endif #ifndef OPENSSL_NO_SLH_DSA -static void slh_dsa_free_key(void *key) -{ - ossl_slh_dsa_key_free(key); -} - static void * slh_dsa_d2i_PKCS8(const uint8_t **der, long der_len, struct der2key_ctx_st *ctx) { @@ -798,7 +768,7 @@ err: #define slh_dsa_sha2_128s_d2i_key_params NULL #define slh_dsa_sha2_128s_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_sha2_128s_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_sha2_128s_free slh_dsa_free_key +#define slh_dsa_sha2_128s_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_sha2_128s_check NULL #define slh_dsa_sha2_128s_adjust NULL @@ -808,7 +778,7 @@ err: #define slh_dsa_sha2_128f_d2i_key_params NULL #define slh_dsa_sha2_128f_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_sha2_128f_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_sha2_128f_free slh_dsa_free_key +#define slh_dsa_sha2_128f_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_sha2_128f_check NULL #define slh_dsa_sha2_128f_adjust NULL @@ -818,7 +788,7 @@ err: #define slh_dsa_sha2_192s_d2i_key_params NULL #define slh_dsa_sha2_192s_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_sha2_192s_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_sha2_192s_free slh_dsa_free_key +#define slh_dsa_sha2_192s_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_sha2_192s_check NULL #define slh_dsa_sha2_192s_adjust NULL @@ -828,7 +798,7 @@ err: #define slh_dsa_sha2_192f_d2i_key_params NULL #define slh_dsa_sha2_192f_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_sha2_192f_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_sha2_192f_free slh_dsa_free_key +#define slh_dsa_sha2_192f_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_sha2_192f_check NULL #define slh_dsa_sha2_192f_adjust NULL @@ -838,7 +808,7 @@ err: #define slh_dsa_sha2_256s_d2i_key_params NULL #define slh_dsa_sha2_256s_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_sha2_256s_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_sha2_256s_free slh_dsa_free_key +#define slh_dsa_sha2_256s_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_sha2_256s_check NULL #define slh_dsa_sha2_256s_adjust NULL @@ -848,7 +818,7 @@ err: #define slh_dsa_sha2_256f_d2i_key_params NULL #define slh_dsa_sha2_256f_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_sha2_256f_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_sha2_256f_free slh_dsa_free_key +#define slh_dsa_sha2_256f_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_sha2_256f_check NULL #define slh_dsa_sha2_256f_adjust NULL @@ -858,7 +828,7 @@ err: #define slh_dsa_shake_128s_d2i_key_params NULL #define slh_dsa_shake_128s_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_shake_128s_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_shake_128s_free slh_dsa_free_key +#define slh_dsa_shake_128s_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_shake_128s_check NULL #define slh_dsa_shake_128s_adjust NULL @@ -868,7 +838,7 @@ err: #define slh_dsa_shake_128f_d2i_key_params NULL #define slh_dsa_shake_128f_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_shake_128f_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_shake_128f_free slh_dsa_free_key +#define slh_dsa_shake_128f_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_shake_128f_check NULL #define slh_dsa_shake_128f_adjust NULL @@ -878,7 +848,7 @@ err: #define slh_dsa_shake_192s_d2i_key_params NULL #define slh_dsa_shake_192s_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_shake_192s_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_shake_192s_free slh_dsa_free_key +#define slh_dsa_shake_192s_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_shake_192s_check NULL #define slh_dsa_shake_192s_adjust NULL @@ -888,7 +858,7 @@ err: #define slh_dsa_shake_192f_d2i_key_params NULL #define slh_dsa_shake_192f_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_shake_192f_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_shake_192f_free slh_dsa_free_key +#define slh_dsa_shake_192f_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_shake_192f_check NULL #define slh_dsa_shake_192f_adjust NULL @@ -898,7 +868,7 @@ err: #define slh_dsa_shake_256s_d2i_key_params NULL #define slh_dsa_shake_256s_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_shake_256s_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_shake_256s_free slh_dsa_free_key +#define slh_dsa_shake_256s_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_shake_256s_check NULL #define slh_dsa_shake_256s_adjust NULL @@ -908,23 +878,18 @@ err: #define slh_dsa_shake_256f_d2i_key_params NULL #define slh_dsa_shake_256f_d2i_PKCS8 slh_dsa_d2i_PKCS8 #define slh_dsa_shake_256f_d2i_PUBKEY slh_dsa_d2i_PUBKEY -#define slh_dsa_shake_256f_free slh_dsa_free_key +#define slh_dsa_shake_256f_free (free_key_fn *)ossl_slh_dsa_key_free #define slh_dsa_shake_256f_check NULL #define slh_dsa_shake_256f_adjust NULL #endif /* OPENSSL_NO_SLH_DSA */ /* ---------------------------------------------------------------------- */ -static void rsa_free_key(void *key) -{ - RSA_free(key); -} - #define rsa_evp_type EVP_PKEY_RSA #define rsa_d2i_private_key (d2i_of_void *)d2i_RSAPrivateKey #define rsa_d2i_public_key (d2i_of_void *)d2i_RSAPublicKey #define rsa_d2i_key_params NULL -#define rsa_free rsa_free_key +#define rsa_free (free_key_fn *)RSA_free static void *rsa_d2i_PKCS8(const unsigned char **der, long der_len, struct der2key_ctx_st *ctx) @@ -972,18 +937,13 @@ static void rsa_adjust(void *key, struct der2key_ctx_st *ctx) #define rsapss_d2i_key_params NULL #define rsapss_d2i_PKCS8 rsa_d2i_PKCS8 #define rsapss_d2i_PUBKEY rsa_d2i_PUBKEY -#define rsapss_free rsa_free_key +#define rsapss_free (free_key_fn *)RSA_free #define rsapss_check rsa_check #define rsapss_adjust rsa_adjust /* ---------------------------------------------------------------------- */ #ifndef OPENSSL_NO_ML_DSA -static void ml_dsa_free_key(void *key) -{ - ossl_ml_dsa_key_free(key); -} - static void * ml_dsa_d2i_PKCS8(const uint8_t **der, long der_len, struct der2key_ctx_st *ctx) { @@ -1014,7 +974,7 @@ static ossl_inline void *ml_dsa_d2i_PUBKEY(const uint8_t **der, long der_len, #define ml_dsa_44_d2i_key_params NULL #define ml_dsa_44_d2i_PUBKEY ml_dsa_d2i_PUBKEY #define ml_dsa_44_d2i_PKCS8 ml_dsa_d2i_PKCS8 -#define ml_dsa_44_free ml_dsa_free_key +#define ml_dsa_44_free (free_key_fn *)ossl_ml_dsa_key_free #define ml_dsa_44_check NULL #define ml_dsa_44_adjust NULL @@ -1024,7 +984,7 @@ static ossl_inline void *ml_dsa_d2i_PUBKEY(const uint8_t **der, long der_len, #define ml_dsa_65_d2i_key_params NULL #define ml_dsa_65_d2i_PUBKEY ml_dsa_d2i_PUBKEY #define ml_dsa_65_d2i_PKCS8 ml_dsa_d2i_PKCS8 -#define ml_dsa_65_free ml_dsa_free_key +#define ml_dsa_65_free (free_key_fn *)ossl_ml_dsa_key_free #define ml_dsa_65_check NULL #define ml_dsa_65_adjust NULL @@ -1034,7 +994,7 @@ static ossl_inline void *ml_dsa_d2i_PUBKEY(const uint8_t **der, long der_len, #define ml_dsa_87_d2i_PUBKEY ml_dsa_d2i_PUBKEY #define ml_dsa_87_d2i_PKCS8 ml_dsa_d2i_PKCS8 #define ml_dsa_87_d2i_key_params NULL -#define ml_dsa_87_free ml_dsa_free_key +#define ml_dsa_87_free (free_key_fn *)ossl_ml_dsa_key_free #define ml_dsa_87_check NULL #define ml_dsa_87_adjust NULL @@ -1043,13 +1003,8 @@ static ossl_inline void *ml_dsa_d2i_PUBKEY(const uint8_t **der, long der_len, /* ---------------------------------------------------------------------- */ #ifndef OPENSSL_NO_LMS -static void lms_free_key(void *key) -{ - ossl_lms_key_free(key); -} - #define lms_evp_type EVP_PKEY_HSS_LMS -#define lms_free lms_free_key +#define lms_free (free_key_fn *)ossl_lms_key_free #define lms_check NULL #define lms_adjust NULL diff --git a/providers/implementations/encode_decode/encode_key2ms.c b/providers/implementations/encode_decode/encode_key2ms.c index 87b4242923..8ae4022e51 100644 --- a/providers/implementations/encode_decode/encode_key2ms.c +++ b/providers/implementations/encode_decode/encode_key2ms.c @@ -68,11 +68,10 @@ static int write_pvk(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout, return ret; } -static OSSL_FUNC_encoder_newctx_fn key2ms_newctx; static OSSL_FUNC_encoder_freectx_fn key2ms_freectx; static OSSL_FUNC_encoder_does_selection_fn key2ms_does_selection; -static void *key2ms_newctx(void *provctx) +static struct key2ms_ctx_st *key2ms_newctx(void *provctx) { struct key2ms_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); diff --git a/providers/implementations/include/prov/ciphercommon_gcm.h b/providers/implementations/include/prov/ciphercommon_gcm.h index 08865b7595..ba5d0b5f87 100644 --- a/providers/implementations/include/prov/ciphercommon_gcm.h +++ b/providers/implementations/include/prov/ciphercommon_gcm.h @@ -123,4 +123,10 @@ int ossl_gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len, int ossl_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, size_t len, unsigned char *out); +#define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \ + fn_set_enc_key(key, (int)(keylen * 8), ks); \ + CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); \ + ctx->ctr = (ctr128_f)fn_ctr; \ + ctx->key_set = 1; + #endif diff --git a/providers/implementations/include/prov/drbg.h b/providers/implementations/include/prov/drbg.h index 42fd8212ac..c93acba96e 100644 --- a/providers/implementations/include/prov/drbg.h +++ b/providers/implementations/include/prov/drbg.h @@ -23,6 +23,10 @@ /* How many times to read the TSC as a randomness source. */ #define TSC_READ_COUNT 4 +/* Maximum reseed intervals */ +#define MAX_RESEED_INTERVAL (1 << 24) +#define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */ + /* Default reseed intervals */ #define RESEED_INTERVAL (1 << 8) #define TIME_INTERVAL (60 * 60) /* 1 hour */ @@ -42,6 +46,13 @@ typedef struct prov_drbg_st PROV_DRBG; +/* DRBG status values */ +typedef enum drbg_status_e { + DRBG_UNINITIALISED, + DRBG_READY, + DRBG_ERROR +} DRBG_STATUS; + /* * The state of all types of DRBGs. */ @@ -138,11 +149,7 @@ struct prov_drbg_st { unsigned int parent_reseed_counter; size_t seedlen; - /* - * state is one of: EVP_RAND_STATE_UNINITIALISED, EVP_RAND_STATE_ERROR, - * EVP_RAND_STATE_READY. - */ - int state; + DRBG_STATUS state; /* DRBG specific data */ void *data; diff --git a/providers/implementations/kem/template_kem.c b/providers/implementations/kem/template_kem.c index 448b1caf4e..509a31e129 100644 --- a/providers/implementations/kem/template_kem.c +++ b/providers/implementations/kem/template_kem.c @@ -166,7 +166,7 @@ static int template_decapsulate(void *vctx, unsigned char *out, size_t *outlen, if (out == NULL) { if (outlen != NULL) - debug_print("decaps outlen set to %zu\n", *outlen); + debug_print("decaps outlen set to %zu \n", *outlen); return 1; } diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 28404502eb..03c7ea3529 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -250,10 +250,19 @@ static ossl_inline int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *t { int ecdh_cofactor_mode = 0, group_check = 0; const char *name = NULL; + point_conversion_form_t format; if (ec == NULL) return 0; + format = EC_KEY_get_conv_form(ec); + name = ossl_ec_pt_format_id2name((int)format); + if (name != NULL + && !ossl_param_build_set_utf8_string(tmpl, params, + OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + name)) + return 0; + group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK; name = ossl_ec_check_group_type_id2name(group_check); if (name != NULL @@ -503,21 +512,19 @@ static int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0) return 0; - if ((bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec))) == NULL) + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) return 0; - BN_CTX_start(bnctx); - if ((tmpl = OSSL_PARAM_BLD_new()) == NULL) { - ok = 0; - goto end; + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { + bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec)); + if (bnctx == NULL) { + ok = 0; + goto end; + } + BN_CTX_start(bnctx); + ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL, ossl_ec_key_get_libctx(ec), ossl_ec_key_get0_propq(ec), bnctx, &genbuf); } - /* - * OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT is added based on the group's - * asn1_form by the call below. - */ - ok = ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL, - ossl_ec_key_get_libctx(ec), ossl_ec_key_get0_propq(ec), - bnctx, &genbuf); if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { int include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; @@ -741,10 +748,6 @@ static int common_get_params(void *key, OSSL_PARAM params[], int sm2) goto err; } - /* - * OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT is added based on the group's - * asn1_form by ossl_ec_group_todata() below. - */ ret = ec_get_ecm_params(ecg, params) && ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx, &genbuf) @@ -1300,18 +1303,6 @@ static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) /* Whether you want it or not, you get a keypair, not just one half */ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - /* - * A generated key's public point has been serialised - * in uncompressed form for many releases, regardless - * of anything requested on the ctx or inherited from - * the template -- callers who consume the SPKI, EC - * PKCS#8 or other encodings rely on that. With group - * and key form now consolidated on a single field on - * the group, force it to uncompressed here rather - * than start emitting compressed public points where - * no caller was expecting them. - */ - EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); #ifndef FIPS_MODULE if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) ret = ret && ossl_ec_generate_key_dhkem(ec, gctx->dhkem_ikm, gctx->dhkem_ikmlen); @@ -1325,6 +1316,18 @@ static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) if (gctx->group_check != NULL) ret = ret && ossl_ec_set_check_group_type_from_name(ec, gctx->group_check); +#ifdef FIPS_MODULE + if (ret > 0 + && !ossl_fips_self_testing() + && EC_KEY_get0_public_key(ec) != NULL + && EC_KEY_get0_private_key(ec) != NULL + && EC_KEY_get0_group(ec) != NULL) { + BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec)); + + ret = bnctx != NULL && ossl_ec_key_pairwise_check(ec, bnctx); + BN_CTX_free(bnctx); + } +#endif /* FIPS_MODULE */ if (ret > 0) return ec; @@ -1373,21 +1376,8 @@ static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) ret = ec_gen_assign_group(ec, gctx->gen_group); /* Whether you want it or not, you get a keypair, not just one half */ - if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - /* - * A generated key's public point has been serialised - * in uncompressed form for many releases, regardless - * of anything requested on the ctx or inherited from - * the template -- callers who consume the SPKI, EC - * PKCS#8 or other encodings rely on that. With group - * and key form now consolidated on a single field on - * the group, force it to uncompressed here rather - * than start emitting compressed public points where - * no caller was expecting them. - */ - EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) ret = ret && EC_KEY_generate_key(ec); - } if (ret) return ec; diff --git a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c index 7a772ad017..deb4960006 100644 --- a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c +++ b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c @@ -75,7 +75,8 @@ int ossl_kdf_data_up_ref(KDF_DATA *kdfdata) if (!ossl_prov_is_running()) return 0; - return CRYPTO_UP_REF(&kdfdata->refcnt, &ref); + CRYPTO_UP_REF(&kdfdata->refcnt, &ref); + return 1; } static void *kdf_newdata(void *provctx) diff --git a/providers/implementations/keymgmt/mac_legacy_kmgmt.c b/providers/implementations/keymgmt/mac_legacy_kmgmt.c index 4c2e8d8cd9..d3082ca772 100644 --- a/providers/implementations/keymgmt/mac_legacy_kmgmt.c +++ b/providers/implementations/keymgmt/mac_legacy_kmgmt.c @@ -110,7 +110,8 @@ int ossl_mac_key_up_ref(MAC_KEY *mackey) if (!ossl_prov_is_running()) return 0; - return CRYPTO_UP_REF(&mackey->refcnt, &ref); + CRYPTO_UP_REF(&mackey->refcnt, &ref); + return 1; } static void *mac_new(void *provctx) diff --git a/providers/implementations/keymgmt/ml_dsa_kmgmt.c b/providers/implementations/keymgmt/ml_dsa_kmgmt.c index 24406ac602..83217066aa 100644 --- a/providers/implementations/keymgmt/ml_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/ml_dsa_kmgmt.c @@ -293,18 +293,8 @@ static int ml_dsa_import(void *keydata, int selection, const OSSL_PARAM params[] int include_priv; int res; - /* - * Once a key is fully initialised (has at least a public component), - * further mutation is no longer safe and disallowed. - */ if (!ossl_prov_is_running() || key == NULL) return 0; - if (ossl_ml_dsa_key_has(key, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) { - /* Invalid attempt to mutate a key. */ - ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_IMMUTABLE_ONCE_SET, - "Keys are immutable once key material has been loaded or generated"); - return 0; - } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) return 0; diff --git a/providers/implementations/keymgmt/ml_kem_kmgmt.c b/providers/implementations/keymgmt/ml_kem_kmgmt.c index d7f2d87685..f82f3e6f68 100644 --- a/providers/implementations/keymgmt/ml_kem_kmgmt.c +++ b/providers/implementations/keymgmt/ml_kem_kmgmt.c @@ -401,7 +401,10 @@ static int ml_kem_key_fromdata(ML_KEM_KEY *key, const OSSL_PARAM params[], const ML_KEM_VINFO *v; struct ml_kem_import_params_st p; - if (!ml_kem_import_params_decoder(params, &p)) + /* Invalid attempt to mutate a key, what is the right error to report? */ + if (key == NULL + || ossl_ml_kem_have_pubkey(key) + || !ml_kem_import_params_decoder(params, &p)) return 0; v = ossl_ml_kem_key_vinfo(key); @@ -486,16 +489,11 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[]) int include_private; int res; - if (!ossl_prov_is_running() - || (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0 - || key == NULL) + if (!ossl_prov_is_running() || key == NULL) return 0; - if (ossl_ml_kem_have_pubkey(key)) { - /* Invalid attempt to mutate a key. */ - ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_IMMUTABLE_ONCE_SET, - "Keys are immutable once key material has been loaded or generated"); + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) return 0; - } include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; res = ml_kem_key_fromdata(key, params, include_private); @@ -688,8 +686,9 @@ static int ml_kem_set_params(void *vkey, const OSSL_PARAM params[]) /* Key mutation is reportedly generally not allowed */ if (ossl_ml_kem_have_pubkey(key)) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_IMMUTABLE_ONCE_SET, - "Keys are immutable once key material has been loaded or generated"); + ERR_raise_data(ERR_LIB_PROV, + PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE, + "ML-KEM keys cannot be mutated"); return 0; } diff --git a/providers/implementations/macs/hmac_prov.c b/providers/implementations/macs/hmac_prov.c index 201d311bfe..f3dcdf962b 100644 --- a/providers/implementations/macs/hmac_prov.c +++ b/providers/implementations/macs/hmac_prov.c @@ -239,7 +239,8 @@ static int hmac_update(void *vmacctx, const unsigned char *data, datalen, macctx->tls_data_size, macctx->key, - macctx->keylen); + macctx->keylen, + 0); } return HMAC_Update(macctx->ctx, data, datalen); diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c index a9ca6e4f68..8d6f9c952e 100644 --- a/providers/implementations/macs/poly1305_prov.c +++ b/providers/implementations/macs/poly1305_prov.c @@ -86,7 +86,7 @@ static size_t poly1305_size(void) static int poly1305_setkey(struct poly1305_data_st *ctx, const unsigned char *key, size_t keylen) { - if (key == NULL || keylen != POLY1305_KEY_SIZE) { + if (keylen != POLY1305_KEY_SIZE) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); return 0; } @@ -115,10 +115,6 @@ static int poly1305_update(void *vmacctx, const unsigned char *data, { struct poly1305_data_st *ctx = vmacctx; - if (!ctx->key_set) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return 0; - } ctx->updated = 1; if (datalen == 0) return 1; diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 67b38cb719..1af996b25f 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -354,7 +354,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) * internally. So we need to check errno for ENOSYS */ #if !defined(__DragonFly__) && !defined(__NetBSD__) && !defined(__FreeBSD__) -#if defined(__GNUC__) && defined(__ELF__) && !defined(__hpux) +#if defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) && !defined(__hpux) extern int getentropy(void *buffer, size_t length) __attribute__((weak)); if (getentropy != NULL) { @@ -396,7 +396,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) return getrandom(buf, buflen, 0); #elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) return sysctl_random(buf, buflen); -#elif defined(__wasi__) || defined(__EMSCRIPTEN__) +#elif defined(__wasi__) if (getentropy(buf, buflen) == 0) return (ssize_t)buflen; return -1; diff --git a/providers/implementations/rands/seeding/rand_win.c b/providers/implementations/rands/seeding/rand_win.c index e1350f7d80..63b523b729 100644 --- a/providers/implementations/rands/seeding/rand_win.c +++ b/providers/implementations/rands/seeding/rand_win.c @@ -7,7 +7,6 @@ * https://www.openssl.org/source/license.html */ -#include "internal/e_os.h" /* For windows.h */ #include "internal/cryptlib.h" #include #include "crypto/rand_pool.h" @@ -20,10 +19,10 @@ #error "Unsupported seeding method configured; must be os" #endif +#include /* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */ -#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 \ - && ((defined(_MSC_VER) && _MSC_VER > 1500) \ - || (defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 2)) +#if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \ + && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 #define USE_BCRYPTGENRANDOM #endif @@ -71,7 +70,7 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) buffer = ossl_rand_pool_add_begin(pool, bytes_needed); if (buffer != NULL) { size_t bytes = 0; - if (BCryptGenRandom(NULL, buffer, (ULONG)bytes_needed, + if (BCryptGenRandom(NULL, buffer, bytes_needed, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) bytes = bytes_needed; diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c index c073b3e5bf..78fef9549e 100644 --- a/providers/implementations/rands/test_rng.c +++ b/providers/implementations/rands/test_rng.c @@ -170,9 +170,8 @@ static size_t test_rng_nonce(void *vtest, unsigned char *out, return 0; if (t->generate) { - if (out != NULL) - for (i = 0; i < min_noncelen; i++) - out[i] = gen_byte(t); + for (i = 0; i < min_noncelen; i++) + out[i] = gen_byte(t); return min_noncelen; } diff --git a/providers/implementations/signature/eddsa_sig.c b/providers/implementations/signature/eddsa_sig.c index 74e9fc11ee..9c25866794 100644 --- a/providers/implementations/signature/eddsa_sig.c +++ b/providers/implementations/signature/eddsa_sig.c @@ -551,7 +551,7 @@ static int ed448_sign(void *vpeddsactx, /* * s390x_ed448_digestsign() does not yet support context-strings or * pre-hashing. Fall back to non-accelerated sign if a context-string or - * pre-hashing is provided. + * pre-hasing is provided. */ if (S390X_CAN_SIGN(ED448) && peddsactx->context_string_len == 0 @@ -673,7 +673,7 @@ static int ed448_verify(void *vpeddsactx, /* * s390x_ed448_digestverify() does not yet support context-strings or * pre-hashing. Fall back to non-accelerated verify if a context-string or - * pre-hashing is provided. + * pre-hasing is provided. */ if (S390X_CAN_SIGN(ED448) && peddsactx->context_string_len == 0 diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c index 232414935f..3d56bd0185 100644 --- a/providers/implementations/signature/rsa_sig.c +++ b/providers/implementations/signature/rsa_sig.c @@ -1026,13 +1026,7 @@ static int rsa_verify_recover(void *vprsactx, } ret = RSA_public_decrypt((int)siglen, sig, rout, prsactx->rsa, prsactx->pad_mode); - /* - * RSA_public_decrypt() returns -1 on error and otherwise the number - * of recovered bytes, which may legitimately be zero for a raw - * PKCS#1 v1.5 signature that encodes an empty payload. Treat only - * a negative result as an error. - */ - if (ret < 0) { + if (ret <= 0) { ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB); return 0; } diff --git a/providers/implementations/storemgmt/file_store.c b/providers/implementations/storemgmt/file_store.c index 894685ce8c..2df5406699 100644 --- a/providers/implementations/storemgmt/file_store.c +++ b/providers/implementations/storemgmt/file_store.c @@ -505,7 +505,7 @@ static int file_setup_decoders(struct file_ctx_st *ctx) * The decoder doesn't need any identification or to be * attached to any provider, since it's only used locally. */ - to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL, 0); + to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL); if (to_obj != NULL) to_obj_inst = ossl_decoder_instance_new_forprov(to_obj, ctx->provctx, input_structure); diff --git a/providers/implementations/storemgmt/winstore_store.c b/providers/implementations/storemgmt/winstore_store.c index 59318e7547..c33763b8d9 100644 --- a/providers/implementations/storemgmt/winstore_store.c +++ b/providers/implementations/storemgmt/winstore_store.c @@ -209,7 +209,7 @@ static int setup_decoder(struct winstore_ctx_st *ctx) * The decoder doesn't need any identification or to be * attached to any provider, since it's only used locally. */ - to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL, 0); + to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL); if (to_obj != NULL) to_obj_inst = ossl_decoder_instance_new_forprov(to_obj, ctx->provctx, input_structure); diff --git a/ssl/methods.c b/ssl/methods.c index 4c7d46efdb..37bd37f719 100644 --- a/ssl/methods.c +++ b/ssl/methods.c @@ -13,7 +13,7 @@ #include "ssl_local.h" /*- - * TLS methods + * TLS/SSLv3 methods */ IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, @@ -42,7 +42,7 @@ IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, ossl_statem_accept, ossl_statem_connect, TLSv1_enc_data) #endif /*- - * TLS server methods + * TLS/SSLv3 server methods */ IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, TLS_server_method, @@ -71,7 +71,7 @@ IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, ssl_undefined_function, TLSv1_enc_data) #endif /*- - * TLS client methods + * TLS/SSLv3 client methods */ IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, TLS_client_method, diff --git a/ssl/quic/quic_ackm.c b/ssl/quic/quic_ackm.c index 24acb8635c..3d419c478b 100644 --- a/ssl/quic/quic_ackm.c +++ b/ssl/quic/quic_ackm.c @@ -1003,7 +1003,6 @@ static void ackm_on_pkts_acked(OSSL_ACKM *ackm, const OSSL_ACKM_TX_PKT *apkt) const OSSL_ACKM_TX_PKT *anext; QUIC_PN last_pn_acked = 0; OSSL_CC_ACK_INFO ainfo = { 0 }; - unsigned int is_inflight; for (; apkt != NULL; apkt = anext) { if (apkt->is_inflight) { @@ -1028,11 +1027,10 @@ static void ackm_on_pkts_acked(OSSL_ACKM *ackm, const OSSL_ACKM_TX_PKT *apkt) ainfo.tx_time = apkt->time; ainfo.tx_size = apkt->num_bytes; - is_inflight = apkt->is_inflight; anext = apkt->anext; apkt->on_acked(apkt->cb_arg); /* may free apkt */ - if (is_inflight) + if (apkt->is_inflight) ackm->cc_method->on_data_acked(ackm->cc_data, &ainfo); } } @@ -1169,21 +1167,8 @@ int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack, int pkt_space, OSSL_TIME rx_time) { OSSL_ACKM_TX_PKT *na_pkts, *lost_pkts; - struct tx_pkt_history_st *h = get_tx_history(ackm, pkt_space); int must_set_timer = 0; - /* - * RFC 9000 s. 13.1 recommends treating an acknowledgment for a packet we - * did not send as a PROTOCOL_VIOLATION, where detectable. The largest - * acknowledged PN is ack_ranges[0].end; if it exceeds the highest PN we have - * sent in this space, reject the ACK. Otherwise the peer-controlled value is - * stored into largest_acked_pkt below, which only ever increases and drives - * loss detection, so a single such ACK would permanently force every - * in-flight and subsequently-sent packet to be declared lost. - */ - if (ack->ack_ranges[0].end > h->highest_sent) - return 0; - if (ackm->largest_acked_pkt[pkt_space] == QUIC_PN_INVALID) ackm->largest_acked_pkt[pkt_space] = ack->ack_ranges[0].end; else diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 99f131cb78..aaabf5a432 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -3325,8 +3325,7 @@ static int ch_enqueue_retire_conn_id(QUIC_CHANNEL *ch, uint64_t seq_num) WPACKET wpkt; size_t l; - if (!ossl_quic_srtm_remove(ch->srtm, ch, seq_num, NULL)) - goto err; + ossl_quic_srtm_remove(ch->srtm, ch, seq_num); if ((buf_mem = BUF_MEM_new()) == NULL) goto err; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 99ddfd082e..1efc149119 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -4906,7 +4906,7 @@ SSL *ossl_quic_new_from_listener(SSL *ssl, uint64_t flags) ossl_quic_channel_set_msg_callback_arg(qc->ch, ql->obj.ssl.ctx->msg_callback_arg); /* - * We deliberately pass NULL for engine and port, because we don't want + * We deliberately pass NULL for engine and port, because we don't want to * to turn QCSO we create here into an event leader, nor port leader. * Both those roles are occupied already by listener (`ssl`) we use * to create a new QCSO here. @@ -5433,8 +5433,9 @@ int ossl_quic_get_peer_token(SSL_CTX *ctx, BIO_ADDR *peer, ossl_crypto_mutex_lock(c->mutex); tok = lh_QUIC_TOKEN_retrieve(c->cache, key); - if (tok != NULL && CRYPTO_UP_REF(&tok->references, &ret)) { + if (tok != NULL) { *token = tok; + CRYPTO_UP_REF(&tok->references, &ret); rc = 1; } @@ -5587,6 +5588,7 @@ long ossl_quic_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) &ctx.qc->obj.ssl); /* This callback also needs to be set on the internal SSL object */ return ssl3_callback_ctrl(ctx.qc->tls, cmd, fp); + ; default: /* Probably a TLS related ctrl. Defer to our internal SSL object */ diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c index 74cfceed05..730b0cf621 100644 --- a/ssl/quic/quic_rx_depack.c +++ b/ssl/quic/quic_rx_depack.c @@ -125,19 +125,8 @@ static int depack_do_frame_ack(PACKET *pkt, QUIC_CHANNEL *ch, } if (!ossl_ackm_on_rx_ack_frame(ch->ackm, &ack, - packet_space, received)) { - /* - * The ACK manager rejects the frame if it acknowledges a packet number - * we have not sent. RFC 9000 s. 13.1 recommends treating this as a - * PROTOCOL_VIOLATION connection error (distinct from a frame decoding - * error, which is handled at the malformed label below). - */ - ossl_quic_channel_raise_protocol_error(ch, - OSSL_QUIC_ERR_PROTOCOL_VIOLATION, - frame_type, - "ACK for unsent packet number"); - return 0; - } + packet_space, received)) + goto malformed; ++ch->diag_num_rx_ack; return 1; diff --git a/ssl/quic/quic_srtm.c b/ssl/quic/quic_srtm.c index 4c8ea10734..1cc2ae6962 100644 --- a/ssl/quic/quic_srtm.c +++ b/ssl/quic/quic_srtm.c @@ -382,24 +382,16 @@ static int srtm_remove_from_rev(QUIC_SRTM *srtm, SRTM_ITEM *item) return 1; } -int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num, - uint8_t *match) +int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num) { SRTM_ITEM *item, *prev = NULL; - uint8_t match_sink; - - if (match == NULL) - match = &match_sink; - *match = 0; if (srtm->alloc_failed) return 0; if ((item = srtm_find(srtm, opaque, seq_num, NULL, &prev)) == NULL) /* No match */ - return 1; - - *match = 1; + return 0; /* Remove from forward mapping. */ if (prev == NULL) { diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c index bd026af3a4..425f76a003 100644 --- a/ssl/quic/quic_txp.c +++ b/ssl/quic/quic_txp.c @@ -1477,7 +1477,7 @@ static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp, * This is not a major concern for clients, since if a client has a 1-RTT EL * provisioned the server is guaranteed to also have a 1-RTT EL provisioned. * - * TODO(QUIC FUTURE): Revisit this when we have reached a decision on how + * TODO(QUIC FUTURE): Revisit this when when have reached a decision on how * best to implement this */ if (*conn_close_enc_level > enc_level diff --git a/ssl/quic/quic_wire_pkt.c b/ssl/quic/quic_wire_pkt.c index 368a585072..8a65ac9869 100644 --- a/ssl/quic/quic_wire_pkt.c +++ b/ssl/quic/quic_wire_pkt.c @@ -870,7 +870,7 @@ int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx, EVP_CIPHER_CTX *cctx = NULL; int ok = 0, l = 0, l2 = 0, wpkt_valid = 0; WPACKET wpkt; - /* Worst case length of the Retry Pseudo-Packet header is 68 bytes. */ + /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */ unsigned char buf[128]; QUIC_PKT_HDR hdr2; size_t hdr_enc_len = 0; @@ -892,7 +892,7 @@ int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx, hdr2 = *hdr; hdr2.len = 0; - /* Assemble retry pseudo-packet. */ + /* Assemble retry psuedo-packet. */ if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0)) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); goto err; diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h index 1bfea26631..d6db9850c0 100644 --- a/ssl/record/methods/recmethod_local.h +++ b/ssl/record/methods/recmethod_local.h @@ -287,7 +287,8 @@ struct ossl_record_layer_st { /* * Do we need to send a prefix empty record before application data as a - * countermeasure against known-IV weakness (necessary for TLSv1.0) + * countermeasure against known-IV weakness (necessary for SSLv3 and + * TLSv1.0) */ int need_empty_fragments; @@ -325,6 +326,9 @@ struct ossl_record_layer_st { size_t block_padding; size_t hs_padding; + /* Only used by SSLv3 */ + unsigned char mac_secret[EVP_MAX_MD_SIZE]; + /* TLSv1.0/TLSv1.1/TLSv1.2 */ int use_etm; @@ -456,6 +460,7 @@ int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion, uint8_t *type, const unsigned char **data, size_t *datalen, uint16_t *epoch, unsigned char *seq_num); int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle, size_t length); +int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version); int tls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version); void tls_set_plain_alerts(OSSL_RECORD_LAYER *rl, int allow); void tls_set_first_handshake(OSSL_RECORD_LAYER *rl, int first); diff --git a/ssl/record/methods/ssl3_cbc.c b/ssl/record/methods/ssl3_cbc.c index 133067ab15..3702c03c52 100644 --- a/ssl/record/methods/ssl3_cbc.c +++ b/ssl/record/methods/ssl3_cbc.c @@ -105,7 +105,8 @@ static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out) #define LARGEST_DIGEST_CTX SHA512_CTX /*- - * ssl3_cbc_digest_record computes the MAC of a decrypted, padded TLS record. + * ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS + * record. * * ctx: the EVP_MD_CTX from which we take the hash function. * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. @@ -117,6 +118,7 @@ static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out) * has been removed. * data_plus_mac_plus_padding_size: the public length of the whole * record, including MAC and padding. + * is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS. * * On entry: we know that data is data_plus_mac_plus_padding_size in length * Returns 1 on success or 0 on error @@ -129,7 +131,7 @@ int ssl3_cbc_digest_record(const EVP_MD *md, size_t data_size, size_t data_plus_mac_plus_padding_size, const unsigned char *mac_secret, - size_t mac_secret_length) + size_t mac_secret_length, char is_sslv3) { union { OSSL_UNION_ALIGN; @@ -138,8 +140,9 @@ int ssl3_cbc_digest_record(const EVP_MD *md, void (*md_final_raw)(void *ctx, unsigned char *md_out); void (*md_transform)(void *ctx, const unsigned char *block); size_t md_size, md_block_size = 64; - size_t header_length, variance_blocks, len, max_mac_bytes, num_blocks, - num_starting_blocks, k, mac_end_offset, c, index_a, index_b; + size_t sslv3_pad_length = 40, header_length, variance_blocks, + len, max_mac_bytes, num_blocks, + num_starting_blocks, k, mac_end_offset, c, index_a, index_b; size_t bits; /* at most 18 bits */ unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; /* hmac_pad is the masked HMAC key. */ @@ -173,6 +176,7 @@ int ssl3_cbc_digest_record(const EVP_MD *md, md_final_raw = tls1_md5_final_raw; md_transform = (void (*)(void *ctx, const unsigned char *block))MD5_Transform; md_size = 16; + sslv3_pad_length = 48; length_is_big_endian = 0; #endif } else if (EVP_MD_is_a(md, "SHA1")) { @@ -225,11 +229,22 @@ int ssl3_cbc_digest_record(const EVP_MD *md, return 0; header_length = 13; + if (is_sslv3) { + header_length = mac_secret_length + + sslv3_pad_length + + 8 /* sequence number */ + + 1 /* record type */ + + 2; /* record length */ + } /* * variance_blocks is the number of blocks of the hash that we have to * calculate in constant time because they could be altered by the - * padding value. + * padding value. In SSLv3, the padding must be minimal so the end of + * the plaintext varies by, at most, 15+20 = 35 bytes. (We conservatively + * assume that the MAC size varies from 0..20 bytes.) In case the 9 bytes + * of hash termination (0x80 + 64-bit length) don't fit in the final + * block, we say that the final two blocks can vary based on the padding. * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not * required to be minimal. Therefore we say that the final |variance_blocks| * blocks can @@ -237,11 +252,14 @@ int ssl3_cbc_digest_record(const EVP_MD *md, * short and there obviously cannot be this many blocks then * variance_blocks can be reduced. */ - variance_blocks = ((255 + 1 + md_size + md_block_size - 1) / md_block_size) + 1; - + variance_blocks = is_sslv3 ? 2 + : (((255 + 1 + md_size + md_block_size - 1) + / md_block_size) + + 1); /* * From now on we're dealing with the MAC, which conceptually has 13 - * bytes of `header' before the start of the data (TLS) + * bytes of `header' before the start of the data (TLS) or 71/75 bytes + * (SSLv3) */ len = data_plus_mac_plus_padding_size + header_length; /* @@ -284,30 +302,37 @@ int ssl3_cbc_digest_record(const EVP_MD *md, * in bits. */ index_b = (mac_end_offset + md_length_size) / md_block_size; - - if (num_blocks > variance_blocks) { - num_starting_blocks = num_blocks - variance_blocks; - k = md_block_size * num_starting_blocks; - } - /* * bits is the hash-length in bits. It includes the additional hash block * for the masked HMAC key, or whole of |header| in the case of SSLv3. */ - bits = 8 * mac_end_offset; /* - * Compute the initial HMAC block. + * For SSLv3, if we're going to have any starting blocks then we need at + * least two because the header is larger than a single block. */ - bits += 8 * md_block_size; - memset(hmac_pad, 0, md_block_size); - if (!ossl_assert(mac_secret_length <= sizeof(hmac_pad))) - return 0; - memcpy(hmac_pad, mac_secret, mac_secret_length); - for (i = 0; i < md_block_size; i++) - hmac_pad[i] ^= 0x36; + if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) { + num_starting_blocks = num_blocks - variance_blocks; + k = md_block_size * num_starting_blocks; + } - md_transform(md_state.c, hmac_pad); + bits = 8 * mac_end_offset; + if (!is_sslv3) { + /* + * Compute the initial HMAC block. For SSLv3, the padding and secret + * bytes are included in |header| because they take more than a + * single block. + */ + bits += 8 * md_block_size; + memset(hmac_pad, 0, md_block_size); + if (!ossl_assert(mac_secret_length <= sizeof(hmac_pad))) + return 0; + memcpy(hmac_pad, mac_secret, mac_secret_length); + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x36; + + md_transform(md_state.c, hmac_pad); + } if (length_is_big_endian) { memset(length_bytes, 0, md_length_size - 4); @@ -324,12 +349,37 @@ int ssl3_cbc_digest_record(const EVP_MD *md, } if (k > 0) { - /* k is a multiple of md_block_size. */ - memcpy(first_block, header, 13); - memcpy(first_block + 13, data, md_block_size - 13); - md_transform(md_state.c, first_block); - for (i = 1; i < k / md_block_size; i++) - md_transform(md_state.c, data + md_block_size * i - 13); + if (is_sslv3) { + size_t overhang; + + /* + * The SSLv3 header is larger than a single block. overhang is + * the number of bytes beyond a single block that the header + * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no + * ciphersuites in SSLv3 that are not SHA1 or MD5 based and + * therefore we can be confident that the header_length will be + * greater than |md_block_size|. However we add a sanity check just + * in case + */ + if (header_length <= md_block_size) { + /* Should never happen */ + return 0; + } + overhang = header_length - md_block_size; + md_transform(md_state.c, header); + memcpy(first_block, header + md_block_size, overhang); + memcpy(first_block + overhang, data, md_block_size - overhang); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size - 1; i++) + md_transform(md_state.c, data + md_block_size * i - overhang); + } else { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block + 13, data, md_block_size - 13); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size; i++) + md_transform(md_state.c, data + md_block_size * i - 13); + } } memset(mac_out, 0, sizeof(mac_out)); @@ -399,15 +449,23 @@ int ssl3_cbc_digest_record(const EVP_MD *md, if (EVP_DigestInit_ex(md_ctx, md, NULL) <= 0) goto err; + if (is_sslv3) { + /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */ + memset(hmac_pad, 0x5c, sslv3_pad_length); - /* Complete the HMAC in the standard manner. */ - for (i = 0; i < md_block_size; i++) - hmac_pad[i] ^= 0x6a; - - if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0 - || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) - goto err; + if (EVP_DigestUpdate(md_ctx, mac_secret, mac_secret_length) <= 0 + || EVP_DigestUpdate(md_ctx, hmac_pad, sslv3_pad_length) <= 0 + || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) + goto err; + } else { + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x6a; + if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0 + || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) + goto err; + } ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u); if (ret && md_out_size) *md_out_size = md_out_size_u; diff --git a/ssl/record/methods/tls1_meth.c b/ssl/record/methods/tls1_meth.c index 717e1ed3ff..f89c365d7f 100644 --- a/ssl/record/methods/tls1_meth.c +++ b/ssl/record/methods/tls1_meth.c @@ -530,6 +530,7 @@ end: #endif /* OPENSSL_NO_COMP */ #endif +/* This function is also used by the SSLv3 implementation */ int tls1_allocate_write_buffers(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates, size_t numtempl, size_t *prefix) @@ -551,6 +552,7 @@ int tls1_allocate_write_buffers(OSSL_RECORD_LAYER *rl, return 1; } +/* This function is also used by the SSLv3 implementation */ int tls1_initialise_write_packets(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates, size_t numtempl, diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index 0363bf23bf..685139531e 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -497,7 +497,7 @@ static int tls_record_app_data_waiting(OSSL_RECORD_LAYER *rl) static int rlayer_early_data_count_ok(OSSL_RECORD_LAYER *rl, size_t length, size_t overhead, int send) { - uint64_t max_early_data = rl->max_early_data; + uint32_t max_early_data = rl->max_early_data; if (max_early_data == 0) { RLAYERfatal(rl, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, @@ -506,7 +506,7 @@ static int rlayer_early_data_count_ok(OSSL_RECORD_LAYER *rl, size_t length, } /* If we are dealing with ciphertext we need to allow for the overhead */ - max_early_data += overhead; + max_early_data += (uint32_t)overhead; if (rl->early_data_count + length > max_early_data) { RLAYERfatal(rl, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, @@ -526,6 +526,8 @@ static int rlayer_early_data_count_ok(OSSL_RECORD_LAYER *rl, size_t length, */ #define MAX_EMPTY_RECORDS 32 +#define SSL2_RT_HEADER_LENGTH 2 + /*- * Call this to buffer new input records in rl->rrec. * It will return a OSSL_RECORD_RETURN_* value. @@ -624,7 +626,12 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl) * rl->rstate == SSL_ST_READ_BODY, get and decode the data. Calculate * how much more data we need to read for the rest of the record */ - more = thisrr->length; + if (thisrr->rec_version == SSL2_VERSION) { + more = thisrr->length + SSL2_RT_HEADER_LENGTH + - SSL3_RT_HEADER_LENGTH; + } else { + more = thisrr->length; + } if (more > 0) { /* now rl->packet_length == SSL3_RT_HEADER_LENGTH */ @@ -639,9 +646,13 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl) /* * At this point, rl->packet_length == SSL3_RT_HEADER_LENGTH + * + thisrr->length, or rl->packet_length == SSL2_RT_HEADER_LENGTH * + thisrr->length and we have that many bytes in rl->packet */ - thisrr->input = &(rl->packet[SSL3_RT_HEADER_LENGTH]); + if (thisrr->rec_version == SSL2_VERSION) + thisrr->input = &(rl->packet[SSL2_RT_HEADER_LENGTH]); + else + thisrr->input = &(rl->packet[SSL3_RT_HEADER_LENGTH]); /* * ok, we can now read from 'rl->packet' data into 'thisrr'. @@ -1401,6 +1412,8 @@ static void tls_int_free(OSSL_RECORD_LAYER *rl) #endif OPENSSL_free(rl->iv); OPENSSL_free(rl->nonce); + if (rl->version == SSL3_VERSION) + OPENSSL_cleanse(rl->mac_secret, sizeof(rl->mac_secret)); TLS_RL_RECORD_release(rl->rrec, SSL_MAX_PIPELINES); diff --git a/ssl/record/methods/tls_pad.c b/ssl/record/methods/tls_pad.c index a017e9221e..7209506bc4 100644 --- a/ssl/record/methods/tls_pad.c +++ b/ssl/record/methods/tls_pad.c @@ -33,6 +33,51 @@ static int ssl3_cbc_copy_mac(size_t *reclen, size_t good, OSSL_LIB_CTX *libctx); +/*- + * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC + * record in |recdata| by updating |reclen| in constant time. It also extracts + * the MAC from the underlying record and places a pointer to it in |mac|. The + * MAC data can either be newly allocated memory, or a pointer inside the + * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is + * set to 0. + * + * origreclen: the original record length before any changes were made + * block_size: the block size of the cipher used to encrypt the record. + * mac_size: the size of the MAC to be extracted + * aead: 1 if an AEAD cipher is in use, or 0 otherwise + * returns: + * 0: if the record is publicly invalid. + * 1: if the record is publicly valid. If the padding removal fails then the + * MAC returned is random. + */ +int ssl3_cbc_remove_padding_and_mac(size_t *reclen, + size_t origreclen, + unsigned char *recdata, + unsigned char **mac, + int *alloced, + size_t block_size, size_t mac_size, + OSSL_LIB_CTX *libctx) +{ + size_t padding_length; + size_t good; + const size_t overhead = 1 /* padding length byte */ + mac_size; + + /* + * These lengths are all public so we can test them in non-constant time. + */ + if (overhead > *reclen) + return 0; + + padding_length = recdata[*reclen - 1]; + good = constant_time_ge_s(*reclen, padding_length + overhead); + /* SSLv3 requires that the padding is minimal. */ + good &= constant_time_ge_s(block_size, padding_length + 1); + *reclen -= good & (padding_length + 1); + + return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced, + block_size, mac_size, good, libctx); +} + /*- * tls1_cbc_remove_padding_and_mac removes padding from the decrypted, TLS, CBC * record in |recdata| by updating |reclen| in constant time. It also extracts diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index d87001ad7b..e68d8f8fa1 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -150,7 +150,7 @@ static uint32_t ossl_get_max_early_data(SSL_CONNECTION *s) static int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length, size_t overhead, int send) { - uint64_t max_early_data; + uint32_t max_early_data; max_early_data = ossl_get_max_early_data(s); @@ -161,7 +161,7 @@ static int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length, } /* If we are dealing with ciphertext we need to allow for the overhead */ - max_early_data += overhead; + max_early_data += (uint32_t)overhead; if (s->early_data_count + length > max_early_data) { SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, @@ -834,6 +834,20 @@ start: * were actually expecting a CCS). */ + /* + * Lets just double check that we've not got an SSLv2 record + */ + if (rr->version == SSL2_VERSION) { + /* + * Should never happen. ssl3_get_record() should only give us an SSLv2 + * record back if this is the first packet and we are looking for an + * initial ClientHello. Therefore |type| should always be equal to + * |rr->type|. If not then something has gone horribly wrong + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return -1; + } + if (ssl->method->version == TLS_ANY_VERSION && (s->server || rr->type != SSL3_RT_ALERT)) { /* @@ -842,14 +856,7 @@ start: * with. We shouldn't be receiving anything other than a ClientHello * if we are a server. */ - int min_version, max_version; - - if (ssl_get_min_max_version(s, &min_version, &max_version, NULL) != 0) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_INTERNAL_ERROR); - return -1; - } - - s->version = min_version; + s->version = rr->version; SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); return -1; } diff --git a/ssl/rio/rio_notifier.c b/ssl/rio/rio_notifier.c index 3f5225db0e..ab635aa7a0 100644 --- a/ssl/rio/rio_notifier.c +++ b/ssl/rio/rio_notifier.c @@ -10,6 +10,7 @@ #include "internal/sockets.h" #include #include +#include "internal/thread_once.h" #include "internal/rio_notifier.h" #if !defined(OPENSSL_SYS_WINDOWS) || RIO_NOTIFIER_METHOD == RIO_NOTIFIER_METHOD_SOCKETPAIR @@ -29,30 +30,64 @@ static int set_cloexec(int fd) #if defined(OPENSSL_SYS_WINDOWS) +static CRYPTO_ONCE ensure_wsa_startup_once = CRYPTO_ONCE_STATIC_INIT; +static CRYPTO_RWLOCK *wsa_lock; +static int wsa_started; +static int wsa_ref; + static void ossl_wsa_cleanup(void) { - WSACleanup(); + if (wsa_started) { + wsa_started = 0; + WSACleanup(); + } + + CRYPTO_THREAD_lock_free(wsa_lock); + wsa_lock = NULL; } -static int do_wsa_startup(void) +DEFINE_RUN_ONCE_STATIC(do_wsa_startup) { WORD versionreq = 0x0202; /* Version 2.2 */ WSADATA wsadata; - if (WSAStartup(versionreq, &wsadata) != 0) + wsa_lock = CRYPTO_THREAD_lock_new(); + if (wsa_lock == NULL) return 0; + if (WSAStartup(versionreq, &wsadata) != 0) { + CRYPTO_THREAD_lock_free(wsa_lock); + wsa_lock = NULL; + return 0; + } + wsa_started = 1; + return 1; } static ossl_inline int ensure_wsa_startup(void) { - return do_wsa_startup(); + int rv, unused; + + rv = RUN_ONCE(&ensure_wsa_startup_once, do_wsa_startup); + if (rv != 0) + CRYPTO_atomic_add(&wsa_ref, 1, &unused, wsa_lock); + + return rv; } static void wsa_done(void) { - ossl_wsa_cleanup(); + int ref; + + if (wsa_lock != NULL) { + CRYPTO_atomic_add(&wsa_ref, -1, &ref, wsa_lock); + if (ref == 0) { + ossl_wsa_cleanup(); + ensure_wsa_startup_once = CRYPTO_ONCE_STATIC_INIT; + wsa_lock = NULL; + } + } } #endif @@ -153,6 +188,8 @@ int ossl_rio_notifier_init(RIO_NOTIFIER *nfy) if (!ensure_wsa_startup()) { ERR_raise_data(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR, "Cannot start Windows sockets"); + + wsa_done(); return 0; } #endif diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 2a51ada2a1..c3479b08aa 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -306,7 +306,7 @@ int ssl_cert_set0_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain) for (i = 0; i < sk_X509_num(chain); i++) { X509 *x = sk_X509_value(chain, i); - r = ssl_security_cert(s, ctx, x, 0); + r = ssl_security_cert(s, ctx, x, 0, 0); if (r != 1) { ERR_raise(ERR_LIB_SSL, r); return 0; @@ -340,7 +340,7 @@ int ssl_cert_add0_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x) if (!cpk) return 0; - r = ssl_security_cert(s, ctx, x, 0); + r = ssl_security_cert(s, ctx, x, 0, 0); if (r != 1) { ERR_raise(ERR_LIB_SSL, r); return 0; @@ -1175,7 +1175,7 @@ int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags) */ for (i = 0; i < sk_X509_num(chain); i++) { x = sk_X509_value(chain, i); - rv = ssl_security_cert(s, ctx, x, 0); + rv = ssl_security_cert(s, ctx, x, 0, 0); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); OSSL_STACK_OF_X509_free(chain); diff --git a/ssl/ssl_cert_comp.c b/ssl/ssl_cert_comp.c index d6eadc5365..2c297178e5 100644 --- a/ssl/ssl_cert_comp.c +++ b/ssl/ssl_cert_comp.c @@ -151,7 +151,7 @@ int OSSL_COMP_CERT_up_ref(OSSL_COMP_CERT *cc) { int i; - if (!CRYPTO_UP_REF(&cc->references, &i)) + if (CRYPTO_UP_REF(&cc->references, &i) <= 0) return 0; REF_PRINT_COUNT("OSSL_COMP_CERT", i, cc); diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 47e3ff4df3..61e8c4abbe 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -618,7 +618,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, /* * We have num_of_ciphers descriptions compiled in, depending on the - * method selected (TLSv1, etc.). + * method selected (SSLv3, TLSv1 etc). * These will later be sorted in a linked list with at most num * entries. */ @@ -2281,7 +2281,7 @@ int ssl_cipher_list_to_bytes(SSL_CONNECTION *s, STACK_OF(SSL_CIPHER) *sk, c = sk_SSL_CIPHER_value(sk, i); /* Skip disabled ciphers */ - if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) continue; if (!ssl->method->put_cipher_by_char(c, pkt, &len)) { diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 57d74f9091..c89f3e4017 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -510,6 +510,10 @@ static int ssl_check_allowed_versions(int min_version, int max_version) if (max_version == TLS1_1_VERSION) max_version = TLS1_VERSION; #endif +#ifdef OPENSSL_NO_TLS1 + if (max_version == TLS1_VERSION) + max_version = SSL3_VERSION; +#endif #ifdef OPENSSL_NO_TLS1 if (min_version == TLS1_VERSION) min_version = TLS1_1_VERSION; @@ -819,6 +823,15 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, SSL *user_ssl, goto err; s->session_ctx = ctx; + if (ctx->ext.ecpointformats != NULL) { + s->ext.ecpointformats = OPENSSL_memdup(ctx->ext.ecpointformats, + ctx->ext.ecpointformats_len); + if (s->ext.ecpointformats == NULL) { + s->ext.ecpointformats_len = 0; + goto err; + } + s->ext.ecpointformats_len = ctx->ext.ecpointformats_len; + } if (ctx->ext.supportedgroups != NULL) { size_t add = 0; @@ -1012,7 +1025,7 @@ int SSL_up_ref(SSL *s) { int i; - if (!CRYPTO_UP_REF(&s->references, &i)) + if (CRYPTO_UP_REF(&s->references, &i) <= 0) return 0; REF_PRINT_COUNT("SSL", i, s); @@ -1518,6 +1531,7 @@ void ossl_ssl_connection_free(SSL *ssl) OPENSSL_free(s->ext.hostname); SSL_CTX_free(s->session_ctx); + OPENSSL_free(s->ext.ecpointformats); OPENSSL_free(s->ext.peer_ecpointformats); OPENSSL_free(s->ext.supportedgroups); OPENSSL_free(s->ext.keyshares); @@ -2088,9 +2102,7 @@ int SSL_copy_session_id(SSL *t, const SSL *f) return 0; } - if (!CRYPTO_UP_REF(&fsc->cert->references, &i)) - return 0; - + CRYPTO_UP_REF(&fsc->cert->references, &i); ssl_cert_free(tsc->cert); tsc->cert = fsc->cert; if (!SSL_set_session_id_context(t, fsc->sid_ctx, (int)fsc->sid_ctx_length)) { @@ -3457,7 +3469,7 @@ STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s) return NULL; for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i); - if (!ssl_cipher_disabled(sc, c, SSL_SECOP_CIPHER_SUPPORTED)) { + if (!ssl_cipher_disabled(sc, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) { if (!sk) sk = sk_SSL_CIPHER_new_null(); if (!sk) @@ -4534,7 +4546,7 @@ int SSL_CTX_up_ref(SSL_CTX *ctx) { int i; - if (!CRYPTO_UP_REF(&ctx->references, &i)) + if (CRYPTO_UP_REF(&ctx->references, &i) <= 0) return 0; REF_PRINT_COUNT("SSL_CTX", i, ctx); @@ -4608,6 +4620,7 @@ void SSL_CTX_free(SSL_CTX *a) ssl_ctx_srp_ctx_free_intern(a); #endif + OPENSSL_free(a->ext.ecpointformats); OPENSSL_free(a->ext.supportedgroups); OPENSSL_free(a->ext.keyshares); OPENSSL_free(a->ext.tuples); @@ -5354,8 +5367,7 @@ SSL *SSL_dup(SSL *s) /* If we're not quiescent, just up_ref! */ if (!SSL_in_init(s) || !SSL_in_before(s)) { - if (!CRYPTO_UP_REF(&s->references, &i)) - return NULL; + CRYPTO_UP_REF(&s->references, &i); return s; } diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 2cfc5cb815..62b0017b9c 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -12,7 +12,6 @@ #ifndef OSSL_SSL_LOCAL_H #define OSSL_SSL_LOCAL_H -#include #include #include #include @@ -294,6 +293,12 @@ */ #define SSL_USE_SIGALGS(s) \ (SSL_CONNECTION_GET_SSL(s)->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SIGALGS) +/* + * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may + * apply to others in future. + */ +#define SSL_USE_TLS1_2_CIPHERS(s) \ + (SSL_CONNECTION_GET_SSL(s)->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) #define IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value) \ (((value) >= TLSEXT_max_fragment_length_512) && ((value) <= TLSEXT_max_fragment_length_4096)) @@ -382,7 +387,7 @@ typedef enum { SSL_PHA_REQUESTED /* request received by client, or sent by server */ } SSL_PHA_STATE; -/* CipherSuite value length. */ +/* CipherSuite length. SSLv3 and all TLS versions. */ #define TLS_CIPHER_LEN 2 /* used to hold info on the particular ciphers used */ struct ssl_cipher_st { @@ -442,7 +447,7 @@ struct ssl_method_st { int (*num_ciphers)(void); const SSL_CIPHER *(*get_cipher)(unsigned ncipher); OSSL_TIME (*get_timeout)(void); - const struct ssl3_enc_method *ssl3_enc; /* Extra TLS stuff */ + const struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */ int (*ssl_version)(void); long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void)); long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void)); @@ -512,21 +517,6 @@ struct ssl_session_st { * to disable session caching and tickets. */ int not_resumable; - /* - * Set when this session's master key was resolved from an external PSK - * identity (psk_find_session_cb(), or the legacy psk_server_callback()) - * rather than from a resumption ticket or session-cache lookup. - * ssl_get_prev_session() uses this to exempt such sessions from sid_ctx - * checks that only make sense for a real cache lookup. - * - * Deliberately not part of the SSL_SESSION ASN.1 encoding: it must not - * survive a real ticket round-trip (a session reconstructed by - * d2i_SSL_SESSION() from a genuine, previously-issued ticket is by - * definition not an external-PSK match, and should get the ordinary - * sid_ctx treatment). ssl_session_dup() resets it to 0 on every copy, - * mirroring not_resumable just above, for the same reason. - */ - int psk_external; /* Peer raw public key, if available */ EVP_PKEY *peer_rpk; /* This is the cert and type for the other end. */ @@ -809,6 +799,16 @@ typedef struct { uint32_t amask; /* authmask corresponding to key type */ } SSL_CERT_LOOKUP; +/* flags values */ +#define TLS_GROUP_TYPE 0x0000000FU /* Mask for group type */ +#define TLS_GROUP_CURVE_PRIME 0x00000001U +#define TLS_GROUP_CURVE_CHAR2 0x00000002U +#define TLS_GROUP_CURVE_CUSTOM 0x00000004U +#define TLS_GROUP_FFDHE 0x00000008U +#define TLS_GROUP_ONLY_FOR_TLS1_3 0x00000010U + +#define TLS_GROUP_FFDHE_FOR_TLS1_3 (TLS_GROUP_FFDHE | TLS_GROUP_ONLY_FOR_TLS1_3) + #if !defined(OPENSSL_NO_TLS1) \ || !defined(OPENSSL_NO_TLS1_1) \ || !defined(OPENSSL_NO_TLS1_2) \ @@ -927,8 +927,11 @@ struct ssl_ctx_st { CRYPTO_EX_DATA ex_data; + const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ + const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3-sha1' */ + STACK_OF(X509) *extra_certs; - STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, TLSv1 */ + STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ /* Default values used when no per-SSL value is defined follow */ @@ -1039,6 +1042,10 @@ struct ssl_ctx_st { /* RFC 4366 Maximum Fragment Length Negotiation */ uint8_t max_fragment_len_mode; + /* EC extension values inherited by SSL structure */ + size_t ecpointformats_len; + unsigned char *ecpointformats; + size_t supportedgroups_len; uint16_t *supportedgroups; @@ -1272,7 +1279,8 @@ struct ssl_connection_st { SSL *user_ssl; /* - * protocol version (one of TLS1_VERSION, DTLS1_VERSION) + * protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, + * DTLS1_VERSION) */ int version; /* @@ -1367,7 +1375,7 @@ struct ssl_connection_st { int in_read_app_data; struct { - /* actually only need to be 12 for TLS */ + /* actually only need to be 16+20 for SSLv3 and 12 for TLS */ unsigned char finish_md[EVP_MAX_MD_SIZE * 2]; size_t finish_md_len; unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2]; @@ -1618,7 +1626,7 @@ struct ssl_connection_st { int first_packet; /* * What was passed in ClientHello.legacy_version. Used for RSA pre-master - * secret and (D)TLS (<=1.2) rollback check + * secret and SSLv3/TLS (<=1.2) rollback check */ int client_version; /* @@ -1649,6 +1657,8 @@ struct ssl_connection_st { unsigned char *scts; /* Length of raw extension data, if seen */ uint16_t scts_len; + /* Expect OCSP CertificateStatus message */ + int status_expected; struct { /* OCSP status request only */ @@ -1660,16 +1670,15 @@ struct ssl_connection_st { STACK_OF(OCSP_RESPONSE) *resp_ex; } ocsp; + /* RFC4507 session ticket expected to be received or sent */ + int ticket_expected; /* TLS 1.3 tickets requested by the application. */ int extra_tickets_expected; - /* - * Peer's advertised ec_point_formats list (TLS 1.2 and below), - * retained as received so SSL_get0_ec_point_formats() can return - * it verbatim. Point format no longer influences cert selection - * or acceptance; the parse hook validates RFC 4492/8422 section - * 5.1.2 ("uncompressed" must be present) inline. - */ + /* our list */ + size_t ecpointformats_len; + unsigned char *ecpointformats; + /* peer's list */ size_t peer_ecpointformats_len; unsigned char *peer_ecpointformats; @@ -1714,12 +1723,19 @@ struct ssl_connection_st { /* The available PSK key exchange modes */ int psk_kex_mode; + /* Set to one if we have negotiated ETM */ + int use_etm; + /* Are we expecting to receive early data? */ int early_data; + /* Is the session suitable for early data? */ + int early_data_ok; /* May be sent by a server in HRR. Must be echoed back in ClientHello */ unsigned char *tls13_cookie; size_t tls13_cookie_len; + /* Have we received a cookie from the client? */ + int cookieok; /* * Maximum Fragment Length as per RFC 4366. @@ -1741,6 +1757,8 @@ struct ssl_connection_st { /* This is the list of algorithms the peer supports that we also support */ int compress_certificate_from_peer[TLSEXT_comp_cert_limit]; + /* indicate that we sent the extension, so we'll accept it */ + int compress_certificate_sent; uint8_t client_cert_type; uint8_t client_cert_type_ctos; @@ -1753,27 +1771,7 @@ struct ssl_connection_st { /* RFC 8701 GREASE */ uint8_t grease_seed[OSSL_GREASE_LAST_INDEX + 1]; - - /* "bool" fields go last, for slightly better packing */ - bool grease_seeded; - - /* Expect OCSP CertificateStatus message */ - bool status_expected; - - /* RFC4507 session ticket expected to be received or sent */ - bool ticket_expected; - - /* Set to one if we have negotiated ETM */ - bool use_etm; - - /* Is the session suitable for early data? */ - bool early_data_ok; - - /* Have we received a cookie from the client? */ - bool cookieok; - - /* indicate that we sent the extension, so we'll accept it */ - bool compress_certificate_sent; + int grease_seeded; } ext; /* @@ -2185,7 +2183,8 @@ typedef struct cert_st { } CERT; /* - * This is for the TLSv1.0 differences in crypto/hash stuff. + * This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit + * of a mess of functions, but hell, think of it as an opaque structure :-) */ typedef struct ssl3_enc_method { int (*setup_key_block)(SSL_CONNECTION *); @@ -2507,6 +2506,7 @@ void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg); __owur int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk); __owur int ssl_verify_rpk(SSL_CONNECTION *s, EVP_PKEY *rpk); +__owur int ssl_verify_ocsp(SSL *s, STACK_OF(X509) *sk); __owur int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags); __owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref); @@ -2821,9 +2821,10 @@ __owur int ssl_validate_ct(SSL_CONNECTION *s); __owur EVP_PKEY *ssl_get_auto_dh(SSL_CONNECTION *s); -__owur int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int is_ee); +__owur int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int vfy, + int is_ee); __owur int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, - X509 *ex); + X509 *ex, int vfy); int tls_choose_sigalg(SSL_CONNECTION *s, int fatalerrs); @@ -2842,7 +2843,7 @@ __owur int tls_check_sigalg_curve(const SSL_CONNECTION *s, int curve); __owur int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t, EVP_PKEY *pkey); __owur int ssl_set_client_disabled(SSL_CONNECTION *s); __owur int ssl_cipher_disabled(const SSL_CONNECTION *s, const SSL_CIPHER *c, - int op); + int op, int echde); __owur int ssl_handshake_hash(SSL_CONNECTION *s, unsigned char *out, size_t outlen, diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 7cfd59d6d0..0e2b1fe9bd 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -42,7 +42,7 @@ int SSL_use_certificate(SSL *ssl, X509 *x) return 0; } - rv = ssl_security_cert(sc, NULL, x, 1); + rv = ssl_security_cert(sc, NULL, x, 0, 1); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); return 0; @@ -247,7 +247,7 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) return 0; } - rv = ssl_security_cert(NULL, ctx, x, 1); + rv = ssl_security_cert(NULL, ctx, x, 0, 1); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); return 0; @@ -993,13 +993,13 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr c = sc != NULL ? sc->cert : ctx->cert; /* Do all security checks before anything else */ - rv = ssl_security_cert(sc, ctx, x509, 1); + rv = ssl_security_cert(sc, ctx, x509, 0, 1); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); goto out; } for (j = 0; j < sk_X509_num(chain); j++) { - rv = ssl_security_cert(sc, ctx, sk_X509_value(chain, j), 0); + rv = ssl_security_cert(sc, ctx, sk_X509_value(chain, j), 0, 0); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); goto out; diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 094ab1a74e..1bd1110973 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -22,7 +22,7 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); -static SSL_SESSION *remove_session_locked(SSL_CTX *ctx, SSL_SESSION *c); +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); DEFINE_STACK_OF(SSL_SESSION) @@ -279,16 +279,8 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) { SSL_SESSION *sess = ssl_session_dup_intern(src, ticket); - if (sess != NULL) { + if (sess != NULL) sess->not_resumable = 0; - /* - * A duplicated session can land in the stateful session cache, and is - * not necessarily a live session just built for an external PSK. The - * caller must explicitly set this field non-zero after duplication as - * needed. - */ - sess->psk_external = 0; - } return sess; } @@ -314,7 +306,7 @@ unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) } /* - * TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling + * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling * the ID with random junk repeatedly until we have no conflict is going to * complete in one iteration pretty much "most" of the time (btw: * understatement). So, if it takes us 10 iterations and we still can't avoid @@ -656,13 +648,7 @@ int ssl_get_prev_session(SSL_CONNECTION *s, CLIENTHELLO_MSG *hello) goto err; /* treat like cache miss */ } - /* - * sid_ctx exists to keep multiple services that happen to share one - * session cache from resuming each other's sessions. This check is not - * relevant to external PSK sessions that are not restored from a cache. - */ - if (!ret->psk_external - && (s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { + if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { /* * We can't be sure if this session is being used out of context, * which is especially important for SSL_VERIFY_PEER. The application @@ -812,14 +798,6 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) ssl_session_calculate_timeout(c); } - /* - * evicted_head is a singly-linked list (via the next pointer, which - * SSL_SESSION_list_remove zeroes out) of sessions evicted from the cache - * that need their remove_session_cb called and their reference dropped - * once the lock is released. - */ - SSL_SESSION *evicted_head = NULL; - if (s == NULL) { /* * new cache entry -- remove old ones if cache has become too large @@ -830,13 +808,10 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) if (SSL_CTX_sess_get_cache_size(ctx) > 0) { while (SSL_CTX_sess_number(ctx) >= SSL_CTX_sess_get_cache_size(ctx)) { - SSL_SESSION *r = remove_session_locked(ctx, ctx->session_cache_tail); - - if (r == NULL) + if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) break; - ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full); - r->next = evicted_head; - evicted_head = r; + else + ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full); } } @@ -853,59 +828,41 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) ret = 0; } CRYPTO_THREAD_unlock(ctx->lock); - - while (evicted_head != NULL) { - SSL_SESSION *next = evicted_head->next; - - evicted_head->next = NULL; - if (ctx->remove_session_cb != NULL) - ctx->remove_session_cb(ctx, evicted_head); - SSL_SESSION_free(evicted_head); - evicted_head = next; - } - return ret; } int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) { - SSL_SESSION *r; - - if (c == NULL || c->session_id_length == 0) - return 0; - if (!CRYPTO_THREAD_write_lock(ctx->lock)) - return 0; - r = remove_session_locked(ctx, c); - CRYPTO_THREAD_unlock(ctx->lock); - - /* - * The callback is invoked even when the session is not in the internal - * cache so that external caches can be notified. - */ - if (ctx->remove_session_cb != NULL) - ctx->remove_session_cb(ctx, c); - SSL_SESSION_free(r); - return r != NULL; + return remove_session_lock(ctx, c, 1); } -/* - * Removes c from the session cache. Caller must hold ctx->lock. - * Returns the removed session (caller must invoke remove_session_cb and - * SSL_SESSION_free), or NULL if not found. - */ -static SSL_SESSION *remove_session_locked(SSL_CTX *ctx, SSL_SESSION *c) +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) { - SSL_SESSION *r = NULL; + SSL_SESSION *r; + int ret = 0; - if (c != NULL && c->session_id_length != 0) { - r = lh_SSL_SESSION_retrieve(ctx->sessions, c); - if (r != NULL) { + if ((c != NULL) && (c->session_id_length != 0)) { + if (lck) { + if (!CRYPTO_THREAD_write_lock(ctx->lock)) + return 0; + } + if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) { + ret = 1; r = lh_SSL_SESSION_delete(ctx->sessions, r); SSL_SESSION_list_remove(ctx, r); } c->not_resumable = 1; + + if (lck) + CRYPTO_THREAD_unlock(ctx->lock); + + if (ctx->remove_session_cb != NULL) + ctx->remove_session_cb(ctx, c); + + if (ret) + SSL_SESSION_free(r); } - return r; + return ret; } void SSL_SESSION_free(SSL_SESSION *ss) @@ -946,7 +903,7 @@ int SSL_SESSION_up_ref(SSL_SESSION *ss) { int i; - if (!CRYPTO_UP_REF(&ss->references, &i)) + if (CRYPTO_UP_REF(&ss->references, &i) <= 0) return 0; REF_PRINT_COUNT("SSL_SESSION", i, ss); @@ -1285,10 +1242,9 @@ void SSL_CTX_flush_sessions_ex(SSL_CTX *s, time_t t) /* * Iterate over the list from the back (oldest), and stop * when a session can no longer be removed. - * Collect removed sessions on a stack to be processed outside the lock, - * so that remove_session_cb is never invoked while holding ctx->lock. - * If the stack failed to create, or a push fails, free the session - * immediately (without invoking the callback). + * Add the session to a temporary list to be freed outside + * the SSL_CTX lock. + * But still do the remove_session_cb() within the lock. */ while (s->session_cache_tail != NULL) { current = s->session_cache_tail; @@ -1296,6 +1252,15 @@ void SSL_CTX_flush_sessions_ex(SSL_CTX *s, time_t t) lh_SSL_SESSION_delete(s->sessions, current); SSL_SESSION_list_remove(s, current); current->not_resumable = 1; + if (s->remove_session_cb != NULL) + s->remove_session_cb(s, current); + /* + * Throw the session on a stack, it's entirely plausible + * that while freeing outside the critical section, the + * session could be re-added, so avoid using the next/prev + * pointers. If the stack failed to create, or the session + * couldn't be put on the stack, just free it here + */ if (sk == NULL || !sk_SSL_SESSION_push(sk, current)) SSL_SESSION_free(current); } else { @@ -1306,13 +1271,7 @@ void SSL_CTX_flush_sessions_ex(SSL_CTX *s, time_t t) lh_SSL_SESSION_set_down_load(s->sessions, i); CRYPTO_THREAD_unlock(s->lock); - while (sk_SSL_SESSION_num(sk) > 0) { - current = sk_SSL_SESSION_pop(sk); - if (s->remove_session_cb != NULL) - s->remove_session_cb(s, current); - SSL_SESSION_free(current); - } - sk_SSL_SESSION_free(sk); + sk_SSL_SESSION_pop_free(sk, SSL_SESSION_free); } int ssl_clear_bad_session(SSL_CONNECTION *s) diff --git a/ssl/ssl_utst.c b/ssl/ssl_utst.c index 7ff8932e42..91be7398ca 100644 --- a/ssl/ssl_utst.c +++ b/ssl/ssl_utst.c @@ -7,9 +7,6 @@ * https://www.openssl.org/source/license.html */ -/* SSL_test_functions() is deprecated but still needs to be implemented */ -#include "internal/deprecated.h" - #include "ssl_local.h" #ifndef OPENSSL_NO_UNIT_TEST diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 753402b84f..2f97850972 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -59,6 +59,8 @@ static int final_ech(SSL_CONNECTION *s, unsigned int context, int sent); static int final_renegotiate(SSL_CONNECTION *s, unsigned int context, int sent); static int init_server_name(SSL_CONNECTION *s, unsigned int context); static int final_server_name(SSL_CONNECTION *s, unsigned int context, int sent); +static int final_ec_pt_formats(SSL_CONNECTION *s, unsigned int context, + int sent); static int init_session_ticket(SSL_CONNECTION *s, unsigned int context); #ifndef OPENSSL_NO_OCSP static int init_status_request(SSL_CONNECTION *s, unsigned int context); @@ -109,9 +111,6 @@ static EXT_RETURN tls_construct_compress_certificate(SSL_CONNECTION *sc, WPACKET static int tls_parse_compress_certificate(SSL_CONNECTION *sc, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -static int tls_parse_ec_pt_formats(SSL_CONNECTION *s, PACKET *pkt, - unsigned int context, - X509 *x, size_t chainidx); /* Structure to define a built-in extension */ typedef struct extensions_definition_st { @@ -218,9 +217,9 @@ static const EXTENSION_DEFINITION ext_defs[] = { SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY, OSSL_ECH_HANDLING_COMPRESS, - init_ec_point_formats, tls_parse_ec_pt_formats, tls_parse_ec_pt_formats, + init_ec_point_formats, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats, tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats, - NULL }, + final_ec_pt_formats }, { /* * "supported_groups" is spread across several specifications. * It was originally specified as "elliptic_curves" in RFC 4492, @@ -749,111 +748,6 @@ static int verify_extension(SSL_CONNECTION *s, unsigned int context, return 1; } -/* - * Parse an ec_point_formats extension off the wire (one function for - * both sides). The peer's list is retained verbatim for - * SSL_get0_ec_point_formats() and for the RFC 4492/8422 section 5.1.2 - * 'uncompressed must be present' check. - * - * The check is gated on the negotiated ciphersuite -- a TLS 1.3 - * handshake or a non-ECC TLS 1.2 ciphersuite makes the extension moot - * and any missing 'uncompressed' codepoint is ignored. On the client - * the chosen ciphersuite is already locked in by the time we parse - * ServerHello, so the check happens inline here. On the server it's - * deferred to tls_construct_stoc_ec_pt_formats(), the first point at - * which s->s3.tmp.new_cipher is set for TLS 1.2. - */ -static int tls_parse_ec_pt_formats(SSL_CONNECTION *s, PACKET *pkt, - unsigned int context, X509 *x, size_t chainidx) -{ - PACKET list; - - if (!PACKET_as_length_prefixed_1(pkt, &list) - || PACKET_remaining(&list) == 0) { - SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - if (!s->hit - && !PACKET_memdup(&list, &s->ext.peer_ecpointformats, - &s->ext.peer_ecpointformats_len)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!s->server) { - unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey; - unsigned long alg_a = s->s3.tmp.new_cipher->algorithm_auth; - - if (((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) - && memchr(PACKET_data(&list), - TLSEXT_ECPOINTFORMAT_uncompressed, - PACKET_remaining(&list)) - == NULL) { - SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, - SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); - return 0; - } - } - - return 1; -} - -/* - * Verify that all extensions in |packet| are known built-in or custom - * extension types. This is used for TLS 1.3 server extension responses where - * unknown extensions are not ignored. - */ -int tls_validate_no_unknown_extensions(SSL_CONNECTION *s, PACKET *packet, - unsigned int context) -{ - PACKET extensions = *packet; - custom_ext_methods *exts = &s->cert->custext; - ENDPOINT role = ENDPOINT_BOTH; - - if ((context & SSL_EXT_CLIENT_HELLO) != 0) { -#ifndef OPENSSL_NO_ECH - if (s->ext.ech.attempted == 1 && s->ext.ech.ch_depth == 1) - role = ENDPOINT_CLIENT; - else - role = ENDPOINT_SERVER; -#else - role = ENDPOINT_SERVER; -#endif - } else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0) { - role = ENDPOINT_CLIENT; - } - - while (PACKET_remaining(&extensions) > 0) { - unsigned int type; - size_t i; - PACKET extension; - const EXTENSION_DEFINITION *thisext; - - if (!PACKET_get_net_2(&extensions, &type) - || !PACKET_get_length_prefixed_2(&extensions, &extension)) { - SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - for (i = 0, thisext = ext_defs; i < OSSL_NELEM(ext_defs); - i++, thisext++) { - if (type == thisext->type) - break; - } - if (i < OSSL_NELEM(ext_defs)) - continue; - - if (exts != NULL && custom_ext_find(exts, role, type, NULL) != NULL) - continue; - - SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, - SSL_R_UNSOLICITED_EXTENSION); - return 0; - } - - return 1; -} - /* * Check whether the context defined for an extension |extctx| means whether * the extension is relevant for the current context |thisctx| or not. Returns @@ -963,10 +857,6 @@ int tls_collect_extensions(SSL_CONNECTION *s, PACKET *packet, SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION); goto err; } - /* The server must tolerate the unknown extension and complete. */ - if (thisex == NULL) - continue; - idx = (unsigned int)(thisex - raw_extensions); /*- * Check that we requested this extension (if appropriate). Requests can @@ -997,15 +887,17 @@ int tls_collect_extensions(SSL_CONNECTION *s, PACKET *packet, SSL_R_UNSOLICITED_EXTENSION); goto err; } - thisex->data = extension; - thisex->present = 1; - thisex->type = type; - thisex->received_order = i++; - if (s->ext.debug_cb) - s->ext.debug_cb(SSL_CONNECTION_GET_USER_SSL(s), !s->server, - thisex->type, PACKET_data(&thisex->data), - (int)PACKET_remaining(&thisex->data), - s->ext.debug_arg); + if (thisex != NULL) { + thisex->data = extension; + thisex->present = 1; + thisex->type = type; + thisex->received_order = i++; + if (s->ext.debug_cb) + s->ext.debug_cb(SSL_CONNECTION_GET_USER_SSL(s), !s->server, + thisex->type, PACKET_data(&thisex->data), + (int)PACKET_remaining(&thisex->data), + s->ext.debug_arg); + } } if (init) { @@ -1468,6 +1360,45 @@ static int final_server_name(SSL_CONNECTION *s, unsigned int context, int sent) } } +static int final_ec_pt_formats(SSL_CONNECTION *s, unsigned int context, + int sent) +{ + unsigned long alg_k, alg_a; + + if (s->server) + return 1; + + alg_k = s->s3.tmp.new_cipher->algorithm_mkey; + alg_a = s->s3.tmp.new_cipher->algorithm_auth; + + /* + * If we are client and using an elliptic curve cryptography cipher + * suite, then if server returns an EC point formats lists extension it + * must contain uncompressed. + */ + if (s->ext.ecpointformats != NULL + && s->ext.ecpointformats_len > 0 + && s->ext.peer_ecpointformats != NULL + && s->ext.peer_ecpointformats_len > 0 + && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) { + /* we are using an ECC cipher */ + size_t i; + unsigned char *list = s->ext.peer_ecpointformats; + + for (i = 0; i < s->ext.peer_ecpointformats_len; i++) { + if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed) + break; + } + if (i == s->ext.peer_ecpointformats_len) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); + return 0; + } + } + + return 1; +} + static int init_session_ticket(SSL_CONNECTION *s, unsigned int context) { if (!s->server) diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index f17fe2c495..f9ece09df3 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -201,8 +201,6 @@ EXT_RETURN tls_construct_ctos_srp(SSL_CONNECTION *s, WPACKET *pkt, * with the sole exception of psk-ke resumption, provided the client is sure * that the server will not want elect a full handshake. The check type then * indicates whether ECDHE or FFDHE negotiation should be performed. - * - * It returns 1 if negotiation is supported, 0 if it's not and -1 on error. */ static int negotiate_dhe(SSL_CONNECTION *s, dhe_check_t check_type, int min_version, int max_version) @@ -216,8 +214,6 @@ static int negotiate_dhe(SSL_CONNECTION *s, dhe_check_t check_type, /* See if we support any EC or FFDHE ciphersuites */ cipher_stack = SSL_get1_supported_ciphers(ssl); - if (cipher_stack == NULL) - return -1; end = sk_SSL_CIPHER_num(cipher_stack); for (i = 0; i < end; i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); @@ -267,20 +263,15 @@ EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL_CONNECTION *s, WPACKET *pkt, { const unsigned char *pformats; size_t num_formats; - int reason, min_version, max_version, dhe_result; + int reason, min_version, max_version; reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL); if (reason != 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason); return EXT_RETURN_FAIL; } - dhe_result = negotiate_dhe(s, ptfmt_check, min_version, max_version); - if (dhe_result == 0) + if (!negotiate_dhe(s, ptfmt_check, min_version, max_version)) return EXT_RETURN_NOT_SENT; - if (dhe_result < 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } tls1_get_formatlist(s, &pformats, &num_formats); if (num_formats == 0) @@ -323,11 +314,7 @@ EXT_RETURN tls_construct_ctos_supported_groups(SSL_CONNECTION *s, WPACKET *pkt, */ use_ecdhe = negotiate_dhe(s, ecdhe_check, min_version, max_version); use_ffdhe = negotiate_dhe(s, ffdhe_check, min_version, max_version); - if (use_ecdhe < 0 || use_ffdhe < 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - if (use_ecdhe == 0 && use_ffdhe == 0 + if (!use_ecdhe && !use_ffdhe && (dtls ? DTLS_VERSION_LE(max_version, DTLS1_2_VERSION) : (max_version <= TLS1_2_VERSION))) return EXT_RETURN_NOT_SENT; @@ -1763,6 +1750,46 @@ int tls_parse_stoc_server_name(SSL_CONNECTION *s, PACKET *pkt, return 1; } +int tls_parse_stoc_ec_pt_formats(SSL_CONNECTION *s, PACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx) +{ + size_t ecpointformats_len; + PACKET ecptformatlist; + + if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); + return 0; + } + if (!s->hit) { + ecpointformats_len = PACKET_remaining(&ecptformatlist); + if (ecpointformats_len == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH); + return 0; + } + + s->ext.peer_ecpointformats_len = 0; + OPENSSL_free(s->ext.peer_ecpointformats); + s->ext.peer_ecpointformats = OPENSSL_malloc(ecpointformats_len); + if (s->ext.peer_ecpointformats == NULL) { + s->ext.peer_ecpointformats_len = 0; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + s->ext.peer_ecpointformats_len = ecpointformats_len; + + if (!PACKET_copy_bytes(&ecptformatlist, + s->ext.peer_ecpointformats, + ecpointformats_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} + int tls_parse_stoc_session_ticket(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) @@ -2415,7 +2442,6 @@ int tls_parse_stoc_psk(SSL_CONNECTION *s, PACKET *pkt, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 - SSL_SESSION *sesstmp; unsigned int identity; if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) { @@ -2457,25 +2483,6 @@ int tls_parse_stoc_psk(SSL_CONNECTION *s, PACKET *pkt, || s->psksession->ext.max_early_data == 0) memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE); - /* - * The psk_use_session_cb()/psk_client_callback() may reuse - * the session across connections we can't mutate it directly. - */ - if ((sesstmp = ssl_session_dup(s->psksession, 0)) == NULL) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - SSL_SESSION_free(s->psksession); - s->psksession = sesstmp; - - /* - * s->psksession (now our private copy) was built by the callback, not via - * ssl_get_new_session(), so it was never stamped with our own sid_ctx. Do - * so now, to avoid rejection of the PSK session in tls_process_server_hello(). - */ - memcpy(s->psksession->sid_ctx, s->sid_ctx, s->sid_ctx_length); - s->psksession->sid_ctx_length = s->sid_ctx_length; - SSL_SESSION_free(s->session); s->session = s->psksession; s->psksession = NULL; diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index a597085e1b..0460cd79e7 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -245,6 +245,30 @@ int tls_parse_ctos_srp(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, } #endif +int tls_parse_ctos_ec_pt_formats(SSL_CONNECTION *s, PACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET ec_point_format_list; + + if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) + || PACKET_remaining(&ec_point_format_list) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + if (!PACKET_memdup(&ec_point_format_list, + &s->ext.peer_ecpointformats, + &s->ext.peer_ecpointformats_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} + int tls_parse_ctos_session_ticket(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) @@ -1397,10 +1421,7 @@ int tls_parse_ctos_psk(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, #endif /* OPENSSL_NO_PSK */ if (sess != NULL) { - /* - * We found an external (not a resumption) PSK - duplicate the - * session, set the session id to our own, and mark it as external. - */ + /* We found a PSK */ SSL_SESSION *sesstmp = ssl_session_dup(sess, 0); if (sesstmp == NULL) { @@ -1416,7 +1437,7 @@ int tls_parse_ctos_psk(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, */ memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length); sess->sid_ctx_length = s->sid_ctx_length; - sess->psk_external = ext = 1; + ext = 1; if (id == 0) s->ext.early_data_ok = 1; s->ext.ticket_expected = 1; @@ -1487,8 +1508,6 @@ int tls_parse_ctos_psk(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, */ s->ext.early_data_ok = 1; } - /* This PSK is not external, use the correct binder label, ... */ - ext = 0; } md = ssl_md(sctx, sess->cipher->algorithm2); @@ -1666,29 +1685,14 @@ EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL_CONNECTION *s, WPACKET *pkt, { unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey; unsigned long alg_a = s->s3.tmp.new_cipher->algorithm_auth; - int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA); + int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) + && (s->ext.peer_ecpointformats != NULL); const unsigned char *plist; size_t plistlen; - /* - * The extension is irrelevant unless we're negotiating an ECC - * ciphersuite at TLS 1.2 or below, and the peer sent a list. This - * is the first point at which the chosen ciphersuite is known, so - * the RFC 4492/8422 section 5.1.2 check for the required - * 'uncompressed' codepoint also happens here. - */ - if (!using_ecc || s->ext.peer_ecpointformats == NULL) + if (!using_ecc) return EXT_RETURN_NOT_SENT; - if (memchr(s->ext.peer_ecpointformats, - TLSEXT_ECPOINTFORMAT_uncompressed, - s->ext.peer_ecpointformats_len) - == NULL) { - SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, - SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); - return EXT_RETURN_FAIL; - } - tls1_get_formatlist(s, &plist, &plistlen); if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) || !WPACKET_start_sub_packet_u16(pkt) @@ -1765,15 +1769,7 @@ EXT_RETURN tls_construct_stoc_session_ticket(SSL_CONNECTION *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { - /* - * Don't tell the client to expect a NewSessionTicket when any - * ticket we'd mint would be rejected by ssl_get_prev_session() - * whenever SSL_VERIFY_PEER is set with no sid_ctx configured (see - * the checks there). In TLS 1.2, once promised the ticket MUST - * be sent. - */ - if (!s->ext.ticket_expected || !tls_use_ticket(s) - || ((s->verify_mode & SSL_VERIFY_PEER) != 0 && s->sid_ctx_length == 0)) { + if (!s->ext.ticket_expected || !tls_use_ticket(s)) { s->ext.ticket_expected = 0; return EXT_RETURN_NOT_SENT; } diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index d719ef8a84..6c77296c31 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1639,7 +1639,7 @@ static int set_client_ciphersuite(SSL_CONNECTION *s, * If it is a disabled cipher we either didn't send it in client hello, * or it's not allowed for the selected protocol. So we return an error. */ - if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK)) { + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CIPHER_RETURNED); return 0; } @@ -1799,8 +1799,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL_CONNECTION *s, PACKET *pkt) if (hrr) { if (!tls_collect_extensions(s, &extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST, &extensions, NULL, 1) - || !tls_validate_no_unknown_extensions(s, &extpkt, - SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) || !tls_parse_extension(s, TLSEXT_IDX_ech, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST, extensions, NULL, 0)) { @@ -1961,10 +1959,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL_CONNECTION *s, PACKET *pkt) SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION); goto err; } - if (SSL_CONNECTION_IS_TLS13(s) - && !tls_validate_no_unknown_extensions(s, &extpkt, context)) - /* SSLfatal() already called */ - goto err; s->hit = 0; diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 465d2eff33..bacbd58218 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1056,7 +1056,7 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i /* Don't leave errors in the queue */ ERR_clear_error(); chain = X509_STORE_CTX_get0_chain(xs_ctx); - i = ssl_security_cert_chain(s, chain, NULL); + i = ssl_security_cert_chain(s, chain, NULL, 0); if (i != 1) { #if 0 /* Dummy error calls so mkerr generates them */ @@ -1081,7 +1081,7 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i } X509_STORE_CTX_free(xs_ctx); } else { - i = ssl_security_cert_chain(s, extra_certs, x); + i = ssl_security_cert_chain(s, extra_certs, x, 0); if (i != 1) { if (!for_comp) SSLfatal(s, SSL_AD_INTERNAL_ERROR, i); @@ -1535,23 +1535,6 @@ WORK_STATE tls_finish_handshake(SSL_CONNECTION *s, ossl_unused WORK_STATE wst, return WORK_FINISHED_STOP; } -/* - * TLS 1.3 reserves handshake message type 0, so a HelloRequest must reach the - * state machine and be rejected there whenever TLS 1.3 is still possible. - * - * By the time a client reads a server handshake message, s->version is either - * the configured maximum for an initial pre-ServerHello handshake, or the - * already negotiated version after ServerHello or during renegotiation. Skip - * only when that version is below TLS 1.3. - */ -static int should_skip_hello_request(const SSL_CONNECTION *s) -{ - if (SSL_CONNECTION_IS_TLS13(s)) - return 0; - - return s->version > 0 && s->version < TLS1_3_VERSION; -} - int tls_get_message_header(SSL_CONNECTION *s, int *mt) { /* s->init_num < SSL3_HM_HEADER_LENGTH */ @@ -1611,8 +1594,7 @@ int tls_get_message_header(SSL_CONNECTION *s, int *mt) skip_message = 0; if (!s->server) if (s->statem.hand_state != TLS_ST_OK - && p[0] == SSL3_MT_HELLO_REQUEST - && should_skip_hello_request(s)) + && p[0] == SSL3_MT_HELLO_REQUEST) /* * The server may always send 'Hello Request' messages -- * we are doing a handshake anyway now, so ignore them if diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h index de9ff299be..68ac803fa9 100644 --- a/ssl/statem/statem_local.h +++ b/ssl/statem/statem_local.h @@ -269,8 +269,6 @@ __owur int tls_validate_all_contexts(SSL_CONNECTION *s, unsigned int thisctx, RAW_EXTENSION *exts); __owur int extension_is_relevant(SSL_CONNECTION *s, unsigned int extctx, unsigned int thisctx); -__owur int tls_validate_no_unknown_extensions(SSL_CONNECTION *s, - PACKET *packet, unsigned int context); __owur int tls_collect_extensions(SSL_CONNECTION *s, PACKET *packet, unsigned int context, RAW_EXTENSION **res, size_t *len, int init); @@ -308,6 +306,9 @@ int tls_parse_ctos_srp(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, int tls_parse_ctos_early_data(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +int tls_parse_ctos_ec_pt_formats(SSL_CONNECTION *s, PACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx); int tls_parse_ctos_supported_groups(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidxl); @@ -517,6 +518,9 @@ int tls_parse_stoc_early_data(SSL_CONNECTION *s, PACKET *pkt, int tls_parse_stoc_maxfragmentlen(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +int tls_parse_stoc_ec_pt_formats(SSL_CONNECTION *s, PACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx); int tls_parse_stoc_session_ticket(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index fc3769a017..46e418676e 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -712,20 +712,17 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL_CONNECTION *s) * session tickets or resumption (e.g. new_session_count = 0 or * resumption_count = 0), this implementation does not currently * interpret or enforce those parameters. - * - * Also skip issuance when SSL_VERIFY_PEER is set with no sid_ctx - * configured: any ticket minted here would be rejected by - * ssl_get_prev_session() in that configuration. */ - if (s->num_tickets <= s->sent_tickets - || ((s->options & SSL_OP_NO_TICKET) != 0 + if (((s->options & SSL_OP_NO_TICKET) != 0 && (SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER) == 0) - || s->ext.psk_kex_mode == TLSEXT_KEX_MODE_FLAG_NONE - || ((s->verify_mode & SSL_VERIFY_PEER) != 0 && s->sid_ctx_length == 0)) + || s->ext.psk_kex_mode == TLSEXT_KEX_MODE_FLAG_NONE) { st->hand_state = TLS_ST_OK; - else + } else if (s->num_tickets > s->sent_tickets) { st->hand_state = TLS_ST_SW_SESSION_TICKET; + } else { + st->hand_state = TLS_ST_OK; + } return WRITE_TRAN_CONTINUE; case TLS_ST_SR_KEY_UPDATE: @@ -2553,6 +2550,18 @@ WORK_STATE tls_post_process_client_hello(SSL_CONNECTION *s, WORK_STATE wst) s->s3.tmp.new_cipher = s->session->cipher; } + /*- + * we now have the following setup. + * client_random + * cipher_list - our preferred list of ciphers + * ciphers - the client's preferred list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - session reuse flag + * s->s3.tmp.new_cipher - the new cipher to use. + */ + /* * Call status_request callback if needed. Has to be done after the * certificate callbacks etc above. @@ -3565,8 +3574,7 @@ static int tls_process_cke_gost(SSL_CONNECTION *s, PACKET *pkt) EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; unsigned char premaster_secret[32]; const unsigned char *start; - size_t outlen = sizeof(premaster_secret); - size_t inlen; + size_t outlen = sizeof(premaster_secret), inlen; unsigned long alg_a; GOST_KX_MESSAGE *pKX = NULL; const unsigned char *ptr; @@ -3632,10 +3640,7 @@ static int tls_process_cke_gost(SSL_CONNECTION *s, PACKET *pkt) goto err; } - inlen = ASN1_STRING_length_ex(pKX->kxBlob->value.sequence); - if (inlen > INT_MAX) - goto err; - + inlen = ASN1_STRING_length(pKX->kxBlob->value.sequence); start = ASN1_STRING_get0_data(pKX->kxBlob->value.sequence); if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index f8056c82da..2a15378570 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1255,17 +1255,6 @@ static const char prefixes[] = { TUPLE_DELIMITER_CHARACTER, * Those callback functions are (indirectly) called by CONF_parse_list with * different separators (nominally ':' or '/'), a variable based on gid_cb_st * is used to keep track of the parsing results between the various calls - * - * Bookkeeping invariants maintained throughout parsing (see gid_cb_st below): - * - gid_arr[0..gidcnt) is the flat list of groups, partitioned into tuples in - * order: tuple t occupies a contiguous run of tuplcnt_arr[t] entries. - * - The per-tuple counts therefore sum to the group count: - * sum(tuplcnt_arr[0..tplcnt]) == gidcnt - * (indices 0..tplcnt-1 are closed tuples, index tplcnt is the active one). - * - ksid_arr[0..ksidcnt) holds keyshare group IDs; each is one of the groups - * in gid_arr and they appear in the same relative order as their groups. - * Every add/remove path must preserve these; an OOB read in the remove path - * (GitHub #31315) was a symptom of the first invariant being violated. */ typedef struct { @@ -1553,16 +1542,9 @@ static int gid_cb(const char *elem, int len, void *arg) * Otherwise, iterate through the tuple check whether any keyshares * remain *after* the index of the group we're removing. The first * of these, if any, is at index `k+1` in the keyshare list, which - * is the only slot we need to check. - * - * If the removal emptied the tuple (tuplcnt_arr[j] == 0 after the - * decrement above) there is no remaining group to float onto: - * gid_arr[tpl_start_idx] would now name a group belonging to the - * next tuple (or be past gid_arr entirely). Drop the keyshare in - * that case too. + * is the only slow we need to check. */ - drop_ks = ks_check_idx > tpl_start_idx || j >= garg->tplcnt - || garg->tuplcnt_arr[j] == 0; + drop_ks = ks_check_idx > tpl_start_idx || j >= garg->tplcnt; if (!drop_ks) { size_t end; /* End index of affected tuple */ @@ -1591,19 +1573,11 @@ static int gid_cb(const char *elem, int len, void *arg) * Adjust closed or current tuple's group count, if a closed tuple * count reaches zero excise the resulting empty tuple. The current * (not yet closed) tuple at the end of the list stays even if empty. - * - * The active tuple lives at index tplcnt, so the slots in use are - * tuplcnt_arr[0..tplcnt] (tplcnt + 1 entries). Excising closed tuple - * j must therefore shift the closed tuples j+1..tplcnt-1 *and* the - * active tuple at index tplcnt down by one, i.e. (tplcnt - j) entries - * counted with the pre-decrement tplcnt. Decrement tplcnt only after - * the move so the active-tuple slot is not left behind (which would - * inflate the per-tuple counts and desynchronise them from gid_arr). */ if (garg->tuplcnt_arr[j] == 0 && j < garg->tplcnt) { + garg->tplcnt--; memmove(garg->tuplcnt_arr + j, garg->tuplcnt_arr + j + 1, (garg->tplcnt - j) * sizeof(size_t)); - garg->tplcnt--; } } else { /* Processing addition of a single new group */ @@ -1912,7 +1886,13 @@ int tls1_check_group_id(SSL_CONNECTION *s, uint16_t group_id, void tls1_get_formatlist(SSL_CONNECTION *s, const unsigned char **pformats, size_t *num_formats) { - if ((s->options & SSL_OP_LEGACY_EC_POINT_FORMATS) != 0) { + /* + * If we have a custom point format list use it otherwise use default + */ + if (s->ext.ecpointformats) { + *pformats = s->ext.ecpointformats; + *num_formats = s->ext.ecpointformats_len; + } else if ((s->options & SSL_OP_LEGACY_EC_POINT_FORMATS) != 0) { *pformats = ecformats_all; /* For Suite B we don't support char2 fields */ if (tls1_suiteb(s)) @@ -1925,6 +1905,53 @@ void tls1_get_formatlist(SSL_CONNECTION *s, const unsigned char **pformats, } } +/* Check a key is compatible with compression extension */ +static int tls1_check_pkey_comp(SSL_CONNECTION *s, EVP_PKEY *pkey) +{ + unsigned char comp_id; + size_t i; + int point_conv; + + /* If not an EC key nothing to check */ + if (!EVP_PKEY_is_a(pkey, "EC")) + return 1; + + /* Get required compression id */ + point_conv = EVP_PKEY_get_ec_point_conv_form(pkey); + if (point_conv == 0) + return 0; + if (point_conv == POINT_CONVERSION_UNCOMPRESSED) { + comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; + } else if (SSL_CONNECTION_IS_TLS13(s)) { + /* + * ec_point_formats extension is not used in TLSv1.3 so we ignore + * this check. + */ + return 1; + } else { + int field_type = EVP_PKEY_get_field_type(pkey); + + if (field_type == NID_X9_62_prime_field) + comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + else if (field_type == NID_X9_62_characteristic_two_field) + comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + else + return 0; + } + /* + * If point formats extension present check it, otherwise everything is + * supported (see RFC4492). + */ + if (s->ext.peer_ecpointformats == NULL) + return 1; + + for (i = 0; i < s->ext.peer_ecpointformats_len; i++) { + if (s->ext.peer_ecpointformats[i] == comp_id) + return 1; + } + return 0; +} + /* Return group id of a key */ static uint16_t tls1_get_group_id(EVP_PKEY *pkey) { @@ -1937,7 +1964,7 @@ static uint16_t tls1_get_group_id(EVP_PKEY *pkey) /* * Check cert parameters compatible with extensions: currently just checks EC - * certificates have compatible curves. + * certificates have compatible curves and compression. */ static int tls1_check_cert_param(SSL_CONNECTION *s, X509 *x, int check_ee_md) { @@ -1949,6 +1976,9 @@ static int tls1_check_cert_param(SSL_CONNECTION *s, X509 *x, int check_ee_md) /* If not EC nothing to do */ if (!EVP_PKEY_is_a(pkey, "EC")) return 1; + /* Check compression */ + if (!tls1_check_pkey_comp(s, pkey)) + return 0; group_id = tls1_get_group_id(pkey); /* * For a server we allow the certificate to not be in our list of supported @@ -2243,14 +2273,16 @@ static const SIGALG_LOOKUP sigalg_lookup_tbl[] = { TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION }, #ifndef OPENSSL_NO_GOST - { TLSEXT_SIGALG_gostr34102012_256_intrinsic_name, /* RFC9189 */ - NULL, TLSEXT_SIGALG_gostr34102012_256_intrinsic, + { TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias, /* RFC9189 */ + TLSEXT_SIGALG_gostr34102012_256_intrinsic_name, + TLSEXT_SIGALG_gostr34102012_256_intrinsic, NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, NID_undef, NID_undef, 1, 0, TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION }, - { TLSEXT_SIGALG_gostr34102012_512_intrinsic_name, /* RFC9189 */ - NULL, TLSEXT_SIGALG_gostr34102012_512_intrinsic, + { TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias, /* RFC9189 */ + TLSEXT_SIGALG_gostr34102012_256_intrinsic_name, + TLSEXT_SIGALG_gostr34102012_512_intrinsic, NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, NID_undef, NID_undef, 1, 0, @@ -2887,11 +2919,13 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey) } if (pkeyid == EVP_PKEY_EC) { - /* - * No point-format check on either the peer's or own cert. - * We accept any form we can decode, and send the cert we - * have. - */ + + /* Check point compression is permitted */ + if (!tls1_check_pkey_comp(s, pkey)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_R_ILLEGAL_POINT_COMPRESSION); + return 0; + } /* For TLS 1.3 or Suite B check curve matches signature algorithm */ if (SSL_CONNECTION_IS_TLS13(s) || tls1_suiteb(s)) { @@ -3020,11 +3054,12 @@ int ssl_set_client_disabled(SSL_CONNECTION *s) * @s: SSL connection that you want to use the cipher on * @c: cipher to check * @op: Security check that you want to do + * @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3 * * Returns 1 when it's disabled, 0 when enabled. */ int ssl_cipher_disabled(const SSL_CONNECTION *s, const SSL_CIPHER *c, - int op) + int op, int ecdhe) { int minversion = SSL_CONNECTION_IS_DTLS(s) ? c->min_dtls : c->min_tls; int maxversion = SSL_CONNECTION_IS_DTLS(s) ? c->max_dtls : c->max_tls; @@ -3046,6 +3081,15 @@ int ssl_cipher_disabled(const SSL_CONNECTION *s, const SSL_CIPHER *c, return 1; } + /* + * For historical reasons we will allow ECHDE to be selected by a server + * in SSLv3 if we are a client + */ + if (minversion == TLS1_VERSION + && ecdhe + && (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0) + minversion = SSL3_VERSION; + if (ssl_version_cmp(s, minversion, s->s3.tmp.max_ver) > 0 || ssl_version_cmp(s, maxversion, s->s3.tmp.min_ver) < 0) return 1; @@ -3495,7 +3539,7 @@ static int tls12_sigalg_allowed(const SSL_CONNECTION *s, int op, c = sk_SSL_CIPHER_value(sk, i); /* Skip disabled ciphers */ - if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) continue; if ((c->algorithm_mkey & (SSL_kGOST | SSL_kGOST18)) != 0) @@ -4199,6 +4243,8 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk, chain = cpk->chain; strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT; if (tls12_rpk_and_privkey(s, idx)) { + if (EVP_PKEY_is_a(pk, "EC") && !tls1_check_pkey_comp(s, pk)) + return 0; *pvalid = rv = CERT_PKEY_RPK; return rv; } @@ -4541,29 +4587,51 @@ static int ssl_security_cert_key(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, return ssl_ctx_security(ctx, op, secbits, 0, x); } -int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int is_ee) +static int ssl_security_cert_sig(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, + int op) { + /* Lookup signature algorithm digest */ + int secbits, nid, pknid; + + /* Don't check signature if self signed */ + if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) + return 1; + if (!X509_get_signature_info(x, &nid, &pknid, &secbits, NULL)) + secbits = -1; + /* If digest NID not defined use signature NID */ + if (nid == NID_undef) + nid = pknid; + if (s != NULL) + return ssl_security(s, op, secbits, nid, x); + else + return ssl_ctx_security(ctx, op, secbits, nid, x); +} + +int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int vfy, + int is_ee) +{ + if (vfy) + vfy = SSL_SECOP_PEER; if (is_ee) { - if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY)) + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy)) return SSL_R_EE_KEY_TOO_SMALL; } else { - if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY)) + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy)) return SSL_R_CA_KEY_TOO_SMALL; } + if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy)) + return SSL_R_CA_MD_TOO_WEAK; return 1; } /* - * Call ssl_security_check() on all certificates in a stack. - * If |x| is non NULL it is checked first, before checking the - * certificates in the stack. - * - * Return values: 1 if ok otherwise the error code from the first - * failing ssl_security_check().; + * Check security of a chain, if |sk| includes the end entity certificate then + * |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending + * one to the peer. Return values: 1 if ok otherwise error code to use */ int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, - X509 *x) + X509 *x, int vfy) { int rv, start_idx, i; @@ -4575,13 +4643,13 @@ int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, } else start_idx = 0; - rv = ssl_security_cert(s, NULL, x, 1); + rv = ssl_security_cert(s, NULL, x, vfy, 1); if (rv != 1) return rv; for (i = start_idx; i < sk_X509_num(sk); i++) { x = sk_X509_value(sk, i); - rv = ssl_security_cert(s, NULL, x, 0); + rv = ssl_security_cert(s, NULL, x, vfy, 0); if (rv != 1) return rv; } diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c index 0e8ddbb8f8..b2b00b3f7c 100644 --- a/ssl/t1_trce.c +++ b/ssl/t1_trce.c @@ -586,6 +586,8 @@ static const ssl_trace_tbl ssl_sigalg_tbl[] = { { TLSEXT_SIGALG_ecdsa_secp384r1_sha384, TLSEXT_SIGALG_ecdsa_secp384r1_sha384_name }, { TLSEXT_SIGALG_ecdsa_secp521r1_sha512, TLSEXT_SIGALG_ecdsa_secp521r1_sha512_name }, { TLSEXT_SIGALG_ecdsa_sha224, TLSEXT_SIGALG_ecdsa_sha224_name }, + { TLSEXT_SIGALG_ed25519, TLSEXT_SIGALG_ed25519_name }, + { TLSEXT_SIGALG_ed448, TLSEXT_SIGALG_ed448_name }, { TLSEXT_SIGALG_ecdsa_sha1, TLSEXT_SIGALG_ecdsa_sha1_name }, { TLSEXT_SIGALG_rsa_pss_rsae_sha256, TLSEXT_SIGALG_rsa_pss_rsae_sha256_name }, { TLSEXT_SIGALG_rsa_pss_rsae_sha384, TLSEXT_SIGALG_rsa_pss_rsae_sha384_name }, @@ -608,27 +610,18 @@ static const ssl_trace_tbl ssl_sigalg_tbl[] = { { TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_name }, { TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_name }, { TLSEXT_SIGALG_gostr34102001_gostr3411, TLSEXT_SIGALG_gostr34102001_gostr3411_name }, - { TLSEXT_SIGALG_sm2sig_sm3, TLSEXT_SIGALG_sm2sig_sm3_name }, - { TLSEXT_SIGALG_ed25519, TLSEXT_SIGALG_ed25519_name }, - { TLSEXT_SIGALG_ed448, TLSEXT_SIGALG_ed448_name }, { TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256, TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name }, { TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384, TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name }, { TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512, TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name }, - { TLSEXT_SIGALG_mldsa44, TLSEXT_SIGALG_mldsa44_name }, - { TLSEXT_SIGALG_mldsa65, TLSEXT_SIGALG_mldsa65_name }, - { TLSEXT_SIGALG_mldsa87, TLSEXT_SIGALG_mldsa87_name }, - { TLSEXT_SIGALG_slhdsa_sha2_128s, TLSEXT_SIGALG_slhdsa_sha2_128s_name }, - { TLSEXT_SIGALG_slhdsa_sha2_128f, TLSEXT_SIGALG_slhdsa_sha2_128f_name }, - { TLSEXT_SIGALG_slhdsa_sha2_192s, TLSEXT_SIGALG_slhdsa_sha2_192s_name }, - { TLSEXT_SIGALG_slhdsa_sha2_192f, TLSEXT_SIGALG_slhdsa_sha2_192f_name }, - { TLSEXT_SIGALG_slhdsa_sha2_256s, TLSEXT_SIGALG_slhdsa_sha2_256s_name }, - { TLSEXT_SIGALG_slhdsa_sha2_256f, TLSEXT_SIGALG_slhdsa_sha2_256f_name }, - { TLSEXT_SIGALG_slhdsa_shake_128s, TLSEXT_SIGALG_slhdsa_shake_128s_name }, - { TLSEXT_SIGALG_slhdsa_shake_128f, TLSEXT_SIGALG_slhdsa_shake_128f_name }, - { TLSEXT_SIGALG_slhdsa_shake_192s, TLSEXT_SIGALG_slhdsa_shake_192s_name }, - { TLSEXT_SIGALG_slhdsa_shake_192f, TLSEXT_SIGALG_slhdsa_shake_192f_name }, - { TLSEXT_SIGALG_slhdsa_shake_256s, TLSEXT_SIGALG_slhdsa_shake_256s_name }, - { TLSEXT_SIGALG_slhdsa_shake_256f, TLSEXT_SIGALG_slhdsa_shake_256f_name }, + /* + * Well known sigalgs that we happen to know about, but only come from + * provider capability declarations (hence no macros for the + * codepoints/names) + */ + { 0x0904, "mldsa44" }, + { 0x0905, "mldsa65" }, + { 0x0906, "mldsa87" }, + { 0x0708, "sm2sig_sm3" }, }; static const ssl_trace_tbl ssl_ctype_tbl[] = { diff --git a/test/README-dev.md b/test/README-dev.md index 3b855d8519..3c29fe2894 100644 --- a/test/README-dev.md +++ b/test/README-dev.md @@ -25,7 +25,7 @@ The number `{nn}` is (somewhat loosely) grouped as follows: 00-04 sanity, internal and essential API tests 05-09 individual symmetric cipher algorithms - 10-14 math (bignum) + 10-14 math (bignum and ossl_fn) 15-19 individual asymmetric cipher algorithms 20-24 openssl commands (some otherwise not tested) 25-29 certificate forms, generation and verification diff --git a/test/README.md b/test/README.md index 1575fb69dc..4bc558817f 100644 --- a/test/README.md +++ b/test/README.md @@ -196,13 +196,6 @@ return 0 when a failure was triggered. The `ADD_MFAIL_ALL_TESTS` and `ADD_MFAIL_ALL_NO_CHECK_TESTS` variants apply the same cycle to each index of a parameterised test, the same way `ADD_ALL_TESTS` does. -The `ADD_MFAIL_SAMPLED_TEST(fn, cnt)` variant (and its `NO_CHECK` and `ALL` -forms) caps injection at `cnt` points: it injects at every allocation when -there are at most `cnt` of them, and otherwise samples `cnt` points spread -across the run. This keeps tests with very many allocations bounded. On -`no-cached-fetch` builds, where allocation counts explode, non-sampled tests -run the counting phase only and skip injection; sampled tests still run. - An mfail test returns 1 on success or 0 on failure; under `NO_CHECK` a 0 is tolerated since a function may legitimately fail when an allocation fails. Returning -1 forces a failure that is reported even under `NO_CHECK`, for @@ -219,11 +212,6 @@ Behavior is controlled with the following environment variables: OPENSSL_TEST_MFAIL_SLOW=N Slow threshold (default 1000). - OPENSSL_TEST_MFAIL_COUNT=N Override the sampled point count, taking - precedence over the per-test value. - - OPENSSL_TEST_MFAIL_COUNT_ONLY=1 Run the counting phase only, never inject. - OPENSSL_TEST_MFAIL_POINT=N Run only failure point N (0-indexed), useful for debugging a specific failure. diff --git a/test/asn1_decode_test.c b/test/asn1_decode_test.c index 8a9629c21d..d7377c8ef7 100644 --- a/test/asn1_decode_test.c +++ b/test/asn1_decode_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2026 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,11 +14,7 @@ #include #include #include -#include -#include -#include #include "internal/numbers.h" -#include "internal/asn1.h" #include "testutil.h" #ifdef __GNUC__ @@ -270,163 +266,6 @@ err: return ret; } -/* - * A minimal, complete DER object: SEQUENCE { INTEGER 0 }. - * asn1_d2i_read_bio() should consume exactly these bytes. - */ -static const unsigned char one_obj[] = { - 0x30, 0x03, /* SEQUENCE, length 3 */ - 0x02, 0x01, 0x00 /* INTEGER 0 */ -}; - -/* - * Reading concatenated DER objects from a BIO must stop cleanly at EOF: - * once the input is exhausted on an object boundary, asn1_d2i_read_bio() - * returns < 0 and must NOT leave an error on the queue. Callers that loop - * over concatenated values (e.g. CPython's ssl module loading the Windows - * certificate store via d2i_X509_bio()) rely on this to detect end-of-input; - * a spurious ASN1_R_NOT_ENOUGH_DATA there is reported as a fatal error. - */ -static int test_d2i_read_bio_clean_eof(void) -{ - unsigned char two_objs[sizeof(one_obj) * 2]; - BIO *bio = NULL; - BUF_MEM *buf = NULL; - int ret = 0; - - memcpy(two_objs, one_obj, sizeof(one_obj)); - memcpy(two_objs + sizeof(one_obj), one_obj, sizeof(one_obj)); - - if (!TEST_ptr(bio = BIO_new_mem_buf(two_objs, sizeof(two_objs)))) - goto err; - ERR_clear_error(); - - /* Both complete objects are read, one per call. */ - if (!TEST_int_eq(asn1_d2i_read_bio(bio, &buf), (int)sizeof(one_obj))) - goto err; - BUF_MEM_free(buf); - buf = NULL; - if (!TEST_int_eq(asn1_d2i_read_bio(bio, &buf), (int)sizeof(one_obj))) - goto err; - BUF_MEM_free(buf); - buf = NULL; - - /* Clean EOF: failure return, but no error must be queued. */ - if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) - goto err; - if (!TEST_ulong_eq(ERR_peek_error(), 0)) - goto err; - - ret = 1; -err: - BUF_MEM_free(buf); - BIO_free(bio); - return ret; -} - -/* - * In contrast, hitting EOF in the middle of an object is genuine truncation - * and must still be reported as ASN1_R_NOT_ENOUGH_DATA. - */ -static int test_d2i_read_bio_truncated(void) -{ - static const unsigned char truncated[] = { - 0x30, 0x05, /* SEQUENCE claims 5 content bytes ... */ - 0x02, 0x01 /* ... but only 2 are present */ - }; - BIO *bio = NULL; - BUF_MEM *buf = NULL; - unsigned long e; - int ret = 0; - - if (!TEST_ptr(bio = BIO_new_mem_buf(truncated, sizeof(truncated)))) - goto err; - ERR_clear_error(); - - if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) - goto err; - e = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(e), ERR_LIB_ASN1) - || !TEST_int_eq(ERR_GET_REASON(e), ASN1_R_NOT_ENOUGH_DATA)) - goto err; - - ret = 1; -err: - BUF_MEM_free(buf); - BIO_free(bio); - return ret; -} - -/* - * An EOF reached while still inside an indefinite-length constructed value, - * before its end-of-contents octets, is truncation too (not a clean boundary), - * so it must also report ASN1_R_NOT_ENOUGH_DATA rather than an empty queue. - */ -static int test_d2i_read_bio_indefinite_truncated(void) -{ - /* SEQUENCE (indefinite) { INTEGER 0 } with the 00 00 EOC missing */ - static const unsigned char truncated_indefinite[] = { - 0x30, 0x80, /* SEQUENCE, indefinite length */ - 0x02, 0x01, 0x00 /* INTEGER 0; no end-of-contents octets follow */ - }; - BIO *bio = NULL; - BUF_MEM *buf = NULL; - unsigned long e; - int ret = 0; - - bio = BIO_new_mem_buf(truncated_indefinite, sizeof(truncated_indefinite)); - if (!TEST_ptr(bio)) - goto err; - ERR_clear_error(); - - if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) - goto err; - e = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(e), ERR_LIB_ASN1) - || !TEST_int_eq(ERR_GET_REASON(e), ASN1_R_NOT_ENOUGH_DATA)) - goto err; - - ret = 1; -err: - BUF_MEM_free(buf); - BIO_free(bio); - return ret; -} - -/* - * An EOF reached part-way through an object's header, with some header bytes - * already buffered, is truncation as well. This exercises the "diff != 0" arm - * of the header-read check (distinct from the body read handled elsewhere). - */ -static int test_d2i_read_bio_partial_header(void) -{ - /* SEQUENCE with a 2-byte long-form length, but only one length byte given */ - static const unsigned char partial_header[] = { - 0x30, 0x82, 0x01 /* SEQUENCE, length declared as 2 bytes, 1 present */ - }; - BIO *bio = NULL; - BUF_MEM *buf = NULL; - unsigned long e; - int ret = 0; - - if (!TEST_ptr(bio = BIO_new_mem_buf(partial_header, sizeof(partial_header)))) - goto err; - ERR_clear_error(); - - if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) - goto err; - e = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(e), ERR_LIB_ASN1) - || !TEST_int_eq(ERR_GET_REASON(e), ASN1_R_NOT_ENOUGH_DATA)) - goto err; - - ret = 1; -err: - BUF_MEM_free(buf); - BIO_free(bio); - return ret; -} - int setup_tests(void) { #ifndef OPENSSL_NO_DEPRECATED_3_0 @@ -440,9 +279,5 @@ int setup_tests(void) ADD_TEST(test_utctime); ADD_TEST(test_invalid_template); ADD_TEST(test_reuse_asn1_object); - ADD_TEST(test_d2i_read_bio_clean_eof); - ADD_TEST(test_d2i_read_bio_truncated); - ADD_TEST(test_d2i_read_bio_indefinite_truncated); - ADD_TEST(test_d2i_read_bio_partial_header); return 1; } diff --git a/test/asn1_internal_test.c b/test/asn1_internal_test.c index 469daafc4c..8edea7ca91 100644 --- a/test/asn1_internal_test.c +++ b/test/asn1_internal_test.c @@ -185,9 +185,9 @@ static int test_unicode_range(void) "\xff\xff\xff\xff"; int ok = 1; - if (!test_unicode(univ_ok, sizeof(univ_ok) - 1, V_ASN1_UTF8STRING)) + if (!test_unicode(univ_ok, sizeof univ_ok - 1, V_ASN1_UTF8STRING)) ok = 0; - if (!test_unicode(univ_bad, sizeof(univ_bad) - 1, -1)) + if (!test_unicode(univ_bad, sizeof univ_bad - 1, -1)) ok = 0; return ok; } @@ -476,7 +476,7 @@ static int posix_time_test(void) /* * Frequently platform conversions can not deal with one second before the - * Unix epoch, due to inheriting terrible API design and knocking this + * the Unix epoch, due to inheriting terrible API design and knocking this * time value out as an error return. * * We should do better. diff --git a/test/asn1_string_test.c b/test/asn1_string_test.c index 865003eeb9..9460ece872 100644 --- a/test/asn1_string_test.c +++ b/test/asn1_string_test.c @@ -410,13 +410,13 @@ asn1_string_new_not_owned_test(void) if (!TEST_ptr(tmp = ASN1_STRING_new_not_owned(V_ASN1_OCTET_STRING, data, sizeof(data)))) goto err; - if (!TEST_true(ASN1_STRING_set_string(tmp, "muppet"))) + if (!TEST_true(ASN1_STRING_set(tmp, "muppet", (int)strlen("muppet")))) goto err; if (!TEST_mem_eq(data, sizeof(data), data2, sizeof(data2))) goto err; - if (!TEST_size_t_eq(ASN1_STRING_length_ex(tmp), strlen("muppet"))) + if (!TEST_int_eq(ASN1_STRING_length(tmp), (int)strlen("muppet"))) goto err; if (!TEST_mem_eq(ASN1_STRING_get0_data(tmp), strlen("muppet"), "muppet", strlen("muppet"))) @@ -428,7 +428,7 @@ asn1_string_new_not_owned_test(void) if (!TEST_ptr(tmp = ASN1_STRING_new_not_owned(V_ASN1_OCTET_STRING, data, sizeof(data)))) goto err; - if (!TEST_ptr(tmpstring = OPENSSL_strdup("puppet"))) + if (!TEST_ptr(tmpstring = strdup("puppet"))) goto err; ASN1_STRING_set0(tmp, tmpstring, 4); @@ -436,13 +436,13 @@ asn1_string_new_not_owned_test(void) if (!TEST_mem_eq(data, sizeof(data), data2, sizeof(data2))) goto err; - if (!TEST_size_t_eq(ASN1_STRING_length_ex(tmp), 4)) + if (!TEST_int_eq(ASN1_STRING_length(tmp), 4)) goto err; if (!TEST_mem_eq(ASN1_STRING_get0_data(tmp), strlen("puppet"), "puppet", strlen("puppet"))) goto err; - memset((uint8_t *)ASN1_STRING_get0_data(tmp), 'z', ASN1_STRING_length_ex(tmp)); + memset((uint8_t *)ASN1_STRING_get0_data(tmp), 'z', ASN1_STRING_length(tmp)); if (!TEST_mem_eq(data, sizeof(data), data2, sizeof(data2))) goto err; @@ -450,8 +450,8 @@ asn1_string_new_not_owned_test(void) if (!TEST_mem_eq(tmpstring, strlen("puppet"), "zzzzet", strlen("puppet"))) goto err; - tmpstring = NULL; ASN1_STRING_clear_free(tmp); + tmpstring = NULL; tmp = NULL; if (!TEST_ptr_null(tmp = ASN1_STRING_new_not_owned(V_ASN1_BIT_STRING, data, sizeof(data)))) @@ -470,92 +470,15 @@ asn1_string_new_not_owned_test(void) err: ASN1_STRING_clear_free(tmp); + free(tmpstring); return success; } -static int -asn1_string_set_data_test(void) -{ - int success = 0; - ASN1_STRING *str = NULL; - const uint8_t *data; - - if (!TEST_ptr(str = ASN1_STRING_new())) - goto err; - - if (!TEST_false(ASN1_STRING_set_data(str, (uint8_t *)"hoobla", -1))) - goto err; - - if (!TEST_false(ASN1_STRING_set_data(str, (uint8_t *)"hoobla", (size_t)INT_MAX + 1))) - goto err; - - if (!TEST_true(ASN1_STRING_set_data(str, NULL, 10))) - goto err; - - if (!TEST_true(ASN1_STRING_set_data(str, (uint8_t *)"hoobla", strlen("hoobla")))) - goto err; - - data = ASN1_STRING_get0_data(str); - - if (!TEST_size_t_eq(ASN1_STRING_length_ex(str), 6)) - goto err; - - if (!TEST_int_eq(memcmp("hoobla", data, strlen("hoobla")), 0)) - goto err; - - if (!TEST_true(ASN1_STRING_set_data(str, (uint8_t *)"hoobla", strlen("hoobla") + 1))) - goto err; - - data = ASN1_STRING_get0_data(str); - - if (!TEST_size_t_eq(ASN1_STRING_length_ex(str), 7)) - goto err; - - if (!TEST_int_eq(strcmp("hoobla", (char *)data), 0)) - goto err; - - success = 1; - -err: - ASN1_STRING_free(str); - return success; -} - -static int -asn1_string_set_string_test(void) -{ - int success = 0; - ASN1_STRING *str = NULL; - - if (!TEST_ptr(str = ASN1_STRING_new())) - goto err; - - if (!TEST_true(ASN1_STRING_set_string(str, "foo"))) - goto err; - - if (!TEST_size_t_eq(ASN1_STRING_length_ex(str), 3)) - goto err; - - if (!TEST_true(ASN1_STRING_set_string(str, "hoob\0la"))) - goto err; - - if (!TEST_size_t_eq(ASN1_STRING_length_ex(str), 4)) - goto err; - - success = 1; - -err: - ASN1_STRING_free(str); - return success; -} - int setup_tests(void) { ADD_ALL_TESTS(asn1_bit_string_get_length_test, OSSL_NELEM(abs_get_length_tests)); ADD_ALL_TESTS(asn1_bit_string_set1_test, OSSL_NELEM(abs_set1_tests)); ADD_TEST(asn1_string_new_not_owned_test); - ADD_TEST(asn1_string_set_data_test); - ADD_TEST(asn1_string_set_string_test); return 1; } diff --git a/test/bftest.c b/test/bftest.c index 3b6d2ee4b6..08f974ec9b 100644 --- a/test/bftest.c +++ b/test/bftest.c @@ -387,7 +387,7 @@ static int test_bf_cfb64(void) memset(cbc_out, 0, 40); memcpy(iv, cbc_iv, 8); n = 0; - BF_cfb64_encrypt((unsigned char *)cbc_data, cbc_out, 13, + BF_cfb64_encrypt((unsigned char *)cbc_data, cbc_out, (long)13, &key, iv, &n, BF_ENCRYPT); BF_cfb64_encrypt((unsigned char *)&(cbc_data[13]), &(cbc_out[13]), len - 13, &key, iv, &n, BF_ENCRYPT); @@ -419,7 +419,7 @@ static int test_bf_ofb64(void) memset(cbc_out, 0, 40); memcpy(iv, cbc_iv, 8); n = 0; - BF_ofb64_encrypt((unsigned char *)cbc_data, cbc_out, 13, &key, iv, + BF_ofb64_encrypt((unsigned char *)cbc_data, cbc_out, (long)13, &key, iv, &n); BF_ofb64_encrypt((unsigned char *)&(cbc_data[13]), &(cbc_out[13]), len - 13, &key, iv, &n); diff --git a/test/bio_core_test.c b/test/bio_core_test.c index 26ff787eec..677bf922e5 100644 --- a/test/bio_core_test.c +++ b/test/bio_core_test.c @@ -108,38 +108,6 @@ err: return testresult; } -static int test_bio_vprintf_boundary(void) -{ - BIO *bio = NULL; - char *data; - long len; - int w; - int testresult = 0; - - /* - * At width 512, vsnprintf() reports 512 bytes excluding the NUL, - * so BIO_vprintf() must use its realloc path. - */ - for (w = 511; w <= 513; w++) { - bio = BIO_new(BIO_s_mem()); - if (!TEST_ptr(bio)) - goto err; - if (!TEST_int_eq(BIO_printf(bio, "%*d", w, 0), w)) - goto err; - len = BIO_get_mem_data(bio, &data); - if (!TEST_long_eq(len, w) - || !TEST_char_eq(data[w - 1], '0') - || !TEST_char_eq(data[0], ' ')) - goto err; - BIO_free(bio); - bio = NULL; - } - testresult = 1; -err: - BIO_free(bio); - return testresult; -} - int setup_tests(void) { if (!test_skip_common_options()) { @@ -148,6 +116,5 @@ int setup_tests(void) } ADD_TEST(test_bio_core); - ADD_TEST(test_bio_vprintf_boundary); return 1; } diff --git a/test/bntest.c b/test/bntest.c index d15af9dbe5..bd2727b8aa 100644 --- a/test/bntest.c +++ b/test/bntest.c @@ -1215,71 +1215,6 @@ err: return st; } -typedef struct sum_all_alias_st { - const char *hex; - int negative; -} SUM_ALL_ALIAS; - -static int test_sum_all_alias_helper(const SUM_ALL_ALIAS *test) -{ - BIGNUM *alias = NULL, *orig = NULL, *expected = NULL; - int st = 0; - - if (!TEST_true(BN_hex2bn(&alias, test->hex))) - goto err; - if (test->negative && !BN_is_zero(alias)) - BN_set_negative(alias, 1); - if (!TEST_ptr(orig = BN_dup(alias)) - || !TEST_ptr(expected = BN_new())) - goto err; - - /* BN_add */ - if (!TEST_true(BN_add(expected, orig, orig)) - || !TEST_true(BN_add(alias, alias, alias)) - || !TEST_BN_eq(expected, alias) - || !TEST_ptr(BN_copy(alias, orig)) - /* BN_sub */ - || !TEST_true(BN_sub(expected, orig, orig)) - || !TEST_true(BN_sub(alias, alias, alias)) - || !TEST_BN_eq(expected, alias) - || !TEST_ptr(BN_copy(alias, orig)) - /* BN_uadd */ - || !TEST_true(BN_uadd(expected, orig, orig)) - || !TEST_true(BN_uadd(alias, alias, alias)) - || !TEST_BN_eq(expected, alias) - || !TEST_ptr(BN_copy(alias, orig)) - /* BN_usub */ - || !TEST_true(BN_usub(expected, orig, orig)) - || !TEST_true(BN_usub(alias, alias, alias)) - || !TEST_BN_eq(expected, alias)) - goto err; - - st = 1; -err: - BN_free(alias); - BN_free(orig); - BN_free(expected); - return st; -} - -static int test_sum_all_alias(void) -{ - static const SUM_ALL_ALIAS tests[] = { - { "2A", 0 }, - { "2A", 1 }, - { "0", 0 }, - { "FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF", 0 }, - { "FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF", 1 } - }; - size_t i; - - for (i = 0; i < OSSL_NELEM(tests); i++) { - if (!test_sum_all_alias_helper(&tests[i])) - return 0; - } - return 1; -} - static int file_sum(STANZA *s) { BIGNUM *a = NULL, *b = NULL, *sum = NULL, *ret = NULL; @@ -1303,6 +1238,7 @@ static int file_sum(STANZA *s) /* * Test that the functions work when |r| and |a| point to the same BIGNUM, * or when |r| and |b| point to the same BIGNUM. + * There is no test for all of |r|, |a|, and |b| pointint to the same BIGNUM. */ if (!TEST_true(BN_copy(ret, a)) || !TEST_true(BN_add(ret, ret, b)) @@ -1341,6 +1277,8 @@ static int file_sum(STANZA *s) /* * Test that the functions work when |r| and |a| point to the same * BIGNUM, or when |r| and |b| point to the same BIGNUM. + * There is no test for all of |r|, |a|, and |b| pointint to the same + * BIGNUM. */ if (!TEST_true(BN_copy(ret, a)) || !TEST_true(BN_uadd(ret, ret, b)) @@ -1800,16 +1738,15 @@ static int file_modexp(STANZA *s) } /* Regression test for carry propagation bug in sqr8x_reduction */ - if (!TEST_true(BN_hex2bn(&a, "050505050505")) - || !TEST_true(BN_hex2bn(&b, "02")) - || !TEST_true(BN_hex2bn(&c, - "4141414141414141414141274141414141414141414141414141414141414141" - "4141414141414141414141414141414141414141414141414141414141414141" - "4141414141414141414141800000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000001"))) - goto err; + BN_hex2bn(&a, "050505050505"); + BN_hex2bn(&b, "02"); + BN_hex2bn(&c, + "4141414141414141414141274141414141414141414141414141414141414141" + "4141414141414141414141414141414141414141414141414141414141414141" + "4141414141414141414141800000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000001"); if (!TEST_true(BN_mod_exp(d, a, b, c, ctx)) || !TEST_true(BN_mul(e, a, a, ctx)) || !TEST_BN_eq(d, e)) @@ -1893,6 +1830,49 @@ err: return st; } +static int file_modinv(STANZA *s) +{ + BIGNUM *a = NULL, *m = NULL, *ainv_check = NULL, *ainv = NULL; + int st = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(m = getBN(s, "M")) + || !TEST_ptr(ainv_check = getBN(s, "ModInv"))) + goto err; + + if (BN_is_negative(ainv_check)) { + /* a negative testcase */ + ERR_set_mark(); + if (!TEST_ptr_null(BN_mod_inverse(NULL, a, m, ctx)) + || !TEST_int_eq(ERR_GET_LIB(ERR_peek_last_error()), ERR_LIB_BN) + || !TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), + BN_R_NO_INVERSE)) + goto err; + ERR_pop_to_mark(); + + st = 1; + goto err; + } + + /* the inverse is unique in [1,M) */ + if (!TEST_ptr(ainv = BN_mod_inverse(NULL, a, m, ctx)) + || !equalBN("inv(A) (mod M)", ainv_check, ainv)) + goto err; + + /* verify A * ainv == 1 (mod M) */ + if (!TEST_true(BN_mod_mul(ainv, a, ainv, m, ctx)) + || !TEST_true(BN_is_one(ainv))) + goto err; + + st = 1; +err: + BN_free(a); + BN_free(m); + BN_free(ainv_check); + BN_free(ainv); + return st; +} + static int file_gcd(STANZA *s) { BIGNUM *a = NULL, *b = NULL, *gcd = NULL, *ret = NULL; @@ -3387,6 +3367,7 @@ static int file_test_run(STANZA *s) { "ModExp", file_modexp }, { "Exp", file_exp }, { "ModSqrt", file_modsqrt }, + { "ModInv", file_modinv }, { "GCD", file_gcd }, }; int numtests = OSSL_NELEM(filetests); @@ -3483,7 +3464,6 @@ int setup_tests(void) ADD_ALL_TESTS(test_signed_mod_replace_ab, OSSL_NELEM(signed_mod_tests)); ADD_ALL_TESTS(test_signed_mod_replace_ba, OSSL_NELEM(signed_mod_tests)); ADD_TEST(test_mod); - ADD_TEST(test_sum_all_alias); ADD_TEST(test_mod_inverse); ADD_ALL_TESTS(test_mod_exp_alias, 2); ADD_TEST(test_modexp_mont5); diff --git a/test/build.info b/test/build.info index 4fbe25030f..9f824d1d73 100644 --- a/test/build.info +++ b/test/build.info @@ -9,10 +9,6 @@ IF[{- !$disabled{hqinterop} -}] SUBDIRS=quic-openssl-docker ENDIF -IF[{- !$disabled{"unit-tests"} -}] - SUBDIRS=unit -ENDIF - # Auxiliary program source (copied from ../apps/build.info) IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}] # It's called 'init', but doesn't have much 'init' in it... @@ -65,7 +61,7 @@ IF[{- !$disabled{tests} -}] x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \ recordlentest drbgtest rand_status_test sslbuffertest \ time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \ - servername_test ocspapitest ocsptest fatalerrtest tls13ccstest \ + servername_test ocspapitest fatalerrtest tls13ccstest \ sysdefaulttest errtest ssl_ctx_test build_wincrypt_test \ context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ keymgmt_internal_test hexstr_test provider_status_test defltfips_test \ @@ -86,12 +82,15 @@ IF[{- !$disabled{tests} -}] ENDIF IF[{- !$disabled{'allocfail-tests'} -}] - PROGRAMS{noinst}=handshake-memfail x509-memfail load_key_certs_crls_memfail + PROGRAMS{noinst}=handshake-memfail x509-memfail load_key_certs_crls_memfail property-memfail ENDIF IF[{- !$disabled{quic} -}] PROGRAMS{noinst}=priority_queue_test quicfaultstest quicapitest \ - quic_newcid_test quic_srt_gen_test rio_notifier_test + quic_newcid_test quic_srt_gen_test + IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}] + PROGRAMS{noinst}=rio_notifier_test + ENDIF ENDIF IF[{- !$disabled{quic} && !$disabled{qlog} -}] @@ -356,10 +355,6 @@ IF[{- !$disabled{tests} -}] INCLUDE[crltest]=../include ../apps/include DEPEND[crltest]=../libcrypto libtestutil.a - SOURCE[ocsptest]=ocsptest.c - INCLUDE[ocsptest]=../include ../apps/include - DEPEND[ocsptest]=../libcrypto libtestutil.a - SOURCE[v3ext]=v3ext.c INCLUDE[v3ext]=../include ../apps/include DEPEND[v3ext]=../libcrypto libtestutil.a @@ -397,9 +392,11 @@ IF[{- !$disabled{tests} -}] DEPEND[packettest]=../libcrypto libtestutil.a IF[{- !$disabled{'quic'} -}] + IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}] SOURCE[rio_notifier_test]=rio_notifier_test.c INCLUDE[rio_notifier_test]=.. ../include ../apps/include DEPEND[rio_notifier_test]=../libcrypto.a ../libssl.a libtestutil.a + ENDIF SOURCE[quic_wire_test]=quic_wire_test.c INCLUDE[quic_wire_test]=../include ../apps/include @@ -659,6 +656,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[load_key_certs_crls_memfail]=.. ../include ../apps/include DEPEND[load_key_certs_crls_memfail]=libtestutil.a ../libcrypto.a ../libssl.a + SOURCE[property-memfail]=property_memfail.c + INCLUDE[property-memfail]=../include ../apps/include + DEPEND[property-memfail]=../libcrypto.a + SOURCE[ssl_handshake_rtt_test]=ssl_handshake_rtt_test.c helpers/ssltestlib.c INCLUDE[ssl_handshake_rtt_test]=../include ../apps/include .. DEPEND[ssl_handshake_rtt_test]=../libcrypto.a ../libssl.a libtestutil.a @@ -941,8 +942,6 @@ IF[{- !$disabled{tests} -}] PROGRAMS{noinst}=cmactest ENDIF - PROGRAMS{noinst}=sha3_x4_internal_test - SOURCE[poly1305_internal_test]=poly1305_internal_test.c INCLUDE[poly1305_internal_test]=.. ../include ../apps/include DEPEND[poly1305_internal_test]=../libcrypto.a libtestutil.a @@ -951,10 +950,6 @@ IF[{- !$disabled{tests} -}] INCLUDE[chacha_internal_test]=.. ../include ../apps/include DEPEND[chacha_internal_test]=../libcrypto.a libtestutil.a - SOURCE[sha3_x4_internal_test]=sha3_x4_internal_test.c - INCLUDE[sha3_x4_internal_test]=.. ../include ../apps/include - DEPEND[sha3_x4_internal_test]=../libcrypto.a libtestutil.a - SOURCE[asn1_internal_test]=asn1_internal_test.c INCLUDE[asn1_internal_test]=.. ../include ../apps/include DEPEND[asn1_internal_test]=../libcrypto.a libtestutil.a @@ -1001,13 +996,6 @@ IF[{- !$disabled{tests} -}] DEPEND[tls12psk_test]=../libcrypto.a ../libssl.a libtestutil.a ENDIF - IF[{- !$disabled{psk} && !$disabled{dtls1_2} -}] - PROGRAMS{noinst}=dtls12psk_test - SOURCE[dtls12psk_test]=dtls12psk.c helpers/ssltestlib.c - INCLUDE[dtls12psk_test]=.. ../include ../apps/include - DEPEND[dtls12psk_test]=../libcrypto.a ../libssl.a libtestutil.a - ENDIF - SOURCE[tls13encryptiontest]=tls13encryptiontest.c INCLUDE[tls13encryptiontest]=.. ../include ../apps/include DEPEND[tls13encryptiontest]=../libcrypto.a ../libssl.a libtestutil.a @@ -1139,6 +1127,21 @@ IF[{- !$disabled{tests} -}] DEPEND[rsa_x931_test]=../libcrypto.a libtestutil.a ENDIF + PROGRAMS{noinst}=fn_internal_test + SOURCE[fn_internal_test]=fn_internal_test.c + INCLUDE[fn_internal_test]=.. ../include ../crypto/fn ../apps/include + DEPEND[fn_internal_test]=../libcrypto.a libtestutil.a + + PROGRAMS{noinst}=fn_api_test + SOURCE[fn_api_test]=fn_api_test.c + INCLUDE[fn_api_test]=.. ../include ../crypto/fn ../apps/include + DEPEND[fn_api_test]=../libcrypto.a libtestutil.a + + PROGRAMS{noinst}=fntest + SOURCE[fntest]=fntest.c + INCLUDE[fntest]=.. ../include ../crypto/fn ../apps/include + DEPEND[fntest]=../libcrypto.a libtestutil.a + SOURCE[bn_internal_test]=bn_internal_test.c INCLUDE[bn_internal_test]=.. ../include ../crypto/bn ../apps/include DEPEND[bn_internal_test]=../libcrypto.a libtestutil.a @@ -1179,21 +1182,11 @@ IF[{- !$disabled{tests} -}] INCLUDE[ssl_old_test]=.. ../include ../apps/include DEPEND[ssl_old_test]=../libcrypto.a ../libssl.a libtestutil.a - PROGRAMS{noinst}=tls_groups_list_test - SOURCE[tls_groups_list_test]=tls_groups_list_test.c - INCLUDE[tls_groups_list_test]=.. ../include ../apps/include - DEPEND[tls_groups_list_test]=../libcrypto.a ../libssl.a libtestutil.a - PROGRAMS{noinst}=ext_internal_test SOURCE[ext_internal_test]=ext_internal_test.c INCLUDE[ext_internal_test]=.. ../include ../apps/include DEPEND[ext_internal_test]=../libcrypto.a ../libssl.a libtestutil.a - PROGRAMS{noinst}=statem_clnt_construct_test - SOURCE[statem_clnt_construct_test]=statem_clnt_construct_test.c - INCLUDE[statem_clnt_construct_test]=.. ../include ../apps/include - DEPEND[statem_clnt_construct_test]=../libcrypto.a ../libssl.a libtestutil.a - PROGRAMS{noinst}=algorithmid_test SOURCE[algorithmid_test]=algorithmid_test.c INCLUDE[algorithmid_test]=../include ../apps/include @@ -1280,16 +1273,6 @@ IF[{- !$disabled{tests} -}] SOURCE[p_minimal]=p_minimal.ld GENERATE[p_minimal.ld]=../util/providers.num ENDIF - # Loadable form of the fake cipher provider. - MODULES{noinst}=fake-cipher - SOURCE[fake-cipher]=fake_cipherprov.c - DEFINE[fake-cipher]=FAKE_CIPHER_AS_MODULE - INCLUDE[fake-cipher]=../include - DEPEND[fake-cipher]=../libcrypto - IF[{- defined $target{shared_defflag} -}] - SOURCE[fake-cipher]=fake-cipher.ld - GENERATE[fake-cipher.ld]=../util/providers.num - ENDIF ENDIF IF[{- $disabled{module} || !$target{dso_scheme} -}] DEFINE[provider_test]=NO_PROVIDER_MODULE diff --git a/test/certs/ee-cert-dsa-sha384.pem b/test/certs/ee-cert-dsa-sha384.pem deleted file mode 100644 index ab3fe14687..0000000000 --- a/test/certs/ee-cert-dsa-sha384.pem +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEdjCCBCSgAwIBAgIUNbayaptPn6T0hvP2mKuB8L/W9k8wCwYJYIZIAWUDBAMD -MCgxJjAkBgNVBAMMHU9wZW5TU0wgVGVzdCBEU0EgU0hBLTM4NCBSb290MB4XDTI2 -MDQxMDA3MzMzMFoXDTM2MDQwNzA3MzMzMFowJjEkMCIGA1UEAwwbT3BlblNTTCBU -ZXN0IERTQSBTSEEtMzg0IEVFMIIDQjCCAjUGByqGSM44BAEwggIoAoIBAQDA154m -/UL7G6MMLDAr2BoxQzgT8eNaOV2Ls89BvjF3SS9qgOMQSv9TK8gcb16jpqd6aQ6G -WLedKu3fRUrXCihRaZZaeftJCntAVaDIhtYaYdsua6IDGjWd1SHHmFdQnH3AYLxV -dRmnq3Jjt6oelPQYKDbpWAtT8DsFJ/d6bGpQ6mxW4J1u1FnmKwzuxbR/ZxOV1gQy -D08gfkct7+UtQ5rJUIiIeK2RWsJhF6tdvH+g8VhBXsXo0ZprA/iQHst/aeXSGUBC -+vby1LYog2VFLXD+zl5rzXZUNJLXPt/9Dvs/qYknPlUEboQ8J/afbyuA8S10gsAu -8bnyQ/oTzmA+4Uy5Ah0A0QDXg1zTwGDdtB3OqMZOhhyL+oLzZeFsowwBzwKCAQAs -wjjcjD2G/brbwZuNaZWDHqrpTmmAhvg17+QGp9gaWWb/08TfZ+PbhIL4jV8kf5PZ -kPZVJyocYGduRJsIxiJDlssdaYzgkJ4zJG0A6gYtpBpaD/h6di0E0nzjm+80a9jo -xrgq3jRxkGVHpHvDd4ps0q2UXH44nFCEPWaoebpR4BXCLzXuFw30gUldrClqcMWt -OqQUwf7/ZndhQvLA2PiJEC/5EQFzeMzjl+XAOjW+781rO8BPmniFVXmRGAVWCycL -Qj0pQzvfDDi1M4LZBAw+g6RAa/IAB1mpKNOfsh2wDYS+nJn6q77COZRVn0DZLiVz -M8ENRqH0uRF1osCgqAuBA4IBBQACggEAXj8recOQ2JRABFgypUmG2PA0ibD5z1j3 -Xx7i5UXdwzOMJrtPtzjTmykgg73JpYA38kyqUtaZLKqtR2up+M9Bpj0l8GPZ5brM -E5zJbWukvSw8pnAUvq92izRHlmEK7QUPrkYM2e+NjJKYEOeJ8I1O7mZUBHNsbYGW -jGi0FW+LpcUywCUH7ccxHLFBXJnMUS7zipc6fwBjumFtYTyjsoeE5pyVGs6Cau0o -dzCgR3Ss0gc73qnHv+7t4NP2385AaTKhNeykrtwhrFL6MDGYf0Bs2Y5SE5vEnIZJ -Rb4I+8YnhsxaPGiKy9N6R+1CisnBg+4cx1mEVl3moQtAT6POruJaMqNCMEAwHQYD -VR0OBBYEFNfDDHDjB5VsPYFzEcuRXWZilvyIMB8GA1UdIwQYMBaAFDXj0oV+Bxtx -dRByLwz7g8OjZg/ZMAsGCWCGSAFlAwQDAwM/ADA8AhwezQQknbLR8wtcYnQJLvlv -tILlrOxyRlvUCUGtAhxGW+R77sJNGghc76jH+g3Kkent+0+G3VxrgrOc ------END CERTIFICATE----- diff --git a/test/certs/ee-cert-dsa-sha512.pem b/test/certs/ee-cert-dsa-sha512.pem deleted file mode 100644 index e3741ed0dd..0000000000 --- a/test/certs/ee-cert-dsa-sha512.pem +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEdzCCBCSgAwIBAgIUG0h9XyzEews1+X1q3CMHaNZuXhkwCwYJYIZIAWUDBAME -MCgxJjAkBgNVBAMMHU9wZW5TU0wgVGVzdCBEU0EgU0hBLTUxMiBSb290MB4XDTI2 -MDQxMDA3MzMzMFoXDTM2MDQwNzA3MzMzMFowJjEkMCIGA1UEAwwbT3BlblNTTCBU -ZXN0IERTQSBTSEEtNTEyIEVFMIIDQjCCAjUGByqGSM44BAEwggIoAoIBAQDA154m -/UL7G6MMLDAr2BoxQzgT8eNaOV2Ls89BvjF3SS9qgOMQSv9TK8gcb16jpqd6aQ6G -WLedKu3fRUrXCihRaZZaeftJCntAVaDIhtYaYdsua6IDGjWd1SHHmFdQnH3AYLxV -dRmnq3Jjt6oelPQYKDbpWAtT8DsFJ/d6bGpQ6mxW4J1u1FnmKwzuxbR/ZxOV1gQy -D08gfkct7+UtQ5rJUIiIeK2RWsJhF6tdvH+g8VhBXsXo0ZprA/iQHst/aeXSGUBC -+vby1LYog2VFLXD+zl5rzXZUNJLXPt/9Dvs/qYknPlUEboQ8J/afbyuA8S10gsAu -8bnyQ/oTzmA+4Uy5Ah0A0QDXg1zTwGDdtB3OqMZOhhyL+oLzZeFsowwBzwKCAQAs -wjjcjD2G/brbwZuNaZWDHqrpTmmAhvg17+QGp9gaWWb/08TfZ+PbhIL4jV8kf5PZ -kPZVJyocYGduRJsIxiJDlssdaYzgkJ4zJG0A6gYtpBpaD/h6di0E0nzjm+80a9jo -xrgq3jRxkGVHpHvDd4ps0q2UXH44nFCEPWaoebpR4BXCLzXuFw30gUldrClqcMWt -OqQUwf7/ZndhQvLA2PiJEC/5EQFzeMzjl+XAOjW+781rO8BPmniFVXmRGAVWCycL -Qj0pQzvfDDi1M4LZBAw+g6RAa/IAB1mpKNOfsh2wDYS+nJn6q77COZRVn0DZLiVz -M8ENRqH0uRF1osCgqAuBA4IBBQACggEADpK5z3E7aC/bPkHbIApYwMui0PlPm9mZ -fJcOUYkUxrGwsVB7MLlFKaYogohKW/6llyTQ9KVv0GhXGBU8KZAwYi2IvEqZWt96 -QWMReZkr85mcfWPPr0nhPaiKPFLuzbrJS5+8pRZ0JZICAs7fWK2ieTFzF5T52+uU -HW3d8hRW0faGy3JVChySx2zKhznax0ugOeO6xpw+GIhh7DtoLN9+WCUD4gHxcT1e -ngH3SPr9kSAc179ZheLPV8K96D6h62xLyDOv66jKqxuEuwKMezKhI8NoWlIjFlwq -qeg+/URRSKaemF7CeEtjfxfyhPyWFBA3ied6v8lgcvm8xEK1fOuWtaNCMEAwHQYD -VR0OBBYEFG70aEHyZTHkRfESJAk59LuyXqj2MB8GA1UdIwQYMBaAFLO3mEJ4Js8i -80dWuZffkE17675DMAsGCWCGSAFlAwQDBANAADA9AhxQI/S0oZhUBxth3amipFkw -px3NJNYZEdKm1x4hAh0AotKopAK/hiDc2IGgHC+L2kjsvg/tqofl54aZ6w== ------END CERTIFICATE----- diff --git a/test/certs/root-cert-dsa-sha384.pem b/test/certs/root-cert-dsa-sha384.pem deleted file mode 100644 index 107e855b42..0000000000 --- a/test/certs/root-cert-dsa-sha384.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEizCCBDigAwIBAgIUL44kPKEDy7eaEgXNH4xXTuVw77owCwYJYIZIAWUDBAMD -MCgxJjAkBgNVBAMMHU9wZW5TU0wgVGVzdCBEU0EgU0hBLTM4NCBSb290MB4XDTI2 -MDQxMDA3MzMzMFoXDTM2MDQwNzA3MzMzMFowKDEmMCQGA1UEAwwdT3BlblNTTCBU -ZXN0IERTQSBTSEEtMzg0IFJvb3QwggNDMIICNQYHKoZIzjgEATCCAigCggEBAMDX -nib9QvsbowwsMCvYGjFDOBPx41o5XYuzz0G+MXdJL2qA4xBK/1MryBxvXqOmp3pp -DoZYt50q7d9FStcKKFFpllp5+0kKe0BVoMiG1hph2y5rogMaNZ3VIceYV1CcfcBg -vFV1GaercmO3qh6U9BgoNulYC1PwOwUn93psalDqbFbgnW7UWeYrDO7FtH9nE5XW -BDIPTyB+Ry3v5S1DmslQiIh4rZFawmEXq128f6DxWEFexejRmmsD+JAey39p5dIZ -QEL69vLUtiiDZUUtcP7OXmvNdlQ0ktc+3/0O+z+piSc+VQRuhDwn9p9vK4DxLXSC -wC7xufJD+hPOYD7hTLkCHQDRANeDXNPAYN20Hc6oxk6GHIv6gvNl4WyjDAHPAoIB -ACzCONyMPYb9utvBm41plYMequlOaYCG+DXv5Aan2BpZZv/TxN9n49uEgviNXyR/ -k9mQ9lUnKhxgZ25EmwjGIkOWyx1pjOCQnjMkbQDqBi2kGloP+Hp2LQTSfOOb7zRr -2OjGuCreNHGQZUeke8N3imzSrZRcfjicUIQ9Zqh5ulHgFcIvNe4XDfSBSV2sKWpw -xa06pBTB/v9md2FC8sDY+IkQL/kRAXN4zOOX5cA6Nb7vzWs7wE+aeIVVeZEYBVYL -JwtCPSlDO98MOLUzgtkEDD6DpEBr8gAHWako05+yHbANhL6cmfqrvsI5lFWfQNku -JXMzwQ1GofS5EXWiwKCoC4EDggEGAAKCAQEAqBWUzoivwm10KhCOVj4dLJ376hik -coO7wh8szq+0lBCKVQu0XgZdpR67ibiInCslpi4D31QX1ciP8Ds3Tnr92Xq9fp6F -Q9+M94it5BWvXq8uWnsCYRLIXds+8DKnUMTPc0U5Qc/HnfkdgHockBya5ZKRLzgW -THC5n29NjBoIH9TBFddxanUqOqM2a0+0uC23jC/rmsmIXKKLIRnBjDjCfWGkpvDR -V0TmgU+wBN7Fu6/PDdb2h1omgx5iJ0hR9bSQMevPzxKWIIYt3jBa3JWRJVshZbCX -zGSycHIM4IPPEWtDEMR/s/aO5+HcQdV42itClvOQxhVfYTtBCV8TiMYFAKNTMFEw -HQYDVR0OBBYEFDXj0oV+BxtxdRByLwz7g8OjZg/ZMB8GA1UdIwQYMBaAFDXj0oV+ -BxtxdRByLwz7g8OjZg/ZMA8GA1UdEwEB/wQFMAMBAf8wCwYJYIZIAWUDBAMDA0AA -MD0CHQC/zbfFT+FeeYr9PmYtblMAGmtUgM2VyUcargqPAhwnaYxJwO0tJHKZDXOG -38UfhwBTUj0PNyAwbOG/ ------END CERTIFICATE----- diff --git a/test/certs/root-cert-dsa-sha512.pem b/test/certs/root-cert-dsa-sha512.pem deleted file mode 100644 index 5dbe393aea..0000000000 --- a/test/certs/root-cert-dsa-sha512.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEiTCCBDagAwIBAgITGBs2j74eZNOfebavEYuJJZKVKTALBglghkgBZQMEAwQw -KDEmMCQGA1UEAwwdT3BlblNTTCBUZXN0IERTQSBTSEEtNTEyIFJvb3QwHhcNMjYw -NDEwMDczMzMwWhcNMzYwNDA3MDczMzMwWjAoMSYwJAYDVQQDDB1PcGVuU1NMIFRl -c3QgRFNBIFNIQS01MTIgUm9vdDCCA0IwggI1BgcqhkjOOAQBMIICKAKCAQEAwNee -Jv1C+xujDCwwK9gaMUM4E/HjWjldi7PPQb4xd0kvaoDjEEr/UyvIHG9eo6anemkO -hli3nSrt30VK1wooUWmWWnn7SQp7QFWgyIbWGmHbLmuiAxo1ndUhx5hXUJx9wGC8 -VXUZp6tyY7eqHpT0GCg26VgLU/A7BSf3emxqUOpsVuCdbtRZ5isM7sW0f2cTldYE -Mg9PIH5HLe/lLUOayVCIiHitkVrCYRerXbx/oPFYQV7F6NGaawP4kB7Lf2nl0hlA -Qvr28tS2KINlRS1w/s5ea812VDSS1z7f/Q77P6mJJz5VBG6EPCf2n28rgPEtdILA -LvG58kP6E85gPuFMuQIdANEA14Nc08Bg3bQdzqjGToYci/qC82XhbKMMAc8CggEA -LMI43Iw9hv2628GbjWmVgx6q6U5pgIb4Ne/kBqfYGllm/9PE32fj24SC+I1fJH+T -2ZD2VScqHGBnbkSbCMYiQ5bLHWmM4JCeMyRtAOoGLaQaWg/4enYtBNJ845vvNGvY -6Ma4Kt40cZBlR6R7w3eKbNKtlFx+OJxQhD1mqHm6UeAVwi817hcN9IFJXawpanDF -rTqkFMH+/2Z3YULywNj4iRAv+REBc3jM45flwDo1vu/NazvAT5p4hVV5kRgFVgsn -C0I9KUM73ww4tTOC2QQMPoOkQGvyAAdZqSjTn7IdsA2EvpyZ+qu+wjmUVZ9A2S4l -czPBDUah9LkRdaLAoKgLgQOCAQUAAoIBAAHb5mq9RGf+mLtQi12GnLIlWF45bhHr -0+gNYMzTA7PBzb/E+SfeizOnNuJtNU3LSiNE+sHNMnn/WY4KvjMCryuRxz7b8Y8+ -0nGwN0YfyY/cK5CehRa+lfhahlTorF8VY98gcQJOyKjG0eloZ8H29MhPhYTF0qTS -5dbDb4nf5r5Uqx5/6gBmskpMG+xiXA2I7q2aLW92pZrFWYrkrNgaAAQqSl0whhG6 -EZXP6fAbndJbt706xFlySr/ZHkgWybEAXYO8TbjyDkZP/h9UyR6CnKeb3L6qw8be -8U5scYfx2HjhCv5GLqqauRm+0oJwbXmOWuMpeynGHy24O+wKAX/ePhujUzBRMB0G -A1UdDgQWBBSzt5hCeCbPIvNHVrmX35BNe+u+QzAfBgNVHSMEGDAWgBSzt5hCeCbP -IvNHVrmX35BNe+u+QzAPBgNVHRMBAf8EBTADAQH/MAsGCWCGSAFlAwQDBANAADA9 -AhxgdnguNQoOQZyseelUWc5tD7m/ESvTuAV2aiEwAh0Apmc4SMIg7nKTA2jp7M1E -V7kA7INPUKKx/+iWgA== ------END CERTIFICATE----- diff --git a/test/certs/server-ec-compressed-cert.pem b/test/certs/server-ec-compressed-cert.pem deleted file mode 100644 index 4e97f49af2..0000000000 --- a/test/certs/server-ec-compressed-cert.pem +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBrzCCATSgAwIBAgIBAjAKBggqhkjOPQQDAjAbMRkwFwYDVQQDDBBFQ0RTQSBQ -LTM4NCByb290MCAXDTI2MDYxOTE4MDA1OFoYDzIxMjYwNTI2MTgwMDU4WjAZMRcw -FQYDVQQDDA5zZXJ2ZXIuZXhhbXBsZTA5MBMGByqGSM49AgEGCCqGSM49AwEHAyIA -A4Mt9T6fKt3APp8/Frw65PDi2eMYdZK98nhBW9pA1Ccho4GIMIGFMB0GA1UdDgQW -BBTozN8kakexZEnc26PUo5K2W9ptbTAfBgNVHSMEGDAWgBQm0I8de1/cHn9BgH1j -yhx1gdaFaTAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD -AjAZBgNVHREEEjAQgg5zZXJ2ZXIuZXhhbXBsZTAKBggqhkjOPQQDAgNpADBmAjEA -hvcNLTyL7vamQEJet5uvOXH7NKPHlG8sbfPvGS/AQ0yk6ARdc1Y1gV6FAnmnQUhX -AjEA2HMTkh+h2ZDm68uRnhsNXIxI4dYF/nr5bdxw8XKN4P84Mg4gs37/IPoVN9jG -Y4yh ------END CERTIFICATE----- diff --git a/test/certs/server-ec-compressed-key.pem b/test/certs/server-ec-compressed-key.pem deleted file mode 100644 index 98218fcb3c..0000000000 --- a/test/certs/server-ec-compressed-key.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MGcCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcETTBLAgEBBCAb1VgxSUhJyh43soLb -FMsebjWSp/Hma3kSyw6lT4txDaEkAyIAA4Mt9T6fKt3APp8/Frw65PDi2eMYdZK9 -8nhBW9pA1Cch ------END PRIVATE KEY----- diff --git a/test/certs/setup.sh b/test/certs/setup.sh index 3056b1f90a..3bee78ec32 100755 --- a/test/certs/setup.sh +++ b/test/certs/setup.sh @@ -497,37 +497,6 @@ OPENSSL_SIGALG="sha3-256" ./mkcert.sh genee server.example ee-key-ec-named-named OPENSSL_SIGALG="sha3-384" ./mkcert.sh genee server.example ee-key-ec-named-named ee-cert-ec-sha3-384 ca-key-ec-named ca-cert-ec-named OPENSSL_SIGALG="sha3-512" ./mkcert.sh genee server.example ee-key-ec-named-named ee-cert-ec-sha3-512 ca-key-ec-named ca-cert-ec-named -# DSA roots and EE certs: id-dsa-with-sha384 / id-dsa-with-sha512 -# (regression for https://github.com/openssl/openssl/issues/30432) -_DSA_CERT_DIR=$(cd "$(dirname "$0")" && pwd) -( - set -e - d=$(mktemp -d) - trap 'rm -rf "$d"' EXIT - cd "$d" - openssl dsaparam -out dsap.pem 2048 - openssl gendsa -out ca384k.pem dsap.pem - openssl req -new -x509 -key ca384k.pem -sha384 -out root-cert-dsa-sha384.pem \ - -days 3650 -subj "/CN=OpenSSL Test DSA SHA-384 Root" -nodes - openssl gendsa -out ee384k.pem dsap.pem - openssl req -new -key ee384k.pem -out ee384.csr \ - -subj "/CN=OpenSSL Test DSA SHA-384 EE" - openssl x509 -req -in ee384.csr -CA root-cert-dsa-sha384.pem -CAkey ca384k.pem \ - -CAcreateserial -out ee-cert-dsa-sha384.pem -days 3650 -sha384 - openssl gendsa -out ca512k.pem dsap.pem - openssl req -new -x509 -key ca512k.pem -sha512 -out root-cert-dsa-sha512.pem \ - -days 3650 -subj "/CN=OpenSSL Test DSA SHA-512 Root" -nodes - openssl gendsa -out ee512k.pem dsap.pem - openssl req -new -key ee512k.pem -out ee512.csr \ - -subj "/CN=OpenSSL Test DSA SHA-512 EE" - openssl x509 -req -in ee512.csr -CA root-cert-dsa-sha512.pem -CAkey ca512k.pem \ - -CAcreateserial -out ee-cert-dsa-sha512.pem -days 3650 -sha512 - cp root-cert-dsa-sha384.pem ee-cert-dsa-sha384.pem \ - root-cert-dsa-sha512.pem ee-cert-dsa-sha512.pem \ - "$_DSA_CERT_DIR" -) -unset _DSA_CERT_DIR - # EC cert seigned RSA intermediate CA OPENSSL_KEYALG=ec OPENSSL_KEYBITS=prime256v1 ./mkcert.sh genee \ "P-256 cert EE issuer" p256-ee-rsa-ca-key \ diff --git a/test/cmp_hdr_test.c b/test/cmp_hdr_test.c index 30f19f6238..cbffb87b23 100644 --- a/test/cmp_hdr_test.c +++ b/test/cmp_hdr_test.c @@ -252,7 +252,7 @@ static int execute_HDR_push0_freeText_test(CMP_HDR_TEST_FIXTURE *fixture) if (!TEST_ptr(text)) return 0; - if (!ASN1_STRING_set_string(text, "A free text")) + if (!ASN1_STRING_set(text, "A free text", -1)) goto err; if (!TEST_int_eq(ossl_cmp_hdr_push0_freeText(fixture->hdr, text), 1)) @@ -285,7 +285,7 @@ static int execute_HDR_push1_freeText_test(CMP_HDR_TEST_FIXTURE *fixture) if (!TEST_ptr(text)) goto err; - if (!ASN1_STRING_set_string(text, "A free text")) + if (!ASN1_STRING_set(text, "A free text", -1)) goto err; if (!TEST_int_eq(ossl_cmp_hdr_push1_freeText(fixture->hdr, text), 1)) diff --git a/test/crltest.c b/test/crltest.c index 15fdef3f3c..3e06df10b7 100644 --- a/test/crltest.c +++ b/test/crltest.c @@ -743,43 +743,6 @@ static const char *kCrlDeltaIndicatorString[] = { NULL }; -static const char *kCrlDeltaBase[] = { - "-----BEGIN X509 CRL-----\n", - "MIICQDCCASgCAQEwDQYJKoZIhvcNAQELBQAwgZAxCzAJBgNVBAYTAlVTMRMwEQYD\n", - "VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQK\n", - "DAxFeGFtcGxlIENvcnAxHjAcBgNVBAsMFUNlcnRpZmljYXRlIEF1dGhvcml0eTEd\n", - "MBsGA1UEAwwURXhhbXBsZSBDb3JwIFJvb3QgQ0EXDTI2MDMxMDA4MDAwMFoXDTI2\n", - "MDYwODA4MDAwMFqgYzBhMB8GA1UdIwQYMBaAFP4UDhMbCWfLSg1L2k/z75C1Q9sz\n", - "MAsGA1UdFAQEAgIQADAxBgNVHS4EKjAoMCagJKAihiBodHRwOi8vY3JsLmV4YW1w\n", - "bGUuY29tL2RlbHRhLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAIxrY08mNQ1L8+nL9\n", - "H6Wn1ElntRzMLnk6FqgxosA0Tq3EDzRWKHj2Xbk1vGdRdZi7ttYH1+8+5UA8JPmN\n", - "tRyvrm3NieEqW2reDoyFxJYsWQlJCFHjDVeNpoi8fv/qrOYxtuMfyiwho9WjovVi\n", - "AS9/oa/kSbD39RN/wc0UVRBtQn/vBAzlYExehiwnmiXXwbQA+waNlnL58F/34gRh\n", - "sJs0C/HJn9VU4gvSVW1vbpA7Fxt4alUj2NlXSXHi44mXuei4qc3Pxlw2A2Pfca7y\n", - "vcd30ZZdoKFzMViOnLtcM4vLw59ZEENJmz3vIIU6jACBy8/FbdPsH/iJTTvc76Yv\n", - "CjQcgQ==\n", - "-----END X509 CRL-----\n", - NULL -}; - -static const char *kCrlDeltaValid[] = { - "-----BEGIN X509 CRL-----\n", - "MIICNDCCARwCAQEwDQYJKoZIhvcNAQELBQAwgZAxCzAJBgNVBAYTAlVTMRMwEQYD\n", - "VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQK\n", - "DAxFeGFtcGxlIENvcnAxHjAcBgNVBAsMFUNlcnRpZmljYXRlIEF1dGhvcml0eTEd\n", - "MBsGA1UEAwwURXhhbXBsZSBDb3JwIFJvb3QgQ0EXDTI2MDMxMDA4MDAwMFoXDTI2\n", - "MDYwODA4MDAwMFowFTATAgIQABcNMjYwMzIwMDAwMDAwWqBAMD4wHwYDVR0jBBgw\n", - "FoAU/hQOExsJZ8tKDUvaT/PvkLVD2zMwCwYDVR0UBAQCAhABMA4GA1UdGwEB/wQE\n", - "AgIQADANBgkqhkiG9w0BAQsFAAOCAQEAjDx5wqkXfcfTtEbMUN1UcKAHQC5Fx/Kq\n", - "wpoDulPh52zmugl9zhEWWuwA0hSJ/qNRo5tatSGvHbIOrwvZ0LKgChHwtdQfAcBY\n", - "xMl8KsVRqgGjJ4NahyAglsnsJ95VvImMJGFm+eS0DxQgGJgvsj/dh3dsJEGIW4Mo\n", - "baF6e6sAYaYjn9QW0uzoc5zqux25/DUR5DG99cbi6NOqCm7U1gvWkZsjx4HInx4r\n", - "CFazu5IQE7gk1qipnROwgfi/QQXZmAueW+XasEqQcQw0WVEmCHq6OBlrelTs165b\n", - "sK0XOqWDfa745ZN0EZwJY6GIVl+KEAC0XkoGZdqudOEQbbWog0OKkQ==\n", - "-----END X509 CRL-----\n", - NULL -}; - static const char *kCrlNumberString[] = { "-----BEGIN X509 CRL-----\n", "MIICJTCCAQ0CAQEwDQYJKoZIhvcNAQELBQAweTELMAkGA1UEBhMCVVMxEzARBgNV\n", @@ -1970,36 +1933,6 @@ end: return ret; } -/* - * Exercise the X509_V_FLAG_USE_DELTAS path. kCrlDeltaBase carries a Freshest - * CRL extension and revokes nothing; kCrlDeltaValid is a current delta that - * revokes kLeaf. The delta is in scope, so verification reports kLeaf revoked. - */ -static int test_crl_delta_valid(void) -{ - X509 *root = X509_from_strings(kRoot); - X509 *leaf = X509_from_strings(kLeaf); - X509_CRL *base = CRL_from_strings(kCrlDeltaBase); - X509_CRL *delta = CRL_from_strings(kCrlDeltaValid); - unsigned long flags = X509_V_FLAG_CRL_CHECK - | X509_V_FLAG_EXTENDED_CRL_SUPPORT | X509_V_FLAG_USE_DELTAS; - int test; - - test = TEST_ptr(root) - && TEST_ptr(leaf) - && TEST_ptr(base) - && TEST_ptr(delta) - && TEST_int_eq(verify(leaf, root, make_CRL_stack(base, delta), - flags, kVerify), - X509_V_ERR_CERT_REVOKED); - - X509_CRL_free(base); - X509_CRL_free(delta); - X509_free(leaf); - X509_free(root); - return test; -} - int setup_tests(void) { ADD_TEST(test_private_keys); @@ -2012,7 +1945,6 @@ int setup_tests(void) ADD_TEST(test_crl_date_invalid); ADD_TEST(test_crl_get_fn_score); ADD_TEST(test_crl_delta_indicator); - ADD_TEST(test_crl_delta_valid); ADD_TEST(test_crl_number); ADD_TEST(test_crl_idp_asn1_wrong_tag); ADD_TEST(test_crl_idp_asn1_wrong_tag2); diff --git a/test/danetest.c b/test/danetest.c index f9e30388e1..1b0320b28d 100644 --- a/test/danetest.c +++ b/test/danetest.c @@ -370,7 +370,7 @@ static int test_tlsafile(SSL_CTX *ctx, const char *base_name, continue; } if (!TEST_int_eq(mdpth, want_depth)) { - TEST_info("In test %d", testno); + TEST_info("In test test %d", testno); ret = 0; } } diff --git a/test/destest.c b/test/destest.c index a5fa3b51a5..26462e3b65 100644 --- a/test/destest.c +++ b/test/destest.c @@ -604,7 +604,7 @@ static int test_des_ede_cfb64(void) return 0; memcpy(cfb_tmp, cfb_iv, sizeof(cfb_iv)); n = 0; - DES_ede3_cfb64_encrypt(cfb_buf1, cfb_buf2, 17, &ks, &ks, &ks, + DES_ede3_cfb64_encrypt(cfb_buf1, cfb_buf2, (long)17, &ks, &ks, &ks, &cfb_tmp, &n, DES_DECRYPT); DES_ede3_cfb64_encrypt(&cfb_buf1[17], &cfb_buf2[17], sizeof(plain) - 17, &ks, &ks, &ks, &cfb_tmp, &n, DES_DECRYPT); diff --git a/test/drbgtest.c b/test/drbgtest.c index 0828ebf7b5..91060cf60a 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -182,7 +182,7 @@ static int test_drbg_reseed(int expect_success, time_t reseed_when) { time_t before_reseed, after_reseed; - int expected_state = (expect_success ? EVP_RAND_STATE_READY : EVP_RAND_STATE_ERROR); + int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR); unsigned int primary_reseed, public_reseed, private_reseed; unsigned char dummy[RANDOM_SIZE]; diff --git a/test/dtls12psk.c b/test/dtls12psk.c deleted file mode 100644 index e784f0660c..0000000000 --- a/test/dtls12psk.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include - -#include "helpers/ssltestlib.h" -#include "testutil.h" - -static const char psk_secret[] = "shared-secret"; -static const char psk_identity[] = "identity"; - -static const unsigned char sid_req[] = { - 0xde, 0xad, 0xbe, 0xef, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c -}; - -static const struct ciphersuites { - char *name; -} css[] = { - { "PSK-AES128-CBC-SHA256" }, - { "PSK-AES256-CBC-SHA384" }, - { "PSK-AES128-GCM-SHA256" }, - { "PSK-AES256-GCM-SHA384" } -}; - -#define HELLO_RANDOM_OFF 6 -#define HELLO_RANDOM_LEN 32 -#define HELLO_SID_LEN_OFF (HELLO_RANDOM_OFF + HELLO_RANDOM_LEN) -#define HELLO_SID_OFF (HELLO_SID_LEN_OFF + 1) -#define HELLO_MIN_LEN (HELLO_SID_LEN_OFF + 1) - -static void hello_session_id(const unsigned char *p, size_t len) -{ - char *str; - size_t sid_len; - - if (len < HELLO_MIN_LEN) - return; - - sid_len = p[HELLO_SID_LEN_OFF]; - if (sid_len == 0 || len < HELLO_SID_OFF + sid_len) - return; - - str = OPENSSL_buf2hexstr(p + HELLO_SID_OFF, (long)sid_len); - TEST_info("session_id(%u): <%s>", (unsigned int)sid_len, str); - OPENSSL_free(str); -} - -static void msg_cb(int write_p, int version, int content_type, - const void *buf, size_t len, SSL *ssl, void *arg) -{ - const unsigned char *p = buf; - - if (content_type != SSL3_RT_HANDSHAKE || len < 1) - return; - - switch (p[0]) { - case SSL3_MT_CLIENT_HELLO: - TEST_info("%p client_hello", (void *)ssl); - hello_session_id(p, len); - break; - - case SSL3_MT_SERVER_HELLO: - TEST_info("%p server_hello", (void *)ssl); - hello_session_id(p, len); - break; - } -} - -static void handshake_finished(const SSL *ssl) -{ - const char *endpoint = SSL_is_server(ssl) ? "server" : "client"; - unsigned int has_ticket = SSL_SESSION_has_ticket(SSL_get_session(ssl)); - - if (SSL_session_reused(ssl)) - TEST_info("%s: Abbreviated handshake finished", endpoint); - else - TEST_info("%s: Full handshake finished", endpoint); - - TEST_info("%s: has_ticket: %u", endpoint, has_ticket); -} - -static void info_cb(const SSL *ssl, int type, int val) -{ - const char *endpoint = SSL_is_server(ssl) ? "server" : "client"; - - if (type & SSL_CB_ALERT) { - const char *dir = (type & SSL_CB_READ) ? "read" : "write"; - - TEST_info("%s: alert %s: %s : %s", endpoint, dir, - SSL_alert_type_string_long(val), - SSL_alert_desc_string_long(val)); - } - if (type & SSL_CB_HANDSHAKE_DONE) - handshake_finished(ssl); -} - -static unsigned int server_psk_cb(SSL *ssl, const char *identity, - unsigned char *psk, unsigned int max) -{ - if (max < (sizeof(psk_secret) - 1)) - return 0; - memcpy(psk, psk_secret, (sizeof(psk_secret) - 1)); - return (unsigned int)(sizeof(psk_secret) - 1); -} - -static unsigned int client_psk_cb(SSL *ssl, const char *hint, - char *identity, unsigned int max_id, - unsigned char *psk, unsigned int max) -{ - if (max < (sizeof(psk_secret) - 1) || max_id < sizeof(psk_identity)) - return 0; - strncpy(identity, psk_identity, max_id); - memcpy(psk, psk_secret, (sizeof(psk_secret) - 1)); - return (unsigned int)(sizeof(psk_secret) - 1); -} - -static SSL_SESSION *sess_cache; -static SSL_SESSION *get_sess_cb(SSL *ssl, const unsigned char *id, int len, int *copy) -{ - *copy = 1; - - if (sess_cache != NULL) { - char *str; - const unsigned char *sid; - unsigned int sid_len; - - sid = SSL_SESSION_get_id(sess_cache, &sid_len); - str = OPENSSL_buf2hexstr(sid, sid_len); - TEST_info("(cached) session_id: <%s>", str); - OPENSSL_free(str); - } - return sess_cache; -} - -static int ctx_set_cache(SSL_CTX *s_ctx, SSL_CTX *c_ctx) -{ - SSL_CTX_set_psk_server_callback(s_ctx, server_psk_cb); - SSL_CTX_set_psk_client_callback(c_ctx, client_psk_cb); - SSL_CTX_set_session_cache_mode(s_ctx, SSL_SESS_CACHE_SERVER); - SSL_CTX_set_session_cache_mode(c_ctx, SSL_SESS_CACHE_CLIENT); - SSL_CTX_set_options(s_ctx, SSL_OP_NO_TICKET); - SSL_CTX_set_verify(c_ctx, SSL_VERIFY_NONE, NULL); - return 1; -} - -static int ctx_set_ticket(SSL_CTX *s_ctx, SSL_CTX *c_ctx) -{ - SSL_CTX_set_psk_server_callback(s_ctx, server_psk_cb); - SSL_CTX_set_psk_client_callback(c_ctx, client_psk_cb); - SSL_CTX_set_session_cache_mode(s_ctx, SSL_SESS_CACHE_SERVER); - SSL_CTX_set_session_cache_mode(c_ctx, SSL_SESS_CACHE_CLIENT); - SSL_CTX_set_verify(c_ctx, SSL_VERIFY_NONE, NULL); - return 1; -} - -static int set_shutdown(SSL *c, SSL *s) -{ - SSL_set_shutdown(c, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); - SSL_set_shutdown(s, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); - return 1; -} - -static int set_server_cache(SSL_CTX *s_ctx) -{ - unsigned int v = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL_STORE; - SSL_CTX_sess_set_get_cb(s_ctx, get_sess_cb); - SSL_CTX_set_session_cache_mode(s_ctx, v); - return 1; -} - -static int set_callbacks(SSL *c, SSL *s) -{ - SSL_set_msg_callback(c, msg_cb); - SSL_set_info_callback(c, info_cb); - SSL_set_msg_callback(s, msg_cb); - SSL_set_info_callback(s, info_cb); - return 1; -} - -static int sessid_matches(SSL *c, SSL *s) -{ - const unsigned char *c_sid, *s_sid; - unsigned int c_len, s_len; - int test; - - test = TEST_ptr(c_sid = SSL_SESSION_get_id(SSL_get0_session(c), &c_len)) - && TEST_ptr(s_sid = SSL_SESSION_get_id(SSL_get0_session(s), &s_len)) - && TEST_uint_eq(c_len, s_len) && TEST_mem_eq(c_sid, c_len, s_sid, s_len); - - return test; -} - -static int test_dtls12_psk_resume_sessid_mismatch(int idx) -{ - const struct ciphersuites *cs = &css[idx]; - SSL_CTX *s_ctx = NULL, *c_ctx = NULL; - SSL *s_ssl = NULL, *c_ssl = NULL, *s = NULL, *c = NULL; - SSL_SESSION *sess = NULL, *r_sess = NULL; - const unsigned char *sid; - unsigned int sid_len; - int test; - - sess_cache = NULL; - - test = TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(), DTLS_client_method(), - DTLS1_2_VERSION, DTLS1_2_VERSION, &s_ctx, &c_ctx, NULL, NULL)) - && TEST_true(SSL_CTX_set_cipher_list(s_ctx, cs->name)) - && TEST_true(SSL_CTX_set_cipher_list(c_ctx, cs->name)) - && TEST_true(ctx_set_cache(s_ctx, c_ctx)) - && TEST_true(create_ssl_objects(s_ctx, c_ctx, &s, &c, NULL, NULL)) - && TEST_true(set_callbacks(c, s)) - && TEST_true(create_ssl_connection(s, c, SSL_ERROR_NONE)) - && TEST_ptr(sess = SSL_get1_session(c)) - && TEST_true(set_shutdown(c, s)) - && TEST_ptr(sid = SSL_SESSION_get_id(sess, &sid_len)) - && TEST_uint_eq(sid_len, 32) - && TEST_ptr(r_sess = SSL_SESSION_dup(sess)) - && TEST_true(SSL_SESSION_set1_id(r_sess, sid_req, sizeof(sid_req))) - && TEST_ptr(sess_cache = sess) - && TEST_true(set_server_cache(s_ctx)) - && TEST_true(create_ssl_objects(s_ctx, c_ctx, &s_ssl, &c_ssl, NULL, NULL)) - && TEST_true(set_callbacks(c_ssl, s_ssl)) - && TEST_true(SSL_set_session(c_ssl, r_sess)) - && TEST_true(create_ssl_connection(s_ssl, c_ssl, SSL_ERROR_NONE)) - && TEST_false(SSL_session_reused(s_ssl)); - - sess_cache = NULL; - SSL_free(s_ssl); - SSL_free(c_ssl); - SSL_SESSION_free(r_sess); - SSL_SESSION_free(sess); - SSL_CTX_free(s_ctx); - SSL_CTX_free(c_ctx); - SSL_free(s); - SSL_free(c); - return test; -} - -/* - * RFC 5077 3.4 requires the server to echo the session ID from ClientHello - * in the ServerHello when accepting a session ticket. Some clients rely on - * this echo to confirm that resumption succeeded. The ticket decryption path - * in tls_decrypt_ticket() guarantees the restored SSL_SESSION carries the - * correct session ID, so tls_construct_server_hello() will echo it correctly. - * If the session ID is empty, its length is set to zero as required by the - * RFC. - */ -static int test_dtls12_psk_resume_ticket_mismatch(int idx) -{ - const struct ciphersuites *cs = &css[idx]; - SSL_CTX *s_ctx = NULL, *c_ctx = NULL; - SSL *s_ssl = NULL, *c_ssl = NULL, *s = NULL, *c = NULL; - SSL_SESSION *c_sess = NULL, *r_sess = NULL; - int test; - - test = TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(), DTLS_client_method(), - DTLS1_2_VERSION, DTLS1_2_VERSION, &s_ctx, &c_ctx, NULL, NULL)) - && TEST_true(SSL_CTX_set_cipher_list(s_ctx, cs->name)) - && TEST_true(SSL_CTX_set_cipher_list(c_ctx, cs->name)) - && TEST_true(ctx_set_ticket(s_ctx, c_ctx)) - && TEST_true(create_ssl_objects(s_ctx, c_ctx, &s, &c, NULL, NULL)) - && TEST_true(set_callbacks(c, s)) - && TEST_true(create_ssl_connection(s, c, SSL_ERROR_NONE)) - && TEST_ptr(c_sess = SSL_get1_session(c)) - && TEST_true(SSL_SESSION_has_ticket(c_sess)) - && TEST_int_eq(set_shutdown(c, s), 1) - && TEST_ptr(r_sess = SSL_SESSION_dup(c_sess)) - && TEST_true(SSL_SESSION_set1_id(r_sess, sid_req, sizeof(sid_req))) - && TEST_true(create_ssl_objects(s_ctx, c_ctx, &s_ssl, &c_ssl, NULL, NULL)) - && TEST_true(set_callbacks(c_ssl, s_ssl)) - && TEST_true(SSL_set_session(c_ssl, r_sess)) - && TEST_true(create_ssl_connection(s_ssl, c_ssl, SSL_ERROR_NONE)) - && TEST_true(SSL_session_reused(s_ssl)) - && TEST_true(sessid_matches(c_ssl, s_ssl)); - - SSL_free(s_ssl); - SSL_free(c_ssl); - SSL_SESSION_free(r_sess); - SSL_SESSION_free(c_sess); - SSL_CTX_free(s_ctx); - SSL_CTX_free(c_ctx); - SSL_free(s); - SSL_free(c); - return test; -} - -OPT_TEST_DECLARE_USAGE("\n") - -int setup_tests(void) -{ - if (!test_skip_common_options()) { - TEST_error("Error parsing test options\n"); - return 0; - } - - ADD_ALL_TESTS(test_dtls12_psk_resume_sessid_mismatch, OSSL_NELEM(css)); - ADD_ALL_TESTS(test_dtls12_psk_resume_ticket_mismatch, OSSL_NELEM(css)); - return 1; -} diff --git a/test/ech_corrupt_test.c b/test/ech_corrupt_test.c index 79d59844fd..7070f4ef37 100644 --- a/test/ech_corrupt_test.c +++ b/test/ech_corrupt_test.c @@ -710,10 +710,10 @@ typedef struct { #define OSSL_ECH_BORK_GREASE (1 << 4) #define OSSL_ECH_BORK_REPLACE (1 << 5) -/* a truncated ECH, padded with a known HRR ext to match overall length */ +/* a truncated ECH, with another bogus ext to match overall length */ static unsigned char shortech[] = { 0xfe, 0x0d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x2c, 0x00, 0x00 + 0xdd, 0xdd, 0x00, 0x00 }; /* a too-long ECH internal length */ diff --git a/test/ectest.c b/test/ectest.c index 363d119c96..4665882e1c 100644 --- a/test/ectest.c +++ b/test/ectest.c @@ -802,22 +802,37 @@ static int char2_curve_test(int n) || !TEST_true(BN_add(yplusone, y, BN_value_one()))) goto err; +/* Change test based on whether binary point compression is enabled or not. */ +#ifdef OPENSSL_EC_BIN_PT_COMP + /* + * When (x, y) is on the curve, (x, y + 1) is, as it happens, not, + * and therefore setting the coordinates should fail. + */ + if (!TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone, ctx)) + || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, + test->y_bit, + ctx)) + || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0) + || !TEST_true(BN_hex2bn(&z, test->order)) + || !TEST_true(BN_hex2bn(&cof, test->cof)) + || !TEST_true(EC_GROUP_set_generator(group, P, z, cof)) + || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx))) + goto err; + TEST_info("%s -- Generator", test->name); + test_output_bignum("x", x); + test_output_bignum("y", y); + /* G_y value taken from the standard: */ + if (!TEST_true(BN_hex2bn(&z, test->y)) + || !TEST_BN_eq(y, z)) + goto err; +#else /* * When (x, y) is on the curve, (x, y + 1) is, as it happens, not, * and therefore setting the coordinates should fail. - * - * Set the generator point P from its affine coordinates, and - * independently recover the same point Q from x and the y-bit via - * compressed coordinates. The two must agree, which exercises both - * the affine and compressed binary point formats in a single pass. */ if (!TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone, ctx)) || !TEST_true(EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0) - || !TEST_true(EC_POINT_set_compressed_coordinates(group, Q, x, - test->ybit, ctx)) - || !TEST_int_gt(EC_POINT_is_on_curve(group, Q, ctx), 0) - || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)) || !TEST_true(BN_hex2bn(&z, test->order)) || !TEST_true(BN_hex2bn(&cof, test->cof)) || !TEST_true(EC_GROUP_set_generator(group, P, z, cof))) @@ -825,6 +840,7 @@ static int char2_curve_test(int n) TEST_info("%s -- Generator:", test->name); test_output_bignum("x", x); test_output_bignum("y", y); +#endif if (!TEST_int_eq(EC_GROUP_get_degree(group), test->degree) || !TEST_int_eq(EC_GROUP_security_bits(group), test->security) @@ -955,19 +971,26 @@ static int char2_field_tests(void) || !TEST_ptr(cof = BN_new()) || !TEST_ptr(yplusone = BN_new()) || !TEST_true(BN_hex2bn(&x, "6")) +/* Change test based on whether binary point compression is enabled or not. */ +#ifdef OPENSSL_EC_BIN_PT_COMP + || !TEST_true(EC_POINT_set_compressed_coordinates(group, Q, x, 1, ctx)) +#else || !TEST_true(BN_hex2bn(&y, "8")) - || !TEST_true(EC_POINT_set_affine_coordinates(group, Q, x, y, ctx))) + || !TEST_true(EC_POINT_set_affine_coordinates(group, Q, x, y, ctx)) +#endif + ) goto err; if (!TEST_int_gt(EC_POINT_is_on_curve(group, Q, ctx), 0)) { +/* Change test based on whether binary point compression is enabled or not. */ +#ifdef OPENSSL_EC_BIN_PT_COMP + if (!TEST_true(EC_POINT_get_affine_coordinates(group, Q, x, y, ctx))) + goto err; +#endif TEST_info("Point is not on curve"); test_output_bignum("x", x); test_output_bignum("y", y); goto err; } - /* The same point recovered from compressed coordinates must agree. */ - if (!TEST_true(EC_POINT_set_compressed_coordinates(group, R, x, 1, ctx)) - || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx))) - goto err; TEST_note("A cyclic subgroup:"); k = 100; @@ -995,6 +1018,8 @@ static int char2_field_tests(void) || !TEST_true(EC_POINT_is_at_infinity(group, P))) goto err; +/* Change test based on whether binary point compression is enabled or not. */ +#ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof(buf), ctx); if (!TEST_size_t_ne(len, 0) @@ -1003,6 +1028,7 @@ static int char2_field_tests(void) goto err; test_output_memory("Generator as octet string, compressed form:", buf, len); +#endif len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), ctx); @@ -1013,6 +1039,8 @@ static int char2_field_tests(void) test_output_memory("Generator as octet string, uncompressed form:", buf, len); +/* Change test based on whether binary point compression is enabled or not. */ +#ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof(buf), ctx); if (!TEST_size_t_ne(len, 0) @@ -1021,6 +1049,7 @@ static int char2_field_tests(void) goto err; test_output_memory("Generator as octet string, hybrid form:", buf, len); +#endif if (!TEST_true(EC_POINT_invert(group, P, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))) @@ -1127,18 +1156,16 @@ static int group_field_test(void) EC_GROUP *secp521r1_group = NULL; EC_GROUP *sect163r2_group = NULL; - if (!TEST_true(BN_hex2bn(&secp521r1_field, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFF")) - || !TEST_true(BN_hex2bn(§163r2_field, - "08000000000000000000000000000000" - "00000000C9"))) { - BN_free(secp521r1_field); - return 0; - } + BN_hex2bn(&secp521r1_field, + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFF"); + + BN_hex2bn(§163r2_field, + "08000000000000000000000000000000" + "00000000C9"); secp521r1_group = EC_GROUP_new_by_curve_name(NID_secp521r1); if (BN_cmp(secp521r1_field, EC_GROUP_get0_field(secp521r1_group))) diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 00ed62f264..3033255103 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -2323,83 +2323,20 @@ out: } #ifndef OPENSSL_NO_POLY1305 -/* Test Poly1305 no-key failures and staged key initialization */ +/* Test that EVP_MAC_final fails for Poly1305 when no key was set */ static int test_evp_mac_poly1305_no_key(void) { int ret = 0; EVP_MAC *mac = NULL; EVP_MAC_CTX *ctx = NULL; - /* RFC 7539 Poly1305 test vector. */ - static const unsigned char staged_data[] = "Cryptographic Forum Research Group"; - static const unsigned char expected[16] = { - 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, - 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 - }; - unsigned char no_key_data[16] = { 0 }; - unsigned char key[32] = { - 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, - 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, - 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, - 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b - }; unsigned char out[16]; - OSSL_PARAM key_params[2]; - OSSL_PARAM null_key_params[2]; size_t outl = 0; - key_params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - key, sizeof(key)); - key_params[1] = OSSL_PARAM_construct_end(); - null_key_params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - NULL, sizeof(key)); - null_key_params[1] = OSSL_PARAM_construct_end(); - if (!TEST_ptr(mac = EVP_MAC_fetch(testctx, "Poly1305", testpropq)) || !TEST_ptr(ctx = EVP_MAC_CTX_new(mac)) - || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1)) + || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1) + || !TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 0)) goto err; - - ERR_clear_error(); - if (!TEST_int_eq(EVP_MAC_update(ctx, no_key_data, sizeof(no_key_data)), 0) - || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NO_KEY_SET)) - goto err; - - /* The failed update must not block staged key initialization. */ - if (!TEST_int_eq(EVP_MAC_CTX_set_params(ctx, key_params), 1) - || !TEST_int_eq(EVP_MAC_update(ctx, staged_data, - sizeof(staged_data) - 1), - 1) - || !TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 1) - || !TEST_size_t_eq(outl, sizeof(expected)) - || !TEST_mem_eq(out, outl, expected, sizeof(expected))) - goto err; - - EVP_MAC_CTX_free(ctx); - ctx = NULL; - - if (!TEST_ptr(ctx = EVP_MAC_CTX_new(mac)) - || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1)) - goto err; - - ERR_clear_error(); - if (!TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 0) - || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NO_KEY_SET)) - goto err; - - ERR_clear_error(); - if (!TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, null_key_params), 0) - || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), - PROV_R_INVALID_KEY_LENGTH)) - goto err; - - ERR_clear_error(); - if (!TEST_int_eq(EVP_MAC_CTX_set_params(ctx, null_key_params), 0) - || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), - PROV_R_INVALID_KEY_LENGTH)) - goto err; - - EVP_MAC_CTX_free(ctx); - ctx = NULL; ret = 1; err: EVP_MAC_CTX_free(ctx); @@ -2474,7 +2411,7 @@ static struct ec_der_pub_keys_st { * Tests the range of the decoded EC char2 public point. * See ec_GF2m_simple_oct2point(). */ -static int test_invalid_ec_char2_pub_range_decode(int id) +static int test_invalide_ec_char2_pub_range_decode(int id) { int ret = 0; EVP_PKEY *pkey; @@ -4244,76 +4181,6 @@ done: return ret; } -/* - * A raw RSA PKCS#1 v1.5 signature whose recovered data is empty must be - * recovered successfully with a length of zero, not rejected as an error. - */ -static int test_RSA_verify_recover_empty_payload(void) -{ - int ret = 0; - int recovered_cap = 0; - EVP_PKEY *pkey = NULL; - EVP_PKEY_CTX *sign_ctx = NULL, *verify_ctx = NULL; - unsigned char *sig = NULL, *recovered = NULL; - size_t sig_len = 0, recovered_len = 0; - /* - * The signed input has zero length, but a valid non-null address is still - * passed so the result does not depend on how lower layers treat NULL for - * zero-length data. - */ - const unsigned char empty[] = { 0 }; - - if (OSSL_PROVIDER_available(testctx, "fips")) - return TEST_skip("Test skipped for FIPS provider"); - - if (!TEST_ptr(pkey = load_example_rsa_key()) - || !TEST_ptr(sign_ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pkey, NULL)) - || !TEST_int_gt(EVP_PKEY_sign_init(sign_ctx), 0) - || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_padding(sign_ctx, RSA_PKCS1_PADDING), 0) - /* - * Deliberately do not configure a signature digest so that the raw - * PKCS#1 v1.5 sign and verify-recover paths are exercised. - */ - || !TEST_int_gt(EVP_PKEY_sign(sign_ctx, NULL, &sig_len, empty, 0), 0) - || !TEST_ptr(sig = OPENSSL_malloc(sig_len)) - || !TEST_int_gt(EVP_PKEY_sign(sign_ctx, sig, &sig_len, empty, 0), 0) - || !TEST_int_gt(recovered_cap = EVP_PKEY_get_size(pkey), 0) - || !TEST_ptr(recovered = OPENSSL_malloc(recovered_cap)) - || !TEST_ptr(verify_ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pkey, NULL)) - || !TEST_int_gt(EVP_PKEY_verify_recover_init(verify_ctx), 0) - || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_padding(verify_ctx, RSA_PKCS1_PADDING), - 0)) - goto done; - - /* Size-query call must succeed. */ - recovered_len = (size_t)recovered_cap; - if (!TEST_int_gt(EVP_PKEY_verify_recover(verify_ctx, NULL, - &recovered_len, sig, sig_len), - 0)) - goto done; - - /* - * The actual recovery call is essential: a NULL output buffer would only - * run the size-query path, which never decodes the signature and so would - * not reproduce the regression. - */ - recovered_len = (size_t)recovered_cap; - if (!TEST_int_gt(EVP_PKEY_verify_recover(verify_ctx, recovered, - &recovered_len, sig, sig_len), - 0) - || !TEST_size_t_eq(recovered_len, 0)) - goto done; - - ret = 1; -done: - EVP_PKEY_CTX_free(sign_ctx); - EVP_PKEY_CTX_free(verify_ctx); - EVP_PKEY_free(pkey); - OPENSSL_free(sig); - OPENSSL_free(recovered); - return ret; -} - static int test_RSA_encrypt(void) { int ret = 0; @@ -4573,139 +4440,6 @@ err: return ret; } #endif /* !OPENSSL_NO_DEPRECATED_3_0 */ - -/* Test that DHX (X9.42) rejects a malicious peer key during the - * derivation phase (specifically EVP_PKEY_derive_set_peer) when the - * remote 'q' does not match the local domain parameters but is still - * consistent with the remote key share. - * (CVE-2026-42770) - */ -static int test_dhx_derive_rejects_bad_peer_q(void) -{ - int ret = 0; - EVP_PKEY *local_key = NULL, *remote_key = NULL; - EVP_PKEY_CTX *pctx = NULL, *derive_ctx = NULL; - OSSL_PARAM_BLD *bld = NULL; - OSSL_PARAM *params = NULL; - - BIGNUM *p = NULL, *g = NULL; - BIGNUM *q_valid = NULL, *pub_local = NULL, *priv_local = NULL; - BIGNUM *q_bad = NULL, *pub_bad = NULL; - - const char *hex_p = "87a8e61db4b6663cffbbd19c651959998ceef608660dd0f25d2ceed4435e3b00" - "e00df8f1d61957d4faf7df4561b2aa3016c3d91134096faa3bf4296d830e9a7c" - "209e0c6497517abd5a8a9d306bcf67ed91f9e6725b4758c022e0b1ef4275bf7b" - "6c5bfc11d45f9088b941f54eb1e59bb8bc39a0bf12307f5c4fdb70c581b23f76" - "b63acae1caa6b7902d52526735488a0ef13c6d9a51bfa4ab3ad8347796524d8e" - "f6a167b5a41825d967e144e5140564251ccacb83e6b486f6b3ca3f7971506026" - "c0b857f689962856ded4010abd0be621c3a3960a54e710c375f26375d7014103" - "a4b54330c198af126116d2276e11715f693877fad7ef09cadb094ae91e1a1597"; - const char *hex_g = "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA125" - "10DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62" - "901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B" - "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193" - "B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0A" - "DB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915" - "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C3" - "2F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659"; - - const char *hex_q_valid = "8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3"; - const char *hex_local_pub = "796e15431470ac86fa8a78b8bcdd1f3589dbf15ffe0e0a7a41dd8640887f3cc3" - "f0439e281f4cf3800bac2dbdfcda589b26cc828512085ce0d3e57aa13cd9e7a4" - "66d881bace91ed10c6064ab36e0d66367c4bfed56a9f907e4daec16732fb5c54" - "891cb0d26251fd61c32040774246b3f8bdcd5ef60e6847cdd69bd6d318d1cda0" - "e8a30a716de4dc1a4eb99b0686b77120c4b69b0005f6a8c3ae768d23c08c85bd" - "1d58f40dc0138d6277436137ae69779fdc218c071c14826f471562033e85ffc9" - "9a2147d539e274136a4a1e7f1db97583b51dc0385a52d7383963758d893398a8" - "d013fdbad20ddf30fbe05fbb2249913ae6751b6b246ae5622ba26c4827417c2d"; - const char *hex_local_priv = "1122334455667788990011223344556677889900112233445566778899001122"; - - /* Remote malicious parameters */ - const char *hex_remote_q = "09f5"; - const char *hex_remote_pub = "54c057903d362235a65c03f001d8a3ea252836b3580250abdc0a1083451af012" - "6fd150f9e8d212b384ae0c23aa7c67fe851368114ccc061a661e986bd7e63d25" - "7513339a6914cbfab209ad793ef25704cd532ddfb7e693de701d17e629ef3c18" - "4d40d5fea1f9edb89c5bf8d7aa19e3374f805932159ca7b5d573b9e2f3c94fe7" - "47c4a3b09e31afa3788d35833aaf2ac8ae8bc48500131464e793a2e0352e7c3e" - "d9da9fcf89b121bc1cee83c544214ceb3338b14ac6891968351746eaf62bb517" - "eb98fc633d8d235bac37bc08e47f1851d05501949a6733965adbfe8e43f7c3b9" - "3ca7515cd6ab36d7ef26bb0fd6033abc39613e880fffc8729b03bfeaddf08833"; - - if (!TEST_true(BN_hex2bn(&p, hex_p)) || !TEST_true(BN_hex2bn(&g, hex_g))) - goto err; - - if (!TEST_true(BN_hex2bn(&q_valid, hex_q_valid)) - || !TEST_true(BN_hex2bn(&pub_local, hex_local_pub)) - || !TEST_true(BN_hex2bn(&priv_local, hex_local_priv))) - goto err; - - if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_valid)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_local)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv_local)) - || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) - goto err; - - if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, "DHX", testpropq)) - || !TEST_int_gt(EVP_PKEY_fromdata_init(pctx), 0) - || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &local_key, EVP_PKEY_KEYPAIR, params), 0)) - goto err; - - OSSL_PARAM_free(params); - OSSL_PARAM_BLD_free(bld); - EVP_PKEY_CTX_free(pctx); - params = NULL; - bld = NULL; - pctx = NULL; - - if (!TEST_true(BN_hex2bn(&q_bad, hex_remote_q)) - || !TEST_true(BN_hex2bn(&pub_bad, hex_remote_pub))) - goto err; - - if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_bad)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_bad)) - || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) - goto err; - - if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, "DHX", testpropq)) - || !TEST_int_gt(EVP_PKEY_fromdata_init(pctx), 0) - || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &remote_key, EVP_PKEY_PUBLIC_KEY, params), 0)) - goto err; - - if (!TEST_ptr(derive_ctx = EVP_PKEY_CTX_new(local_key, NULL)) - || !TEST_int_gt(EVP_PKEY_derive_init(derive_ctx), 0)) - goto err; - - /* reject the remote key share, even if it is self-consistent, correct - * code needs to use local q, not remote-provided q. */ - if (!TEST_int_le(EVP_PKEY_derive_set_peer(derive_ctx, remote_key), 0)) { - TEST_error("EVP_PKEY_derive_set_peer incorrectly accepted a peer with malicious 'q'"); - goto err; - } - - ret = 1; - -err: - BN_free(p); - BN_free(g); - BN_free(q_valid); - BN_free(pub_local); - BN_free(priv_local); - BN_free(q_bad); - BN_free(pub_bad); - OSSL_PARAM_free(params); - OSSL_PARAM_BLD_free(bld); - EVP_PKEY_CTX_free(pctx); - EVP_PKEY_CTX_free(derive_ctx); - EVP_PKEY_free(local_key); - EVP_PKEY_free(remote_key); - return ret; -} #endif /* !OPENSSL_NO_DH */ /* @@ -5844,476 +5578,6 @@ err: EVP_CIPHER_CTX_free(ctx_onestep); return testresult; } - -/*- - * A zero-length AEAD message driven through the one-shot EVP_Cipher() interface - * must agree with the streaming EVP_CipherFinal_ex() path. This checks: - * - an empty message yields the same tag via both interfaces - * - the true tag passes verification on decrypt - * - the modified tag fails verification on decrypt - */ -static int test_evp_oneshot_aead_zerolen(int idx) -{ - const EVP_CIPHER_TEST_INFO *info = &cipher_list[idx]; - EVP_CIPHER_CTX *ctx_stream = NULL; /* reference: final only */ - EVP_CIPHER_CTX *ctx_oneshot = NULL; /* encrypt via EVP_Cipher(in == NULL) */ - EVP_CIPHER_CTX *ctx_dec = NULL; /* decrypt via EVP_Cipher(in == NULL) */ - EVP_CIPHER_CTX *ctx_dec_bad = NULL; /* decrypt with a corrupted tag */ - EVP_CIPHER_CTX *ctx_dec_s = NULL; /* streaming decrypt */ - EVP_CIPHER_CTX *ctx_dec_s_bad = NULL; /* streaming decrypt, corrupted tag */ - - OSSL_PARAM get_tagparams[2]; - OSSL_PARAM set_tagparams[2]; - - int taglen = info->taglen; - unsigned char key[EVP_MAX_KEY_LENGTH] = { 0 }; - unsigned char iv[EVP_MAX_IV_LENGTH] = { 0 }; - - unsigned char ct[16] = { 0 }; /* scratch out; AEAD finalize writes no data */ - int finlen = 0, oneshot_flen = 0, dec_flen = 0; - - unsigned char tag_stream[EVPTEST_TAG_LEN_MAX] = { 0 }; - unsigned char tag_oneshot[EVPTEST_TAG_LEN_MAX] = { 0 }; - unsigned char tag_bad[EVPTEST_TAG_LEN_MAX] = { 0 }; - - int i = 0, testresult = 1; - char *errmsg = NULL; - - /* filter out various modes */ - if (info->taglen == 0 - || info->mode == EVP_CIPH_CCM_MODE - || info->mode == EVP_CIPH_OCB_MODE - || info->mode == EVP_CIPH_GCM_SIV_MODE - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA1") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA1") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA256") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA256") - || EVP_CIPHER_is_a(info->ciph, "ChaCha20-Poly1305")) - return 1; - - for (i = 0; i < info->keylen && i < (int)sizeof(key); i++) - key[i] = (unsigned char)(0xA0 + i); - for (i = 0; i < info->ivlen && i < (int)sizeof(iv); i++) - iv[i] = (unsigned char)(0xB0 + i); - - /* reference: streaming finalize of an empty message */ - if (!TEST_ptr(ctx_stream = EVP_CIPHER_CTX_new())) { - errmsg = "STREAM_ALLOC"; - goto err; - } - if (!TEST_true(EVP_EncryptInit_ex2(ctx_stream, info->ciph, key, iv, NULL))) { - errmsg = "STREAM_INIT"; - goto err; - } - if (!TEST_true(EVP_EncryptFinal_ex(ctx_stream, ct, &finlen))) { - errmsg = "STREAM_FINAL"; - goto err; - } - - /* clamp to the negotiated tag length if the cipher reports one */ - i = EVP_CIPHER_CTX_get_tag_length(ctx_stream); - if (i > 0) - taglen = i; - - /* bound the memcpy, should never happen but helps static analysis */ - if (taglen > EVPTEST_TAG_LEN_MAX) { - errmsg = "TAGLEN_EXCEEDS_BUF"; - goto err; - } - - get_tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag_stream, taglen); - get_tagparams[1] = OSSL_PARAM_construct_end(); - if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx_stream, get_tagparams))) { - errmsg = "STREAM_GET_TAG"; - goto err; - } - - /* one-shot encrypt: finalize the empty message with in == NULL */ - if (!TEST_ptr(ctx_oneshot = EVP_CIPHER_CTX_new())) { - errmsg = "ONESHOT_ALLOC"; - goto err; - } - if (!TEST_true(EVP_EncryptInit_ex2(ctx_oneshot, info->ciph, key, iv, NULL))) { - errmsg = "ONESHOT_INIT"; - goto err; - } - oneshot_flen = EVP_Cipher(ctx_oneshot, ct, NULL, 0); - if (!TEST_int_ge(oneshot_flen, 0)) { - errmsg = "ONESHOT_FINAL_NULL"; - goto err; - } - - get_tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag_oneshot, taglen); - if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx_oneshot, get_tagparams))) { - errmsg = "ONESHOT_GET_TAG"; - goto err; - } - if (!TEST_mem_eq(tag_oneshot, taglen, tag_stream, taglen)) { - errmsg = "TAG_MISMATCH_ONESHOT_vs_STREAM"; - goto err; - } - - /* one-shot decrypt: the correct tag must verify via in == NULL */ - if (!TEST_ptr(ctx_dec = EVP_CIPHER_CTX_new())) { - errmsg = "DEC_ALLOC"; - goto err; - } - if (!TEST_true(EVP_DecryptInit_ex2(ctx_dec, info->ciph, key, iv, NULL))) { - errmsg = "DEC_INIT"; - goto err; - } - set_tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag_stream, taglen); - set_tagparams[1] = OSSL_PARAM_construct_end(); - if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx_dec, set_tagparams))) { - errmsg = "DEC_SET_TAG"; - goto err; - } - dec_flen = EVP_Cipher(ctx_dec, ct, NULL, 0); - if (!TEST_int_ge(dec_flen, 0)) { - errmsg = "DEC_VERIFY_NULL"; - goto err; - } - - /* - * ...and a corrupted tag must be rejected. EVP_Cipher() returns < 0 on a - * failed one-shot, so a non-negative result here means verification was - * skipped or wrongly accepted the bad tag. - */ - memcpy(tag_bad, tag_stream, taglen); - tag_bad[0] ^= 0x01; - if (!TEST_ptr(ctx_dec_bad = EVP_CIPHER_CTX_new())) { - errmsg = "DEC_BAD_ALLOC"; - goto err; - } - if (!TEST_true(EVP_DecryptInit_ex2(ctx_dec_bad, info->ciph, key, iv, NULL))) { - errmsg = "DEC_BAD_INIT"; - goto err; - } - set_tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag_bad, taglen); - if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx_dec_bad, set_tagparams))) { - errmsg = "DEC_BAD_SET_TAG"; - goto err; - } - if (!TEST_int_lt(EVP_Cipher(ctx_dec_bad, ct, NULL, 0), 0)) { - errmsg = "DEC_BADTAG_NOT_REJECTED"; - goto err; - } - - /* streaming decrypt: the correct tag must verify via EVP_DecryptFinal_ex */ - if (!TEST_ptr(ctx_dec_s = EVP_CIPHER_CTX_new())) { - errmsg = "DEC_STREAM_ALLOC"; - goto err; - } - if (!TEST_true(EVP_DecryptInit_ex2(ctx_dec_s, info->ciph, key, iv, NULL))) { - errmsg = "DEC_STREAM_INIT"; - goto err; - } - set_tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag_stream, taglen); - if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx_dec_s, set_tagparams))) { - errmsg = "DEC_STREAM_SET_TAG"; - goto err; - } - if (!TEST_true(EVP_DecryptFinal_ex(ctx_dec_s, ct, &finlen))) { - errmsg = "DEC_STREAM_VERIFY"; - goto err; - } - - /* streaming decrypt: a corrupted tag must be rejected */ - if (!TEST_ptr(ctx_dec_s_bad = EVP_CIPHER_CTX_new())) { - errmsg = "DEC_STREAM_BAD_ALLOC"; - goto err; - } - if (!TEST_true(EVP_DecryptInit_ex2(ctx_dec_s_bad, info->ciph, key, iv, NULL))) { - errmsg = "DEC_STREAM_BAD_INIT"; - goto err; - } - set_tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag_bad, taglen); - if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx_dec_s_bad, set_tagparams))) { - errmsg = "DEC_STREAM_BAD_SET_TAG"; - goto err; - } - if (!TEST_false(EVP_DecryptFinal_ex(ctx_dec_s_bad, ct, &finlen))) { - errmsg = "DEC_STREAM_BADTAG_NOT_REJECTED"; - goto err; - } - -err: - if (errmsg != NULL) { - TEST_info("test_evp_oneshot_aead_zerolen %d, %s: %s", - idx, errmsg, info->name); - testresult = 0; - } - EVP_CIPHER_CTX_free(ctx_stream); - EVP_CIPHER_CTX_free(ctx_oneshot); - EVP_CIPHER_CTX_free(ctx_dec); - EVP_CIPHER_CTX_free(ctx_dec_bad); - EVP_CIPHER_CTX_free(ctx_dec_s); - EVP_CIPHER_CTX_free(ctx_dec_s_bad); - return testresult; -} - -/* - * With AEAD ciphers, a tag is an input for decryption (the value to verify) - * and an output of encryption (the generated value). Therefore: - * - supplying a tag value while encrypting must fail - * - reading a tag while decrypting must fail - * - error codes should be consistent across all AEADs - */ -static int test_evp_aead_tag_direction(int idx) -{ - const EVP_CIPHER_TEST_INFO *info = &cipher_list[idx]; - EVP_CIPHER_CTX *ctx_enc = NULL; /* set tag while encrypting: must fail */ - EVP_CIPHER_CTX *ctx_dec = NULL; /* get tag while decrypting: must fail */ - - OSSL_PARAM tagparams[2]; - - unsigned char key[EVP_MAX_KEY_LENGTH] = { 0 }; - unsigned char iv[EVP_MAX_IV_LENGTH] = { 0 }; - unsigned char tag[EVPTEST_TAG_LEN_MAX] = { 0 }; - - int i = 0, testresult = 0, expected = 0; - char *errmsg = NULL; - unsigned long err_code = 0; - - /* filter out various modes */ - if (info->taglen == 0 - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA1") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA1") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA256") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA256")) - return 1; - - for (i = 0; i < info->keylen && i < (int)sizeof(key); i++) - key[i] = (unsigned char)(0xA0 + i); - for (i = 0; i < info->ivlen && i < (int)sizeof(iv); i++) - iv[i] = (unsigned char)(0xB0 + i); - - /* - * a tag value supplied while encrypting must be rejected. data is non-NULL - * so this is a value-set, not the data == NULL tag-length query. - */ - if (!TEST_ptr(ctx_enc = EVP_CIPHER_CTX_new())) { - errmsg = "ENC_ALLOC"; - goto err; - } - if (!TEST_true(EVP_EncryptInit_ex2(ctx_enc, info->ciph, key, iv, NULL))) { - errmsg = "ENC_INIT"; - goto err; - } - tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag, info->taglen); - tagparams[1] = OSSL_PARAM_construct_end(); - ERR_set_mark(); - if (!TEST_false(EVP_CIPHER_CTX_set_params(ctx_enc, tagparams))) { - ERR_clear_last_mark(); - errmsg = "ENC_SET_TAG_NOT_REJECTED"; - goto err; - } - err_code = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(err_code), ERR_LIB_PROV) - || !TEST_int_eq(ERR_GET_REASON(err_code), PROV_R_TAG_NOT_NEEDED)) { - ERR_clear_last_mark(); - expected = PROV_R_TAG_NOT_NEEDED; - errmsg = "ENC_SET_TAG_WRONG_REASON"; - goto err; - } - ERR_pop_to_mark(); - - /* a tag read while decrypting must be rejected */ - if (!TEST_ptr(ctx_dec = EVP_CIPHER_CTX_new())) { - errmsg = "DEC_ALLOC"; - goto err; - } - if (!TEST_true(EVP_DecryptInit_ex2(ctx_dec, info->ciph, key, iv, NULL))) { - errmsg = "DEC_INIT"; - goto err; - } - tagparams[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - tag, info->taglen); - tagparams[1] = OSSL_PARAM_construct_end(); - - /* set a tag so the get below is exercised with one present */ - if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx_dec, tagparams))) { - errmsg = "DEC_SET_TAG_REJECTED"; - goto err; - } - - /* but a tag must never be readable back while decrypting */ - ERR_set_mark(); - if (!TEST_false(EVP_CIPHER_CTX_get_params(ctx_dec, tagparams))) { - ERR_clear_last_mark(); - errmsg = "DEC_GET_TAG_NOT_REJECTED"; - goto err; - } - err_code = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(err_code), ERR_LIB_PROV) - || !TEST_int_eq(ERR_GET_REASON(err_code), PROV_R_TAG_NOT_SET)) { - ERR_clear_last_mark(); - expected = PROV_R_TAG_NOT_SET; - errmsg = "DEC_GET_TAG_WRONG_REASON"; - goto err; - } - ERR_pop_to_mark(); - - testresult = 1; - -err: - if (errmsg != NULL) { - if (expected != 0) - TEST_info("test_evp_aead_tag_direction %d, %s: %s" - " (expected reason %d, got %d)", - idx, errmsg, info->name, - expected, ERR_GET_REASON(err_code)); - else - TEST_info("test_evp_aead_tag_direction %d, %s: %s", - idx, errmsg, info->name); - } - EVP_CIPHER_CTX_free(ctx_enc); - EVP_CIPHER_CTX_free(ctx_dec); - return testresult; -} - -/* - * With AEAD ciphers, associated data must precede the payload. Once plaintext - * or ciphertext processing has begun, a further AAD update (out == NULL) must - * be rejected, and the rejection must be reported the same way across every - * AEAD: ERR_LIB_PROV / PROV_R_UPDATE_CALL_OUT_OF_ORDER. The invariant is - * checked in both the encrypt and decrypt directions. - */ -static int test_evp_aead_late_aad(int idx) -{ - const EVP_CIPHER_TEST_INFO *info = &cipher_list[idx]; - EVP_CIPHER_CTX *ctx_enc = NULL; /* late AAD after plaintext: must fail */ - EVP_CIPHER_CTX *ctx_dec = NULL; /* late AAD after ciphertext: must fail */ - - unsigned char key[EVP_MAX_KEY_LENGTH] = { 0 }; - unsigned char iv[EVP_MAX_IV_LENGTH] = { 0 }; - unsigned char aad[] = "aad"; - unsigned char msg[] = "message"; - unsigned char out[sizeof(msg) + EVP_MAX_BLOCK_LENGTH]; - - int i = 0, len = 0, testresult = 0, expected = 0; - char *errmsg = NULL; - unsigned long err_code = 0; - - if (info->taglen == 0 /* skip non-AEAD */ - || info->mode == EVP_CIPH_GCM_MODE /* rejects, raises 102 PROV_R_CIPHER_OPERATION_FAILED */ - || info->mode == EVP_CIPH_CCM_MODE /* fails at first AAD */ - || info->mode == EVP_CIPH_OCB_MODE /* accepts late AAD */ - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA1") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA1") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA256") - /* skip TLS stitched MTE cipher */ - || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA256")) - return 1; - - for (i = 0; i < info->keylen && i < (int)sizeof(key); i++) - key[i] = (unsigned char)(0xA0 + i); - for (i = 0; i < info->ivlen && i < (int)sizeof(iv); i++) - iv[i] = (unsigned char)(0xB0 + i); - - /* encrypt: aad, then plaintext, then a late aad update must be rejected */ - if (!TEST_ptr(ctx_enc = EVP_CIPHER_CTX_new())) { - errmsg = "ENC_ALLOC"; - goto err; - } - if (!TEST_true(EVP_EncryptInit_ex2(ctx_enc, info->ciph, key, iv, NULL))) { - errmsg = "ENC_INIT"; - goto err; - } - if (!TEST_true(EVP_EncryptUpdate(ctx_enc, NULL, &len, aad, sizeof(aad)))) { - errmsg = "ENC_AAD"; - goto err; - } - if (!TEST_true(EVP_EncryptUpdate(ctx_enc, out, &len, msg, sizeof(msg)))) { - errmsg = "ENC_PLAINTEXT"; - goto err; - } - ERR_set_mark(); - if (!TEST_false(EVP_EncryptUpdate(ctx_enc, NULL, &len, aad, sizeof(aad)))) { - ERR_clear_last_mark(); - errmsg = "ENC_LATE_AAD_NOT_REJECTED"; - goto err; - } - err_code = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(err_code), ERR_LIB_PROV) - || !TEST_int_eq(ERR_GET_REASON(err_code), PROV_R_UPDATE_CALL_OUT_OF_ORDER)) { - ERR_clear_last_mark(); - expected = PROV_R_UPDATE_CALL_OUT_OF_ORDER; - errmsg = "ENC_LATE_AAD_WRONG_REASON"; - goto err; - } - ERR_pop_to_mark(); - - /* decrypt: same sequence, late aad after ciphertext must be rejected */ - if (!TEST_ptr(ctx_dec = EVP_CIPHER_CTX_new())) { - errmsg = "DEC_ALLOC"; - goto err; - } - if (!TEST_true(EVP_DecryptInit_ex2(ctx_dec, info->ciph, key, iv, NULL))) { - errmsg = "DEC_INIT"; - goto err; - } - if (!TEST_true(EVP_DecryptUpdate(ctx_dec, NULL, &len, aad, sizeof(aad)))) { - errmsg = "DEC_AAD"; - goto err; - } - /* the ciphertext content is irrelevant; the tag is never finalized here */ - if (!TEST_true(EVP_DecryptUpdate(ctx_dec, out, &len, msg, sizeof(msg)))) { - errmsg = "DEC_CIPHERTEXT"; - goto err; - } - ERR_set_mark(); - if (!TEST_false(EVP_DecryptUpdate(ctx_dec, NULL, &len, aad, sizeof(aad)))) { - ERR_clear_last_mark(); - errmsg = "DEC_LATE_AAD_NOT_REJECTED"; - goto err; - } - err_code = ERR_peek_last_error(); - if (!TEST_int_eq(ERR_GET_LIB(err_code), ERR_LIB_PROV) - || !TEST_int_eq(ERR_GET_REASON(err_code), PROV_R_UPDATE_CALL_OUT_OF_ORDER)) { - ERR_clear_last_mark(); - expected = PROV_R_UPDATE_CALL_OUT_OF_ORDER; - errmsg = "DEC_LATE_AAD_WRONG_REASON"; - goto err; - } - ERR_pop_to_mark(); - - testresult = 1; - -err: - if (errmsg != NULL) { - if (expected != 0) - TEST_info("test_evp_aead_late_aad %d, %s: %s" - " (expected reason %d, got %d)", - idx, errmsg, info->name, - expected, ERR_GET_REASON(err_code)); - else - TEST_info("test_evp_aead_late_aad %d, %s: %s", - idx, errmsg, info->name); - } - EVP_CIPHER_CTX_free(ctx_enc); - EVP_CIPHER_CTX_free(ctx_dec); - return testresult; -} - /* * Verify stale key is not being used after providing a new key in multiple steps. * This test performs a full round of encryption and then changes the @@ -8137,70 +7401,6 @@ end: return ret; } -static int test_aes_xts_rejects_missing_iv(void) -{ - static const unsigned char key[32] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }; - static const unsigned char in[32] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, - 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 - }; - static const unsigned char iv[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 - }; - EVP_CIPHER_CTX *ctx = NULL; - EVP_CIPHER *cipher = NULL; - unsigned char out[sizeof(in)]; - int outl = 0; - int ret = 0; - - if ((cipher = EVP_CIPHER_fetch(testctx, "AES-128-XTS", testpropq)) == NULL) - return TEST_skip("AES-128-XTS cipher is not available"); - - /* Initialize with a valid IV as a positive control */ - if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) - || !TEST_true(EVP_EncryptInit_ex2(ctx, cipher, key, iv, NULL)) - || !TEST_true(EVP_EncryptUpdate(ctx, out, &outl, in, sizeof(in))) - || !TEST_int_eq(outl, (int)sizeof(in))) - goto err; - - EVP_CIPHER_CTX_free(ctx); - ctx = NULL; - outl = 0; - - if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())) - goto err; - - /* Initialize with a NULL IV, which may fail immediately */ - ERR_set_mark(); - if (!EVP_EncryptInit_ex2(ctx, cipher, key, NULL, NULL)) { - ERR_pop_to_mark(); - ret = 1; - goto err; - } - - /* Test EVP_EncryptUpdate after NULL IV initialization, which should fail */ - if (!TEST_false(EVP_EncryptUpdate(ctx, out, &outl, in, sizeof(in)))) { - ERR_clear_last_mark(); - goto err; - } - ERR_pop_to_mark(); - - ret = 1; - -err: - EVP_CIPHER_free(cipher); - EVP_CIPHER_CTX_free(ctx); - return ret; -} - /* * Cross-driver round-trip test for AEAD one-shot vs streaming paths. * @@ -9286,7 +8486,12 @@ int setup_tests(void) ADD_TEST(test_EVP_SM2_verify); #endif ADD_ALL_TESTS(test_set_get_raw_keys, OSSL_NELEM(keys)); +#if defined(_MSC_VER) || defined(OPENSSL_NO_CACHED_FETCH) + ADD_MFAIL_ALL_NO_CHECK_TESTS(test_set_get_raw_keys_mfail, + OSSL_NELEM(keys)); +#else ADD_MFAIL_ALL_TESTS(test_set_get_raw_keys_mfail, OSSL_NELEM(keys)); +#endif ADD_ALL_TESTS(test_EVP_PKEY_check, OSSL_NELEM(keycheckdata)); #ifndef OPENSSL_NO_CMAC ADD_TEST(test_CMAC_keygen); @@ -9297,7 +8502,7 @@ int setup_tests(void) #ifndef OPENSSL_NO_EC ADD_TEST(test_X509_PUBKEY_inplace); ADD_TEST(test_X509_PUBKEY_dup); - ADD_ALL_TESTS(test_invalid_ec_char2_pub_range_decode, + ADD_ALL_TESTS(test_invalide_ec_char2_pub_range_decode, OSSL_NELEM(ec_der_pub_keys)); #endif #ifndef OPENSSL_NO_DSA @@ -9308,7 +8513,6 @@ int setup_tests(void) ADD_TEST(test_RSA_OAEP_set_get_params); ADD_TEST(test_RSA_OAEP_set_null_label); ADD_TEST(test_RSA_verify_recover_rejects_short_buffer); - ADD_TEST(test_RSA_verify_recover_empty_payload); ADD_TEST(test_RSA_encrypt); #ifndef OPENSSL_NO_DEPRECATED_3_0 ADD_TEST(test_RSA_legacy); @@ -9321,7 +8525,6 @@ int setup_tests(void) #ifndef OPENSSL_NO_DEPRECATED_3_0 ADD_TEST(test_EVP_PKEY_set1_DH); #endif - ADD_TEST(test_dhx_derive_rejects_bad_peer_q); #endif #ifndef OPENSSL_NO_EC ADD_TEST(test_EC_priv_pub); @@ -9356,9 +8559,6 @@ int setup_tests(void) ADD_ALL_TESTS(test_evp_diff_order_init, cipher_list_n); ADD_ALL_TESTS(test_evp_stale_key_reinit, cipher_list_n); ADD_ALL_TESTS(test_evp_decrypt_roundtrip_multistep, cipher_list_n); - ADD_ALL_TESTS(test_evp_oneshot_aead_zerolen, cipher_list_n); - ADD_ALL_TESTS(test_evp_aead_tag_direction, cipher_list_n); - ADD_ALL_TESTS(test_evp_aead_late_aad, cipher_list_n); ADD_ALL_TESTS(test_evp_init_seq, OSSL_NELEM(evp_init_tests)); ADD_ALL_TESTS(test_evp_reset, OSSL_NELEM(evp_reset_tests)); @@ -9394,7 +8594,6 @@ int setup_tests(void) ADD_TEST(test_invalid_ctx_for_digest); ADD_TEST(test_evp_cipher_negative_length); - ADD_TEST(test_aes_xts_rejects_missing_iv); ADD_TEST(test_evp_cipher_pipeline); diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c index 6d4a55d11e..73093119e3 100644 --- a/test/evp_kdf_test.c +++ b/test/evp_kdf_test.c @@ -2097,73 +2097,6 @@ static int test_kdf_get_kdf(void) return ok; } -static int test_kdf_ctx_get_kdf(void) -{ - EVP_KDF *kdf = NULL; - const EVP_KDF *kdf_get0 = NULL; - EVP_KDF *kdf_get1 = NULL; - EVP_KDF_CTX *kctx = NULL; - int ok = 0; - - kdf = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_PBKDF2, NULL); - if (!TEST_ptr(kdf)) - goto out; - - kctx = EVP_KDF_CTX_new(kdf); - if (!TEST_ptr(kdf)) - goto out; - - kdf_get0 = EVP_KDF_CTX_get0_kdf(kctx); - if (!TEST_ptr_eq(kdf, kdf_get0)) - goto out; - - kdf_get1 = EVP_KDF_CTX_get1_kdf(kctx); - if (!TEST_ptr(kdf_get1) - || !TEST_true(EVP_KDF_is_a(kdf_get1, EVP_KDF_get0_name(kdf)))) - goto out; - - ok = 1; - -out: - EVP_KDF_free(kdf_get1); - EVP_KDF_CTX_free(kctx); - EVP_KDF_free(kdf); - - return ok; -} - -#if !defined(OPENSSL_NO_DEPRECATED_4_1) -static int test_kdf_ctx_kdf(void) -{ - EVP_KDF *kdf = NULL; - const EVP_KDF *kdf_get = NULL; - EVP_KDF_CTX *kctx = NULL; - int ok = 0; - - kdf = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_PBKDF2, NULL); - if (!TEST_ptr(kdf)) - goto out; - - kctx = EVP_KDF_CTX_new(kdf); - if (!TEST_ptr(kdf)) - goto out; - - OSSL_BEGIN_ALLOW_DEPRECATED - kdf_get = EVP_KDF_CTX_kdf(kctx); - OSSL_END_ALLOW_DEPRECATED - if (!TEST_ptr_eq(kdf, kdf_get)) - goto out; - - ok = 1; - -out: - EVP_KDF_CTX_free(kctx); - EVP_KDF_free(kdf); - - return ok; -} -#endif /* !OPENSSL_NO_DEPRECATED_4_1 */ - #if !defined(OPENSSL_NO_CMS) && !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_X942KDF) static int test_kdf_x942_asn1(void) { @@ -2433,10 +2366,6 @@ int setup_tests(void) ADD_TEST(test_kdf_kbkdf_kmac); #endif /* OPENSSL_NO_KBKDF */ ADD_TEST(test_kdf_get_kdf); - ADD_TEST(test_kdf_ctx_get_kdf); -#if !defined(OPENSSL_NO_DEPRECATED_4_1) - ADD_TEST(test_kdf_ctx_kdf); -#endif ADD_TEST(test_kdf_tls1_prf); ADD_TEST(test_kdf_tls1_prf_set_skey); ADD_TEST(test_kdf_tls1_prf_derive_skey); diff --git a/test/evp_test.c b/test/evp_test.c index 77029f40db..ef359a72ef 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -4151,7 +4151,7 @@ static int kdf_test_ctrl(EVP_TEST *t, EVP_KDF_CTX *kctx, KDF_DATA *kdata = t->data; int rv; char *p, *name; - const OSSL_PARAM *defs = EVP_KDF_settable_ctx_params(EVP_KDF_CTX_get0_kdf(kctx)); + const OSSL_PARAM *defs = EVP_KDF_settable_ctx_params(EVP_KDF_CTX_kdf(kctx)); if (!TEST_ptr(name = OPENSSL_strdup(value))) return 0; diff --git a/test/fake_cipherprov.c b/test/fake_cipherprov.c index ad28a6b94b..16fde61221 100644 --- a/test/fake_cipherprov.c +++ b/test/fake_cipherprov.c @@ -9,13 +9,13 @@ */ #include -#include #include #include #include #include #include #include +#include "testutil.h" #include "fake_cipherprov.h" #define MAX_KEYNAME 32 @@ -65,7 +65,7 @@ static void *fake_skeymgmt_import(void *provctx, int selection, const OSSL_PARAM { PROV_CIPHER_FAKE_CTX *ctx = NULL; - if ((ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX))) == NULL) + if (!TEST_ptr(ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX)))) return 0; if (ctx_from_key_params(ctx, p) != 1) { @@ -76,26 +76,6 @@ static void *fake_skeymgmt_import(void *provctx, int selection, const OSSL_PARAM return ctx; } -static void *fake_skeymgmt_generate(void *provctx, const OSSL_PARAM *params) -{ - PROV_CIPHER_FAKE_CTX *ctx = NULL; - size_t i; - - if ((ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX))) == NULL) - return NULL; - - if (ctx_from_key_params(ctx, params) != 1) { - OPENSSL_free(ctx); - return NULL; - } - - /* Deterministic fill so the provider doesn't depend on a DRBG. */ - for (i = 0; i < sizeof(ctx->key); i++) - ctx->key[i] = (unsigned char)i; - - return ctx; -} - static int fake_skeymgmt_export(void *keydata, int selection, OSSL_CALLBACK *param_callback, void *cbarg) { @@ -123,7 +103,6 @@ static int fake_skeymgmt_export(void *keydata, int selection, static const OSSL_DISPATCH fake_skeymgmt_funcs[] = { { OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))fake_skeymgmt_free }, - { OSSL_FUNC_SKEYMGMT_GENERATE, (void (*)(void))fake_skeymgmt_generate }, { OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))fake_skeymgmt_import }, { OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))fake_skeymgmt_export }, OSSL_DISPATCH_END @@ -329,29 +308,19 @@ static int fake_cipher_provider_init(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, const OSSL_DISPATCH **out, void **provctx) { - if ((*provctx = OSSL_LIB_CTX_new()) == NULL) + if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new())) return 0; *out = fake_cipher_method; return 1; } -#ifdef FAKE_CIPHER_AS_MODULE -/* Entry point when built as a loadable module (e.g. -provider fake-cipher). */ -int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, - const OSSL_DISPATCH *in, - const OSSL_DISPATCH **out, void **provctx) -{ - return fake_cipher_provider_init(handle, in, out, provctx); -} -#endif - OSSL_PROVIDER *fake_cipher_start(OSSL_LIB_CTX *libctx) { OSSL_PROVIDER *p; - if (!OSSL_PROVIDER_add_builtin(libctx, FAKE_PROV_NAME, - fake_cipher_provider_init) - || (p = OSSL_PROVIDER_try_load(libctx, FAKE_PROV_NAME, 1)) == NULL) + if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, FAKE_PROV_NAME, + fake_cipher_provider_init)) + || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, FAKE_PROV_NAME, 1))) return NULL; return p; diff --git a/test/fn_api_test.c b/test/fn_api_test.c new file mode 100644 index 0000000000..8dcddd7b8d --- /dev/null +++ b/test/fn_api_test.c @@ -0,0 +1,3598 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * @file API tests of OSSL_FN + * + * This tests the OSSL_FN "public" API, i.e. anything that only requires + * including crypto/fn.h. including crypto/fn_intern.h is included too, + * for introspection. + */ + +#include +#include +#include "crypto/fn.h" +#include "crypto/fn_intern.h" +#include "crypto/fnerr.h" +#include "testutil.h" + +/* + * Helper to pollute a number before writing to it. + * This is a destructive function, use with care! + */ +static int pollute(OSSL_FN *f, size_t start, size_t end) +{ + /* Constness deliberately violated here */ + OSSL_FN_ULONG *u = (OSSL_FN_ULONG *)ossl_fn_get_words(f); + size_t l = ossl_fn_get_dsize(f); + + if (end > l) + end = l; + if (start > end) + start = end; + + unsigned char tmp_char; + (void)RAND_bytes(&tmp_char, 1); + memset(u + start, tmp_char, sizeof(OSSL_FN_ULONG) * (end - start)); + return 1; +} + +static int check_limbs_value(const OSSL_FN *f, size_t start, size_t end, + OSSL_FN_ULONG value) +{ + const OSSL_FN_ULONG *u = ossl_fn_get_words(f); + size_t l = ossl_fn_get_dsize(f); + + if (end > l) + end = l; + if (start > end) + start = end; + + for (size_t i = start; i < end; i++) + if (!TEST_size_t_eq(u[i], value)) { + TEST_note("start = %zu, end = %zu, i = %zu\n", start, end, i); + return 0; + } + return 1; +} + +/* A set of numbers on OSSL_FN_ULONG array form */ +/* $num0 = 0x8000000000000001 */ +static const OSSL_FN_ULONG num0[] = { OSSL_FN_ULONG64_C(0x80000000, 0x00000001) }; +/* $num1 = 0x0000000180000000 */ +static const OSSL_FN_ULONG num1[] = { OSSL_FN_ULONG64_C(0x00000001, 0x80000000) }; +/* $num2 = 0x0123456789abcdef */ +static const OSSL_FN_ULONG num2[] = { OSSL_FN_ULONG64_C(0x01234567, 0x89abcdef) }; +/* $num3 = 0x76543210fedcba98 */ +static const OSSL_FN_ULONG num3[] = { OSSL_FN_ULONG64_C(0xfedcba98, 0x76543210) }; + +/* Numbers for edge cases */ +/* $num4 = 0x0000000000000000 */ +static const OSSL_FN_ULONG num4[] = { OSSL_FN_ULONG64_C(0x00000000, 0x00000000) }; +/* $num5 = 0xffffffffffffffff */ +static const OSSL_FN_ULONG num5[] = { OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff) }; +/* $num6 = 0x10000000000000000000000000000000 */ +static const OSSL_FN_ULONG num6[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x10000000, 0x00000000), +}; +/* [32-bit] $num7 = 0xffffffff00000000000000000000000000000000 */ +/* [64-bit] $num7 = 0xffffffffffffffff00000000000000000000000000000000 */ +static const OSSL_FN_ULONG num7[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +#if OSSL_FN_BYTES == 4 + OSSL_FN_ULONG_C(0xffffffff) +#elif OSSL_FN_BYTES == 8 + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff) +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +}; +static const OSSL_FN_ULONG num8[] = { + OSSL_FN_ULONG64_C(0x01234567, 0x89abcdef), + OSSL_FN_ULONG_C(0x00000001), +}; + +/* + * For each test function using predefined numbers, set up an + * arrays of test cases to simply run through, and call common + * test function for the operation being tested. + * + * All sizes are in number of limbs, the LIMBSOF() macro is there to help + */ +#define LIMBSOF(num) ((sizeof(num) + OSSL_FN_BYTES - 1) / OSSL_FN_BYTES) +#define OSSL_FN_BITS (OSSL_FN_BYTES * 8) +struct test_case_st { + /* Two operands and expected full result (possibly two numbers) */ + const OSSL_FN_ULONG *op1; + size_t op1_size; + const OSSL_FN_ULONG *op2; + size_t op2_size; + const OSSL_FN_ULONG *ex1; + size_t ex1_size; + const OSSL_FN_ULONG *ex2; + size_t ex2_size; + + /* Setup sizes for creating OSSL_FNs */ + size_t op1_live_size; + size_t op2_live_size; + size_t res1_live_size; + size_t res2_live_size; + + /* Number of limbs to compare the result's OSSL_FN_ULONG array against ex1 and ex2 */ + size_t check1_size; + size_t check2_size; + + /* When the result is larger than check1_size or check2_size, the expected extended value */ + OSSL_FN_ULONG extended_limb_value1; + OSSL_FN_ULONG extended_limb_value2; +#define EXTENDED_LIMB_ZERO ((OSSL_FN_ULONG)0) +#define EXTENDED_LIMB_MINUS_ONE ((OSSL_FN_ULONG)-1) +}; + +struct mod_op_test_st { + const OSSL_FN_ULONG *a; + size_t a_size; + const OSSL_FN_ULONG *b; + size_t b_size; + const OSSL_FN_ULONG *m; + size_t m_size; + int n; +}; + +/* $num0 + $num0 == 0x10000000000000002 */ +static const OSSL_FN_ULONG ex_add_num0_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000002), + OSSL_FN_ULONG_C(0x1), +}; +/* $num0 + $num1 == 0x8000000180000001 */ +static const OSSL_FN_ULONG ex_add_num0_num1[] = { + OSSL_FN_ULONG64_C(0x80000001, 0x80000001), +}; +/* $num0 + $num2 == 0x8123456789abcdf0 */ +static const OSSL_FN_ULONG ex_add_num0_num2[] = { + OSSL_FN_ULONG64_C(0x81234567, 0x89abcdf0), +}; +/* $num0 + $num3 == 0x17edcba9876543211 */ +static const OSSL_FN_ULONG ex_add_num0_num3[] = { + OSSL_FN_ULONG64_C(0x7edcba98, 0x76543211), + OSSL_FN_ULONG_C(0x1), +}; +static const OSSL_FN_ULONG ex_add_num1_num1[] = { + OSSL_FN_ULONG64_C(0x00000003, 0x00000000), +}; +static const OSSL_FN_ULONG ex_add_num1_num2[] = { + OSSL_FN_ULONG64_C(0x01234569, 0x09abcdef), +}; +static const OSSL_FN_ULONG ex_add_num1_num3[] = { + OSSL_FN_ULONG64_C(0xfedcba99, 0xf6543210), +}; +static const OSSL_FN_ULONG ex_add_num2_num2[] = { + OSSL_FN_ULONG64_C(0x02468acf, 0x13579bde), +}; +static const OSSL_FN_ULONG ex_add_num2_num3[] = { + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +}; +static const OSSL_FN_ULONG ex_add_num3_num3[] = { + OSSL_FN_ULONG64_C(0xfdb97530, 0xeca86420), + OSSL_FN_ULONG_C(0x1), +}; +static const OSSL_FN_ULONG ex_add_num0_num7[] = { + OSSL_FN_ULONG64_C(0x80000000, 0x00000001), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +#if OSSL_FN_BYTES == 4 + OSSL_FN_ULONG_C(0xffffffff) +#elif OSSL_FN_BYTES == 8 + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff) +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +}; + +static int test_add_common(struct test_case_st test_case) +{ + const OSSL_FN_ULONG *n1 = test_case.op1; + size_t n1_limbs = test_case.op1_size; + const OSSL_FN_ULONG *n2 = test_case.op2; + size_t n2_limbs = test_case.op2_size; + const OSSL_FN_ULONG *ex = test_case.ex1; + size_t n1_new_limbs = test_case.op1_live_size; + size_t n2_new_limbs = test_case.op2_live_size; + size_t res_limbs = test_case.res1_live_size; + size_t check_limbs = test_case.check1_size; + OSSL_FN_ULONG extended_value = test_case.extended_limb_value1; + int ret = 1; + OSSL_FN *fn1 = NULL, *fn2 = NULL, *res = NULL; + const OSSL_FN_ULONG *u = NULL; + + /* To test that OSSL_FN_add() does a complete job, 'res' is pre-polluted */ + + if (!TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs)) + || !TEST_ptr(fn2 = OSSL_FN_new_limbs(n2_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs)) + || !TEST_true(ossl_fn_set_words(fn2, n2, n2_limbs)) + || !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs)) + || !TEST_true(pollute(res, 0, res_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + if (!TEST_true(OSSL_FN_add(res, fn1, fn2)) + || !TEST_ptr(u = ossl_fn_get_words(res)) + || !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES, + ex, check_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(res, check_limbs, res_limbs, + extended_value))) + ret = 0; + +end: + OSSL_FN_free(fn1); + OSSL_FN_free(fn2); + OSSL_FN_free(res); + + return ret; +} + +#define ADD_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) + 3, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex), \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_add_cases[] = { + ADD_CASE(1, num0, num0, ex_add_num0_num0), + ADD_CASE(2, num0, num1, ex_add_num0_num1), + ADD_CASE(3, num0, num2, ex_add_num0_num2), + ADD_CASE(4, num0, num3, ex_add_num0_num3), + ADD_CASE(5, num1, num0, ex_add_num0_num1), /* Commutativity check */ + ADD_CASE(6, num1, num1, ex_add_num1_num1), + ADD_CASE(7, num1, num2, ex_add_num1_num2), + ADD_CASE(8, num1, num3, ex_add_num1_num3), + ADD_CASE(9, num2, num0, ex_add_num0_num2), /* Commutativity check */ + ADD_CASE(10, num2, num1, ex_add_num1_num2), /* Commutativity check */ + ADD_CASE(11, num2, num2, ex_add_num2_num2), + ADD_CASE(12, num2, num3, ex_add_num2_num3), + ADD_CASE(13, num3, num0, ex_add_num0_num3), /* Commutativity check */ + ADD_CASE(14, num3, num1, ex_add_num1_num3), /* Commutativity check */ + ADD_CASE(15, num3, num2, ex_add_num2_num3), /* Commutativity check */ + ADD_CASE(16, num3, num3, ex_add_num3_num3), + ADD_CASE(17, num0, num7, ex_add_num0_num7), +}; + +static int test_add(int i) +{ + return test_add_common(test_add_cases[i]); +} + +#define ADD_TRUNCATED_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) - 1, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) - 1, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_add_truncated_cases[] = { + ADD_TRUNCATED_CASE(1, num0, num0, ex_add_num0_num0), + ADD_TRUNCATED_CASE(2, num0, num1, ex_add_num0_num1), + ADD_TRUNCATED_CASE(3, num0, num2, ex_add_num0_num2), + ADD_TRUNCATED_CASE(4, num0, num3, ex_add_num0_num3), + ADD_TRUNCATED_CASE(5, num1, num0, ex_add_num0_num1), /* Commutativity check */ + ADD_TRUNCATED_CASE(6, num1, num1, ex_add_num1_num1), + ADD_TRUNCATED_CASE(7, num1, num2, ex_add_num1_num2), + ADD_TRUNCATED_CASE(8, num1, num3, ex_add_num1_num3), + ADD_TRUNCATED_CASE(9, num2, num0, ex_add_num0_num2), /* Commutativity check */ + ADD_TRUNCATED_CASE(10, num2, num1, ex_add_num1_num2), /* Commutativity check */ + ADD_TRUNCATED_CASE(11, num2, num2, ex_add_num2_num2), + ADD_TRUNCATED_CASE(12, num2, num3, ex_add_num2_num3), + ADD_TRUNCATED_CASE(13, num3, num0, ex_add_num0_num3), /* Commutativity check */ + ADD_TRUNCATED_CASE(14, num3, num1, ex_add_num1_num3), /* Commutativity check */ + ADD_TRUNCATED_CASE(15, num3, num2, ex_add_num2_num3), /* Commutativity check */ + ADD_TRUNCATED_CASE(16, num3, num3, ex_add_num3_num3), + ADD_TRUNCATED_CASE(17, num0, num7, ex_add_num0_num7), +}; + +static int test_add_truncated(int i) +{ + return test_add_common(test_add_truncated_cases[i]); +} + +static const OSSL_FN_ULONG ex_sub_num0_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +static const OSSL_FN_ULONG ex_sub_num0_num1[] = { + OSSL_FN_ULONG64_C(0x7ffffffe, 0x80000001), +}; +static const OSSL_FN_ULONG ex_sub_num0_num2[] = { + OSSL_FN_ULONG64_C(0x7edcba98, 0x76543212), +}; +static const OSSL_FN_ULONG ex_sub_num0_num3[] = { + OSSL_FN_ULONG64_C(0x81234567, 0x89abcdf1), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff) +}; +static const OSSL_FN_ULONG ex_sub_num1_num0[] = { + OSSL_FN_ULONG64_C(0x80000001, 0x7fffffff), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +}; +static const OSSL_FN_ULONG ex_sub_num1_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +static const OSSL_FN_ULONG ex_sub_num1_num2[] = { + OSSL_FN_ULONG64_C(0xfedcba99, 0xf6543211), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +}; +static const OSSL_FN_ULONG ex_sub_num1_num3[] = { + OSSL_FN_ULONG64_C(0x01234569, 0x09abcdf0), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +}; +static const OSSL_FN_ULONG ex_sub_num2_num0[] = { + OSSL_FN_ULONG64_C(0x81234567, 0x89abcdee), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +}; +static const OSSL_FN_ULONG ex_sub_num2_num1[] = { + OSSL_FN_ULONG64_C(0x01234566, 0x09abcdef), +}; +static const OSSL_FN_ULONG ex_sub_num2_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +static const OSSL_FN_ULONG ex_sub_num2_num3[] = { + OSSL_FN_ULONG64_C(0x02468acf, 0x13579bdf), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +}; +static const OSSL_FN_ULONG ex_sub_num3_num0[] = { + OSSL_FN_ULONG64_C(0x7edcba98, 0x7654320f), +}; +static const OSSL_FN_ULONG ex_sub_num3_num1[] = { + OSSL_FN_ULONG64_C(0xfedcba96, 0xf6543210), +}; +static const OSSL_FN_ULONG ex_sub_num3_num2[] = { + OSSL_FN_ULONG64_C(0xfdb97530, 0xeca86421), +}; +static const OSSL_FN_ULONG ex_sub_num3_num3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +static const OSSL_FN_ULONG ex_sub_num0_num7[] = { + OSSL_FN_ULONG64_C(0x80000000, 0x00000001), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG_C(0x1), +}; +static const OSSL_FN_ULONG ex_sub_num7_num0[] = { + OSSL_FN_ULONG64_C(0x7fffffff, 0xffffffff), + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), +#if OSSL_FN_BYTES == 4 + OSSL_FN_ULONG_C(0xfffffffe) +#elif OSSL_FN_BYTES == 8 + OSSL_FN_ULONG64_C(0xffffffff, 0xfffffffe) +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +}; + +/* $num2 << 1 == 0x02468acf13579bde */ +static const OSSL_FN_ULONG ex_lshift1_num2[] = { + OSSL_FN_ULONG64_C(0x02468acf, 0x13579bde), +}; +/* $num0 << 1 == 0x10000000000000002 */ +static const OSSL_FN_ULONG ex_lshift1_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000002), + OSSL_FN_ULONG_C(0x1), +}; +/* $num2 << 4 == 0x123456789abcdef0 */ +static const OSSL_FN_ULONG ex_lshift_num2_4[] = { + OSSL_FN_ULONG64_C(0x12345678, 0x9abcdef0), +}; +#if OSSL_FN_BYTES == 4 +/* $num2 << 32 == 0x0123456789abcdef00000000 */ +static const OSSL_FN_ULONG ex_lshift_num2_limb[] = { + OSSL_FN_ULONG_C(0x00000000), + OSSL_FN_ULONG_C(0x89abcdef), + OSSL_FN_ULONG_C(0x01234567), +}; +#elif OSSL_FN_BYTES == 8 +/* $num2 << 64 == 0x0123456789abcdef0000000000000000 */ +static const OSSL_FN_ULONG ex_lshift_num2_limb[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x01234567, 0x89abcdef), +}; +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +#if OSSL_FN_BYTES == 4 +/* $num2 << 35 == 0x091a2b3c4d5e6f7800000000 */ +static const OSSL_FN_ULONG ex_lshift_num2_limb_3[] = { + OSSL_FN_ULONG_C(0x00000000), + OSSL_FN_ULONG_C(0x4d5e6f78), + OSSL_FN_ULONG_C(0x091a2b3c), +}; +#elif OSSL_FN_BYTES == 8 +/* $num2 << 67 == 0x091a2b3c4d5e6f780000000000000000 */ +static const OSSL_FN_ULONG ex_lshift_num2_limb_3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x091a2b3c, 0x4d5e6f78), +}; +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif + +/* $num2 >> 1 == 0x0091a2b3c4d5e6f7 */ +static const OSSL_FN_ULONG ex_rshift1_num2[] = { + OSSL_FN_ULONG64_C(0x0091a2b3, 0xc4d5e6f7), +}; +/* $num8 >> 1 == 0x000000008091a2b3c4d5e6f7 */ +static const OSSL_FN_ULONG ex_rshift1_num8[] = { + OSSL_FN_ULONG64_C(0x8091a2b3, 0xc4d5e6f7), +}; +/* $num2 >> 4 == 0x00123456789abcde */ +static const OSSL_FN_ULONG ex_rshift_num2_4[] = { + OSSL_FN_ULONG64_C(0x00123456, 0x789abcde), +}; +#if OSSL_FN_BYTES == 4 +/* $num8 >> 32 == 0x0000000101234567 */ +static const OSSL_FN_ULONG ex_rshift_num8_limb[] = { + OSSL_FN_ULONG_C(0x01234567), + OSSL_FN_ULONG_C(0x00000001), +}; +#elif OSSL_FN_BYTES == 8 +/* $num8 >> 64 == 0x0000000000000001 */ +static const OSSL_FN_ULONG ex_rshift_num8_limb[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +#if OSSL_FN_BYTES == 4 +/* $num8 >> 35 == 0x00000000202468ac */ +static const OSSL_FN_ULONG ex_rshift_num8_limb_3[] = { + OSSL_FN_ULONG_C(0x202468ac), +}; +#elif OSSL_FN_BYTES == 8 +/* $num8 >> 67 == 0x0000000000000000 */ +static const OSSL_FN_ULONG ex_rshift_num8_limb_3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +#if OSSL_FN_BYTES == 4 +/* $num2 >> 32 == 0x01234567 */ +static const OSSL_FN_ULONG ex_rshift_num2_limb[] = { + OSSL_FN_ULONG_C(0x01234567), + OSSL_FN_ULONG_C(0x00000000), +}; +#elif OSSL_FN_BYTES == 8 +/* $num2 >> 64 == 0x0000000000000000 */ +static const OSSL_FN_ULONG ex_rshift_num2_limb[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif +/* Expected all-zero result for shifts beyond the operand's width. */ +static const OSSL_FN_ULONG ex_rshift_zero[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; + +static int test_sub_common(struct test_case_st test_case) +{ + const OSSL_FN_ULONG *n1 = test_case.op1; + size_t n1_limbs = test_case.op1_size; + const OSSL_FN_ULONG *n2 = test_case.op2; + size_t n2_limbs = test_case.op2_size; + const OSSL_FN_ULONG *ex = test_case.ex1; + size_t n1_new_limbs = test_case.op1_live_size; + size_t n2_new_limbs = test_case.op2_live_size; + size_t res_limbs = test_case.res1_live_size; + size_t check_limbs = test_case.check1_size; + OSSL_FN_ULONG extended_value = test_case.extended_limb_value1; + int ret = 1; + OSSL_FN *fn1 = NULL, *fn2 = NULL, *res = NULL; + const OSSL_FN_ULONG *u = NULL; + + /* To test that OSSL_FN_sub() does a complete job, 'res' is pre-polluted */ + + if (!TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs)) + || !TEST_ptr(fn2 = OSSL_FN_new_limbs(n2_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs)) + || !TEST_true(ossl_fn_set_words(fn2, n2, n2_limbs)) + || !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs)) + || !TEST_true(pollute(res, 0, res_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + if (!TEST_true(OSSL_FN_sub(res, fn1, fn2)) + || !TEST_ptr(u = ossl_fn_get_words(res)) + || !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES, + ex, check_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(res, check_limbs, res_limbs, + extended_value))) + ret = 0; + +end: + OSSL_FN_free(fn1); + OSSL_FN_free(fn2); + OSSL_FN_free(res); + + return ret; +} + +#define SUB_CASE(i, op1, op2, ex, ext) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) + 3, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex), \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ (ext), \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_sub_cases[] = { + SUB_CASE(1, num0, num0, ex_sub_num0_num0, EXTENDED_LIMB_ZERO), + SUB_CASE(2, num0, num1, ex_sub_num0_num1, EXTENDED_LIMB_ZERO), + SUB_CASE(3, num0, num2, ex_sub_num0_num2, EXTENDED_LIMB_ZERO), + SUB_CASE(4, num0, num3, ex_sub_num0_num3, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(5, num1, num0, ex_sub_num1_num0, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(6, num1, num1, ex_sub_num1_num1, EXTENDED_LIMB_ZERO), + SUB_CASE(7, num1, num2, ex_sub_num1_num2, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(8, num1, num3, ex_sub_num1_num3, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(9, num2, num0, ex_sub_num2_num0, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(10, num2, num1, ex_sub_num2_num1, EXTENDED_LIMB_ZERO), + SUB_CASE(11, num2, num2, ex_sub_num2_num2, EXTENDED_LIMB_ZERO), + SUB_CASE(12, num2, num3, ex_sub_num2_num3, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(13, num3, num0, ex_sub_num3_num0, EXTENDED_LIMB_ZERO), + SUB_CASE(14, num3, num1, ex_sub_num3_num1, EXTENDED_LIMB_ZERO), + SUB_CASE(15, num3, num2, ex_sub_num3_num2, EXTENDED_LIMB_ZERO), + SUB_CASE(16, num3, num3, ex_sub_num3_num3, EXTENDED_LIMB_ZERO), + SUB_CASE(17, num0, num7, ex_sub_num0_num7, EXTENDED_LIMB_MINUS_ONE), + SUB_CASE(18, num7, num0, ex_sub_num7_num0, EXTENDED_LIMB_ZERO), +}; + +static int test_sub(int i) +{ + return test_sub_common(test_sub_cases[i]); +} + +#define SUB_TRUNCATED_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) - 1, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) - 1, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_sub_truncated_cases[] = { + SUB_TRUNCATED_CASE(1, num0, num0, ex_sub_num0_num0), + SUB_TRUNCATED_CASE(2, num0, num1, ex_sub_num0_num1), + SUB_TRUNCATED_CASE(3, num0, num2, ex_sub_num0_num2), + SUB_TRUNCATED_CASE(4, num0, num3, ex_sub_num0_num3), + SUB_TRUNCATED_CASE(5, num1, num0, ex_sub_num1_num0), + SUB_TRUNCATED_CASE(6, num1, num1, ex_sub_num1_num1), + SUB_TRUNCATED_CASE(7, num1, num2, ex_sub_num1_num2), + SUB_TRUNCATED_CASE(8, num1, num3, ex_sub_num1_num3), + SUB_TRUNCATED_CASE(9, num2, num0, ex_sub_num2_num0), + SUB_TRUNCATED_CASE(10, num2, num1, ex_sub_num2_num1), + SUB_TRUNCATED_CASE(11, num2, num2, ex_sub_num2_num2), + SUB_TRUNCATED_CASE(12, num2, num3, ex_sub_num2_num3), + SUB_TRUNCATED_CASE(13, num3, num0, ex_sub_num3_num0), + SUB_TRUNCATED_CASE(14, num3, num1, ex_sub_num3_num1), + SUB_TRUNCATED_CASE(15, num3, num2, ex_sub_num3_num2), + SUB_TRUNCATED_CASE(16, num3, num3, ex_sub_num3_num3), + SUB_TRUNCATED_CASE(17, num0, num7, ex_sub_num0_num7), + SUB_TRUNCATED_CASE(18, num7, num0, ex_sub_num7_num0), +}; + +static int test_sub_truncated(int i) +{ + return test_sub_common(test_sub_truncated_cases[i]); +} + +static int test_num_bits(void) +{ + int ret = 0; + OSSL_FN *zero = NULL, *fn1 = NULL, *fn2 = NULL, *wide = NULL; + + if (!TEST_ptr(zero = OSSL_FN_new_limbs(2)) + || !TEST_ptr(fn1 = OSSL_FN_new_limbs(2)) + || !TEST_ptr(fn2 = OSSL_FN_new_limbs(2)) + || !TEST_ptr(wide = OSSL_FN_new_limbs(4)) + || !TEST_true(ossl_fn_set_words(fn1, num1, LIMBSOF(num1))) + || !TEST_true(ossl_fn_set_words(fn2, num2, LIMBSOF(num2))) + || !TEST_true(ossl_fn_set_words(wide, num8, LIMBSOF(num8)))) + goto err; + + if (!TEST_size_t_eq(OSSL_FN_num_bits(zero), 0) + || !TEST_size_t_eq(OSSL_FN_num_bits(fn1), 33) + || !TEST_size_t_eq(OSSL_FN_num_bits(fn2), 57) + || !TEST_size_t_eq(OSSL_FN_num_bits(wide), 65)) + goto err; + + ret = 1; +err: + OSSL_FN_free(zero); + OSSL_FN_free(fn1); + OSSL_FN_free(fn2); + OSSL_FN_free(wide); + return ret; +} + +static int test_cmp(void) +{ + int ret = 0; + OSSL_FN *zero = NULL, *fn1 = NULL, *fn1_wide = NULL, *fn2 = NULL; + OSSL_FN *fn2_wide = NULL; + + if (!TEST_ptr(zero = OSSL_FN_new_limbs(2)) + || !TEST_ptr(fn1 = OSSL_FN_new_limbs(2)) + || !TEST_ptr(fn1_wide = OSSL_FN_new_limbs(4)) + || !TEST_ptr(fn2 = OSSL_FN_new_limbs(2)) + || !TEST_ptr(fn2_wide = OSSL_FN_new_limbs(4)) + || !TEST_true(ossl_fn_set_words(fn1, num1, LIMBSOF(num1))) + || !TEST_true(ossl_fn_set_words(fn1_wide, num1, LIMBSOF(num1))) + || !TEST_true(ossl_fn_set_words(fn2, num2, LIMBSOF(num2))) + || !TEST_true(ossl_fn_set_words(fn2_wide, num2, LIMBSOF(num2)))) + goto err; + + if (!TEST_int_eq(OSSL_FN_cmp(zero, zero), 0) + || !TEST_int_eq(OSSL_FN_cmp(fn2, fn2_wide), 0) + || !TEST_int_eq(OSSL_FN_cmp(fn2_wide, fn2), 0) + || !TEST_int_eq(OSSL_FN_cmp(fn2, fn1), 1) + || !TEST_int_eq(OSSL_FN_cmp(fn1, fn2), -1) + || !TEST_int_eq(OSSL_FN_cmp(fn2_wide, fn1), 1) + || !TEST_int_eq(OSSL_FN_cmp(fn1, fn2_wide), -1) + || !TEST_int_eq(OSSL_FN_cmp(fn2, fn1_wide), 1) + || !TEST_int_eq(OSSL_FN_cmp(fn1_wide, fn2), -1) + || !TEST_int_eq(OSSL_FN_cmp(zero, fn1), -1) + || !TEST_int_eq(OSSL_FN_cmp(fn1, zero), 1)) + goto err; + + ret = 1; +err: + OSSL_FN_free(zero); + OSSL_FN_free(fn1); + OSSL_FN_free(fn1_wide); + OSSL_FN_free(fn2); + OSSL_FN_free(fn2_wide); + return ret; +} + +/*- + * Focused tests for the OSSL_FN introspection predicates: is_word, is_zero, + * is_one, is_odd. Covers plain values, fixed-top zero-padding (a value + * whose high limbs are zero limbs by dsize rather than by trimming), and the + * dsize == 0 (zero-limb) degenerate case. + */ +static int test_introspection(void) +{ + int ret = 0; + OSSL_FN *z = NULL; /* dsize 2, value 0 */ + OSSL_FN *z_wide = NULL; /* dsize 4, value 0 (fixed-top zero padding) */ + OSSL_FN *z_empty = NULL; /* dsize 0, value 0 */ + OSSL_FN *one = NULL; /* dsize 2, value 1 */ + OSSL_FN *one_wide = NULL; /* dsize 4, value 1 (fixed-top zero padding) */ + OSSL_FN *w5 = NULL; /* dsize 2, value 5 */ + OSSL_FN *w5_wide = NULL; /* dsize 4, value 5 (fixed-top zero padding) */ + OSSL_FN *even = NULL; /* dsize 2, value 0x...76543210 (even) */ + OSSL_FN *odd = NULL; /* dsize 2, value 0x...01234567 (odd) */ + OSSL_FN *two_limbs = NULL; /* dsize 2, value 0x...76543210 fedcba98 (nonzero high limb) */ + OSSL_FN_ULONG one_word = OSSL_FN_ULONG_C(1); + OSSL_FN_ULONG five_word = OSSL_FN_ULONG_C(5); + OSSL_FN_ULONG even_word = OSSL_FN_ULONG_C(0x76543210); + OSSL_FN_ULONG odd_word = OSSL_FN_ULONG_C(0x01234567); + const OSSL_FN_ULONG two_limbs_words[] = { + OSSL_FN_ULONG_C(0x76543210), + OSSL_FN_ULONG_C(0xfedcba98) + }; + + if (!TEST_ptr(z = OSSL_FN_new_limbs(2)) + || !TEST_ptr(z_wide = OSSL_FN_new_limbs(4)) + || !TEST_ptr(z_empty = OSSL_FN_new_limbs(0)) + || !TEST_ptr(one = OSSL_FN_new_limbs(2)) + || !TEST_ptr(one_wide = OSSL_FN_new_limbs(4)) + || !TEST_ptr(w5 = OSSL_FN_new_limbs(2)) + || !TEST_ptr(w5_wide = OSSL_FN_new_limbs(4)) + || !TEST_ptr(even = OSSL_FN_new_limbs(2)) + || !TEST_ptr(odd = OSSL_FN_new_limbs(2)) + || !TEST_ptr(two_limbs = OSSL_FN_new_limbs(2))) + goto err; + + /* All fresh allocations are zero-initialised, so z, z_wide, z_empty are 0. */ + if (!TEST_true(ossl_fn_set_words(one, &one_word, 1)) + || !TEST_true(ossl_fn_set_words(one_wide, &one_word, 1)) + || !TEST_true(ossl_fn_set_words(w5, &five_word, 1)) + || !TEST_true(ossl_fn_set_words(w5_wide, &five_word, 1)) + || !TEST_true(ossl_fn_set_words(even, &even_word, 1)) + || !TEST_true(ossl_fn_set_words(odd, &odd_word, 1)) + || !TEST_true(ossl_fn_set_words(two_limbs, two_limbs_words, + LIMBSOF(two_limbs_words)))) + goto err; + + /* OSSL_FN_is_zero */ + if (!TEST_int_eq(OSSL_FN_is_zero(z), 1) + || !TEST_int_eq(OSSL_FN_is_zero(z_wide), 1) /* fixed-top zero padding */ + || !TEST_int_eq(OSSL_FN_is_zero(z_empty), 1) /* dsize == 0 */ + || !TEST_int_eq(OSSL_FN_is_zero(one), 0) + || !TEST_int_eq(OSSL_FN_is_zero(w5_wide), 0)) + goto err; + + /* OSSL_FN_is_one */ + if (!TEST_int_eq(OSSL_FN_is_one(one), 1) + || !TEST_int_eq(OSSL_FN_is_one(one_wide), 1) /* fixed-top zero padding */ + || !TEST_int_eq(OSSL_FN_is_one(z), 0) + || !TEST_int_eq(OSSL_FN_is_one(w5), 0) + || !TEST_int_eq(OSSL_FN_is_one(z_empty), 0)) + goto err; + + /* OSSL_FN_is_word -- value equality against a single-limb word */ + if (!TEST_int_eq(OSSL_FN_is_word(z, 0), 1) + || !TEST_int_eq(OSSL_FN_is_word(z_wide, 0), 1) /* fixed-top zero padding */ + || !TEST_int_eq(OSSL_FN_is_word(z_empty, 0), 1) + || !TEST_int_eq(OSSL_FN_is_word(z, 1), 0) + || !TEST_int_eq(OSSL_FN_is_word(one, 1), 1) + || !TEST_int_eq(OSSL_FN_is_word(one_wide, 1), 1) /* fixed-top zero padding */ + || !TEST_int_eq(OSSL_FN_is_word(one, 0), 0) + || !TEST_int_eq(OSSL_FN_is_word(w5, 5), 1) + || !TEST_int_eq(OSSL_FN_is_word(w5_wide, 5), 1) /* fixed-top zero padding */ + || !TEST_int_eq(OSSL_FN_is_word(w5, 1), 0) + /* A value whose high limb is nonzero is not equal to a single word. */ + || !TEST_int_eq(OSSL_FN_is_word(two_limbs, even_word), 0) + || !TEST_int_eq(OSSL_FN_is_word(two_limbs, 0), 0)) + goto err; + + /* OSSL_FN_is_odd */ + if (!TEST_int_eq(OSSL_FN_is_odd(one), 1) + || !TEST_int_eq(OSSL_FN_is_odd(odd), 1) + || !TEST_int_eq(OSSL_FN_is_odd(w5), 1) + || !TEST_int_eq(OSSL_FN_is_odd(z), 0) + || !TEST_int_eq(OSSL_FN_is_odd(z_wide), 0) + || !TEST_int_eq(OSSL_FN_is_odd(z_empty), 0) + || !TEST_int_eq(OSSL_FN_is_odd(even), 0)) + goto err; + + ret = 1; +err: + OSSL_FN_free(z); + OSSL_FN_free(z_wide); + OSSL_FN_free(z_empty); + OSSL_FN_free(one); + OSSL_FN_free(one_wide); + OSSL_FN_free(w5); + OSSL_FN_free(w5_wide); + OSSL_FN_free(even); + OSSL_FN_free(odd); + OSSL_FN_free(two_limbs); + return ret; +} + +/*- + * Focused tests for OSSL_FN_add_word() / OSSL_FN_sub_word(). Each case is + * cross-checked against OSSL_FN_add() / OSSL_FN_sub() with a single-limb + * operand, an independent oracle that exercises the exact fixed-size + * truncation / 2's-complement semantics the word variants must match. + * + * OSSL_FN_add_word()/OSSL_FN_sub_word() take the word by value; the earlier + * pointer-typed declaration had no implementation and no callers, and is + * corrected together with the implementation landing here. + */ +struct word_op_case_st { + const OSSL_FN_ULONG *a_words; + size_t a_limbs; /* significant limbs of a */ + size_t a_dsize; /* allocated dsize (>= a_limbs; exercises padding) */ + OSSL_FN_ULONG w; +}; + +static const OSSL_FN_ULONG w_zero[] = { OSSL_FN_ULONG_C(0) }; +static const OSSL_FN_ULONG w_5[] = { OSSL_FN_ULONG_C(5) }; +static const OSSL_FN_ULONG w_01234567[] = { OSSL_FN_ULONG_C(0x01234567) }; +static const OSSL_FN_ULONG w_FFFFFFFF[] = { OSSL_FN_ULONG_C(0xffffffff) }; +static const OSSL_FN_ULONG w_FFFFFFFE[] = { OSSL_FN_ULONG_C(0xfffffffe) }; +static const OSSL_FN_ULONG w_7FFFFFFF[] = { OSSL_FN_ULONG_C(0x7fffffff) }; +static const OSSL_FN_ULONG w_0_1[] = { OSSL_FN_ULONG_C(0), OSSL_FN_ULONG_C(1) }; +static const OSSL_FN_ULONG w_0_0[] = { OSSL_FN_ULONG_C(0), OSSL_FN_ULONG_C(0) }; +static const OSSL_FN_ULONG w_FF_FF[] = { OSSL_FN_ULONG_C(0xffffffff), + OSSL_FN_ULONG_C(0xffffffff) }; +static const OSSL_FN_ULONG w_FE_FF[] = { OSSL_FN_ULONG_C(0xfffffffe), + OSSL_FN_ULONG_C(0xffffffff) }; +static const OSSL_FN_ULONG w_67_89[] = { OSSL_FN_ULONG_C(0x01234567), + OSSL_FN_ULONG_C(0x89abcdef) }; + +static const struct word_op_case_st add_word_cases[] = { + { w_zero, 1, 2, OSSL_FN_ULONG_C(5) }, /* a == 0 */ + { w_01234567, 1, 2, OSSL_FN_ULONG_C(1) }, /* no carry */ + { w_FFFFFFFF, 1, 2, OSSL_FN_ULONG_C(1) }, /* carry into next limb */ + { w_FF_FF, 2, 2, OSSL_FN_ULONG_C(1) }, /* carry out truncated */ + { w_FE_FF, 2, 2, OSSL_FN_ULONG_C(2) }, /* carry propagates one limb */ + { w_67_89, 2, 2, OSSL_FN_ULONG_C(0) }, /* w == 0 noop */ + { w_FFFFFFFF, 1, 1, OSSL_FN_ULONG_C(1) }, /* dsize 1, carry truncated */ + { w_7FFFFFFF, 1, 1, OSSL_FN_ULONG_C(0x7fffffff) }, /* no carry, near boundary */ +}; + +static const struct word_op_case_st sub_word_cases[] = { + { w_zero, 1, 2, OSSL_FN_ULONG_C(5) }, /* borrow out -> 2's complement */ + { w_01234567, 1, 2, OSSL_FN_ULONG_C(1) }, /* no borrow */ + { w_0_1, 2, 2, OSSL_FN_ULONG_C(1) }, /* borrow repaid at limb 1 */ + { w_0_0, 2, 2, OSSL_FN_ULONG_C(1) }, /* borrow out truncated */ + { w_67_89, 2, 2, OSSL_FN_ULONG_C(0) }, /* w == 0 noop */ + { w_zero, 1, 1, OSSL_FN_ULONG_C(1) }, /* dsize 1, borrow truncated */ + { w_5, 1, 1, OSSL_FN_ULONG_C(5) }, /* exact, no borrow */ + { w_FFFFFFFE, 1, 2, OSSL_FN_ULONG_C(0xffffffff) }, /* borrow through to limb 1 */ +}; + +/* + * Cross-check OSSL_FN__word(a, w) against OSSL_FN_(r, a_ref, b) where + * b is a single-limb operand holding w. The two-limb/general operation and + * the word variant must agree on the full dsize, including truncation and + * 2's-complement wrap behaviour. + */ +static int test_word_op_common(int i, + const struct word_op_case_st *cases, size_t ncases, + int (*word_op)(OSSL_FN *, OSSL_FN_ULONG), + int (*ref_op)(OSSL_FN *, const OSSL_FN *, + const OSSL_FN *)) +{ + const struct word_op_case_st *tc = &cases[i]; + OSSL_FN *a = NULL, *a_ref = NULL, *b = NULL, *res = NULL; + const OSSL_FN_ULONG *u = NULL, *r = NULL; + int ret = 0; + + if (!TEST_ptr(a = OSSL_FN_new_limbs(tc->a_dsize)) + || !TEST_ptr(a_ref = OSSL_FN_new_limbs(tc->a_dsize)) + || !TEST_ptr(b = OSSL_FN_new_limbs(1)) + || !TEST_ptr(res = OSSL_FN_new_limbs(tc->a_dsize)) + || !TEST_true(ossl_fn_set_words(a, tc->a_words, tc->a_limbs)) + || !TEST_true(ossl_fn_set_words(a_ref, tc->a_words, tc->a_limbs)) + || !TEST_true(ossl_fn_set_words(b, &tc->w, 1)) + || !TEST_true(pollute(res, 0, tc->a_dsize))) + goto err; + + if (!TEST_true(word_op(a, tc->w)) + || !TEST_true(ref_op(res, a_ref, b))) + goto err; + + u = ossl_fn_get_words(a); + r = ossl_fn_get_words(res); + if (!TEST_mem_eq(u, tc->a_dsize * OSSL_FN_BYTES, + r, tc->a_dsize * OSSL_FN_BYTES)) + goto err; + + ret = 1; +err: + OSSL_FN_free(a); + OSSL_FN_free(a_ref); + OSSL_FN_free(b); + OSSL_FN_free(res); + return ret; +} + +static int test_add_word(int i) +{ + return test_word_op_common(i, add_word_cases, OSSL_NELEM(add_word_cases), + OSSL_FN_add_word, OSSL_FN_add); +} + +static int test_sub_word(int i) +{ + return test_word_op_common(i, sub_word_cases, OSSL_NELEM(sub_word_cases), + OSSL_FN_sub_word, OSSL_FN_sub); +} + +/*- + * Focused tests for the assignment helpers: OSSL_FN_set_word(), OSSL_FN_one(), + * OSSL_FN_zero(). set_word is cross-checked against the internal + * ossl_fn_set_words() (an independent setter) and pollutes the destination + * first so that zeroing of high limbs is verified rather than assumed. + */ +struct set_word_case_st { + size_t dsize; /* allocated dsize */ + OSSL_FN_ULONG w; + int expect_err; /* 1 if the call should fail (dsize == 0) */ +}; + +static const struct set_word_case_st set_word_cases[] = { + { 1, OSSL_FN_ULONG_C(5), 0 }, /* minimal dsize */ + { 1, OSSL_FN_ULONG_C(0), 0 }, /* zero, minimal dsize */ + { 4, OSSL_FN_ULONG_C(0x01234567), 0 }, /* high limbs must be zeroed */ + { 4, OSSL_FN_ULONG_C(0), 0 }, /* zero, high limbs zeroed */ + { 2, OSSL_FN_ULONG_C(0xffffffff), 0 }, /* all-ones word */ + { 0, OSSL_FN_ULONG_C(5), 1 }, /* dsize 0 -> error */ +}; + +static int test_set_word(int i) +{ + const struct set_word_case_st *tc = &set_word_cases[i]; + OSSL_FN *a = NULL, *ref = NULL; + const OSSL_FN_ULONG *u = NULL, *r = NULL; + int ret = 0; + + if (!TEST_ptr(a = OSSL_FN_new_limbs(tc->dsize)) + || !TEST_ptr(ref = OSSL_FN_new_limbs(tc->dsize))) + goto err; + + /* Pollute both so that zeroing of untouched limbs is detectable. */ + if (tc->dsize > 0) { + if (!TEST_true(pollute(a, 0, tc->dsize)) + || !TEST_true(pollute(ref, 0, tc->dsize))) + goto err; + } + + if (tc->expect_err) { + if (!TEST_false(OSSL_FN_set_word(a, tc->w))) + goto err; + /* ossl_fn_set_words() with 1 limb also fails on dsize 0. */ + if (!TEST_false(ossl_fn_set_words(ref, &tc->w, 1))) + goto err; + ret = 1; + goto err; + } + + if (!TEST_true(OSSL_FN_set_word(a, tc->w)) + || !TEST_true(ossl_fn_set_words(ref, &tc->w, 1))) + goto err; + + u = ossl_fn_get_words(a); + r = ossl_fn_get_words(ref); + if (!TEST_mem_eq(u, tc->dsize * OSSL_FN_BYTES, + r, tc->dsize * OSSL_FN_BYTES)) + goto err; + /* High limbs beyond limb 1 must be zero. */ + if (tc->dsize > 1 + && !TEST_true(check_limbs_value(a, 1, tc->dsize, 0))) + goto err; + + ret = 1; +err: + OSSL_FN_free(a); + OSSL_FN_free(ref); + return ret; +} + +static int test_one(void) +{ + int ret = 0; + OSSL_FN *a = NULL; + const OSSL_FN_ULONG *u = NULL; + size_t dsize = 4; + + if (!TEST_ptr(a = OSSL_FN_new_limbs(dsize)) + || !TEST_true(pollute(a, 0, dsize)) + || !TEST_true(OSSL_FN_one(a))) + goto err; + + u = ossl_fn_get_words(a); + if (!TEST_int_eq((int)u[0], 1) + || !TEST_true(check_limbs_value(a, 1, dsize, 0))) + goto err; + + ret = 1; +err: + OSSL_FN_free(a); + return ret; +} + +static int test_zero(void) +{ + int ret = 0; + OSSL_FN *a = NULL; + size_t dsize = 4; + + if (!TEST_ptr(a = OSSL_FN_new_limbs(dsize)) + || !TEST_true(pollute(a, 0, dsize)) + || !TEST_true(OSSL_FN_zero(a))) + goto err; + + /* OSSL_FN_is_zero() (added in the introspection commit) reads the result. */ + if (!TEST_int_eq(OSSL_FN_is_zero(a), 1) + || !TEST_true(check_limbs_value(a, 0, dsize, 0))) + goto err; + + ret = 1; +err: + OSSL_FN_free(a); + return ret; +} + +static int test_lshift_common(int i, int use_lshift1) +{ + const OSSL_FN_ULONG *a_words = NULL; + const OSSL_FN_ULONG *ex_words = NULL; + OSSL_FN *a = NULL, *r = NULL; + size_t a_limbs = 0, a_live_limbs = 0, r_limbs = 0, check_limbs = 0; + int shift = 0, ret = 0; + const OSSL_FN_ULONG *u = NULL; + + switch (i) { + case 0: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_lshift1_num2) + 2; + ex_words = ex_lshift1_num2; + check_limbs = LIMBSOF(ex_lshift1_num2); + shift = 1; + break; + case 1: + a_words = num0; + a_limbs = LIMBSOF(num0); + a_live_limbs = LIMBSOF(num0); + r_limbs = LIMBSOF(ex_lshift1_num0) + 2; + ex_words = ex_lshift1_num0; + check_limbs = LIMBSOF(ex_lshift1_num0); + shift = 1; + break; + case 2: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_lshift_num2_4) + 2; + ex_words = ex_lshift_num2_4; + check_limbs = LIMBSOF(ex_lshift_num2_4); + shift = 4; + break; + case 3: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2) + 2; + r_limbs = LIMBSOF(ex_lshift_num2_limb) + 2; + ex_words = ex_lshift_num2_limb; + check_limbs = LIMBSOF(ex_lshift_num2_limb); + shift = OSSL_FN_BYTES * 8; + break; + case 4: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_lshift1_num2) - 1; + ex_words = ex_lshift1_num2; + check_limbs = r_limbs; + shift = 1; + break; + case 5: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_lshift_num2_limb_3) + 2; + ex_words = ex_lshift_num2_limb_3; + check_limbs = LIMBSOF(ex_lshift_num2_limb_3); + shift = OSSL_FN_BYTES * 8 + 3; + break; + default: + return 0; + } + + if (!TEST_ptr(a = OSSL_FN_new_limbs(a_live_limbs)) + || !TEST_ptr(r = OSSL_FN_new_limbs(r_limbs)) + || !TEST_true(ossl_fn_set_words(a, a_words, a_limbs)) + || !TEST_true(pollute(r, 0, r_limbs))) + goto err; + + if (use_lshift1) { + if (!TEST_int_eq(shift, 1) + || !TEST_true(OSSL_FN_lshift1(r, a))) + goto err; + } else { + if (!TEST_true(OSSL_FN_lshift(r, a, shift))) + goto err; + } + + if (!TEST_ptr(u = ossl_fn_get_words(r)) + || !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES, + ex_words, check_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(r, check_limbs, r_limbs, + EXTENDED_LIMB_ZERO))) + goto err; + + ret = 1; +err: + OSSL_FN_free(a); + OSSL_FN_free(r); + return ret; +} + +static int test_lshift1(int i) +{ + return test_lshift_common(i, 1); +} + +static int test_lshift(int i) +{ + return test_lshift_common(i, 0); +} + +static int test_rshift_common(int i, int use_rshift1, int alias) +{ + const OSSL_FN_ULONG *a_words = NULL; + const OSSL_FN_ULONG *ex_words = NULL; + OSSL_FN *a = NULL, *r = NULL; + size_t a_limbs = 0, a_live_limbs = 0, r_limbs = 0, check_limbs = 0; + int shift = 0, ret = 0; + const OSSL_FN_ULONG *u = NULL; + + switch (i) { + case 0: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_rshift1_num2) + 2; + ex_words = ex_rshift1_num2; + check_limbs = LIMBSOF(ex_rshift1_num2); + shift = 1; + break; + case 1: + a_words = num8; + a_limbs = LIMBSOF(num8); + a_live_limbs = LIMBSOF(num8); + r_limbs = LIMBSOF(ex_rshift1_num8) + 2; + ex_words = ex_rshift1_num8; + check_limbs = LIMBSOF(ex_rshift1_num8); + shift = 1; + break; + case 2: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_rshift_num2_4) + 2; + ex_words = ex_rshift_num2_4; + check_limbs = LIMBSOF(ex_rshift_num2_4); + shift = 4; + break; + case 3: + a_words = num8; + a_limbs = LIMBSOF(num8); + a_live_limbs = LIMBSOF(num8); + r_limbs = LIMBSOF(ex_rshift_num8_limb) + 2; + ex_words = ex_rshift_num8_limb; + check_limbs = LIMBSOF(ex_rshift_num8_limb); + shift = OSSL_FN_BYTES * 8; + break; + case 4: + a_words = num8; + a_limbs = LIMBSOF(num8); + a_live_limbs = LIMBSOF(num8); + r_limbs = LIMBSOF(ex_rshift_num8_limb_3) + 2; + ex_words = ex_rshift_num8_limb_3; + check_limbs = LIMBSOF(ex_rshift_num8_limb_3); + shift = OSSL_FN_BYTES * 8 + 3; + break; + case 5: + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_rshift_num2_limb) + 2; + ex_words = ex_rshift_num2_limb; + check_limbs = LIMBSOF(ex_rshift_num2_limb); + shift = OSSL_FN_BYTES * 8; + break; + case 6: + a_words = num8; + a_limbs = LIMBSOF(num8); + a_live_limbs = LIMBSOF(num8); + r_limbs = LIMBSOF(num8) - 1; + ex_words = num8; + check_limbs = r_limbs; + shift = 0; + break; + case 7: + /* Shifting by more than the operand's width must yield zero. */ + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(num2) + 2; + ex_words = ex_rshift_zero; + check_limbs = LIMBSOF(num2); + shift = OSSL_FN_BYTES * 8 * (LIMBSOF(num2) + 1); + break; + case 8: + /* Exact-fit destination (no padding) with a non-zero shift. */ + a_words = num2; + a_limbs = LIMBSOF(num2); + a_live_limbs = LIMBSOF(num2); + r_limbs = LIMBSOF(ex_rshift_num2_4); + ex_words = ex_rshift_num2_4; + check_limbs = LIMBSOF(ex_rshift_num2_4); + shift = 4; + break; + default: + return 0; + } + + if (!TEST_ptr(a = OSSL_FN_new_limbs(a_live_limbs)) + || !TEST_true(ossl_fn_set_words(a, a_words, a_limbs))) + goto err; + + if (alias) { + r = a; + } else if (!TEST_ptr(r = OSSL_FN_new_limbs(r_limbs)) + || !TEST_true(pollute(r, 0, r_limbs))) { + goto err; + } + + if (use_rshift1) { + if (!TEST_int_eq(shift, 1) + || !TEST_true(OSSL_FN_rshift1(r, a))) + goto err; + } else { + if (!TEST_true(OSSL_FN_rshift(r, a, shift))) + goto err; + } + + if (!TEST_ptr(u = ossl_fn_get_words(r)) + || !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES, + ex_words, check_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(r, check_limbs, r_limbs, + EXTENDED_LIMB_ZERO))) + goto err; + + ret = 1; +err: + if (!alias) + OSSL_FN_free(r); + OSSL_FN_free(a); + return ret; +} + +static int test_rshift1(int i) +{ + return test_rshift_common(i, 1, 0); +} + +static int test_rshift(int i) +{ + return test_rshift_common(i, 0, 0); +} + +/* + * In-place (r == a) coverage: rshift1 (case 0), rshift by 1 (case 1), + * by 4 (case 2), and by a full limb width (case 3). The low-to-high + * walk makes in-place safe for any shift, so this exercises the + * multi-limb carry path under aliasing beyond shift-by-1. + */ +static int test_rshift_alias(int i) +{ + return test_rshift_common(i, i == 0, 1); +} + +static int test_rshift_invalid_shift(void) +{ + OSSL_FN *a = NULL, *r = NULL; + int ret = 0; + + if (!TEST_ptr(a = OSSL_FN_new_limbs(LIMBSOF(num2))) + || !TEST_ptr(r = OSSL_FN_new_limbs(LIMBSOF(num2))) + || !TEST_true(ossl_fn_set_words(a, num2, LIMBSOF(num2)))) + goto err; + + if (!TEST_false(OSSL_FN_rshift(r, a, -1))) + goto err; + + ERR_clear_error(); + ret = 1; +err: + OSSL_FN_free(a); + OSSL_FN_free(r); + return ret; +} + +/* A set of expected results, also in OSSL_FN_ULONG array form */ +static const OSSL_FN_ULONG ex_mul_num0_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), + OSSL_FN_ULONG64_C(0x40000000, 0x00000001), +}; +static const OSSL_FN_ULONG ex_mul_num0_num1[] = { + OSSL_FN_ULONG64_C(0x00000001, 0x80000000), + OSSL_FN_ULONG64_C(0x00000000, 0xC0000000), +}; +static const OSSL_FN_ULONG ex_mul_num0_num2[] = { + OSSL_FN_ULONG64_C(0x81234567, 0x89ABCDEF), + OSSL_FN_ULONG64_C(0x0091A2B3, 0xC4D5E6F7), +}; +static const OSSL_FN_ULONG ex_mul_num0_num3[] = { + OSSL_FN_ULONG64_C(0xFEDCBA98, 0x76543210), + OSSL_FN_ULONG64_C(0x7F6E5D4C, 0x3B2A1908), +}; +static const OSSL_FN_ULONG ex_mul_num1_num1[] = { + OSSL_FN_ULONG64_C(0x40000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000002), +}; +static const OSSL_FN_ULONG ex_mul_num1_num2[] = { + OSSL_FN_ULONG64_C(0x4E81B4E6, 0x80000000), + OSSL_FN_ULONG64_C(0x00000000, 0x01B4E81B), +}; +static const OSSL_FN_ULONG ex_mul_num1_num3[] = { + OSSL_FN_ULONG64_C(0xB17E4B18, 0x00000000), + OSSL_FN_ULONG64_C(0x00000001, 0x7E4B17E4), +}; +static const OSSL_FN_ULONG ex_mul_num2_num2[] = { + OSSL_FN_ULONG64_C(0xDCA5E208, 0x90F2A521), + OSSL_FN_ULONG64_C(0x00014B66, 0xDC33F6AC), +}; +static const OSSL_FN_ULONG ex_mul_num2_num3[] = { + OSSL_FN_ULONG64_C(0x2236D88F, 0xE5618CF0), + OSSL_FN_ULONG64_C(0x0121FA00, 0xAD77D742), +}; +static const OSSL_FN_ULONG ex_mul_num3_num3[] = { + OSSL_FN_ULONG64_C(0xDEEC6CD7, 0xA44A4100), + OSSL_FN_ULONG64_C(0xFDBAC097, 0xC8DC5ACC), +}; +/* Expected results for edge cases */ +static const OSSL_FN_ULONG ex_mul_num4_num4[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +static const OSSL_FN_ULONG ex_mul_num5_num5[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), + OSSL_FN_ULONG64_C(0xFFFFFFFF, 0xFFFFFFFE), +}; +/* $num6 * $num6 == 0x0100000000000000000000000000000000000000000000000000000000000000 */ +static const OSSL_FN_ULONG ex_mul_num6_num6[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x01000000, 0x00000000), +}; + +static int test_mul_feature_r_is_operand(int i) +{ + int ret = 1; + const OSSL_FN_ULONG *a_data = num0; + size_t a_limbs = sizeof(num0) / OSSL_FN_BYTES; + const OSSL_FN_ULONG *b_data = num1; + size_t b_limbs = sizeof(num1) / OSSL_FN_BYTES; + OSSL_FN *a = NULL, *b = NULL, *res = NULL; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 1, a_limbs + b_limbs)) + || !TEST_ptr(a = OSSL_FN_new_limbs(a_limbs)) + || !TEST_ptr(b = OSSL_FN_new_limbs(b_limbs)) + || !TEST_true(ossl_fn_set_words(a, a_data, a_limbs)) + || !TEST_true(ossl_fn_set_words(b, b_data, b_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + const OSSL_FN *op1 = NULL, *op2 = NULL; + const OSSL_FN_ULONG *u = NULL; + const OSSL_FN_ULONG *ex_data = NULL; + size_t ex_limbs = 0; + + switch (i) { + case 0: + /* a * b, result in separate OSSL_FN */ + if (!TEST_ptr(res = OSSL_FN_new_limbs(a_limbs + b_limbs))) { + ret = 0; + goto end; + } + op1 = a; + op2 = b; + ex_data = ex_mul_num0_num1; + ex_limbs = ossl_fn_get_dsize(res); + break; + case 1: + /* a * b, result in a */ + res = a; + op1 = a; + op2 = b; + ex_data = ex_mul_num0_num1; + ex_limbs = ossl_fn_get_dsize(res); + break; + case 2: + /* a * b, result in b */ + res = b; + op1 = a; + op2 = b; + ex_data = ex_mul_num0_num1; + ex_limbs = ossl_fn_get_dsize(res); + break; + case 3: + /* a * a, result in a */ + res = a; + op1 = a; + op2 = a; + ex_data = ex_mul_num0_num0; + ex_limbs = ossl_fn_get_dsize(res); + break; + default: + /* Invalid call */ + ret = 0; + goto end; + } + + if (!TEST_true(OSSL_FN_mul(res, op1, op2, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(res)) + || !TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES, + ex_data, ex_limbs * OSSL_FN_BYTES)) + ret = 0; + + if (TEST_ptr(u = ossl_fn_get_words(a))) { + if (res == a) { + if (!TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES, + ex_data, ex_limbs * OSSL_FN_BYTES)) + ret = 0; + } else { + if (!TEST_mem_eq(u, a_limbs * OSSL_FN_BYTES, + a_data, a_limbs * OSSL_FN_BYTES)) + ret = 0; + } + } + + if (TEST_ptr(u = ossl_fn_get_words(b))) { + if (res == b) { + if (!TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES, + ex_data, ex_limbs * OSSL_FN_BYTES)) + ret = 0; + } else { + if (!TEST_mem_eq(u, b_limbs * OSSL_FN_BYTES, + b_data, b_limbs * OSSL_FN_BYTES)) + ret = 0; + } + } + +end: + OSSL_FN_CTX_free(ctx); + if (res != a && res != b) + OSSL_FN_free(res); + OSSL_FN_free(a); + OSSL_FN_free(b); + return ret; +} + +static int test_mul_common(struct test_case_st test_case) +{ + int ret = 1; + const OSSL_FN_ULONG *n1 = test_case.op1; + size_t n1_limbs = test_case.op1_size; + const OSSL_FN_ULONG *n2 = test_case.op2; + size_t n2_limbs = test_case.op2_size; + const OSSL_FN_ULONG *ex = test_case.ex1; + size_t n1_new_limbs = test_case.op1_live_size; + size_t n2_new_limbs = test_case.op2_live_size; + size_t res_limbs = test_case.res1_live_size; + size_t check_limbs = test_case.check1_size; + OSSL_FN_ULONG extended_value = test_case.extended_limb_value1; + OSSL_FN *fn1 = NULL, *fn2 = NULL, *res = NULL; + const OSSL_FN_ULONG *u = NULL; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 1, res_limbs)) + || !TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs)) + || !TEST_ptr(fn2 = OSSL_FN_new_limbs(n2_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs)) + || !TEST_true(ossl_fn_set_words(fn2, n2, n2_limbs)) + || !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + /* To test that OSSL_FN_mul() does a complete job, 'res' is pre-polluted */ + + if (!TEST_true(pollute(res, 0, res_limbs)) + || !TEST_true(OSSL_FN_mul(res, fn1, fn2, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(res)) + || !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES, + ex, check_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(res, check_limbs, res_limbs, + extended_value))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fn1); + OSSL_FN_free(fn2); + OSSL_FN_free(res); + + return ret; +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define MUL_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ ex, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(op1) + LIMBSOF(op2) + ((i - 1) % 4), \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex), \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_mul_cases[] = { + MUL_CASE(1, num0, num0, ex_mul_num0_num0), + MUL_CASE(2, num0, num1, ex_mul_num0_num1), + MUL_CASE(3, num0, num2, ex_mul_num0_num2), + MUL_CASE(4, num0, num3, ex_mul_num0_num3), + MUL_CASE(5, num1, num0, ex_mul_num0_num1), /* Commutativity check */ + MUL_CASE(6, num1, num1, ex_mul_num1_num1), + MUL_CASE(7, num1, num2, ex_mul_num1_num2), + MUL_CASE(8, num1, num3, ex_mul_num1_num3), + MUL_CASE(9, num2, num0, ex_mul_num0_num2), /* Commutativity check */ + MUL_CASE(10, num2, num1, ex_mul_num1_num2), /* Commutativity check */ + MUL_CASE(11, num2, num2, ex_mul_num2_num2), + MUL_CASE(12, num2, num3, ex_mul_num2_num3), + MUL_CASE(13, num3, num0, ex_mul_num0_num3), /* Commutativity check */ + MUL_CASE(14, num3, num1, ex_mul_num1_num3), /* Commutativity check */ + MUL_CASE(15, num3, num2, ex_mul_num2_num3), /* Commutativity check */ + MUL_CASE(16, num3, num3, ex_mul_num3_num3), + + /* Edge cases */ + MUL_CASE(17, num4, num4, ex_mul_num4_num4), + MUL_CASE(18, num5, num5, ex_mul_num5_num5), + MUL_CASE(19, num6, num6, ex_mul_num6_num6), +}; + +static int test_mul(int i) +{ + return test_mul_common(test_mul_cases[i]); +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define MUL_TRUNCATED_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) / 2, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) / 2, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } +/* A special case, where the truncation is set to the size of ex minus 64 bits */ +#define MUL_TRUNCATED_SPECIAL_CASE1(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) - 8 / OSSL_FN_BYTES, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) - 8 / OSSL_FN_BYTES, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_mul_truncate_cases[] = { + MUL_TRUNCATED_CASE(1, num0, num0, ex_mul_num0_num0), + MUL_TRUNCATED_CASE(2, num0, num1, ex_mul_num0_num1), + MUL_TRUNCATED_CASE(3, num0, num2, ex_mul_num0_num2), + MUL_TRUNCATED_CASE(4, num0, num3, ex_mul_num0_num3), + MUL_TRUNCATED_CASE(5, num1, num0, ex_mul_num0_num1), /* Commutativity check */ + MUL_TRUNCATED_CASE(6, num1, num1, ex_mul_num1_num1), + MUL_TRUNCATED_CASE(7, num1, num2, ex_mul_num1_num2), + MUL_TRUNCATED_CASE(8, num1, num3, ex_mul_num1_num3), + MUL_TRUNCATED_CASE(9, num2, num0, ex_mul_num0_num2), /* Commutativity check */ + MUL_TRUNCATED_CASE(10, num2, num1, ex_mul_num1_num2), /* Commutativity check */ + MUL_TRUNCATED_CASE(11, num2, num2, ex_mul_num2_num2), + MUL_TRUNCATED_CASE(12, num2, num3, ex_mul_num2_num3), + MUL_TRUNCATED_CASE(13, num3, num0, ex_mul_num0_num3), /* Commutativity check */ + MUL_TRUNCATED_CASE(14, num3, num1, ex_mul_num1_num3), /* Commutativity check */ + MUL_TRUNCATED_CASE(15, num3, num2, ex_mul_num2_num3), /* Commutativity check */ + MUL_TRUNCATED_CASE(16, num3, num3, ex_mul_num3_num3), + + /* Edge cases */ + MUL_TRUNCATED_CASE(17, num4, num4, ex_mul_num4_num4), + MUL_TRUNCATED_CASE(18, num5, num5, ex_mul_num5_num5), + MUL_TRUNCATED_SPECIAL_CASE1(19, num6, num6, ex_mul_num6_num6), +}; + +static int test_mul_truncated(int i) +{ + return test_mul_common(test_mul_truncate_cases[i]); +} + +/* All sqr tests reuse selected mul result numbers (ex_mul_num{n}_num{n}), except one */ +#define ex_sqr_num0 ex_mul_num0_num0 +#define ex_sqr_num1 ex_mul_num1_num1 +#define ex_sqr_num2 ex_mul_num2_num2 +#define ex_sqr_num3 ex_mul_num3_num3 +#define ex_sqr_num4 ex_mul_num4_num4 +#define ex_sqr_num5 ex_mul_num5_num5 +#define ex_sqr_num6 ex_mul_num6_num6 +static const OSSL_FN_ULONG ex_sqr_num7[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +#if OSSL_FN_BYTES == 4 + OSSL_FN_ULONG64_C(0xFFFFFFFE, 0x00000001), +#elif OSSL_FN_BYTES == 8 + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), + OSSL_FN_ULONG64_C(0xFFFFFFFF, 0xFFFFFFFE), +#endif +}; + +static int test_sqr_feature_r_is_operand(int i) +{ + int ret = 1; + const OSSL_FN_ULONG *a_data = num0; + size_t a_limbs = sizeof(num0) / OSSL_FN_BYTES; + OSSL_FN *a = NULL, *res = NULL; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 2, a_limbs * 4)) + || !TEST_ptr(a = OSSL_FN_new_limbs(a_limbs)) + || !TEST_true(ossl_fn_set_words(a, a_data, a_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + switch (i) { + case 0: + /* a ** 2, result in separate OSSL_FN */ + if (!TEST_ptr(res = OSSL_FN_new_limbs(a_limbs * 2))) { + ret = 0; + goto end; + } + break; + case 1: + /* a ** 2, result in a */ + res = a; + break; + default: + /* Invalid call */ + ret = 0; + goto end; + } + + const OSSL_FN_ULONG *u = NULL; + const OSSL_FN_ULONG *ex_data = ex_mul_num0_num0; + size_t ex_limbs = ossl_fn_get_dsize(res); + + if (!TEST_true(OSSL_FN_sqr(res, a, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(res)) + || !TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES, + ex_data, ex_limbs * OSSL_FN_BYTES)) + ret = 0; + + if (TEST_ptr(u = ossl_fn_get_words(a))) { + if (res == a) { + if (!TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES, + ex_data, ex_limbs * OSSL_FN_BYTES)) + ret = 0; + } else { + if (!TEST_mem_eq(u, a_limbs * OSSL_FN_BYTES, + a_data, a_limbs * OSSL_FN_BYTES)) + ret = 0; + } + } + +end: + OSSL_FN_CTX_free(ctx); + if (res != a) + OSSL_FN_free(res); + OSSL_FN_free(a); + return ret; +} + +static int test_sqr_common(struct test_case_st test_case) +{ + int ret = 1; + const OSSL_FN_ULONG *n1 = test_case.op1; + size_t n1_limbs = test_case.op1_size; + const OSSL_FN_ULONG *ex = test_case.ex1; + size_t n1_new_limbs = test_case.op1_live_size; + size_t res_limbs = test_case.res1_live_size; + size_t check_limbs = test_case.check1_size; + OSSL_FN_ULONG extended_value = test_case.extended_limb_value1; + OSSL_FN *fn1 = NULL, *res = NULL; + const OSSL_FN_ULONG *u = NULL; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 2, n1_new_limbs * 4)) + || !TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs)) + || !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + /* To test that OSSL_FN_sqr() does a complete job, 'res' is pre-polluted */ + + if (!TEST_true(pollute(res, 0, res_limbs)) + || !TEST_true(OSSL_FN_sqr(res, fn1, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(res)) + || !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES, + ex, check_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(res, check_limbs, res_limbs, + extended_value))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fn1); + OSSL_FN_free(res); + + return ret; +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define SQR_CASE(i, op1, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ NULL, \ + /* op2_size */ 0, \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ 0, \ + /* res1_live_size */ LIMBSOF(op1) * 2 + ((i - 1) % 4), \ + /* res2_live_size */ 0, \ + /* check_size */ LIMBSOF(ex), \ + /* check_size */ 0, \ + /* extended_limb_value */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value */ 0, \ + } + +static struct test_case_st test_sqr_cases[] = { + SQR_CASE(1, num0, ex_sqr_num0), + SQR_CASE(2, num1, ex_sqr_num1), + SQR_CASE(3, num2, ex_sqr_num2), + SQR_CASE(4, num3, ex_sqr_num3), + + /* Edge cases */ + SQR_CASE(5, num4, ex_sqr_num4), + SQR_CASE(6, num5, ex_sqr_num5), + SQR_CASE(7, num6, ex_sqr_num6), + SQR_CASE(8, num7, ex_sqr_num7), +}; + +static int test_sqr(int i) +{ + return test_sqr_common(test_sqr_cases[i]); +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define SQR_TRUNCATED_CASE(i, op1, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ NULL, \ + /* op2_size */ 0, \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ 0, \ + /* res1_live_size */ LIMBSOF(ex) / 2, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) / 2, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } +/* A special case, where the truncation is set to the size of ex minus 64 bits */ +#define SQR_TRUNCATED_SPECIAL_CASE1(i, op1, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ NULL, \ + /* op2_size */ 0, \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ 0, \ + /* res1_live_size */ LIMBSOF(ex) - 8 / OSSL_FN_BYTES, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) - 8 / OSSL_FN_BYTES, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_sqr_truncate_cases[] = { + SQR_TRUNCATED_CASE(1, num0, ex_sqr_num0), + SQR_TRUNCATED_CASE(2, num1, ex_sqr_num1), + SQR_TRUNCATED_CASE(3, num2, ex_sqr_num2), + SQR_TRUNCATED_CASE(4, num3, ex_sqr_num3), + + /* Edge cases */ + SQR_TRUNCATED_CASE(5, num4, ex_sqr_num4), + SQR_TRUNCATED_CASE(6, num5, ex_sqr_num5), + SQR_TRUNCATED_SPECIAL_CASE1(7, num6, ex_sqr_num6), + SQR_TRUNCATED_CASE(7, num7, ex_sqr_num7), +}; + +static int test_sqr_truncated(int i) +{ + return test_sqr_common(test_sqr_truncate_cases[i]); +} + +/* A set of expected results, also in OSSL_FN_ULONG array form */ +/* : $num0 / $num0 == 1 */ +static const OSSL_FN_ULONG ex_div_num0_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +/* : $num0 % $num0 == 0 */ +static const OSSL_FN_ULONG ex_rem_num0_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num0 / $num1 == 0x55555555 */ +static const OSSL_FN_ULONG ex_div_num0_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x55555555), +}; +/* : $num0 % $num1 == 0x80000001 */ +static const OSSL_FN_ULONG ex_rem_num0_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x80000001), +}; +/* : $num0 / $num2 == 0x70 */ +static const OSSL_FN_ULONG ex_div_num0_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000070), +}; +/* : $num0 % $num2 == 0x91a2b3 c4d5e771 */ +static const OSSL_FN_ULONG ex_rem_num0_num2[] = { + OSSL_FN_ULONG64_C(0x0091A2B3, 0xC4D5E771), +}; +/* : $num0 / $num3 == 1 */ +static const OSSL_FN_ULONG ex_div_num0_num3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num0 % $num3 == 0x9abcdef 01234569 */ +static const OSSL_FN_ULONG ex_rem_num0_num3[] = { + OSSL_FN_ULONG64_C(0x80000000, 0x00000001), +}; +/* : $num1 / $num0 == 0 */ +static const OSSL_FN_ULONG ex_div_num1_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num1 % $num0 == 0x180000000 */ +static const OSSL_FN_ULONG ex_rem_num1_num0[] = { + OSSL_FN_ULONG64_C(0x00000001, 0x80000000), +}; +/* : $num1 / $num1 == 1 */ +static const OSSL_FN_ULONG ex_div_num1_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +/* : $num1 % $num1 == 0 */ +static const OSSL_FN_ULONG ex_rem_num1_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num1 / $num2 == 0 */ +static const OSSL_FN_ULONG ex_div_num1_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num1 % $num2 == 0x180000000 */ +static const OSSL_FN_ULONG ex_rem_num1_num2[] = { + OSSL_FN_ULONG64_C(0x00000001, 0x80000000), +}; +/* : $num1 / $num3 == 0 */ +static const OSSL_FN_ULONG ex_div_num1_num3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num1 % $num3 == 0x180000000 */ +static const OSSL_FN_ULONG ex_rem_num1_num3[] = { + OSSL_FN_ULONG64_C(0x00000001, 0x80000000), +}; +/* : $num2 / $num0 == 0 */ +static const OSSL_FN_ULONG ex_div_num2_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num2 % $num0 == 0X123456789abcdef */ +static const OSSL_FN_ULONG ex_rem_num2_num0[] = { + OSSL_FN_ULONG64_C(0X01234567, 0x89ABCDEF), +}; +/* : $num2 / $num1 == 0xc22e45 */ +static const OSSL_FN_ULONG ex_div_num2_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00C22E45), +}; +/* : $num2 % $num1 == 0x9abcdef */ +static const OSSL_FN_ULONG ex_rem_num2_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x09ABCDEF), +}; +/* : $num2 / $num2 == 1 */ +static const OSSL_FN_ULONG ex_div_num2_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +/* : $num2 % $num2 == 0 */ +static const OSSL_FN_ULONG ex_rem_num2_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num2 / $num3 == 0 */ +static const OSSL_FN_ULONG ex_div_num2_num3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* : $num2 % $num3 == 0X0123456789abcdef */ +static const OSSL_FN_ULONG ex_rem_num2_num3[] = { + OSSL_FN_ULONG64_C(0X01234567, 0x89ABCDEF), +}; +/* : $num3 / $num0 == 1 */ +static const OSSL_FN_ULONG ex_div_num3_num0[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +/* : $num3 % $num0 == 0x7edcba987654320f */ +static const OSSL_FN_ULONG ex_rem_num3_num0[] = { + OSSL_FN_ULONG64_C(0x7edcba98, 0x7654320f), +}; +/* : $num3 / $num1 == 0xa9e87c65 */ +static const OSSL_FN_ULONG ex_div_num3_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0xa9e87c65), +}; +/* : $num3 % $num1 == 0x00000000f6543210 */ +static const OSSL_FN_ULONG ex_rem_num3_num1[] = { + OSSL_FN_ULONG64_C(0x00000000, 0xf6543210), +}; +/* : $num3 / $num2 == 0xe0 */ +static const OSSL_FN_ULONG ex_div_num3_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x000000e0), +}; +/* : $num3 % $num2 == 0xf0 */ +static const OSSL_FN_ULONG ex_rem_num3_num2[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x000000f0), +}; +/* : $num3 / $num3 == 1 */ +static const OSSL_FN_ULONG ex_div_num3_num3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +/* : $num3 % $num3 == o */ +static const OSSL_FN_ULONG ex_rem_num3_num3[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* Expected results for edge cases */ +/* $num5 / $num5 == 1 */ +static const OSSL_FN_ULONG ex_div_num5_num5[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), +}; +/* $num5 % $num5 == 0 */ +static const OSSL_FN_ULONG ex_rem_num5_num5[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* $num6 / $num6 == 1 */ +static const OSSL_FN_ULONG ex_div_num6_num6[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000001), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; +/* $num6 % $num6 == 0 */ +static const OSSL_FN_ULONG ex_rem_num6_num6[] = { + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), + OSSL_FN_ULONG64_C(0x00000000, 0x00000000), +}; + +static int test_div_common(struct test_case_st test_case) +{ + int ret = 1; + const OSSL_FN_ULONG *n = test_case.op1; + size_t n_limbs = test_case.op1_size; + const OSSL_FN_ULONG *d = test_case.op2; + size_t d_limbs = test_case.op2_size; + const OSSL_FN_ULONG *ex_q = test_case.ex1; + const OSSL_FN_ULONG *ex_r = test_case.ex2; + size_t n_new_limbs = test_case.op1_live_size; + size_t d_new_limbs = test_case.op2_live_size; + size_t q_limbs = test_case.res1_live_size; + size_t r_limbs = test_case.res2_live_size; + size_t check_q_limbs = test_case.check1_size; + size_t check_r_limbs = test_case.check2_size; + OSSL_FN_ULONG extended_q = test_case.extended_limb_value1; + OSSL_FN_ULONG extended_r = test_case.extended_limb_value2; + OSSL_FN *fn = NULL, *fd = NULL, *fq = NULL, *fr = NULL; + const OSSL_FN_ULONG *u = NULL; + /* Calculate total number of limbs for OSSL_FN_CTX */ + size_t ctx_numcopy_limbs = ((n_new_limbs <= d_new_limbs) ? d_new_limbs : n_new_limbs) + 1; + size_t ctx_divcopy_limbs = d_new_limbs; + size_t ctx_tmp_limbs = d_new_limbs + 1; + size_t ctx_res_limbs = n_new_limbs; + size_t ctx_max_limbs = ctx_numcopy_limbs + ctx_divcopy_limbs + ctx_res_limbs + ctx_tmp_limbs; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 4, ctx_max_limbs)) + || !TEST_ptr(fn = OSSL_FN_new_limbs(n_new_limbs)) + || !TEST_ptr(fd = OSSL_FN_new_limbs(d_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn, n, n_limbs)) + || !TEST_true(ossl_fn_set_words(fd, d, d_limbs)) + || !TEST_ptr(fq = OSSL_FN_new_limbs(q_limbs)) + || !TEST_ptr(fr = OSSL_FN_new_limbs(r_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + /* To test that OSSL_FN_div() does a complete job, 'res' is pre-polluted */ + + if (!TEST_true(pollute(fq, 0, q_limbs)) + || !TEST_true(pollute(fr, 0, r_limbs)) + || !TEST_true(OSSL_FN_div(fq, fr, fn, fd, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(fq)) + || !TEST_mem_eq(u, check_q_limbs * OSSL_FN_BYTES, + ex_q, check_q_limbs * OSSL_FN_BYTES) + || !TEST_ptr(u = ossl_fn_get_words(fr)) + || !TEST_mem_eq(u, check_r_limbs * OSSL_FN_BYTES, + ex_r, check_r_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(fq, check_q_limbs, q_limbs, extended_q)) + || !TEST_true(check_limbs_value(fr, check_r_limbs, r_limbs, extended_r))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fn); + OSSL_FN_free(fd); + OSSL_FN_free(fq); + OSSL_FN_free(fr); + + return ret; +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define DIV_CASE(i, op1, op2, ex_q, ex_r) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex_q, \ + /* ex1_size */ LIMBSOF(ex_q), \ + /* ex2 */ ex_r, \ + /* ex2_size */ LIMBSOF(ex_r), \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(op1) + ((i - 1) % 4), \ + /* res2_live_size */ LIMBSOF(op1) + ((i - 1) % 4), \ + /* check1_size */ LIMBSOF(ex_q), \ + /* check2_size */ LIMBSOF(ex_r), \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ EXTENDED_LIMB_ZERO, \ + } + +static struct test_case_st test_div_cases[] = { + DIV_CASE(1, num0, num0, ex_div_num0_num0, ex_rem_num0_num0), + DIV_CASE(2, num0, num1, ex_div_num0_num1, ex_rem_num0_num1), + DIV_CASE(3, num0, num2, ex_div_num0_num2, ex_rem_num0_num2), + DIV_CASE(4, num0, num3, ex_div_num0_num3, ex_rem_num0_num3), + DIV_CASE(5, num1, num0, ex_div_num1_num0, ex_rem_num1_num0), + DIV_CASE(6, num1, num1, ex_div_num1_num1, ex_rem_num1_num1), + DIV_CASE(7, num1, num2, ex_div_num1_num2, ex_rem_num1_num2), + DIV_CASE(8, num1, num3, ex_div_num1_num3, ex_rem_num1_num3), + DIV_CASE(9, num2, num0, ex_div_num2_num0, ex_rem_num2_num0), + DIV_CASE(10, num2, num1, ex_div_num2_num1, ex_rem_num2_num1), + DIV_CASE(11, num2, num2, ex_div_num2_num2, ex_rem_num2_num2), + DIV_CASE(12, num2, num3, ex_div_num2_num3, ex_rem_num2_num3), + DIV_CASE(13, num3, num0, ex_div_num3_num0, ex_rem_num3_num0), + DIV_CASE(14, num3, num1, ex_div_num3_num1, ex_rem_num3_num1), + DIV_CASE(15, num3, num2, ex_div_num3_num2, ex_rem_num3_num2), + DIV_CASE(16, num3, num3, ex_div_num3_num3, ex_rem_num3_num3), + + /* Edge cases */ + DIV_CASE(17, num5, num5, ex_div_num5_num5, ex_rem_num5_num5), + DIV_CASE(18, num6, num6, ex_div_num6_num6, ex_rem_num6_num6), +}; + +static int test_div(int i) +{ + return test_div_common(test_div_cases[i]); +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define DIV_TRUNCATED_CASE(i, op1, op2, ex_q, ex_r) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex_q, \ + /* ex1_size */ LIMBSOF(ex_q), \ + /* ex2 */ ex_r, \ + /* ex2_size */ LIMBSOF(ex_r), \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex_q) / 2, \ + /* res2_live_size */ LIMBSOF(ex_r) / 2, \ + /* check1_size */ LIMBSOF(ex_q) / 2, \ + /* check2_size */ LIMBSOF(ex_r) / 2, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ EXTENDED_LIMB_ZERO, \ + } + +static struct test_case_st test_div_truncate_cases[] = { + DIV_TRUNCATED_CASE(1, num0, num0, ex_div_num0_num0, ex_rem_num0_num0), + DIV_TRUNCATED_CASE(2, num0, num1, ex_div_num0_num1, ex_rem_num0_num1), + DIV_TRUNCATED_CASE(3, num0, num2, ex_div_num0_num2, ex_rem_num0_num2), + DIV_TRUNCATED_CASE(4, num0, num3, ex_div_num0_num3, ex_rem_num0_num3), + DIV_TRUNCATED_CASE(5, num1, num0, ex_div_num1_num0, ex_rem_num1_num0), + DIV_TRUNCATED_CASE(6, num1, num1, ex_div_num1_num1, ex_rem_num1_num1), + DIV_TRUNCATED_CASE(7, num1, num2, ex_div_num1_num2, ex_rem_num1_num2), + DIV_TRUNCATED_CASE(8, num1, num3, ex_div_num1_num3, ex_rem_num1_num3), + DIV_TRUNCATED_CASE(9, num2, num0, ex_div_num2_num0, ex_rem_num2_num0), + DIV_TRUNCATED_CASE(10, num2, num1, ex_div_num2_num1, ex_rem_num2_num1), + DIV_TRUNCATED_CASE(11, num2, num2, ex_div_num2_num2, ex_rem_num2_num2), + DIV_TRUNCATED_CASE(12, num2, num3, ex_div_num2_num3, ex_rem_num2_num3), + DIV_TRUNCATED_CASE(13, num3, num0, ex_div_num3_num0, ex_rem_num3_num0), + DIV_TRUNCATED_CASE(14, num3, num1, ex_div_num3_num1, ex_rem_num3_num1), + DIV_TRUNCATED_CASE(15, num3, num2, ex_div_num3_num2, ex_rem_num3_num2), + DIV_TRUNCATED_CASE(16, num3, num3, ex_div_num3_num3, ex_rem_num3_num3), + + /* Edge cases */ + DIV_TRUNCATED_CASE(17, num5, num5, ex_div_num5_num5, ex_rem_num5_num5), + DIV_TRUNCATED_CASE(18, num6, num6, ex_div_num6_num6, ex_rem_num6_num6), +}; + +static int test_div_truncated(int i) +{ + return test_div_common(test_div_truncate_cases[i]); +} + +/* + * The modulo tests are a bit silly, 'cause we know that OSSL_FN_mod() + * simply calls OSSL_FN_div() with NULL for the quotient. Still, these + * tests ensure that calling OSSL_FN_div() like that works without flaws. + */ +static int test_mod_common(struct test_case_st test_case) +{ + int ret = 1; + const OSSL_FN_ULONG *n = test_case.op1; + size_t n_limbs = test_case.op1_size; + const OSSL_FN_ULONG *d = test_case.op2; + size_t d_limbs = test_case.op2_size; + const OSSL_FN_ULONG *ex = test_case.ex1; + size_t n_new_limbs = test_case.op1_live_size; + size_t d_new_limbs = test_case.op2_live_size; + size_t res_limbs = test_case.res1_live_size; + size_t check_res_limbs = test_case.check1_size; + OSSL_FN_ULONG extended_res = test_case.extended_limb_value1; + OSSL_FN *fn = NULL, *fd = NULL, *fres = NULL; + const OSSL_FN_ULONG *u = NULL; + /* Calculate total number of limbs for OSSL_FN_CTX */ + size_t ctx_numcopy_limbs = ((n_new_limbs <= d_new_limbs) ? d_new_limbs : n_new_limbs) + 1; + size_t ctx_divcopy_limbs = d_new_limbs; + size_t ctx_tmp_limbs = d_new_limbs + 1; + size_t ctx_res_limbs = n_new_limbs; + size_t ctx_max_limbs = ctx_numcopy_limbs + ctx_divcopy_limbs + ctx_res_limbs + ctx_tmp_limbs; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 4, ctx_max_limbs)) + || !TEST_ptr(fn = OSSL_FN_new_limbs(n_new_limbs)) + || !TEST_ptr(fd = OSSL_FN_new_limbs(d_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn, n, n_limbs)) + || !TEST_true(ossl_fn_set_words(fd, d, d_limbs)) + || !TEST_ptr(fres = OSSL_FN_new_limbs(res_limbs))) { + ret = 0; + /* There's no way to continue tests in this case */ + goto end; + } + + /* To test that OSSL_FN_mod() does a complete job, 'res' is pre-polluted */ + + if (!TEST_true(pollute(fres, 0, res_limbs)) + || !TEST_true(OSSL_FN_mod(fres, fn, fd, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(fres)) + || !TEST_mem_eq(u, check_res_limbs * OSSL_FN_BYTES, + ex, check_res_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(fres, check_res_limbs, res_limbs, extended_res))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fn); + OSSL_FN_free(fd); + OSSL_FN_free(fres); + + return ret; +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define MOD_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(op1) + ((i - 1) % 4), \ + /* res2_live_size */ LIMBSOF(op1) + ((i - 1) % 4), \ + /* check1_size */ LIMBSOF(ex), \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_mod_cases[] = { + MOD_CASE(1, num0, num0, ex_rem_num0_num0), + MOD_CASE(2, num0, num1, ex_rem_num0_num1), + MOD_CASE(3, num0, num2, ex_rem_num0_num2), + MOD_CASE(4, num0, num3, ex_rem_num0_num3), + MOD_CASE(5, num1, num0, ex_rem_num1_num0), + MOD_CASE(6, num1, num1, ex_rem_num1_num1), + MOD_CASE(7, num1, num2, ex_rem_num1_num2), + MOD_CASE(8, num1, num3, ex_rem_num1_num3), + MOD_CASE(9, num2, num0, ex_rem_num2_num0), + MOD_CASE(10, num2, num1, ex_rem_num2_num1), + MOD_CASE(11, num2, num2, ex_rem_num2_num2), + MOD_CASE(12, num2, num3, ex_rem_num2_num3), + MOD_CASE(13, num3, num0, ex_rem_num3_num0), + MOD_CASE(14, num3, num1, ex_rem_num3_num1), + MOD_CASE(15, num3, num2, ex_rem_num3_num2), + MOD_CASE(16, num3, num3, ex_rem_num3_num3), + + /* Edge cases */ + MOD_CASE(17, num5, num5, ex_rem_num5_num5), + MOD_CASE(18, num6, num6, ex_rem_num6_num6), +}; + +static int test_mod(int i) +{ + return test_mod_common(test_mod_cases[i]); +} + +/* i should be set to match the iteration number that's displayed when testing */ +#define MOD_TRUNCATED_CASE(i, op1, op2, ex) \ + { \ + /* op1 */ op1, \ + /* op1_size */ LIMBSOF(op1), \ + /* op2 */ op2, \ + /* op2_size */ LIMBSOF(op2), \ + /* ex1 */ ex, \ + /* ex1_size */ LIMBSOF(ex), \ + /* ex2 */ NULL, \ + /* ex2_size */ 0, \ + /* op1_live_size */ LIMBSOF(op1) + 1, \ + /* op2_live_size */ LIMBSOF(op2) + 2, \ + /* res1_live_size */ LIMBSOF(ex) / 2, \ + /* res2_live_size */ 0, \ + /* check1_size */ LIMBSOF(ex) / 2, \ + /* check2_size */ 0, \ + /* extended_limb_value1 */ EXTENDED_LIMB_ZERO, \ + /* extended_limb_value2 */ 0, \ + } + +static struct test_case_st test_mod_truncate_cases[] = { + MOD_TRUNCATED_CASE(1, num0, num0, ex_rem_num0_num0), + MOD_TRUNCATED_CASE(2, num0, num1, ex_rem_num0_num1), + MOD_TRUNCATED_CASE(3, num0, num2, ex_rem_num0_num2), + MOD_TRUNCATED_CASE(4, num0, num3, ex_rem_num0_num3), + MOD_TRUNCATED_CASE(5, num1, num0, ex_rem_num1_num0), + MOD_TRUNCATED_CASE(6, num1, num1, ex_rem_num1_num1), + MOD_TRUNCATED_CASE(7, num1, num2, ex_rem_num1_num2), + MOD_TRUNCATED_CASE(8, num1, num3, ex_rem_num1_num3), + MOD_TRUNCATED_CASE(9, num2, num0, ex_rem_num2_num0), + MOD_TRUNCATED_CASE(10, num2, num1, ex_rem_num2_num1), + MOD_TRUNCATED_CASE(11, num2, num2, ex_rem_num2_num2), + MOD_TRUNCATED_CASE(12, num2, num3, ex_rem_num2_num3), + MOD_TRUNCATED_CASE(13, num3, num0, ex_rem_num3_num0), + MOD_TRUNCATED_CASE(14, num3, num1, ex_rem_num3_num1), + MOD_TRUNCATED_CASE(15, num3, num2, ex_rem_num3_num2), + MOD_TRUNCATED_CASE(16, num3, num3, ex_rem_num3_num3), + + /* Edge cases */ + MOD_TRUNCATED_CASE(17, num5, num5, ex_rem_num5_num5), + MOD_TRUNCATED_CASE(18, num6, num6, ex_rem_num6_num6), +}; + +static int test_mod_truncated(int i) +{ + return test_mod_common(test_mod_truncate_cases[i]); +} + +static int check_div_by_zero_error(void) +{ + unsigned long err = ERR_get_error(); + + return TEST_ulong_ne(err, 0) + && TEST_int_eq(ERR_GET_LIB(err), ERR_LIB_OSSL_FN) + && TEST_int_eq(ERR_GET_REASON(err), OSSL_FN_R_DIV_BY_ZERO); +} + +static int test_div_by_zero_common(int test_mod) +{ + int ret = 1; + OSSL_FN *fn = NULL, *fd = NULL, *fq = NULL, *fr = NULL; + OSSL_FN_CTX *ctx = NULL; + size_t n_new_limbs = LIMBSOF(num0) + 1; + size_t d_new_limbs = LIMBSOF(num4) + 2; + size_t q_limbs = LIMBSOF(num0) + 1; + size_t r_limbs = LIMBSOF(num0) + 1; + size_t ctx_numcopy_limbs = ((n_new_limbs <= d_new_limbs) ? d_new_limbs : n_new_limbs) + 1; + size_t ctx_divcopy_limbs = d_new_limbs; + size_t ctx_tmp_limbs = d_new_limbs + 1; + size_t ctx_res_limbs = n_new_limbs; + size_t ctx_max_limbs = ctx_numcopy_limbs + ctx_divcopy_limbs + ctx_res_limbs + ctx_tmp_limbs; + + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 4, ctx_max_limbs)) + || !TEST_ptr(fn = OSSL_FN_new_limbs(n_new_limbs)) + || !TEST_ptr(fd = OSSL_FN_new_limbs(d_new_limbs)) + || !TEST_ptr(fq = OSSL_FN_new_limbs(q_limbs)) + || !TEST_ptr(fr = OSSL_FN_new_limbs(r_limbs)) + || !TEST_true(ossl_fn_set_words(fn, num0, LIMBSOF(num0)))) { + ret = 0; + goto end; + } + + ERR_clear_error(); + if (test_mod) { + if (!TEST_false(OSSL_FN_mod(fr, fn, fd, ctx)) + || !TEST_true(check_div_by_zero_error())) + ret = 0; + } else { + if (!TEST_false(OSSL_FN_div(fq, fr, fn, fd, ctx)) + || !TEST_true(check_div_by_zero_error())) + ret = 0; + } + +end: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fn); + OSSL_FN_free(fd); + OSSL_FN_free(fq); + OSSL_FN_free(fr); + + return ret; +} + +static int test_div_by_zero(void) +{ + return test_div_by_zero_common(0); +} + +static int test_mod_by_zero(void) +{ + return test_div_by_zero_common(1); +} + +/* + * Test OSSL_FN_div() with r == NULL, i.e. quotient only. + * Reuses test_div_cases since the expected quotient is the same. + */ +static int test_div_quotient_only_common(struct test_case_st test_case) +{ + int ret = 1; + const OSSL_FN_ULONG *n = test_case.op1; + size_t n_limbs = test_case.op1_size; + const OSSL_FN_ULONG *d = test_case.op2; + size_t d_limbs = test_case.op2_size; + const OSSL_FN_ULONG *ex_q = test_case.ex1; + size_t n_new_limbs = test_case.op1_live_size; + size_t d_new_limbs = test_case.op2_live_size; + size_t q_limbs = test_case.res1_live_size; + size_t check_q_limbs = test_case.check1_size; + OSSL_FN_ULONG extended_q = test_case.extended_limb_value1; + OSSL_FN *fn = NULL, *fd = NULL, *fq = NULL; + const OSSL_FN_ULONG *u = NULL; + + OSSL_FN_CTX *ctx = NULL; + if (!TEST_ptr(fn = OSSL_FN_new_limbs(n_new_limbs)) + || !TEST_ptr(fd = OSSL_FN_new_limbs(d_new_limbs)) + || !TEST_true(ossl_fn_set_words(fn, n, n_limbs)) + || !TEST_true(ossl_fn_set_words(fd, d, d_limbs)) + || !TEST_ptr(fq = OSSL_FN_new_limbs(q_limbs)) + || !TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_div_ctx_size(fq, NULL, fn, fd)))) { + ret = 0; + goto end; + } + + if (!TEST_true(pollute(fq, 0, q_limbs)) + || !TEST_true(OSSL_FN_div(fq, NULL, fn, fd, ctx)) + || !TEST_ptr(u = ossl_fn_get_words(fq)) + || !TEST_mem_eq(u, check_q_limbs * OSSL_FN_BYTES, + ex_q, check_q_limbs * OSSL_FN_BYTES) + || !TEST_true(check_limbs_value(fq, check_q_limbs, q_limbs, extended_q))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fn); + OSSL_FN_free(fd); + OSSL_FN_free(fq); + + return ret; +} + +static int test_div_quotient_only(int i) +{ + return test_div_quotient_only_common(test_div_cases[i]); +} + +static int test_div_quotient_only_truncated(int i) +{ + return test_div_quotient_only_common(test_div_truncate_cases[i]); +} + +/*- + * Focused tests for OSSL_FN_rand() / OSSL_FN_priv_rand() and the range + * variants. Random values cannot be compared against a fixed oracle, so + * these tests verify the mathematical contract the functions guarantee: + * the result fits in |bits|, the |top| and |bottom| bit constraints hold, + * the destination's high limbs are zeroed, and range results satisfy + * 0 <= r < range. The byte-to-limb shaping is exercised through + * non-limb-multiple bit counts and wider-than-needed destinations. + */ +struct rand_bits_case_st { + int bits; + int top; + int bottom; +}; + +static const struct rand_bits_case_st rand_bits_cases[] = { + /* bit counts that are not limb multiples, to stress the top-byte mask */ + { 1, OSSL_FN_RAND_TOP_ANY, OSSL_FN_RAND_BOTTOM_ANY }, + { 1, OSSL_FN_RAND_TOP_ONE, OSSL_FN_RAND_BOTTOM_ANY }, + { 7, OSSL_FN_RAND_TOP_ANY, OSSL_FN_RAND_BOTTOM_ANY }, + { 7, OSSL_FN_RAND_TOP_ONE, OSSL_FN_RAND_BOTTOM_ODD }, + { 7, OSSL_FN_RAND_TOP_TWO, OSSL_FN_RAND_BOTTOM_ODD }, + { OSSL_FN_BITS - 1, OSSL_FN_RAND_TOP_ANY, OSSL_FN_RAND_BOTTOM_ANY }, + { OSSL_FN_BITS - 1, OSSL_FN_RAND_TOP_ONE, OSSL_FN_RAND_BOTTOM_ODD }, + { OSSL_FN_BITS, OSSL_FN_RAND_TOP_ANY, OSSL_FN_RAND_BOTTOM_ANY }, + { OSSL_FN_BITS, OSSL_FN_RAND_TOP_TWO, OSSL_FN_RAND_BOTTOM_ODD }, + { OSSL_FN_BITS + 1, OSSL_FN_RAND_TOP_ANY, OSSL_FN_RAND_BOTTOM_ANY }, + { OSSL_FN_BITS + 1, OSSL_FN_RAND_TOP_ONE, OSSL_FN_RAND_BOTTOM_ANY }, + { 3 * OSSL_FN_BITS, OSSL_FN_RAND_TOP_TWO, OSSL_FN_RAND_BOTTOM_ODD }, +}; + +static int test_rand_bits(int i) +{ + int ret = 0, bits = rand_bits_cases[i].bits; + int top = rand_bits_cases[i].top; + int bottom = rand_bits_cases[i].bottom; + /* Destination sized with one extra limb to check zero-padding above bits. */ + size_t limbs_needed = (bits + OSSL_FN_BITS - 1) / OSSL_FN_BITS; + size_t dst_limbs = limbs_needed + 1; + OSSL_FN *r = NULL; + const OSSL_FN_ULONG *words = NULL; + size_t dsize, j; + + if (!TEST_ptr(r = OSSL_FN_new_limbs(dst_limbs)) + || !TEST_true(pollute(r, 0, dst_limbs)) + /* Use the private pool; the public one is exercised by test_rand below. */ + || !TEST_true(OSSL_FN_priv_rand(r, bits, top, bottom, 0, NULL))) + goto err; + + /* The result must fit in |bits| bits. */ + if (!TEST_size_t_le(OSSL_FN_num_bits(r), (size_t)bits)) + goto err; + + /* top constraint: the requested high bit(s) must be set. */ + if (top == OSSL_FN_RAND_TOP_ONE + && !TEST_int_eq(OSSL_FN_is_bit_set(r, bits - 1), 1)) + goto err; + if (top == OSSL_FN_RAND_TOP_TWO) { + if (!TEST_int_eq(OSSL_FN_is_bit_set(r, bits - 1), 1) + || !TEST_int_eq(OSSL_FN_is_bit_set(r, bits - 2), 1)) + goto err; + } + + /* bottom constraint: the low bit must be set when ODD is requested. */ + if (bottom == OSSL_FN_RAND_BOTTOM_ODD + && !TEST_int_eq(OSSL_FN_is_bit_set(r, 0), 1)) + goto err; + + /* + * Limbs above those needed for |bits| must be zeroed. bytes = + * (bits+7)/8, so limbs covering the bytes are (bytes + BYTES - 1) / BYTES; + * anything above that is padding. + */ + words = ossl_fn_get_words(r); + dsize = ossl_fn_get_dsize(r); + for (j = limbs_needed; j < dsize; j++) + if (!TEST_size_t_eq(words[j], 0)) + goto err; + + ret = 1; +err: + OSSL_FN_free(r); + return ret; +} + +/* The public-pool variant (OSSL_FN_rand) must satisfy the same contract. */ +static int test_rand(int i) +{ + int ret = 0, bits = rand_bits_cases[i].bits; + int top = rand_bits_cases[i].top; + int bottom = rand_bits_cases[i].bottom; + size_t limbs_needed = (bits + OSSL_FN_BITS - 1) / OSSL_FN_BITS; + OSSL_FN *r = NULL; + + if (!TEST_ptr(r = OSSL_FN_new_limbs(limbs_needed)) + || !TEST_true(pollute(r, 0, limbs_needed)) + || !TEST_true(OSSL_FN_rand(r, bits, top, bottom, 0, NULL))) + goto err; + if (!TEST_size_t_le(OSSL_FN_num_bits(r), (size_t)bits)) + goto err; + if (top == OSSL_FN_RAND_TOP_ONE + && !TEST_int_eq(OSSL_FN_is_bit_set(r, bits - 1), 1)) + goto err; + if (top == OSSL_FN_RAND_TOP_TWO + && (!TEST_int_eq(OSSL_FN_is_bit_set(r, bits - 1), 1) + || !TEST_int_eq(OSSL_FN_is_bit_set(r, bits - 2), 1))) + goto err; + if (bottom == OSSL_FN_RAND_BOTTOM_ODD + && !TEST_int_eq(OSSL_FN_is_bit_set(r, 0), 1)) + goto err; + ret = 1; +err: + OSSL_FN_free(r); + return ret; +} + +/* A destination too small for |bits| is an error, not an expansion. */ +static int test_rand_result_too_small(void) +{ + int ret = 0; + OSSL_FN *r = NULL; + + /* bits needs 2 limbs on every platform; one-limb destination is too small. */ + if (!TEST_ptr(r = OSSL_FN_new_limbs(1)) + || !TEST_true(pollute(r, 0, 1)) + || !TEST_false(OSSL_FN_priv_rand(r, 2 * OSSL_FN_BITS, + OSSL_FN_RAND_TOP_ANY, + OSSL_FN_RAND_BOTTOM_ANY, 0, NULL)) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + OSSL_FN_R_RESULT_ARG_TOO_SMALL)) + goto err; + ret = 1; +err: + OSSL_FN_free(r); + return ret; +} + +/* bits == 0 with top/bottom set, or bits == 1 with top > 0, are BITS_TOO_SMALL errors. */ +static int test_rand_bits_too_small(void) +{ + int ret = 0; + OSSL_FN *r = NULL; + + if (!TEST_ptr(r = OSSL_FN_new_limbs(2))) + goto err; + + ERR_clear_error(); + if (!TEST_false(OSSL_FN_priv_rand(r, 0, OSSL_FN_RAND_TOP_ONE, + OSSL_FN_RAND_BOTTOM_ANY, 0, NULL)) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + OSSL_FN_R_BITS_TOO_SMALL)) + goto err; + + ERR_clear_error(); + if (!TEST_false(OSSL_FN_priv_rand(r, 1, OSSL_FN_RAND_TOP_TWO, + OSSL_FN_RAND_BOTTOM_ANY, 0, NULL)) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + OSSL_FN_R_BITS_TOO_SMALL)) + goto err; + + /* bits == 0 with ANY/ANY is the one legal zero-bit case: result is zero. */ + if (!TEST_true(OSSL_FN_priv_rand(r, 0, OSSL_FN_RAND_TOP_ANY, + OSSL_FN_RAND_BOTTOM_ANY, 0, NULL)) + || !TEST_true(OSSL_FN_is_zero(r))) + goto err; + + ret = 1; +err: + OSSL_FN_free(r); + return ret; +} + +/* + * Range variants: 0 <= r < range must hold. Covers both range shapes + * (range = 100..._2 and range = 11..._2 / 101..._2) and the n == 1 case. + */ +static const OSSL_FN_ULONG range_words[][4] = { + { OSSL_FN_ULONG_C(1) }, /* range == 1 */ + { OSSL_FN_ULONG_C(0), OSSL_FN_ULONG_C(1) }, /* 2^BITS: 100..._2 */ + { OSSL_FN_ULONG_C(3) }, /* 11_2 */ + { OSSL_FN_ULONG_C(5) }, /* 101_2 */ + { OSSL_FN_ULONG_C(0), OSSL_FN_ULONG_C(3) }, /* 3 * 2^BITS: 11..._2 */ + { OSSL_FN_ULONG_C(2), OSSL_FN_ULONG_C(1) }, /* 2^BITS + 2: 101..._2 */ +}; + +static int test_rand_range(int i) +{ + int ret = 0; + const OSSL_FN_ULONG *rw = range_words[i]; + size_t range_limbs = OSSL_NELEM(range_words[i]); + OSSL_FN *range = NULL, *r = NULL; + + if (!TEST_ptr(range = OSSL_FN_new_limbs(range_limbs)) + || !TEST_true(ossl_fn_set_words(range, rw, range_limbs)) + || !TEST_ptr(r = OSSL_FN_new_limbs(range_limbs + 1)) + || !TEST_true(pollute(r, 0, range_limbs + 1))) + goto err; + + if (!TEST_true(OSSL_FN_priv_rand_range(r, range, 0, NULL))) + goto err; + + /* 0 <= r < range (OSSL_FN is unsigned, so the lower bound is implicit). */ + if (!TEST_int_lt(OSSL_FN_cmp(r, range), 0)) + goto err; + + ret = 1; +err: + OSSL_FN_free(range); + OSSL_FN_free(r); + return ret; +} + +/* A zero range is rejected as INVALID_RANGE. */ +static int test_rand_range_zero(void) +{ + int ret = 0; + OSSL_FN *range = NULL, *r = NULL; + + if (!TEST_ptr(range = OSSL_FN_new_limbs(2)) + || !TEST_true(OSSL_FN_zero(range)) + || !TEST_ptr(r = OSSL_FN_new_limbs(2)) + || !TEST_true(pollute(r, 0, 2)) + || !TEST_false(OSSL_FN_rand_range(r, range, 0, NULL)) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + OSSL_FN_R_INVALID_RANGE)) + goto err; + ret = 1; +err: + OSSL_FN_free(range); + OSSL_FN_free(r); + return ret; +} + +/* + * Regression test for an exactly-sized destination with a sparse range + * (range = 100..._2): the optimized path draws n + 1 bits and needs room for + * them, so an |r| sized to hold exactly num_bits(range) bits must fall back to + * standard n-bit rejection sampling rather than fail with + * OSSL_FN_R_RESULT_ARG_TOO_SMALL. + */ +static int test_rand_range_exactly_sized(void) +{ + int ret = 0; + OSSL_FN_ULONG rw[1] = { OSSL_FN_ULONG_C(1) << (OSSL_FN_BITS - 1) }; + OSSL_FN *range = NULL, *r = NULL; + + /* range = 2^(BITS-1) = 100..._2, so num_bits(range) == BITS (1 limb). */ + if (!TEST_ptr(range = OSSL_FN_new_limbs(1)) + || !TEST_true(ossl_fn_set_words(range, rw, 1)) + /* r sized to hold exactly BITS bits: one limb, no slack for n + 1. */ + || !TEST_ptr(r = OSSL_FN_new_limbs(1)) + || !TEST_true(pollute(r, 0, 1))) + goto err; + + if (!TEST_true(OSSL_FN_priv_rand_range(r, range, 0, NULL))) + goto err; + + /* 0 <= r < range. */ + if (!TEST_int_lt(OSSL_FN_cmp(r, range), 0)) + goto err; + + ret = 1; +err: + OSSL_FN_free(range); + OSSL_FN_free(r); + return ret; +} + +static struct mod_op_test_st test_mod_add_cases[] = { + { num0, LIMBSOF(num0), num1, LIMBSOF(num1), num2, LIMBSOF(num2), 0 }, + { num2, LIMBSOF(num2), num3, LIMBSOF(num3), num2, LIMBSOF(num2), 0 }, + { num4, LIMBSOF(num4), num0, LIMBSOF(num0), num3, LIMBSOF(num3), 0 }, + { num5, LIMBSOF(num5), num5, LIMBSOF(num5), num6, LIMBSOF(num6), 0 }, +}; + +static struct mod_op_test_st test_mod_sub_cases[] = { + { num0, LIMBSOF(num0), num1, LIMBSOF(num1), num2, LIMBSOF(num2), 0 }, + { num3, LIMBSOF(num3), num2, LIMBSOF(num2), num2, LIMBSOF(num2), 0 }, + { num3, LIMBSOF(num3), num3, LIMBSOF(num3), num2, LIMBSOF(num2), 0 }, + { num5, LIMBSOF(num5), num4, LIMBSOF(num4), num6, LIMBSOF(num6), 0 }, +}; + +static struct mod_op_test_st test_mod_mul_cases[] = { + { num0, LIMBSOF(num0), num1, LIMBSOF(num1), num2, LIMBSOF(num2), 0 }, + { num2, LIMBSOF(num2), num3, LIMBSOF(num3), num2, LIMBSOF(num2), 0 }, + { num0, LIMBSOF(num0), num0, LIMBSOF(num0), num3, LIMBSOF(num3), 0 }, + { num5, LIMBSOF(num5), num5, LIMBSOF(num5), num6, LIMBSOF(num6), 0 }, +}; + +static struct mod_op_test_st test_mod_sqr_cases[] = { + { num0, LIMBSOF(num0), NULL, 0, num2, LIMBSOF(num2), 0 }, + { num2, LIMBSOF(num2), NULL, 0, num2, LIMBSOF(num2), 0 }, + { num5, LIMBSOF(num5), NULL, 0, num6, LIMBSOF(num6), 0 }, +}; + +static struct mod_op_test_st test_mod_lshift1_cases[] = { + { num0, LIMBSOF(num0), NULL, 0, num2, LIMBSOF(num2), 0 }, + { num2, LIMBSOF(num2), NULL, 0, num3, LIMBSOF(num3), 0 }, + { num5, LIMBSOF(num5), NULL, 0, num6, LIMBSOF(num6), 0 }, +}; + +static struct mod_op_test_st test_mod_lshift_cases[] = { + { num0, LIMBSOF(num0), NULL, 0, num2, LIMBSOF(num2), 1 }, + { num0, LIMBSOF(num0), NULL, 0, num2, LIMBSOF(num2), 3 }, + { num2, LIMBSOF(num2), NULL, 0, num3, LIMBSOF(num3), 5 }, + { num5, LIMBSOF(num5), NULL, 0, num6, LIMBSOF(num6), 7 }, +}; + +static int test_mod_add(int i) +{ + struct mod_op_test_st *tc = &test_mod_add_cases[i]; + size_t m_size = tc->m_size; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fb = NULL, *fm = NULL; + OSSL_FN *r_gen = NULL, *r_quick = NULL, *expected = NULL; + OSSL_FN *tmp = NULL, *fa_red = NULL, *fb_red = NULL; + int ret = 0; + const OSSL_FN_ULONG *u_gen, *u_quick, *u_exp; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 8 * m_size + 8); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fb = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r_gen = OSSL_FN_new_limbs(m_size); + r_quick = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(m_size); + fa_red = OSSL_FN_new_limbs(m_size); + fb_red = OSSL_FN_new_limbs(m_size); + tmp = OSSL_FN_new_limbs(m_size + 1); + if (!TEST_ptr(fa) || !TEST_ptr(fb) || !TEST_ptr(fm) + || !TEST_ptr(r_gen) || !TEST_ptr(r_quick) || !TEST_ptr(expected) + || !TEST_ptr(fa_red) || !TEST_ptr(fb_red) || !TEST_ptr(tmp)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, tc->a, tc->a_size)) + || !TEST_true(ossl_fn_set_words(fb, tc->b, tc->b_size)) + || !TEST_true(ossl_fn_set_words(fm, tc->m, tc->m_size))) + goto err; + + /* expected = (a + b) mod m */ + if (!TEST_true(OSSL_FN_add(tmp, fa, fb))) + goto err; + if (!TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx))) + goto err; + + /* general = mod_add(a, b, m, ctx) */ + if (!TEST_true(OSSL_FN_mod_add(r_gen, fa, fb, fm, ctx))) + goto err; + + /* reduce a and b for quick variant */ + if (!TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fb_red, fb, fm, ctx))) + goto err; + + /* quick = mod_add_quick(a_red, b_red, m) */ + if (!TEST_true(OSSL_FN_mod_add_quick(r_quick, fa_red, fb_red, fm))) + goto err; + + u_gen = ossl_fn_get_words(r_gen); + u_quick = ossl_fn_get_words(r_quick); + u_exp = ossl_fn_get_words(expected); + + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_quick, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_quick, m_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fb); + OSSL_FN_free(fm); + OSSL_FN_free(r_gen); + OSSL_FN_free(r_quick); + OSSL_FN_free(expected); + OSSL_FN_free(fa_red); + OSSL_FN_free(fb_red); + OSSL_FN_free(tmp); + return ret; +} + +static int test_mod_sub(int i) +{ + struct mod_op_test_st *tc = &test_mod_sub_cases[i]; + size_t m_size = tc->m_size; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fb = NULL, *fm = NULL; + OSSL_FN *r_gen = NULL, *r_quick = NULL, *expected = NULL; + OSSL_FN *tmp = NULL, *fa_red = NULL, *fb_red = NULL; + int ret = 0; + const OSSL_FN_ULONG *u_gen, *u_quick, *u_exp; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 8 * m_size + 8); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fb = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r_gen = OSSL_FN_new_limbs(m_size); + r_quick = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(m_size); + fa_red = OSSL_FN_new_limbs(m_size); + fb_red = OSSL_FN_new_limbs(m_size); + tmp = OSSL_FN_new_limbs(m_size); + if (!TEST_ptr(fa) || !TEST_ptr(fb) || !TEST_ptr(fm) + || !TEST_ptr(r_gen) || !TEST_ptr(r_quick) || !TEST_ptr(expected) + || !TEST_ptr(fa_red) || !TEST_ptr(fb_red) || !TEST_ptr(tmp)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, tc->a, tc->a_size)) + || !TEST_true(ossl_fn_set_words(fb, tc->b, tc->b_size)) + || !TEST_true(ossl_fn_set_words(fm, tc->m, tc->m_size))) + goto err; + + /* expected = (a - b) mod m */ + if (!TEST_true(OSSL_FN_sub(tmp, fa, fb))) + goto err; + if (!TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx))) + goto err; + + /* general = mod_sub(a, b, m, ctx) */ + if (!TEST_true(OSSL_FN_mod_sub(r_gen, fa, fb, fm, ctx))) + goto err; + + /* reduce a and b for quick variant */ + if (!TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fb_red, fb, fm, ctx))) + goto err; + + /* quick = mod_sub_quick(a_red, b_red, m) */ + if (!TEST_true(OSSL_FN_mod_sub_quick(r_quick, fa_red, fb_red, fm))) + goto err; + + u_gen = ossl_fn_get_words(r_gen); + u_quick = ossl_fn_get_words(r_quick); + u_exp = ossl_fn_get_words(expected); + + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_quick, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_quick, m_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fb); + OSSL_FN_free(fm); + OSSL_FN_free(r_gen); + OSSL_FN_free(r_quick); + OSSL_FN_free(expected); + OSSL_FN_free(fa_red); + OSSL_FN_free(fb_red); + OSSL_FN_free(tmp); + return ret; +} + +static int test_mod_mul(int i) +{ + struct mod_op_test_st *tc = &test_mod_mul_cases[i]; + size_t m_size = tc->m_size; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fb = NULL, *fm = NULL; + OSSL_FN *r = NULL, *expected = NULL, *tmp = NULL; + int ret = 0; + const OSSL_FN_ULONG *u_r, *u_exp; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 8 * m_size + 8); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fb = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(m_size); + tmp = OSSL_FN_new_limbs(m_size * 2); + if (!TEST_ptr(fa) || !TEST_ptr(fb) || !TEST_ptr(fm) + || !TEST_ptr(r) || !TEST_ptr(expected) || !TEST_ptr(tmp)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, tc->a, tc->a_size)) + || !TEST_true(ossl_fn_set_words(fb, tc->b, tc->b_size)) + || !TEST_true(ossl_fn_set_words(fm, tc->m, tc->m_size))) + goto err; + + /* expected = (a * b) mod m */ + if (!TEST_true(OSSL_FN_mul(tmp, fa, fb, ctx))) + goto err; + if (!TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx))) + goto err; + + /* r = mod_mul(a, b, m, ctx) */ + if (!TEST_true(OSSL_FN_mod_mul(r, fa, fb, fm, ctx))) + goto err; + + u_r = ossl_fn_get_words(r); + u_exp = ossl_fn_get_words(expected); + + if (!TEST_mem_eq(u_r, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fb); + OSSL_FN_free(fm); + OSSL_FN_free(r); + OSSL_FN_free(expected); + OSSL_FN_free(tmp); + return ret; +} + +static int test_mod_sqr(int i) +{ + struct mod_op_test_st *tc = &test_mod_sqr_cases[i]; + size_t m_size = tc->m_size; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fm = NULL; + OSSL_FN *r = NULL, *expected = NULL, *tmp = NULL; + int ret = 0; + const OSSL_FN_ULONG *u_r, *u_exp; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 8 * m_size + 8); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(m_size); + tmp = OSSL_FN_new_limbs(m_size * 2); + if (!TEST_ptr(fa) || !TEST_ptr(fm) + || !TEST_ptr(r) || !TEST_ptr(expected) || !TEST_ptr(tmp)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, tc->a, tc->a_size)) + || !TEST_true(ossl_fn_set_words(fm, tc->m, tc->m_size))) + goto err; + + /* expected = (a * a) mod m */ + if (!TEST_true(OSSL_FN_sqr(tmp, fa, ctx))) + goto err; + if (!TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx))) + goto err; + + /* r = mod_sqr(a, m, ctx) */ + if (!TEST_true(OSSL_FN_mod_sqr(r, fa, fm, ctx))) + goto err; + + u_r = ossl_fn_get_words(r); + u_exp = ossl_fn_get_words(expected); + + if (!TEST_mem_eq(u_r, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fm); + OSSL_FN_free(r); + OSSL_FN_free(expected); + OSSL_FN_free(tmp); + return ret; +} + +static int test_mod_lshift1(int i) +{ + struct mod_op_test_st *tc = &test_mod_lshift1_cases[i]; + size_t m_size = tc->m_size; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fm = NULL; + OSSL_FN *r_gen = NULL, *r_quick = NULL, *expected = NULL; + OSSL_FN *tmp = NULL, *fa_red = NULL; + int ret = 0; + const OSSL_FN_ULONG *u_gen, *u_quick, *u_exp; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 8 * m_size + 8); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r_gen = OSSL_FN_new_limbs(m_size); + r_quick = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(m_size); + tmp = OSSL_FN_new_limbs(m_size + 1); + fa_red = OSSL_FN_new_limbs(m_size); + if (!TEST_ptr(fa) || !TEST_ptr(fm) + || !TEST_ptr(r_gen) || !TEST_ptr(r_quick) || !TEST_ptr(expected) + || !TEST_ptr(tmp) || !TEST_ptr(fa_red)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, tc->a, tc->a_size)) + || !TEST_true(ossl_fn_set_words(fm, tc->m, tc->m_size))) + goto err; + + /* expected = (a + a) mod m */ + if (!TEST_true(OSSL_FN_add(tmp, fa, fa))) + goto err; + if (!TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx))) + goto err; + + /* general = mod_lshift1(a, m, ctx) */ + if (!TEST_true(OSSL_FN_mod_lshift1(r_gen, fa, fm, ctx))) + goto err; + + /* reduce a for quick variant */ + if (!TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx))) + goto err; + + /* quick = mod_lshift1_quick(a_red, m) */ + if (!TEST_true(OSSL_FN_mod_lshift1_quick(r_quick, fa_red, fm))) + goto err; + + u_gen = ossl_fn_get_words(r_gen); + u_quick = ossl_fn_get_words(r_quick); + u_exp = ossl_fn_get_words(expected); + + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_quick, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_quick, m_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fm); + OSSL_FN_free(r_gen); + OSSL_FN_free(r_quick); + OSSL_FN_free(expected); + OSSL_FN_free(tmp); + OSSL_FN_free(fa_red); + return ret; +} + +static int test_mod_lshift(int i) +{ + struct mod_op_test_st *tc = &test_mod_lshift_cases[i]; + size_t m_size = tc->m_size; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fm = NULL; + OSSL_FN *r_gen = NULL, *r_quick = NULL, *expected = NULL; + OSSL_FN *tmp = NULL, *fa_red = NULL, *pow2n = NULL; + OSSL_FN_ULONG pow2_word; + int ret = 0; + const OSSL_FN_ULONG *u_gen, *u_quick, *u_exp; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 8 * m_size + 8); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r_gen = OSSL_FN_new_limbs(m_size); + r_quick = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(m_size); + tmp = OSSL_FN_new_limbs(m_size + 1); + fa_red = OSSL_FN_new_limbs(m_size); + pow2n = OSSL_FN_new_limbs(1); + if (!TEST_ptr(fa) || !TEST_ptr(fm) + || !TEST_ptr(r_gen) || !TEST_ptr(r_quick) || !TEST_ptr(expected) + || !TEST_ptr(tmp) || !TEST_ptr(fa_red) || !TEST_ptr(pow2n)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, tc->a, tc->a_size)) + || !TEST_true(ossl_fn_set_words(fm, tc->m, tc->m_size))) + goto err; + + pow2_word = ((OSSL_FN_ULONG)1) << tc->n; + if (!TEST_true(ossl_fn_set_words(pow2n, &pow2_word, 1))) + goto err; + + /* expected = (a * 2^n) mod m */ + if (!TEST_true(OSSL_FN_mul(tmp, fa, pow2n, ctx))) + goto err; + if (!TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx))) + goto err; + + /* general = mod_lshift(a, n, m, ctx) */ + if (!TEST_true(OSSL_FN_mod_lshift(r_gen, fa, tc->n, fm, ctx))) + goto err; + + /* reduce a for quick variant */ + if (!TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx))) + goto err; + + /* quick = mod_lshift_quick(a_red, n, m) */ + if (!TEST_true(OSSL_FN_mod_lshift_quick(r_quick, fa_red, tc->n, fm))) + goto err; + + u_gen = ossl_fn_get_words(r_gen); + u_quick = ossl_fn_get_words(r_quick); + u_exp = ossl_fn_get_words(expected); + + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_quick, m_size * OSSL_FN_BYTES, + u_exp, m_size * OSSL_FN_BYTES)) + goto err; + if (!TEST_mem_eq(u_gen, m_size * OSSL_FN_BYTES, + u_quick, m_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fm); + OSSL_FN_free(r_gen); + OSSL_FN_free(r_quick); + OSSL_FN_free(expected); + OSSL_FN_free(tmp); + OSSL_FN_free(fa_red); + OSSL_FN_free(pow2n); + return ret; +} + +static const OSSL_FN_ULONG mod_secp128r1_p[] = { + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff), + OSSL_FN_ULONG64_C(0xfffffffd, 0xffffffff), +}; +static const OSSL_FN_ULONG mod_secp128r1_a[] = { + OSSL_FN_ULONG64_C(0xffffffff, 0xfffffffc), + OSSL_FN_ULONG64_C(0xfffffff7, 0xffffffff), +}; +static const OSSL_FN_ULONG mod_secp128r1_x2[] = { + OSSL_FN_ULONG64_C(0x7f04aa75, 0x6b2f9496), + OSSL_FN_ULONG64_C(0x74e2ecb0, 0x826a5208), +}; +static const OSSL_FN_ULONG mod_secp128r1_x2_plus_a[] = { + OSSL_FN_ULONG64_C(0x7f04aa75, 0x6b2f9493), + OSSL_FN_ULONG64_C(0x74e2ecaa, 0x826a5208), +}; + +static const OSSL_FN_ULONG mod_sub_wide_a[] = { + OSSL_FN_ULONG_C(0x7), +#if OSSL_FN_BYTES == 4 + OSSL_FN_ULONG_C(0), +#endif + OSSL_FN_ULONG_C(0x1), +}; +static const OSSL_FN_ULONG mod_sub_wide_b[] = { + OSSL_FN_ULONG_C(0x1), +}; +static const OSSL_FN_ULONG mod_sub_wide_m[] = { + OSSL_FN_ULONG64_C(0xffffffff, 0xffffffc5), +}; +static const OSSL_FN_ULONG mod_sub_wide_expected[] = { + OSSL_FN_ULONG_C(0x41), +}; +static const OSSL_FN_ULONG mod_sub_negative_a[] = { + OSSL_FN_ULONG_C(0x1), +}; +static const OSSL_FN_ULONG mod_sub_negative_b[] = { + OSSL_FN_ULONG_C(0x3), +}; +static const OSSL_FN_ULONG mod_sub_negative_m[] = { + OSSL_FN_ULONG_C(0x5), +}; +static const OSSL_FN_ULONG mod_sub_negative_expected[] = { + OSSL_FN_ULONG_C(0x3), +}; + +static int test_mod_quick_wide_operands(void) +{ + size_t m_size = LIMBSOF(mod_secp128r1_p); + size_t wide_size = m_size + 2; + OSSL_FN *fa = NULL, *fb = NULL, *fm = NULL; + OSSL_FN *r = NULL, *expected = NULL; + const OSSL_FN_ULONG *u_r = NULL, *u_exp = NULL; + int ret = 0; + + fa = OSSL_FN_new_limbs(wide_size); + fb = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + r = OSSL_FN_new_limbs(wide_size); + expected = OSSL_FN_new_limbs(wide_size); + if (!TEST_ptr(fa) || !TEST_ptr(fb) || !TEST_ptr(fm) + || !TEST_ptr(r) || !TEST_ptr(expected)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, mod_secp128r1_x2, + LIMBSOF(mod_secp128r1_x2))) + || !TEST_true(ossl_fn_set_words(fb, mod_secp128r1_a, + LIMBSOF(mod_secp128r1_a))) + || !TEST_true(ossl_fn_set_words(fm, mod_secp128r1_p, + LIMBSOF(mod_secp128r1_p))) + || !TEST_true(ossl_fn_set_words(expected, mod_secp128r1_x2_plus_a, + LIMBSOF(mod_secp128r1_x2_plus_a))) + || !TEST_true(pollute(r, 0, wide_size)) + || !TEST_true(OSSL_FN_mod_add_quick(r, fa, fb, fm))) + goto err; + + u_r = ossl_fn_get_words(r); + u_exp = ossl_fn_get_words(expected); + if (!TEST_mem_eq(u_r, wide_size * OSSL_FN_BYTES, + u_exp, wide_size * OSSL_FN_BYTES)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, mod_secp128r1_x2_plus_a, + LIMBSOF(mod_secp128r1_x2_plus_a))) + || !TEST_true(ossl_fn_set_words(expected, mod_secp128r1_x2, + LIMBSOF(mod_secp128r1_x2))) + || !TEST_true(pollute(r, 0, wide_size)) + || !TEST_true(OSSL_FN_mod_sub_quick(r, fa, fb, fm))) + goto err; + + u_r = ossl_fn_get_words(r); + u_exp = ossl_fn_get_words(expected); + if (!TEST_mem_eq(u_r, wide_size * OSSL_FN_BYTES, + u_exp, wide_size * OSSL_FN_BYTES)) + goto err; + + ret = 1; +err: + OSSL_FN_free(fa); + OSSL_FN_free(fb); + OSSL_FN_free(fm); + OSSL_FN_free(r); + OSSL_FN_free(expected); + return ret; +} + +static int test_mod_sub_general_wide_operands(void) +{ + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fb = NULL, *fm = NULL; + OSSL_FN *r = NULL, *expected = NULL; + const OSSL_FN_ULONG *u_r = NULL, *u_exp = NULL; + int ret = 0; + + ctx = OSSL_FN_CTX_new(NULL, 4, 8, 32); + fa = OSSL_FN_new_limbs(LIMBSOF(mod_sub_wide_a)); + fb = OSSL_FN_new_limbs(LIMBSOF(mod_sub_wide_b)); + fm = OSSL_FN_new_limbs(LIMBSOF(mod_sub_wide_m)); + r = OSSL_FN_new_limbs(LIMBSOF(mod_sub_wide_m)); + expected = OSSL_FN_new_limbs(LIMBSOF(mod_sub_wide_m)); + if (!TEST_ptr(ctx) || !TEST_ptr(fa) || !TEST_ptr(fb) || !TEST_ptr(fm) + || !TEST_ptr(r) || !TEST_ptr(expected)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, mod_sub_wide_a, + LIMBSOF(mod_sub_wide_a))) + || !TEST_true(ossl_fn_set_words(fb, mod_sub_wide_b, + LIMBSOF(mod_sub_wide_b))) + || !TEST_true(ossl_fn_set_words(fm, mod_sub_wide_m, + LIMBSOF(mod_sub_wide_m))) + || !TEST_true(ossl_fn_set_words(expected, mod_sub_wide_expected, + LIMBSOF(mod_sub_wide_expected))) + || !TEST_true(pollute(r, 0, LIMBSOF(mod_sub_wide_m))) + || !TEST_true(OSSL_FN_mod_sub(r, fa, fb, fm, ctx))) + goto err; + + u_r = ossl_fn_get_words(r); + u_exp = ossl_fn_get_words(expected); + if (!TEST_mem_eq(u_r, LIMBSOF(mod_sub_wide_m) * OSSL_FN_BYTES, + u_exp, LIMBSOF(mod_sub_wide_m) * OSSL_FN_BYTES)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, mod_sub_negative_a, + LIMBSOF(mod_sub_negative_a))) + || !TEST_true(ossl_fn_set_words(fb, mod_sub_negative_b, + LIMBSOF(mod_sub_negative_b))) + || !TEST_true(ossl_fn_set_words(fm, mod_sub_negative_m, + LIMBSOF(mod_sub_negative_m))) + || !TEST_true(ossl_fn_set_words(expected, mod_sub_negative_expected, + LIMBSOF(mod_sub_negative_expected))) + || !TEST_true(pollute(r, 0, LIMBSOF(mod_sub_negative_m))) + || !TEST_true(OSSL_FN_mod_sub(r, fa, fb, fm, ctx))) + goto err; + + u_r = ossl_fn_get_words(r); + u_exp = ossl_fn_get_words(expected); + if (!TEST_mem_eq(u_r, LIMBSOF(mod_sub_negative_m) * OSSL_FN_BYTES, + u_exp, LIMBSOF(mod_sub_negative_m) * OSSL_FN_BYTES)) + goto err; + + ret = 1; +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fb); + OSSL_FN_free(fm); + OSSL_FN_free(r); + OSSL_FN_free(expected); + return ret; +} + +static int test_mod_ops_result_size(int i) +{ + size_t m_size = LIMBSOF(num7); + size_t r_size = i == 0 ? m_size - 1 : i == 1 ? m_size + : m_size + 2; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *fa = NULL, *fb = NULL, *fm = NULL, *expected = NULL; + OSSL_FN *r_gen = NULL, *r_quick = NULL, *tmp = NULL, *fa_red = NULL; + OSSL_FN *fb_red = NULL, *pow2n = NULL; + OSSL_FN_ULONG pow2_word = 1 << 7; + const OSSL_FN_ULONG *u_gen = NULL, *u_quick = NULL, *u_exp = NULL; + int ret = 0; + + ctx = OSSL_FN_CTX_new(NULL, 6, 12, 16 * m_size + 16); + if (!TEST_ptr(ctx)) + goto err; + + fa = OSSL_FN_new_limbs(m_size); + fb = OSSL_FN_new_limbs(m_size); + fm = OSSL_FN_new_limbs(m_size); + expected = OSSL_FN_new_limbs(r_size); + r_gen = OSSL_FN_new_limbs(r_size); + r_quick = OSSL_FN_new_limbs(r_size); + tmp = OSSL_FN_new_limbs(2 * m_size); + fa_red = OSSL_FN_new_limbs(m_size); + fb_red = OSSL_FN_new_limbs(m_size); + pow2n = OSSL_FN_new_limbs(1); + if (!TEST_ptr(fa) || !TEST_ptr(fb) || !TEST_ptr(fm) + || !TEST_ptr(expected) || !TEST_ptr(r_gen) || !TEST_ptr(r_quick) + || !TEST_ptr(tmp) || !TEST_ptr(fa_red) || !TEST_ptr(fb_red) + || !TEST_ptr(pow2n)) + goto err; + + if (!TEST_true(ossl_fn_set_words(fa, num5, LIMBSOF(num5))) + || !TEST_true(ossl_fn_set_words(fb, num5, LIMBSOF(num5))) + || !TEST_true(ossl_fn_set_words(fm, num7, LIMBSOF(num7))) + || !TEST_true(ossl_fn_set_words(pow2n, &pow2_word, 1))) + goto err; + +#define CHECK_MOD_OP_RESULT(opname) \ + do { \ + u_gen = ossl_fn_get_words(r_gen); \ + u_quick = ossl_fn_get_words(r_quick); \ + u_exp = ossl_fn_get_words(expected); \ + if (!TEST_mem_eq(u_gen, r_size * OSSL_FN_BYTES, \ + u_exp, r_size * OSSL_FN_BYTES)) { \ + TEST_note("%s general, r_size = %zu", opname, r_size); \ + goto err; \ + } \ + if (!TEST_mem_eq(u_quick, r_size * OSSL_FN_BYTES, \ + u_exp, r_size * OSSL_FN_BYTES)) { \ + TEST_note("%s quick, r_size = %zu", opname, r_size); \ + goto err; \ + } \ + } while (0) + + if (!TEST_true(pollute(expected, 0, r_size)) + || !TEST_true(pollute(r_gen, 0, r_size)) + || !TEST_true(pollute(r_quick, 0, r_size)) + || !TEST_true(OSSL_FN_add(tmp, fa, fb)) + || !TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx)) + || !TEST_true(OSSL_FN_mod_add(r_gen, fa, fb, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fb_red, fb, fm, ctx)) + || !TEST_true(OSSL_FN_mod_add_quick(r_quick, fa_red, fb_red, fm))) + goto err; + CHECK_MOD_OP_RESULT("mod_add"); + + if (!TEST_true(ossl_fn_set_words(fa, num5, LIMBSOF(num5))) + || !TEST_true(ossl_fn_set_words(fb, num4, LIMBSOF(num4))) + || !TEST_true(pollute(expected, 0, r_size)) + || !TEST_true(pollute(r_gen, 0, r_size)) + || !TEST_true(pollute(r_quick, 0, r_size)) + || !TEST_true(OSSL_FN_sub(tmp, fa, fb)) + || !TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx)) + || !TEST_true(OSSL_FN_mod_sub(r_gen, fa, fb, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fb_red, fb, fm, ctx)) + || !TEST_true(OSSL_FN_mod_sub_quick(r_quick, fa_red, fb_red, fm))) + goto err; + CHECK_MOD_OP_RESULT("mod_sub"); + + if (!TEST_true(ossl_fn_set_words(fb, num5, LIMBSOF(num5))) + || !TEST_true(pollute(expected, 0, r_size)) + || !TEST_true(pollute(r_gen, 0, r_size)) + || !TEST_true(pollute(r_quick, 0, r_size)) + || !TEST_true(OSSL_FN_mul(tmp, fa, fb, ctx)) + || !TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx)) + || !TEST_true(OSSL_FN_mod_mul(r_gen, fa, fb, fm, ctx)) + || !TEST_true(OSSL_FN_mod_mul(r_quick, fa, fb, fm, ctx))) + goto err; + CHECK_MOD_OP_RESULT("mod_mul"); + + if (!TEST_true(pollute(expected, 0, r_size)) + || !TEST_true(pollute(r_gen, 0, r_size)) + || !TEST_true(pollute(r_quick, 0, r_size)) + || !TEST_true(OSSL_FN_sqr(tmp, fa, ctx)) + || !TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx)) + || !TEST_true(OSSL_FN_mod_sqr(r_gen, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod_sqr(r_quick, fa, fm, ctx))) + goto err; + CHECK_MOD_OP_RESULT("mod_sqr"); + + if (!TEST_true(pollute(expected, 0, r_size)) + || !TEST_true(pollute(r_gen, 0, r_size)) + || !TEST_true(pollute(r_quick, 0, r_size)) + || !TEST_true(OSSL_FN_add(tmp, fa, fa)) + || !TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx)) + || !TEST_true(OSSL_FN_mod_lshift1(r_gen, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod_lshift1_quick(r_quick, fa_red, fm))) + goto err; + CHECK_MOD_OP_RESULT("mod_lshift1"); + + if (!TEST_true(pollute(expected, 0, r_size)) + || !TEST_true(pollute(r_gen, 0, r_size)) + || !TEST_true(pollute(r_quick, 0, r_size)) + || !TEST_true(OSSL_FN_mul(tmp, fa, pow2n, ctx)) + || !TEST_true(OSSL_FN_mod(expected, tmp, fm, ctx)) + || !TEST_true(OSSL_FN_mod_lshift(r_gen, fa, 7, fm, ctx)) + || !TEST_true(OSSL_FN_mod(fa_red, fa, fm, ctx)) + || !TEST_true(OSSL_FN_mod_lshift_quick(r_quick, fa_red, 7, fm))) + goto err; + CHECK_MOD_OP_RESULT("mod_lshift"); + +#undef CHECK_MOD_OP_RESULT + + ret = 1; + +err: + OSSL_FN_CTX_free(ctx); + OSSL_FN_free(fa); + OSSL_FN_free(fb); + OSSL_FN_free(fm); + OSSL_FN_free(expected); + OSSL_FN_free(r_gen); + OSSL_FN_free(r_quick); + OSSL_FN_free(tmp); + OSSL_FN_free(fa_red); + OSSL_FN_free(fb_red); + OSSL_FN_free(pow2n); + return ret; +} + +int setup_tests(void) +{ + ADD_ALL_TESTS(test_add, 17); + ADD_ALL_TESTS(test_add_truncated, 17); + ADD_ALL_TESTS(test_sub, 18); + ADD_ALL_TESTS(test_sub_truncated, 18); + ADD_TEST(test_num_bits); + ADD_TEST(test_cmp); + ADD_TEST(test_introspection); + ADD_ALL_TESTS(test_add_word, OSSL_NELEM(add_word_cases)); + ADD_ALL_TESTS(test_sub_word, OSSL_NELEM(sub_word_cases)); + ADD_ALL_TESTS(test_set_word, OSSL_NELEM(set_word_cases)); + ADD_TEST(test_one); + ADD_TEST(test_zero); + ADD_ALL_TESTS(test_lshift1, 2); + ADD_ALL_TESTS(test_lshift, 6); + ADD_ALL_TESTS(test_rshift1, 2); + ADD_ALL_TESTS(test_rshift, 9); + ADD_ALL_TESTS(test_rshift_alias, 4); + ADD_TEST(test_rshift_invalid_shift); + ADD_ALL_TESTS(test_mul_feature_r_is_operand, 4); + ADD_ALL_TESTS(test_mul, OSSL_NELEM(test_mul_cases)); + ADD_ALL_TESTS(test_mul_truncated, OSSL_NELEM(test_mul_truncate_cases)); + ADD_ALL_TESTS(test_sqr_feature_r_is_operand, 2); + ADD_ALL_TESTS(test_sqr, OSSL_NELEM(test_sqr_cases)); + ADD_ALL_TESTS(test_sqr_truncated, OSSL_NELEM(test_sqr_truncate_cases)); + ADD_ALL_TESTS(test_div, OSSL_NELEM(test_div_cases)); + ADD_ALL_TESTS(test_div_truncated, OSSL_NELEM(test_div_truncate_cases)); + ADD_TEST(test_div_by_zero); + ADD_ALL_TESTS(test_mod, OSSL_NELEM(test_mod_cases)); + ADD_ALL_TESTS(test_mod_truncated, OSSL_NELEM(test_mod_truncate_cases)); + ADD_TEST(test_mod_by_zero); + ADD_ALL_TESTS(test_div_quotient_only, + OSSL_NELEM(test_div_cases)); + ADD_ALL_TESTS(test_div_quotient_only_truncated, + OSSL_NELEM(test_div_truncate_cases)); + ADD_ALL_TESTS(test_rand_bits, OSSL_NELEM(rand_bits_cases)); + ADD_ALL_TESTS(test_rand, OSSL_NELEM(rand_bits_cases)); + ADD_TEST(test_rand_result_too_small); + ADD_TEST(test_rand_bits_too_small); + ADD_ALL_TESTS(test_rand_range, OSSL_NELEM(range_words)); + ADD_TEST(test_rand_range_zero); + ADD_TEST(test_rand_range_exactly_sized); + ADD_ALL_TESTS(test_mod_add, OSSL_NELEM(test_mod_add_cases)); + ADD_ALL_TESTS(test_mod_sub, OSSL_NELEM(test_mod_sub_cases)); + ADD_ALL_TESTS(test_mod_mul, OSSL_NELEM(test_mod_mul_cases)); + ADD_ALL_TESTS(test_mod_sqr, OSSL_NELEM(test_mod_sqr_cases)); + ADD_ALL_TESTS(test_mod_lshift1, OSSL_NELEM(test_mod_lshift1_cases)); + ADD_ALL_TESTS(test_mod_lshift, OSSL_NELEM(test_mod_lshift_cases)); + ADD_TEST(test_mod_quick_wide_operands); + ADD_TEST(test_mod_sub_general_wide_operands); + ADD_ALL_TESTS(test_mod_ops_result_size, 3); + + return 1; +} diff --git a/test/fn_internal_test.c b/test/fn_internal_test.c new file mode 100644 index 0000000000..b6b316a445 --- /dev/null +++ b/test/fn_internal_test.c @@ -0,0 +1,457 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * @file Internal tests of OSSL_FN + * + * This tests OSSL_FN internals only, i.e. anything that requires including + * ../crypto/fn/fn_local.h, such as introspection. + */ + +#include "crypto/fn.h" +#include "crypto/fn_intern.h" +#include "fn_local.h" +#include "testutil.h" + +static int test_struct(void) +{ + TEST_note("OSSL_FN struct is %zu bytes\n", sizeof(OSSL_FN)); + TEST_note("OSSL_FN 'd' array starts at offset %zu\n", offsetof(OSSL_FN, d)); + + /* + * Note: The working theory for the moment is that the 'd' array *must* + * align with the end of the OSSL_FN struct. + * If it turns out that this isn't the case, we can choose to run + * TEST_size_t_eq() for display purposes, but ignore its result and + * return 1. + */ + return TEST_size_t_eq(sizeof(OSSL_FN), offsetof(OSSL_FN, d)); +} + +static int test_alloc(void) +{ + int ret = 1; + OSSL_FN *f = NULL; + const OSSL_FN_ULONG *u = NULL; + + /* + * OSSL_FN_new_bits() calls OSSL_FN_new_bytes(), which calls + * OSSL_FN_new_limbs(), so we're exercising all three in one go. + * + * The curious size formula is there to check that the number of bits that + * is passed in gets properly rounded up to the number of limbs they fit + * into. + * This formula aims for two limbs (each of which is at least 32 bits), + * shaving off 17 bits for demonstration purposes. + */ + if (!TEST_ptr(f = OSSL_FN_new_bits(sizeof(OSSL_FN_ULONG) * 16 - 17)) + || !TEST_true(ossl_fn_is_dynamically_allocated(f)) + || !TEST_false(ossl_fn_is_securely_allocated(f)) + || !TEST_size_t_eq(ossl_fn_get_dsize(f), 2) + || !TEST_ptr(u = ossl_fn_get_words(f)) + || !TEST_size_t_eq(u[0], 0) + || !TEST_size_t_eq(u[1], 0)) + ret = 0; + OSSL_FN_free(f); + + return ret; +} + +static int test_secure_alloc(void) +{ + int ret = 1; + OSSL_FN *f = NULL; + const OSSL_FN_ULONG *u = NULL; + + /* + * OSSL_FN_secure_new_bits() calls OSSL_FN_secure_new_bytes(), which calls + * OSSL_FN_secure_new_limbs(), so we're exercising all three in one go. + * + * The curious size formula is there to check that the number of bits that + * is passed in gets properly rounded up to the number of limbs they fit + * into. + * This formula aims for two limbs (each of which is at least 32 bits), + * shaving off 17 bits for demonstration purposes. + */ + if (!TEST_ptr(f = OSSL_FN_secure_new_bits(sizeof(OSSL_FN_ULONG) * 16 - 17)) + || !TEST_true(ossl_fn_is_dynamically_allocated(f)) + || !TEST_true(ossl_fn_is_securely_allocated(f)) + || !TEST_size_t_eq(ossl_fn_get_dsize(f), 2) + || !TEST_ptr(u = ossl_fn_get_words(f)) + || !TEST_size_t_eq(u[0], 0) + || !TEST_size_t_eq(u[1], 0)) + ret = 0; + OSSL_FN_free(f); + + return ret; +} + +static int test_ctx(void) +{ + int ret = 1; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *f = NULL; + const void *token = NULL; + + /* + * Make a CTX that is likely to contain two 2048-bit or one 4096-bit OSSL_FN + * and one frame (let's overestimate its size to 128 bytes). + * Note that OSSL_FN_CTX_new() takes a maximum number of limbs in the last + * parameter, so we must ensure that we get that number right. + */ + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 2, 4096 / OSSL_FN_BITS))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + + /* Check that we can get 1 2048-bit OSSL_FN instance, and check its metadata */ + if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_false(ossl_fn_is_dynamically_allocated(f)) + || !TEST_false(ossl_fn_is_securely_allocated(f))) + ret = 0; + if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + + /* Check that we can get 2 2048-bit OSSL_FN instances, but not 3 */ + if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048))) + ret = 0; + if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + + /* Check that we can get 1 4096-bit OSSL_FN instance, but not 2 */ + if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 4096)) + || !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048))) + ret = 0; + if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + +end: + OSSL_FN_CTX_free(ctx); + + return ret; +} + +static int test_ctx_size(void) +{ + int ret = 1; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *f = NULL; + const void *token = NULL; + size_t size = OSSL_FN_CTX_size(1, 2, 4096 / OSSL_FN_BITS); + + if (!TEST_size_t_ne(size, 0) + || !TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, size))) { + ret = 0; + goto end; + } + + if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) { + ret = 0; + goto end; + } + + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_false(ossl_fn_is_dynamically_allocated(f)) + || !TEST_false(ossl_fn_is_securely_allocated(f)) + || !TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048))) + ret = 0; + + if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + + /* + * Force each term of OSSL_FN_CTX_size() to overflow in turn, + * keeping the others at a minimal valid context (1 frame, 1 + * number, 1 limb) so only the overflowing term is unrealistic. + */ + if (!TEST_size_t_eq(OSSL_FN_CTX_size(SIZE_MAX, 1, 1), 0)) + ret = 0; + if (!TEST_size_t_eq(OSSL_FN_CTX_size(1, SIZE_MAX, 1), 0)) + ret = 0; + if (!TEST_size_t_eq(OSSL_FN_CTX_size(1, 1, SIZE_MAX), 0)) + ret = 0; + /* A context must have at least one frame. */ + if (!TEST_size_t_eq(OSSL_FN_CTX_size(0, 1, 1), 0)) + ret = 0; + /* + * Numbers and limbs must both be present or both absent: a context + * with one budget but not the other can never allocate a usable + * number, since OSSL_FN_CTX_get_limbs() allocates the OSSL_FN header + * and its limbs together. + */ + if (!TEST_size_t_eq(OSSL_FN_CTX_size(1, 0, 1), 0)) + ret = 0; + if (!TEST_size_t_eq(OSSL_FN_CTX_size(1, 1, 0), 0)) + ret = 0; + if (!TEST_ptr_null(OSSL_FN_CTX_new_size(NULL, SIZE_MAX))) + ret = 0; + /* A size of 0 is the error return of OSSL_FN_CTX_size(). */ + if (!TEST_ptr_null(OSSL_FN_CTX_new_size(NULL, 0))) + ret = 0; + + return ret; +} + +static int test_secure_ctx(void) +{ + int ret = 1; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *f = NULL; + const void *token = NULL; + + /* + * Make a CTX that is likely to contain two 2048-bit OSSL_FN and one frame + * (let's overestimate its size to 128 bytes). + * Note that OSSL_FN_CTX_new() takes a maximum number of limbs in the last + * parameter, so we must ensure that we get that number right. + */ + if (!TEST_ptr(ctx = OSSL_FN_CTX_secure_new(NULL, 1, 2, 2048 / OSSL_FN_BITS))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + + /* Check that we can get 1 2048-bit OSSL_FN instance, and check its metadata */ + if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_false(ossl_fn_is_dynamically_allocated(f)) + || !TEST_true(ossl_fn_is_securely_allocated(f))) + ret = 0; + if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) { + ret = 0; + /* It's pointless to try more tests after this failure */ + goto end; + } + +end: + OSSL_FN_CTX_free(ctx); + + return ret; +} + +static int test_secure_ctx_size(void) +{ + int ret = 1; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *f = NULL; + const void *token = NULL; + size_t size = OSSL_FN_CTX_size(1, 1, 2048 / OSSL_FN_BITS); + + if (!TEST_size_t_ne(size, 0) + || !TEST_ptr(ctx = OSSL_FN_CTX_secure_new_size(NULL, size))) { + ret = 0; + goto end; + } + + if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) { + ret = 0; + goto end; + } + + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048)) + || !TEST_false(ossl_fn_is_dynamically_allocated(f)) + || !TEST_true(ossl_fn_is_securely_allocated(f)) + || !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048))) + ret = 0; + + if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + + if (!TEST_ptr_null(OSSL_FN_CTX_secure_new_size(NULL, SIZE_MAX))) + ret = 0; + /* A size of 0 is the error return of OSSL_FN_CTX_size(). */ + if (!TEST_ptr_null(OSSL_FN_CTX_secure_new_size(NULL, 0))) + ret = 0; + + return ret; +} + +static int test_ctx_peak_used(void) +{ + int ret = 1; + OSSL_FN_CTX *ctx = NULL; + OSSL_FN *f = NULL; + const void *token1 = NULL; + const void *token2 = NULL; + size_t frames, numbers, limbs; + size_t limbs_2048 = 2048 / 8 / OSSL_FN_BYTES; + size_t limbs_4096 = 4096 / 8 / OSSL_FN_BYTES; + + if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 2, 4, 256))) { + ret = 0; + goto end; + } + + /* + * Fresh context. + */ + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 0) + || !TEST_size_t_eq(numbers, 0) + || !TEST_size_t_eq(limbs, 0)) + ret = 0; + + /* + * NULL context: all out parameters set to 0. + */ + OSSL_FN_CTX_peak_usage(NULL, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 0) + || !TEST_size_t_eq(numbers, 0) + || !TEST_size_t_eq(limbs, 0)) + ret = 0; + + /* + * NULL out parameters are tolerated. + */ + OSSL_FN_CTX_peak_usage(ctx, NULL, NULL, NULL); + + /* + * Start frame 1. + */ + if (!TEST_ptr(token1 = OSSL_FN_CTX_start(ctx))) { + ret = 0; + goto end; + } + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 1) + || !TEST_size_t_eq(numbers, 0) + || !TEST_size_t_eq(limbs, 0)) + ret = 0; + + /* + * Allocate one number in frame 1. + */ + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))) + ret = 0; + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 1) + || !TEST_size_t_eq(numbers, 1) + || !TEST_size_t_eq(limbs, limbs_2048)) + ret = 0; + + /* + * Start frame 2 (nested inside frame 1). + */ + if (!TEST_ptr(token2 = OSSL_FN_CTX_start(ctx))) { + ret = 0; + goto end; + } + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 2) + || !TEST_size_t_eq(numbers, 1) + || !TEST_size_t_eq(limbs, limbs_2048)) + ret = 0; + + /* + * Allocate one number in frame 2. + */ + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 4096))) + ret = 0; + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 2) + || !TEST_size_t_eq(numbers, 2) + || !TEST_size_t_eq(limbs, limbs_2048 + limbs_4096)) + ret = 0; + + /* + * Allocate a second number in frame 2. + */ + if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))) + ret = 0; + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 2) + || !TEST_size_t_eq(numbers, 3) + || !TEST_size_t_eq(limbs, limbs_2048 + limbs_4096 + limbs_2048)) + ret = 0; + + if (!TEST_true(OSSL_FN_CTX_end(ctx, token2))) { + ret = 0; + goto end; + } + + /* + * After ending frame 2: peaks must not decrease. + */ + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 2) + || !TEST_size_t_eq(numbers, 3) + || !TEST_size_t_eq(limbs, limbs_2048 + limbs_4096 + limbs_2048)) + ret = 0; + + if (!TEST_true(OSSL_FN_CTX_end(ctx, token1))) { + ret = 0; + goto end; + } + + /* + * After ending frame 1: peaks still preserved. + */ + OSSL_FN_CTX_peak_usage(ctx, &frames, &numbers, &limbs); + if (!TEST_size_t_eq(frames, 2) + || !TEST_size_t_eq(numbers, 3) + || !TEST_size_t_eq(limbs, limbs_2048 + limbs_4096 + limbs_2048)) + ret = 0; + +end: + OSSL_FN_CTX_free(ctx); + + return ret; +} + +int setup_tests(void) +{ + ADD_TEST(test_struct); + ADD_TEST(test_alloc); + ADD_TEST(test_secure_alloc); + ADD_TEST(test_ctx); + ADD_TEST(test_ctx_size); + ADD_TEST(test_secure_ctx); + ADD_TEST(test_secure_ctx_size); + ADD_TEST(test_ctx_peak_used); + + return 1; +} diff --git a/test/fntest.c b/test/fntest.c new file mode 100644 index 0000000000..da6a9e54df --- /dev/null +++ b/test/fntest.c @@ -0,0 +1,766 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "crypto/fn.h" +#include "crypto/bn.h" +#include "crypto/fn_intern.h" +#include "internal/nelem.h" +#include "testutil.h" + +/* + * This is a stanza-driven arithmetic test for OSSL_FN. Non-stanza API tests + * belong in fn_api_test. + */ + +typedef struct filetest_st { + const char *name; + int (*func)(STANZA *s); + int skipped; +} FILETEST; + +static const char *findattr(STANZA *s, const char *key) +{ + int i = s->numpairs; + PAIR *pp = s->pairs; + + for (; --i >= 0; pp++) + if (OPENSSL_strcasecmp(pp->key, key) == 0) + return pp->value; + return NULL; +} + +static int parseBN(BIGNUM **out, const char *in) +{ + *out = NULL; + return BN_hex2bn(out, in); +} + +static BIGNUM *getBN(STANZA *s, const char *attribute) +{ + const char *hex; + BIGNUM *ret = NULL; + + if ((hex = findattr(s, attribute)) == NULL) { + TEST_error("%s:%d: Can't find %s", s->test_file, s->start, attribute); + return NULL; + } + + if (parseBN(&ret, hex) != (int)strlen(hex)) { + TEST_error("Could not decode '%s'", hex); + BN_free(ret); + return NULL; + } + return ret; +} + +static int getint(STANZA *s, int *out, const char *attribute) +{ + BIGNUM *ret; + BN_ULONG word; + int st = 0; + + if (!TEST_ptr(ret = getBN(s, attribute)) + || !TEST_uint64_t_le(word = BN_get_word(ret), INT_MAX)) + goto err; + + *out = (int)word; + st = 1; +err: + BN_free(ret); + return st; +} + +static int equalBN(const char *op, const BIGNUM *expected, const BIGNUM *actual) +{ + if (!TEST_BN_eq(expected, actual)) { + TEST_error("unexpected %s value", op); + return 0; + } + return 1; +} + +/* + * Number of limbs needed to hold bn's value, equivalent to the (properly + * adjusted) BIGNUM 'top' field, which is not directly accessible here. + */ +static int limbs(const BIGNUM *bn) +{ + int ret = (BN_num_bits(bn) + BN_BITS2 - 1) / BN_BITS2; + + return ret > 0 ? ret : 1; +} + +static int set_result_addsub(OSSL_FN *r, OSSL_FN *a, int a_neg, + OSSL_FN *b, int b_neg, int *neg) +{ + int cmp; + + *neg = 0; + if (a_neg == b_neg) { + *neg = a_neg; + return OSSL_FN_add(r, a, b); + } + + cmp = OSSL_FN_cmp(a, b); + if (cmp >= 0) { + *neg = a_neg; + return OSSL_FN_sub(r, a, b); + } + + *neg = b_neg; + return OSSL_FN_sub(r, b, a); +} + +static int file_sum(STANZA *s) +{ + BIGNUM *a = NULL, *b = NULL, *sum = NULL, *ret = NULL; + OSSL_FN *af = NULL, *bf = NULL, *rf = NULL; + int a_neg = 0, b_neg = 0, r_neg = 0, st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(b = getBN(s, "B")) + || !TEST_ptr(sum = getBN(s, "Sum")) + || !TEST_ptr(ret = BN_new())) + goto err; + + a_neg = BN_is_negative(a); + b_neg = BN_is_negative(b); + nlimbs = limbs(sum); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(bf = bn_get_ossl_fn(b)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + + if (!TEST_true(set_result_addsub(rf, af, a_neg, bf, b_neg, &r_neg))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, r_neg); + r_acq = 0; + if (!equalBN("A + B", sum, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + BN_free(a); + BN_free(b); + BN_free(sum); + BN_free(ret); + return st; +} + +static int file_product(STANZA *s) +{ + BIGNUM *a = NULL, *b = NULL, *product = NULL, *ret = NULL; + OSSL_FN *af = NULL, *bf = NULL, *rf = NULL; + OSSL_FN_CTX *ctx = NULL; + int a_neg = 0, b_neg = 0, r_neg = 0, st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(b = getBN(s, "B")) + || !TEST_ptr(product = getBN(s, "Product")) + || !TEST_ptr(ret = BN_new())) + goto err; + + a_neg = BN_is_negative(a); + b_neg = BN_is_negative(b); + r_neg = a_neg ^ b_neg; + nlimbs = limbs(product); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(bf = bn_get_ossl_fn(b)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_mul_ctx_size(rf, af, bf)))) + goto err; + + if (!TEST_true(OSSL_FN_mul(rf, af, bf, ctx))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, r_neg); + r_acq = 0; + if (!equalBN("A * B", product, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + OSSL_FN_CTX_free(ctx); + BN_free(a); + BN_free(b); + BN_free(product); + BN_free(ret); + return st; +} + +static int file_square(STANZA *s) +{ + BIGNUM *a = NULL, *square = NULL, *ret = NULL; + OSSL_FN *af = NULL, *rf = NULL; + OSSL_FN_CTX *ctx = NULL; + int st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(square = getBN(s, "Square")) + || !TEST_ptr(ret = BN_new())) + goto err; + + nlimbs = limbs(square); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_sqr_ctx_size(rf, af)))) + goto err; + + if (!TEST_true(OSSL_FN_sqr(rf, af, ctx))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, 0); + r_acq = 0; + if (!equalBN("A^2", square, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + OSSL_FN_CTX_free(ctx); + BN_free(a); + BN_free(square); + BN_free(ret); + return st; +} + +static int file_quotient(STANZA *s) +{ + BIGNUM *a = NULL, *b = NULL, *quotient = NULL, *remainder = NULL; + BIGNUM *qret = NULL, *rret = NULL, *mret = NULL; + OSSL_FN *af = NULL, *bf = NULL, *qf = NULL, *rf = NULL, *mf = NULL; + OSSL_FN_CTX *ctx = NULL, *mod_ctx = NULL; + int a_neg = 0, b_neg = 0, q_neg = 0, r_neg = 0, st = 0; + int q_acq = 0, r_acq = 0, m_acq = 0; + int q_limbs = 0, r_limbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(b = getBN(s, "B")) + || !TEST_ptr(quotient = getBN(s, "Quotient")) + || !TEST_ptr(remainder = getBN(s, "Remainder")) + || !TEST_ptr(qret = BN_new()) + || !TEST_ptr(rret = BN_new()) + || !TEST_ptr(mret = BN_new())) + goto err; + + a_neg = BN_is_negative(a); + b_neg = BN_is_negative(b); + q_neg = a_neg ^ b_neg; + r_neg = a_neg; + q_limbs = limbs(quotient); + r_limbs = limbs(remainder); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(bf = bn_get_ossl_fn(b)) + || !TEST_ptr(qf = bn_acquire_ossl_fn(qret, q_limbs))) + goto err; + q_acq = 1; + if (!TEST_ptr(rf = bn_acquire_ossl_fn(rret, r_limbs))) + goto err; + r_acq = 1; + if (!TEST_ptr(mf = bn_acquire_ossl_fn(mret, r_limbs))) + goto err; + m_acq = 1; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_div_ctx_size(qf, rf, af, bf))) + || !TEST_ptr(mod_ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_mod_ctx_size(mf, af, bf)))) + goto err; + + if (!TEST_true(OSSL_FN_div(qf, rf, af, bf, ctx))) + goto err; + bn_release(qret, q_limbs); + if (!BN_is_zero(qret)) + BN_set_negative(qret, q_neg); + q_acq = 0; + bn_release(rret, r_limbs); + if (!BN_is_zero(rret)) + BN_set_negative(rret, r_neg); + r_acq = 0; + if (!equalBN("A / B", quotient, qret) + || !equalBN("A % B", remainder, rret)) + goto err; + + if (!TEST_true(OSSL_FN_mod(mf, af, bf, mod_ctx))) + goto err; + bn_release(mret, r_limbs); + if (!BN_is_zero(mret)) + BN_set_negative(mret, r_neg); + m_acq = 0; + if (!equalBN("A % B (mod)", remainder, mret)) + goto err; + + st = 1; +err: + if (m_acq) + bn_release(mret, r_limbs); + if (r_acq) + bn_release(rret, r_limbs); + if (q_acq) + bn_release(qret, q_limbs); + OSSL_FN_CTX_free(mod_ctx); + OSSL_FN_CTX_free(ctx); + BN_free(a); + BN_free(b); + BN_free(quotient); + BN_free(remainder); + BN_free(qret); + BN_free(rret); + BN_free(mret); + return st; +} + +static int file_lshift1(STANZA *s) +{ + BIGNUM *a = NULL, *lshift1 = NULL, *two = NULL, *ret = NULL; + OSSL_FN *af = NULL, *lf = NULL, *tf = NULL, *rf = NULL; + OSSL_FN_CTX *ctx = NULL; + int a_neg = 0, st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(lshift1 = getBN(s, "LShift1")) + || !TEST_ptr(two = BN_new()) + || !TEST_ptr(ret = BN_new())) + goto err; + + a_neg = BN_is_negative(a); + nlimbs = limbs(lshift1); + BN_set_word(two, 2); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(lf = bn_get_ossl_fn(lshift1)) + || !TEST_ptr(tf = bn_get_ossl_fn(two)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_mul_ctx_size(rf, af, tf)))) + goto err; + + /* A + A == LShift1 */ + if (!TEST_true(OSSL_FN_add(rf, af, af))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("A + A", lshift1, ret)) + goto err; + + /* A * 2 == LShift1 */ + if (!TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_true(OSSL_FN_mul(rf, af, tf, ctx))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("A * 2", lshift1, ret)) + goto err; + + /* + * TODO(FIXNUM): bntest.c also checks the division/modulus identities + * LShift1 / 2 == A ("LShift1 / 2") + * LShift1 % 2 == 0 ("LShift1 % 2") + * using BN_div(). These cannot be ported yet: there is no OSSL_FN_div(). + */ + + /* A << 1 == LShift1 */ + if (!TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_true(OSSL_FN_lshift1(rf, af))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg); + r_acq = 0; + if (!equalBN("A << 1", lshift1, ret)) + goto err; + + /* + * Round-trip: LShift1 >> 1 == A, done twice to match bntest.c's + * double-check structure. + * + * TODO(FIXNUM): bntest.c's second iteration forces the LSB of LShift1 + * to 1 (BN_set_bit(lshift1, 0)) and then checks + * (LShift1 | 1) / 2 == A ("(LShift1 | 1) / 2") + * (LShift | 1) >> 1 == A ("(LShift | 1) >> 1") + * to exercise rshift1's flooring of an odd operand. This cannot be + * ported yet: there is no OSSL_FN_set_bit(), and the division variant + * also needs OSSL_FN_div(). For now we just repeat the even case to + * preserve the two-iteration shape. + */ + if (!TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_true(OSSL_FN_rshift1(rf, lf))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("LShift >> 1", a, ret)) + goto err; + + if (!TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_true(OSSL_FN_rshift1(rf, lf))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("LShift >> 1", a, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + OSSL_FN_CTX_free(ctx); + BN_free(a); + BN_free(lshift1); + BN_free(two); + BN_free(ret); + return st; +} + +static int file_lshift(STANZA *s) +{ + BIGNUM *a = NULL, *lshift = NULL, *ret = NULL; + OSSL_FN *af = NULL, *lf = NULL, *rf = NULL; + int a_neg = 0, n = 0, st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(lshift = getBN(s, "LShift")) + || !TEST_ptr(ret = BN_new()) + || !getint(s, &n, "N")) + goto err; + + a_neg = BN_is_negative(a); + nlimbs = limbs(lshift); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(lf = bn_get_ossl_fn(lshift)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + + if (!TEST_true(OSSL_FN_lshift(rf, af, n))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg); + r_acq = 0; + if (!equalBN("A << N", lshift, ret)) + goto err; + + /* Round-trip: shift the result back and recover A */ + if (!TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_true(OSSL_FN_rshift(rf, lf, n))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("A >> N", a, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + BN_free(a); + BN_free(lshift); + BN_free(ret); + return st; +} + +static int file_rshift(STANZA *s) +{ + BIGNUM *a = NULL, *rshift = NULL, *ret = NULL; + OSSL_FN *af = NULL, *rf = NULL; + int a_neg = 0, n = 0, st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(rshift = getBN(s, "RShift")) + || !TEST_ptr(ret = BN_new()) + || !getint(s, &n, "N")) + goto err; + + a_neg = BN_is_negative(a); + nlimbs = limbs(rshift); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + + if (!TEST_true(OSSL_FN_rshift(rf, af, n))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("A >> N", rshift, ret)) + goto err; + + /* If N == 1, try with rshift1 as well */ + if (n == 1) { + if (!TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + if (!TEST_true(OSSL_FN_rshift1(rf, af))) + goto err; + bn_release(ret, nlimbs); + BN_set_negative(ret, a_neg && !BN_is_zero(ret)); + r_acq = 0; + if (!equalBN("A >> 1 (rshift1)", rshift, ret)) + goto err; + } + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + BN_free(a); + BN_free(rshift); + BN_free(ret); + return st; +} + +static int file_modmul(STANZA *s) +{ + BIGNUM *a = NULL, *b = NULL, *m = NULL, *mod_mul = NULL, *ret = NULL; + OSSL_FN *af = NULL, *bf = NULL, *rf = NULL, *mf = NULL; + OSSL_FN_CTX *ctx = NULL; + int a_neg = 0, b_neg = 0, st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(b = getBN(s, "B")) + || !TEST_ptr(m = getBN(s, "M")) + || !TEST_ptr(mod_mul = getBN(s, "ModMul")) + || !TEST_ptr(ret = BN_new())) + goto err; + + a_neg = BN_is_negative(a); + b_neg = BN_is_negative(b); + nlimbs = limbs(m); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(bf = bn_get_ossl_fn(b)) + || !TEST_ptr(mf = bn_get_ossl_fn(m)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + + if (!TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_mod_mul_ctx_size(rf, af, bf, mf)))) + goto err; + + /* + * OSSL_FN is unsigned, so the multiplication is on absolute values. + * If the operands have different signs, the non-negative modular + * residue of A * B is M - ((|A| * |B|) mod M), unless that is zero. + */ + if (!TEST_true(OSSL_FN_mod_mul(rf, af, bf, mf, ctx))) + goto err; + bn_release(ret, nlimbs); + r_acq = 0; + if ((a_neg ^ b_neg) && !BN_is_zero(ret)) { + if (!TEST_true(BN_sub(ret, m, ret))) + goto err; + } + if (!equalBN("A * B (mod M)", mod_mul, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + OSSL_FN_CTX_free(ctx); + BN_free(a); + BN_free(b); + BN_free(m); + BN_free(mod_mul); + BN_free(ret); + return st; +} + +static int file_modsqr(STANZA *s) +{ + BIGNUM *a = NULL, *m = NULL, *mod_sqr = NULL, *ret = NULL; + OSSL_FN *af = NULL, *rf = NULL, *mf = NULL; + OSSL_FN_CTX *ctx = NULL; + int st = 0; + int r_acq = 0; + int nlimbs = 0; + + if (!TEST_ptr(a = getBN(s, "A")) + || !TEST_ptr(m = getBN(s, "M")) + || !TEST_ptr(mod_sqr = getBN(s, "ModSqr")) + || !TEST_ptr(ret = BN_new())) + goto err; + + nlimbs = limbs(m); + + if (!TEST_ptr(af = bn_get_ossl_fn(a)) + || !TEST_ptr(mf = bn_get_ossl_fn(m)) + || !TEST_ptr(rf = bn_acquire_ossl_fn(ret, nlimbs))) + goto err; + r_acq = 1; + + if (!TEST_ptr(ctx = OSSL_FN_CTX_new_size(NULL, + OSSL_FN_mod_sqr_ctx_size(rf, af, mf)))) + goto err; + + /* + * Squaring is always non-negative, so no sign fixup is needed. + */ + if (!TEST_true(OSSL_FN_mod_sqr(rf, af, mf, ctx))) + goto err; + bn_release(ret, nlimbs); + r_acq = 0; + if (!equalBN("A^2 (mod M)", mod_sqr, ret)) + goto err; + + st = 1; +err: + if (r_acq) + bn_release(ret, nlimbs); + OSSL_FN_CTX_free(ctx); + BN_free(a); + BN_free(m); + BN_free(mod_sqr); + BN_free(ret); + return st; +} +static FILETEST filetests[] = { + { "Sum", file_sum, 0 }, + { "LShift1", file_lshift1, 0 }, + { "LShift", file_lshift, 0 }, + { "RShift", file_rshift, 0 }, + { "Square", file_square, 0 }, + { "Product", file_product, 0 }, + { "Quotient", file_quotient, 0 }, + { "ModMul", file_modmul, 0 }, + { "ModSqr", file_modsqr, 0 }, + { "ModExp", NULL, 0 }, + { "Exp", NULL, 0 }, + { "ModSqrt", NULL, 0 }, + { "GCD", NULL, 0 }, +}; + +static int file_test_run(STANZA *s) +{ + const FILETEST *tp = filetests; + size_t i; + + for (i = 0; i < OSSL_NELEM(filetests); i++, tp++) { + if (findattr(s, tp->name) != NULL) { + if (tp->func == NULL) { + filetests[i].skipped++; + return 1; + } + if (!tp->func(s)) { + TEST_info("%s:%d: Failed %s test", + s->test_file, s->start, tp->name); + return 0; + } + return 1; + } + } + + TEST_info("%s:%d: Unknown test, skipped", s->test_file, s->start); + return 1; +} + +static int run_file_tests(int i) +{ + STANZA *s = NULL; + char *testfile = test_get_argument(i); + int c; + size_t j; + + for (j = 0; j < OSSL_NELEM(filetests); j++) + filetests[j].skipped = 0; + + if (!TEST_ptr(s = OPENSSL_zalloc(sizeof(*s)))) + return 0; + if (!test_start_file(s, testfile)) { + OPENSSL_free(s); + return 0; + } + + while (!BIO_eof(s->fp) && test_readstanza(s)) { + if (s->numpairs == 0) + continue; + if (!file_test_run(s)) + s->errors++; + s->numtests++; + test_clearstanza(s); + } + test_end_file(s); + + for (j = 0; j < OSSL_NELEM(filetests); j++) + if (filetests[j].skipped > 0) + TEST_info("%s: skipped %d unsupported %s stanzas", + testfile, filetests[j].skipped, filetests[j].name); + + c = s->errors; + OPENSSL_free(s); + + return c == 0; +} + +OPT_TEST_DECLARE_USAGE("file...\n") + +int setup_tests(void) +{ + size_t n = test_get_argument_count(); + + if (!TEST_size_t_gt(n, 0)) + return 0; + + ADD_ALL_TESTS(run_file_tests, (int)n); + return 1; +} diff --git a/test/helpers/pkcs12.c b/test/helpers/pkcs12.c index 3ecfd020b6..abc70db1b7 100644 --- a/test/helpers/pkcs12.c +++ b/test/helpers/pkcs12.c @@ -468,21 +468,21 @@ static int check_asn1_string(const ASN1_TYPE *av, const char *txt) switch (av->type) { case V_ASN1_BMPSTRING: value = OPENSSL_uni2asc(ASN1_STRING_get0_data(av->value.bmpstring), - (int)ASN1_STRING_length_ex(av->value.bmpstring)); + ASN1_STRING_length(av->value.bmpstring)); if (!TEST_str_eq(txt, (char *)value)) goto err; break; case V_ASN1_UTF8STRING: if (!TEST_mem_eq(txt, strlen(txt), ASN1_STRING_get0_data(av->value.utf8string), - ASN1_STRING_length_ex(av->value.utf8string))) + ASN1_STRING_length(av->value.utf8string))) goto err; break; case V_ASN1_OCTET_STRING: if (!TEST_mem_eq(txt, strlen(txt), (char *)ASN1_STRING_get0_data(av->value.octet_string), - ASN1_STRING_length_ex(av->value.octet_string))) + ASN1_STRING_length(av->value.octet_string))) goto err; break; diff --git a/test/http_test.c b/test/http_test.c index d122a45426..70f48a4607 100644 --- a/test/http_test.c +++ b/test/http_test.c @@ -635,7 +635,7 @@ static int test_hdr_resp_hdr_limit_none(void) static int test_hdr_resp_hdr_limit_short(void) { - return test_http_resp_hdr_limit(1); + return (test_http_resp_hdr_limit(1)); } static int test_hdr_resp_hdr_limit_256(void) diff --git a/test/ideatest.c b/test/ideatest.c index 4ad7f67054..b426429198 100644 --- a/test/ideatest.c +++ b/test/ideatest.c @@ -98,7 +98,7 @@ static int test_idea_cfb64(void) IDEA_set_decrypt_key(&eks, &dks); memcpy(cfb_tmp, cfb_iv, sizeof(cfb_tmp)); n = 0; - IDEA_cfb64_encrypt(plain, cfb_buf1, 12, &eks, + IDEA_cfb64_encrypt(plain, cfb_buf1, (long)12, &eks, cfb_tmp, &n, IDEA_ENCRYPT); IDEA_cfb64_encrypt(&plain[12], &cfb_buf1[12], (long)CFB_TEST_SIZE - 12, &eks, @@ -107,7 +107,7 @@ static int test_idea_cfb64(void) return 0; memcpy(cfb_tmp, cfb_iv, sizeof(cfb_tmp)); n = 0; - IDEA_cfb64_encrypt(cfb_buf1, cfb_buf2, 13, &eks, + IDEA_cfb64_encrypt(cfb_buf1, cfb_buf2, (long)13, &eks, cfb_tmp, &n, IDEA_DECRYPT); IDEA_cfb64_encrypt(&cfb_buf1[13], &cfb_buf2[13], (long)CFB_TEST_SIZE - 13, &eks, diff --git a/test/igetest.c b/test/igetest.c index 7e7ad0606f..d19c116d40 100644 --- a/test/igetest.c +++ b/test/igetest.c @@ -43,7 +43,7 @@ struct ige_test { const int encrypt; }; -static const struct ige_test ige_test_vectors[] = { +static struct ige_test const ige_test_vectors[] = { { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -88,7 +88,7 @@ struct bi_ige_test { const int encrypt; }; -static const struct bi_ige_test bi_ige_test_vectors[] = { +static struct bi_ige_test const bi_ige_test_vectors[] = { { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* key1 */ { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, diff --git a/test/mfail/mfail.c b/test/mfail/mfail.c index ec391c8e85..254a6a965f 100644 --- a/test/mfail/mfail.c +++ b/test/mfail/mfail.c @@ -38,9 +38,6 @@ static struct { int single_point; int start_point; int env_count; - int count_only; - int count_only_env; - int sample_count; int slow_threshold; int print_bt; int mode; @@ -158,13 +155,11 @@ int mfail_install(int optional) mf.single_point = env_int("OPENSSL_TEST_MFAIL_POINT", -1); mf.start_point = env_int("OPENSSL_TEST_MFAIL_START", 0); mf.env_count = env_int("OPENSSL_TEST_MFAIL_COUNT", 0); - mf.count_only_env = env_is_true("OPENSSL_TEST_MFAIL_COUNT_ONLY"); mf.slow_threshold = env_int("OPENSSL_TEST_MFAIL_SLOW", 1000); mf.print_bt = env_is_true("OPENSSL_TEST_MFAIL_BACKTRACE"); /* if optional and nothing configured, then no point installing hooks */ - if (optional && mf.env_count <= 0 && mf.single_point < 0 - && !mf.count_only_env) + if (optional && mf.env_count <= 0 && mf.single_point < 0) return 0; if (!CRYPTO_set_mem_functions(mf_malloc, mf_realloc, mf_free)) @@ -213,11 +208,6 @@ static int compute_point(int i, int total, int n, int seq, int start) } void mfail_init(int seq, int flags) -{ - mfail_init_ex(seq, flags, 0); -} - -void mfail_init_ex(int seq, int flags, int count) { mf.seq = seq; mf.iter_index = 0; @@ -231,13 +221,10 @@ void mfail_init_ex(int seq, int flags, int count) mf.counting = 0; mf.slow_skipped = 0; mf.no_check = flags & MFAIL_FLAG_NO_CHECK; - mf.count_only = mf.count_only_env || (flags & MFAIL_FLAG_COUNT_ONLY) != 0; - /* env count overrides the requested per-test sample count */ - mf.sample_count = mf.env_count > 0 ? mf.env_count : count; if (mf.single_point >= 0) { mf.mode = MFAIL_MODE_SINGLE; - } else if ((flags & MFAIL_FLAG_COUNT) && mf.sample_count > 0) { + } else if ((flags & MFAIL_FLAG_COUNT) && mf.env_count > 0) { mf.mode = MFAIL_MODE_SAMPLED; } else { mf.mode = MFAIL_MODE_EXHAUSTIVE; @@ -253,13 +240,7 @@ int mfail_has_next(void) switch (mf.phase) { case MFAIL_PHASE_COUNTING: mf.total = mf.alloc_count; - if (mf.count_only) { - mf.phase = MFAIL_PHASE_DONE; - break; - } - /* sampled runs are bounded, so slow-skip only applies otherwise */ - if (mf.skip_slow && mf.mode != MFAIL_MODE_SAMPLED - && mf.total > mf.slow_threshold) { + if (mf.skip_slow && mf.total > mf.slow_threshold) { mf.slow_skipped = 1; mf.phase = MFAIL_PHASE_DONE; break; @@ -275,7 +256,7 @@ int mfail_has_next(void) mf.phase = MFAIL_PHASE_DONE; } } else { /* mf.mode is MFAIL_MODE_SAMPLED */ - mf.n = mf.sample_count; + mf.n = mf.env_count; if (mf.n > mf.total) mf.n = mf.total; if (mf.n > 0 && mf.total > mf.start_point) { @@ -355,11 +336,6 @@ int mfail_was_slow_skipped(void) return mf.slow_skipped; } -int mfail_is_count_only(void) -{ - return mf.count_only; -} - int mfail_get_count(void) { return mf.alloc_count; diff --git a/test/mfail/mfail.h b/test/mfail/mfail.h index c93be44fca..6c16e4fe65 100644 --- a/test/mfail/mfail.h +++ b/test/mfail/mfail.h @@ -13,8 +13,6 @@ /* Flags for mfail_init(). */ #define MFAIL_FLAG_COUNT (1 << 0) #define MFAIL_FLAG_NO_CHECK (1 << 1) -/* Force count-only run for this init */ -#define MFAIL_FLAG_COUNT_ONLY (1 << 2) /* Modes */ #define MFAIL_MODE_EXHAUSTIVE 0 @@ -32,8 +30,6 @@ int mfail_install(int optional); int mfail_is_installed(void); /* Initialize the mfail for test case runs */ void mfail_init(int seq, int flags); -/* As mfail_init() but caps injection at |count| sampled points */ -void mfail_init_ex(int seq, int flags, int count); /* Check for the failure loop if another fail execution should be done */ int mfail_has_next(void); /* Start the failure triggering block */ @@ -44,8 +40,6 @@ void mfail_end(void); int mfail_was_triggered(void); /* Check if the inject phase was skipped because it got over slow threshold */ int mfail_was_slow_skipped(void); -/* Check if mfail counts allocations and not inject */ -int mfail_is_count_only(void); /* If the counting was executed, get the total number of allocations */ int mfail_get_count(void); /* Get the total number of failure points */ diff --git a/test/ml_dsa_test.c b/test/ml_dsa_test.c index ca1c1225e2..1553f66c8f 100644 --- a/test/ml_dsa_test.c +++ b/test/ml_dsa_test.c @@ -8,13 +8,10 @@ */ #include -#include #include -#include #include "internal/nelem.h" #include "testutil.h" #include "ml_dsa.inc" -#include "crypto/evp.h" #include "crypto/ml_dsa.h" typedef enum OPTION_choice { @@ -647,108 +644,6 @@ err: return ret; } -/* - * Test that the keymgmt import dispatch refuses to import into a key whose - * public component is already set, i.e. the key is immutable once initialised. - * - * Four sub-cases are exercised: - * 1. public-key-only → re-import public key → must fail - * 2. public-key-only → import keypair → must fail - * 3. full keypair → re-import keypair → must fail - * 4. full keypair → import public key only → must fail - * - * All failures must raise PROV_R_KEY_IMMUTABLE_ONCE_SET. - */ -static int ml_dsa_key_immutable_test(void) -{ - int ret = 0; - EVP_KEYMGMT *keymgmt = NULL; - void *keydata = NULL; - const ML_DSA_KEYGEN_TEST_DATA *tst = &ml_dsa_keygen_testdata[0]; - OSSL_PARAM pub_params[2], keypair_params[3]; - - pub_params[0] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PUB_KEY, (void *)tst->pub, tst->pub_len); - pub_params[1] = OSSL_PARAM_construct_end(); - - keypair_params[0] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PRIV_KEY, (void *)tst->priv, tst->priv_len); - keypair_params[1] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PUB_KEY, (void *)tst->pub, tst->pub_len); - keypair_params[2] = OSSL_PARAM_construct_end(); - - if (!TEST_ptr(keymgmt = EVP_KEYMGMT_fetch(lib_ctx, tst->name, NULL))) - goto end; - - /* Sub-case 1 & 2: start from a public-key-only import */ - if (!TEST_ptr(keydata = evp_keymgmt_newdata(keymgmt, NULL))) - goto end; - - if (!TEST_true(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - pub_params))) - goto end; - - /* Re-import of the same public key must fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - pub_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - /* Import of a full keypair into a public-key-only key must also fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_KEYPAIR, - keypair_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - evp_keymgmt_freedata(keymgmt, keydata); - keydata = NULL; - - /* Sub-case 3 & 4: start from a full keypair import */ - if (!TEST_ptr(keydata = evp_keymgmt_newdata(keymgmt, NULL))) - goto end; - - if (!TEST_true(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_KEYPAIR, - keypair_params))) - goto end; - - /* Re-import of the same keypair must fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_KEYPAIR, - keypair_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - /* Import of a public-key-only into a full keypair must also fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - pub_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - ret = 1; -end: - if (keymgmt != NULL) - evp_keymgmt_freedata(keymgmt, keydata); - EVP_KEYMGMT_free(keymgmt); - return ret; -} - const OPTIONS *test_get_options(void) { static const OPTIONS options[] = { @@ -797,13 +692,6 @@ int setup_tests(void) ADD_TEST(from_data_bad_input_test); ADD_TEST(ml_dsa_digest_sign_verify_test); ADD_TEST(ml_dsa_priv_pub_bad_t0_test); - - /* - * Tested only in the default configuration, with a non-default provider - * configuration this test is expected to fail for some older providers. - */ - if (config_file == NULL) - ADD_TEST(ml_dsa_key_immutable_test); return 1; } diff --git a/test/ml_kem_evp_extra_test.c b/test/ml_kem_evp_extra_test.c index 2aa704427a..4d8e506c5f 100644 --- a/test/ml_kem_evp_extra_test.c +++ b/test/ml_kem_evp_extra_test.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include "crypto/evp.h" @@ -493,154 +492,6 @@ err: } #endif /* OPENSSL_NO_EC */ -/* - * Test that ML-KEM keys are immutable once key material is set. - * - * Part 1 — keymgmt import dispatch (ml_kem_import): - * Sub-case A: public-key-only first import succeeds; re-import of the - * same public key and any keypair import must fail with - * PROV_R_KEY_IMMUTABLE_ONCE_SET. - * Sub-case B: full keypair first import succeeds; re-import of the - * keypair and public-key-only import must fail with - * PROV_R_KEY_IMMUTABLE_ONCE_SET. - * - * Part 2 — EVP_PKEY_set1_encoded_public_key (ml_kem_set_params): - * The second call on a key that already has a public component must - * also fail with PROV_R_KEY_IMMUTABLE_ONCE_SET.. - */ -static int test_ml_kem_key_immutable(void) -{ - int ret = 0; - EVP_PKEY *akey = NULL, *bkey = NULL; - EVP_KEYMGMT *keymgmt = NULL; - void *keydata = NULL; - uint8_t *rawpub = NULL, *rawprv = NULL; - size_t publen = 0, prvlen = 0; - OSSL_PARAM pub_params[2], keypair_params[3]; - - /* Generate a key pair and extract the raw public and private key bytes. */ - if (!TEST_ptr(akey = EVP_PKEY_Q_keygen(testctx, NULL, "ML-KEM-768"))) - goto end; - if (!TEST_int_eq(EVP_PKEY_get_raw_public_key(akey, NULL, &publen), 1) - || !TEST_ptr(rawpub = OPENSSL_malloc(publen)) - || !TEST_int_eq(EVP_PKEY_get_raw_public_key(akey, rawpub, &publen), 1)) - goto end; - if (!TEST_int_eq(EVP_PKEY_get_raw_private_key(akey, NULL, &prvlen), 1) - || !TEST_ptr(rawprv = OPENSSL_malloc(prvlen)) - || !TEST_int_eq(EVP_PKEY_get_raw_private_key(akey, rawprv, &prvlen), 1)) - goto end; - - pub_params[0] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PUB_KEY, rawpub, publen); - pub_params[1] = OSSL_PARAM_construct_end(); - - keypair_params[0] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PRIV_KEY, rawprv, prvlen); - keypair_params[1] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PUB_KEY, rawpub, publen); - keypair_params[2] = OSSL_PARAM_construct_end(); - - if (!TEST_ptr(keymgmt = EVP_KEYMGMT_fetch(testctx, "ML-KEM-768", NULL))) - goto end; - - /* --- Part 1A: public-key-only import then re-import --- */ - if (!TEST_ptr(keydata = evp_keymgmt_newdata(keymgmt, NULL))) - goto end; - - if (!TEST_true(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - pub_params))) - goto end; - - /* Re-import of the same public key must fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - pub_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - /* Import of a full keypair into a public-key-only key must also fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_KEYPAIR, - keypair_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - evp_keymgmt_freedata(keymgmt, keydata); - keydata = NULL; - - /* --- Part 1B: full keypair import then re-import --- */ - if (!TEST_ptr(keydata = evp_keymgmt_newdata(keymgmt, NULL))) - goto end; - - if (!TEST_true(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_KEYPAIR, - keypair_params))) - goto end; - - /* Re-import of the same keypair must fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_KEYPAIR, - keypair_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - /* Import of a public-key-only into a full keypair must also fail */ - if (!TEST_false(evp_keymgmt_import(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - pub_params))) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - evp_keymgmt_freedata(keymgmt, keydata); - keydata = NULL; - - /* --- Part 2: EVP_PKEY_set1_encoded_public_key immutability --- */ - - /* - * Create an empty typed key (algorithm set, no key material) by - * copying parameters from the generated key. - */ - if (!TEST_ptr(bkey = EVP_PKEY_new()) - || !TEST_int_gt(EVP_PKEY_copy_parameters(bkey, akey), 0)) - goto end; - - /* First call must succeed: the key is still embryonic */ - if (!TEST_int_eq(EVP_PKEY_set1_encoded_public_key(bkey, rawpub, publen), 1)) - goto end; - - /* Second call must fail: the key now has a public component */ - if (!TEST_int_eq(EVP_PKEY_set1_encoded_public_key(bkey, rawpub, publen), 0)) - goto end; - if (!TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), - PROV_R_KEY_IMMUTABLE_ONCE_SET)) - goto end; - ERR_clear_error(); - - ret = 1; -end: - if (keymgmt != NULL) - evp_keymgmt_freedata(keymgmt, keydata); - EVP_KEYMGMT_free(keymgmt); - EVP_PKEY_free(akey); - EVP_PKEY_free(bkey); - OPENSSL_free(rawpub); - OPENSSL_free(rawprv); - return ret; -} - int setup_tests(void) { int test_rand = 0; @@ -669,7 +520,6 @@ int setup_tests(void) ADD_TEST(test_ml_kem); ADD_TEST(test_ml_kem_from_data_propq); - ADD_TEST(test_ml_kem_key_immutable); #ifndef OPENSSL_NO_EC ADD_ALL_TESTS(test_mlx_kem_dup_partial_selection, OSSL_NELEM(mlx_kem_algs)); #endif diff --git a/test/ocsptest.c b/test/ocsptest.c deleted file mode 100644 index 96dc07423b..0000000000 --- a/test/ocsptest.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include -#include -#include -#ifndef OPENSSL_NO_OCSP -#include -#endif - -#include "testutil.h" - -#ifndef OPENSSL_NO_OCSP - -/* - * Fixtures for the OCSP stapled-response verification path - * (check_cert_ocsp_resp() in x509_vfy.c), reached from X509_verify_cert() - * when X509_V_FLAG_OCSP_RESP_CHECK is set and responses are attached with - * X509_STORE_CTX_set_ocsp_resp(). - * - * Root CA (self-signed trust anchor) - * \-- leaf (signed by the Root CA) - * - * The flat chain makes the root both the trust anchor and the authorized OCSP - * responder for the leaf, and having the root key lets each test build its own - * signed responses at run time. The certificates have a long validity because - * OCSP_check_validity() compares against the wall clock and cannot be pinned - * via X509_VERIFY_PARAM_set_time(). - * - * The arrays below are generated by the test-tools ocsptest command. - */ - -static const char *kOcspTestRoot[] = { - "-----BEGIN CERTIFICATE-----\n", - "MIID+DCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBmjELMAkGA1UEBhMCVVMx\n", - "EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFTAT\n", - "BgNVBAoMDEV4YW1wbGUgQ29ycDEeMBwGA1UECwwVQ2VydGlmaWNhdGUgQXV0aG9y\n", - "aXR5MScwJQYDVQQDDB5FeGFtcGxlIENvcnAgT0NTUCBUZXN0IFJvb3QgQ0EwIBcN\n", - "MjYwMTAxMDAwMDAwWhgPMjEyNjAxMDEwMDAwMDBaMIGaMQswCQYDVQQGEwJVUzET\n", - "MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEVMBMG\n", - "A1UECgwMRXhhbXBsZSBDb3JwMR4wHAYDVQQLDBVDZXJ0aWZpY2F0ZSBBdXRob3Jp\n", - "dHkxJzAlBgNVBAMMHkV4YW1wbGUgQ29ycCBPQ1NQIFRlc3QgUm9vdCBDQTCCASIw\n", - "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKuZRsVUiwQoVlwfXY0nVpvMQiJN\n", - "Su5YfrxzKJ9sMfPI2rEg9d8kW2qsfnCB0isj+SK+CkcfVu5aXcUVUnp08VuKpsI9\n", - "idkeC7bhXkQgBR1p1mBwChc+UUD6qEindJPhFxYur+7gCmpamSHYr8iYmjVe78l8\n", - "vRHVuw8KMsiGegvPsuxIYWdY4mgKSCu3o6DeK4XehXU4Ll5j0fGX5eJgbaI6g8qE\n", - "j71J6G8Y4Ur/WqzTp/GZueTY0wzU8k45HS5uWarGYB2PH8DfM2SRQBw5hYd2xIvS\n", - "jgFYzCXeIZFnHVCMeB//VaUyYGIaw+Dreh+Wb5zBPh9FyJkrOXYyMeFZUScCAwEA\n", - "AaNFMEMwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O\n", - "BBYEFGSeLzT7Ur6wrLpFYVDHmNi/TQp5MA0GCSqGSIb3DQEBCwUAA4IBAQAMMukk\n", - "I0VRfxY1vZngu3LdnBk5If6TbQ6lmWatT4q3BrAID3L9zG/qev6DlyruvnVqoNdU\n", - "WcWXnzFSDInOKM64wU2oxdosMPWuAKKLHgDdCicikJtF+N0qJgOcyD+Gv9t0kwDB\n", - "O094nZUgrkCafJiy5y7KtZvqOjcvfEK+oD7fXX/VURv8NMOxpuassPHnHGvHqwKu\n", - "7jBZMjkOoZH4hJSo5EzZxRZHz6ay7Q8e+6C6PG8CIYXpIqukjVNq9jBb2yog67mW\n", - "lHlfnEENCyQDSmnEXAVNpJS67jmcItoD1utnDINVzu87DY9WiLZB06Y1xSp1ie7s\n", - "FIfS7bZ1cxVkt5wS\n", - "-----END CERTIFICATE-----\n", - NULL -}; - -static const char *kOcspTestRootKey[] = { - "-----BEGIN RSA PRIVATE KEY-----\n", - "MIIEowIBAAKCAQEAq5lGxVSLBChWXB9djSdWm8xCIk1K7lh+vHMon2wx88jasSD1\n", - "3yRbaqx+cIHSKyP5Ir4KRx9W7lpdxRVSenTxW4qmwj2J2R4LtuFeRCAFHWnWYHAK\n", - "Fz5RQPqoSKd0k+EXFi6v7uAKalqZIdivyJiaNV7vyXy9EdW7DwoyyIZ6C8+y7Ehh\n", - "Z1jiaApIK7ejoN4rhd6FdTguXmPR8Zfl4mBtojqDyoSPvUnobxjhSv9arNOn8Zm5\n", - "5NjTDNTyTjkdLm5ZqsZgHY8fwN8zZJFAHDmFh3bEi9KOAVjMJd4hkWcdUIx4H/9V\n", - "pTJgYhrD4Ot6H5ZvnME+H0XImSs5djIx4VlRJwIDAQABAoIBAAj+6w/d47/JtuVI\n", - "xlMSXzRMW/cyYsg7SWxAWT5/oeAW2n1zWJBkdopmv+YkAsw81uBfDWjhwraSHtz9\n", - "xioh8U6MO+ZuQB4VY3soi2mPiCpyPvPP9nzLc9+v2ZydcrtsjxTxnkrWjJU7afsK\n", - "l1nbw3x4HU1McG5RQbzYcFsaJFHJcVdxIYkDfEgnBok1ALaQuRUGfUVYZDVk6Ztg\n", - "fMUh5nfNSHWu6y2i8YCphprIfu/zwadicaYLYljYqgP9J1MOPwuMcoCoWgotBUCZ\n", - "+29qIPn1mK3ReBmYdE8IIEiSLHYJjJ7EVu8IUfSPotBGGC5PjC11HcCXx0xB9AfB\n", - "I8VcDikCgYEA089WizVCWZMxWnCPLDG036vsug3/rrPr/O3W5VXTdpr00CBRzund\n", - "7QnaxUyxw37SOAQUtzcKhC0CF3c7Dbryb8d51koROVlWC8rngoDMxiZkbZZe0kL1\n", - "jHkOHEOoi83uY0tFoRhYtrcOYObNT9JDifdIDYCnxbLW4UQLo/9mFmUCgYEAz2ZH\n", - "hxoxXJ9y3qmIcc2vZTRPdaB4r+qQi5krUgtYg1uKImrvDnnl/4xCnCG9G1s1M/wE\n", - "cvuFG5FWGz6TtS0TsCGUXVWZ9s67JT53l02RIVTog/VRHbKsOnj+d9oXglGcxALT\n", - "qG02lKocNHzrPUXEw/EIMETKR6WvATZCzhM9mpsCgYB9RoKfb27A4Cgun6husS+T\n", - "o3IuUR1KzSvkux+BIRQjcF8fwh3gzb3u9wcn7satJBNeAjvmaW2U47H7AxAwfMPr\n", - "jQXo0oIBc29LJkVrkJaNFCQOFQQcRHJLFUZdPT8xASngHKMgNvAxkW+1rIz+ixRb\n", - "Q6CgK9oPOkmRjtd7thFBaQKBgQCMbt0QBhRWe0D0tCbHqFaTWJBVPYt60oF9hQFo\n", - "VHZiu6EVHQMx8ihimT6hKdc6ps+nm4YHtXez6v07BWxOyW8DXDlx2XyfOexOk7W2\n", - "pbcXsr6eW4XJbipgjX0A+pPgkhJsRt26tfi3QVhH0i4XFx7c7mB1Dp9JVE7jqzIh\n", - "B7Y28QKBgCg93v7zP5GFmOa6zCZreIIfi1dy50otxfqYewcXy4Egt90cE67vY55u\n", - "3B44ySrLkKDuzX2Inrwp5Vao8b9pDQ/AisRzt617eO1H5JtRF3lzZJukYC6j4urU\n", - "24kB2IhZCB6/3pwGiS21ma9E6OF9tO5YaGGYo02ZqkoflN+XgoeZ\n", - "-----END RSA PRIVATE KEY-----\n", - NULL -}; - -static const char *kOcspTestLeaf[] = { - "-----BEGIN CERTIFICATE-----\n", - "MIIEOzCCAyOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZoxCzAJBgNVBAYTAlVT\n", - "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUw\n", - "EwYDVQQKDAxFeGFtcGxlIENvcnAxHjAcBgNVBAsMFUNlcnRpZmljYXRlIEF1dGhv\n", - "cml0eTEnMCUGA1UEAwweRXhhbXBsZSBDb3JwIE9DU1AgVGVzdCBSb290IENBMCAX\n", - "DTI2MDEwMTAwMDAwMFoYDzIxMjYwMTAxMDAwMDAwWjCBiDELMAkGA1UEBhMCVVMx\n", - "EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFTAT\n", - "BgNVBAoMDEV4YW1wbGUgQ29ycDEVMBMGA1UECwwMV2ViIFNlcnZpY2VzMR4wHAYD\n", - "VQQDDBVvY3NwLWxlYWYuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB\n", - "DwAwggEKAoIBAQCoQbsBGnLjATBzU8eWYMeyzu6vy4scpVDdhGnTWMaSIrqoXXge\n", - "JXrMHavT13cv2wNTExA6BNqFZA6YLBXYpDJ5oXyOlY1SYjbapX4M0kry4tBZdGWu\n", - "vnh04Q07SI8JvjtScB3lAIIhGr1WrQNLfEz+O80j4Pp8kLe1fWi0joB1CG4RWiuH\n", - "/2Ls1rSEMTr6dABtQ+zwxRHcFlEAoR9ZEDzfN1hIQEByWJd7TMnv738usyp52wMi\n", - "Gh/sruYHkpsO2tVoLCwm1OMSR1BLdGO1tJWSYN2+Tj2JVleQWcwwCgzDX4OlIdPF\n", - "/CM/6aQA6BkDeMW//tO4Ec4X+530zPiFKcZLAgMBAAGjgZgwgZUwDAYDVR0TAQH/\n", - "BAIwADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0O\n", - "BBYEFBEZYONIpHIGBtlfPSlUTcDccGMiMB8GA1UdIwQYMBaAFGSeLzT7Ur6wrLpF\n", - "YVDHmNi/TQp5MCAGA1UdEQQZMBeCFW9jc3AtbGVhZi5leGFtcGxlLmNvbTANBgkq\n", - "hkiG9w0BAQsFAAOCAQEAaFYoQjmWdBBiD/hfSgV34Jf+PVKkecuu60VKDasPLNyV\n", - "ZwZcW8dXF9NOYcebGIEx4rjQTC3xiHUknqfOzc2jmPdU/xBAyRiltQnUh3OFH1qn\n", - "bX0YNUgfluLW+YSwNkriFLuzESBVadGhlX94mQwoqYyQJ+6/Ht2j4P4ZiIDRWfgc\n", - "z9pN8YoCiXh/I/IxVIWunk7Dla+Gr6BDJ762iQMMzPQ5D3cRAe9BDRgGiN0lPeIa\n", - "LMtqDeZZ+dR0KZAr3yZcfyci8SNXwCBbjsoVjmuUj6dlN12pRKxxtBSa23KT6/Dy\n", - "ijXZ+PtyIJz8FVBxO0RoECLimwbUPHfNjAWjuJkugA==\n", - "-----END CERTIFICATE-----\n", - NULL -}; - -/* Load the fixed PKI. Any of the out params may be NULL to skip it. */ -static int load_pki(X509 **root, EVP_PKEY **root_key, X509 **leaf) -{ - if (root != NULL && !TEST_ptr(*root = X509_from_strings(kOcspTestRoot))) - return 0; - if (root_key != NULL - && !TEST_ptr(*root_key = PKEY_from_strings(kOcspTestRootKey))) - return 0; - if (leaf != NULL && !TEST_ptr(*leaf = X509_from_strings(kOcspTestLeaf))) - return 0; - return 1; -} - -/* - * Build a signed OCSP response for |cert| (issued by |issuer|). |resp_status| - * is the outer response status, |cert_status| the single-response certificate - * status. thisUpdate and nextUpdate are the current time offset by - * |this_off_sec| and |next_off_sec| seconds, so callers can also produce - * expired or not-yet-valid responses. The response is signed by - * |signer|/|signer_key|. Returns a response the caller must free, or NULL. - */ -static OCSP_RESPONSE *make_ocsp_response(X509 *cert, X509 *issuer, - int resp_status, int cert_status, int this_off_sec, int next_off_sec, - X509 *signer, EVP_PKEY *signer_key) -{ - OCSP_RESPONSE *resp = NULL; - OCSP_BASICRESP *bs = NULL; - OCSP_CERTID *cid = NULL; - ASN1_TIME *thisupd = NULL, *nextupd = NULL, *revtime = NULL; - - if (cert_status == V_OCSP_CERTSTATUS_REVOKED - && !TEST_ptr(revtime = X509_gmtime_adj(NULL, 0))) - goto end; - - if (!TEST_ptr(bs = OCSP_BASICRESP_new()) - || !TEST_ptr(thisupd = X509_time_adj_ex(NULL, 0, this_off_sec, NULL)) - || !TEST_ptr(nextupd = X509_time_adj_ex(NULL, 0, next_off_sec, NULL)) - || !TEST_ptr(cid = OCSP_cert_to_id(EVP_sha256(), cert, issuer)) - || !TEST_ptr(OCSP_basic_add1_status(bs, cid, cert_status, 0, revtime, - thisupd, nextupd)) - || !TEST_true(OCSP_basic_sign(bs, signer, signer_key, EVP_sha256(), - NULL, OCSP_NOCERTS))) - goto end; - - resp = OCSP_response_create(resp_status, bs); - -end: - ASN1_TIME_free(revtime); - ASN1_TIME_free(thisupd); - ASN1_TIME_free(nextupd); - OCSP_CERTID_free(cid); - OCSP_BASICRESP_free(bs); - return resp; -} - -/* Wrap |resp| into a stack, taking ownership on success. */ -static STACK_OF(OCSP_RESPONSE) *make_ocsp_resp_stack(OCSP_RESPONSE *resp) -{ - STACK_OF(OCSP_RESPONSE) *sk = sk_OCSP_RESPONSE_new_null(); - - if (!TEST_ptr(sk)) - return NULL; - if (!TEST_true(sk_OCSP_RESPONSE_push(sk, resp))) { - sk_OCSP_RESPONSE_free(sk); - return NULL; - } - return sk; -} - -/* - * Verify |leaf| against |root| with the stapled |resps| and |flags|, taking - * ownership of |resps|. Returns X509_V_OK or an X509_V_ERR_xxx code. The - * X509_verify_cert() call is wrapped for malloc-failure injection. - */ -static int verify_ocsp(X509 *leaf, X509 *root, STACK_OF(OCSP_RESPONSE) *resps, - unsigned long flags) -{ - X509_STORE *store = X509_STORE_new(); - X509_STORE_CTX *ctx = X509_STORE_CTX_new(); - X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); - int status = X509_V_ERR_UNSPECIFIED; - - if (!TEST_ptr(store) || !TEST_ptr(ctx) || !TEST_ptr(param)) - goto end; - - if (!TEST_true(X509_STORE_add_cert(store, root)) - || !TEST_true(X509_STORE_CTX_init(ctx, store, leaf, NULL))) - goto end; - - X509_STORE_CTX_set_ocsp_resp(ctx, resps); - - X509_VERIFY_PARAM_set_depth(param, 16); - if (flags != 0) - X509_VERIFY_PARAM_set_flags(param, flags); - X509_STORE_CTX_set0_param(ctx, param); - param = NULL; - - ERR_clear_error(); - MFAIL_start(); - status = X509_verify_cert(ctx) == 1 ? X509_V_OK - : X509_STORE_CTX_get_error(ctx); - MFAIL_end(); - -end: - X509_VERIFY_PARAM_free(param); - X509_STORE_CTX_free(ctx); - X509_STORE_free(store); - sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); - return status; -} - -/* - * Build a single response for the leaf and verify it, expecting |expected|. - * Every failure inside check_cert_ocsp_resp() surfaces as - * X509_V_ERR_OCSP_VERIFY_FAILED at the X509_verify_cert() level. - */ -static int run_ocsp_verify(int resp_status, int cert_status, int this_off_sec, - int next_off_sec, int expected) -{ - X509 *root = NULL, *leaf = NULL; - EVP_PKEY *root_key = NULL; - OCSP_RESPONSE *resp = NULL; - STACK_OF(OCSP_RESPONSE) *resps = NULL; - int testresult = 0; - - if (!load_pki(&root, &root_key, &leaf)) - goto end; - - if (!TEST_ptr(resp = make_ocsp_response(leaf, root, resp_status, cert_status, - this_off_sec, next_off_sec, root, root_key)) - || !TEST_ptr(resps = make_ocsp_resp_stack(resp))) - goto end; - resp = NULL; /* owned by resps */ - - testresult = TEST_int_eq(verify_ocsp(leaf, root, resps, - X509_V_FLAG_OCSP_RESP_CHECK), - expected); - resps = NULL; /* freed by verify_ocsp */ - -end: - sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); - OCSP_RESPONSE_free(resp); - EVP_PKEY_free(root_key); - X509_free(leaf); - X509_free(root); - return testresult; -} - -/* - * A good response that expired a moment ago is still accepted, because stapled - * responses are honoured for up to five minutes past nextUpdate. - */ -static int test_ocsp_resp_good(void) -{ - return run_ocsp_verify(OCSP_RESPONSE_STATUS_SUCCESSFUL, - V_OCSP_CERTSTATUS_GOOD, -10 * 60, -2 * 60, X509_V_OK); -} - -/* An outer response status other than successful is rejected. */ -static int test_ocsp_resp_not_successful(void) -{ - return run_ocsp_verify(OCSP_RESPONSE_STATUS_TRYLATER, - V_OCSP_CERTSTATUS_GOOD, 0, 24 * 60 * 60, X509_V_ERR_OCSP_VERIFY_FAILED); -} - -/* A response more than five minutes past nextUpdate is rejected as expired. */ -static int test_ocsp_resp_expired(void) -{ - return run_ocsp_verify(OCSP_RESPONSE_STATUS_SUCCESSFUL, - V_OCSP_CERTSTATUS_GOOD, -20 * 60, -10 * 60, X509_V_ERR_OCSP_VERIFY_FAILED); -} - -/* No response for the leaf's depth: sk_OCSP_RESPONSE_num() <= error_depth. */ -static int test_ocsp_resp_none(void) -{ - X509 *root = NULL, *leaf = NULL; - STACK_OF(OCSP_RESPONSE) *resps = NULL; - int testresult = 0; - - if (!load_pki(&root, NULL, &leaf) - || !TEST_ptr(resps = sk_OCSP_RESPONSE_new_null())) - goto end; - - testresult = TEST_int_eq(verify_ocsp(leaf, root, resps, - X509_V_FLAG_OCSP_RESP_CHECK), - X509_V_ERR_OCSP_VERIFY_FAILED); - resps = NULL; /* freed by verify_ocsp */ - -end: - sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); - X509_free(leaf); - X509_free(root); - return testresult; -} - -/* - * A well-formed response carrying a single response for a different certificate: - * no CertID matches the leaf, so no status is found for it. - */ -static int test_ocsp_resp_wrong_cert(void) -{ - X509 *root = NULL, *leaf = NULL; - EVP_PKEY *root_key = NULL; - OCSP_RESPONSE *resp = NULL; - STACK_OF(OCSP_RESPONSE) *resps = NULL; - int testresult = 0; - - if (!load_pki(&root, &root_key, &leaf)) - goto end; - - /* the response is about the root, not the leaf being verified */ - if (!TEST_ptr(resp = make_ocsp_response(root, root, - OCSP_RESPONSE_STATUS_SUCCESSFUL, V_OCSP_CERTSTATUS_GOOD, 0, - 24 * 60 * 60, root, root_key)) - || !TEST_ptr(resps = make_ocsp_resp_stack(resp))) - goto end; - resp = NULL; /* owned by resps */ - - testresult = TEST_int_eq(verify_ocsp(leaf, root, resps, - X509_V_FLAG_OCSP_RESP_CHECK), - X509_V_ERR_OCSP_VERIFY_FAILED); - resps = NULL; /* freed by verify_ocsp */ - -end: - sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); - OCSP_RESPONSE_free(resp); - EVP_PKEY_free(root_key); - X509_free(leaf); - X509_free(root); - return testresult; -} - -/* Exercise the success path under mfail. */ -static int test_ocsp_resp_mfail(void) -{ - X509 *root = NULL, *leaf = NULL; - EVP_PKEY *root_key = NULL; - OCSP_RESPONSE *resp = NULL; - STACK_OF(OCSP_RESPONSE) *resps = NULL; - int testresult = 0; - - if (!load_pki(&root, &root_key, &leaf)) - goto end; - - if (!TEST_ptr(resp = make_ocsp_response(leaf, root, - OCSP_RESPONSE_STATUS_SUCCESSFUL, V_OCSP_CERTSTATUS_GOOD, 0, - 24 * 60 * 60, root, root_key)) - || !TEST_ptr(resps = make_ocsp_resp_stack(resp))) - goto end; - resp = NULL; /* owned by resps */ - - testresult = verify_ocsp(leaf, root, resps, X509_V_FLAG_OCSP_RESP_CHECK) - == X509_V_OK; - resps = NULL; /* freed by verify_ocsp */ - -end: - sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); - OCSP_RESPONSE_free(resp); - EVP_PKEY_free(root_key); - X509_free(leaf); - X509_free(root); - return testresult; -} - -#endif /* OPENSSL_NO_OCSP */ - -int setup_tests(void) -{ -#ifndef OPENSSL_NO_OCSP - ADD_TEST(test_ocsp_resp_good); - ADD_TEST(test_ocsp_resp_not_successful); - ADD_TEST(test_ocsp_resp_expired); - ADD_TEST(test_ocsp_resp_none); - ADD_TEST(test_ocsp_resp_wrong_cert); - ADD_MFAIL_NO_CHECK_TEST(test_ocsp_resp_mfail); -#endif - return 1; -} diff --git a/test/p_ossltest.c b/test/p_ossltest.c index 06bd9bc64c..6d775520ba 100644 --- a/test/p_ossltest.c +++ b/test/p_ossltest.c @@ -695,7 +695,6 @@ static const OSSL_DISPATCH ossl_testaes128_cbc_functions[] = { typedef struct { OSSL_LIB_CTX *libctx; EVP_CIPHER_CTX *sub_ctx; - int tls1_aad; } PROV_EVP_AES128_GCM_CTX; /** @@ -839,16 +838,10 @@ static int ossl_test_aes128gcm_update(void *vprovctx, char *out, size_t *outl, size_t inl) { PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx; - int ret = 0, soutl = 0; - uint8_t *inbuf = NULL; + int ret, soutl; + uint8_t *inbuf; - *outl = 0; - - if (in != NULL && inl > 0) { - inbuf = OPENSSL_memdup(in, inl); - if (inbuf == NULL) - goto end; - } + inbuf = OPENSSL_memdup(in, inl); if (EVP_CIPHER_CTX_is_encrypting(ctx->sub_ctx)) ret = EVP_EncryptUpdate(ctx->sub_ctx, (unsigned char *)out, @@ -856,31 +849,16 @@ static int ossl_test_aes128gcm_update(void *vprovctx, char *out, size_t *outl, else ret = EVP_DecryptUpdate(ctx->sub_ctx, (unsigned char *)out, &soutl, in, (int)inl); + *outl = soutl; /* * Once the cipher is complete, throw it away and use the * plaintext as our output */ - if (ret > 0 && inbuf != NULL && out != NULL) { - if (ctx->tls1_aad && EVP_CIPHER_CTX_is_encrypting(ctx->sub_ctx)) { - if (inl < EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN) { - ret = 0; - goto end; - } - - memcpy(out + EVP_GCM_TLS_EXPLICIT_IV_LEN, - inbuf + EVP_GCM_TLS_EXPLICIT_IV_LEN, - inl - EVP_GCM_TLS_EXPLICIT_IV_LEN - EVP_GCM_TLS_TAG_LEN); - } else { - memcpy(out, inbuf, inl); - } - } - - *outl = soutl; - -end: - ctx->tls1_aad = 0; + if (inbuf != NULL && out != NULL) + memcpy(out, inbuf, inl); OPENSSL_free(inbuf); + return ret; } @@ -977,15 +955,8 @@ static int ossl_test_aes128gcm_get_ctx_params(void *vprovctx, OSSL_PARAM params[ static int ossl_test_aes128gcm_set_ctx_params(void *vprovctx, const OSSL_PARAM params[]) { PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx; - int tls1_aad; - int ret; - tls1_aad = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD) != NULL; - ret = EVP_CIPHER_CTX_set_params(ctx->sub_ctx, params); - if (ret) - ctx->tls1_aad = tls1_aad; - - return ret; + return EVP_CIPHER_CTX_set_params(ctx->sub_ctx, params); } /** @@ -1782,84 +1753,6 @@ static const OSSL_ALGORITHM ossltest_rands[] = { { NULL, NULL, NULL } }; -/* - * The implementations for the p_ossltest provider decoder/encoder/store objects - * are defined below, but they are dummy implementations and do nothing. They exist - * for the sole purpose of returning algorithms from this provider so that we can test if - * object creation and refcounting work when a provider requests no caching of the algorithm. - */ - -static int ossl_test_decode(void *ctx, OSSL_CORE_BIO *in, int selection, - OSSL_CALLBACK *cb, void *cbarg, - OSSL_PASSPHRASE_CALLBACK *pb, void *pbarg) -{ - return 1; -} - -static const OSSL_DISPATCH ossl_test_decoder_functions[] = { - { OSSL_FUNC_DECODER_DECODE, (void (*)(void))ossl_test_decode }, - OSSL_DISPATCH_END -}; - -static const OSSL_ALGORITHM ossl_test_decoders[] = { - ALG("p_ossltest_decoder", ossl_test_decoder_functions), - { NULL, NULL, NULL } -}; - -static int ossl_test_encode(void *ctx, OSSL_CORE_BIO *out, const void *obj, - const OSSL_PARAM obj_abstract[], - int selection, OSSL_PASSPHRASE_CALLBACK *pb, - void *pbarg) -{ - return 1; -} - -static const OSSL_DISPATCH ossl_test_encoder_functions[] = { - { OSSL_FUNC_ENCODER_ENCODE, (void (*)(void))ossl_test_encode }, - OSSL_DISPATCH_END -}; - -static const OSSL_ALGORITHM ossl_test_encoders[] = { - ALG("p_ossltest_encoder", ossl_test_encoder_functions), - { NULL, NULL, NULL } -}; - -static int dummy_store_value = 0; - -static void *ossl_test_store_open(void *provctx, const char *uri) -{ - return (void *)&dummy_store_value; -} - -static int ossl_test_store_load(void *ctx, OSSL_CALLBACK *object_fn, void *cbarg, - OSSL_PASSPHRASE_CALLBACK *pb, void *pbarg) -{ - return 0; -} - -static int ossl_test_store_eof(void *ctx) -{ - return 1; -} - -static int ossl_test_store_close(void *ctx) -{ - return 1; -} - -static const OSSL_DISPATCH ossl_test_store_functions[] = { - { OSSL_FUNC_STORE_OPEN, (void (*)(void))ossl_test_store_open }, - { OSSL_FUNC_STORE_LOAD, (void (*)(void))ossl_test_store_load }, - { OSSL_FUNC_STORE_EOF, (void (*)(void))ossl_test_store_eof }, - { OSSL_FUNC_STORE_CLOSE, (void (*)(void))ossl_test_store_close }, - OSSL_DISPATCH_END -}; - -static const OSSL_ALGORITHM ossl_test_stores[] = { - ALG("p_ossltest_store", ossl_test_store_functions), - { NULL, NULL, NULL } -}; - /** * @brief Implement ossltest query. * @@ -1873,10 +1766,6 @@ static const OSSL_ALGORITHM *ossltest_query(void *provctx, int operation_id, int *no_cache) { *no_cache = 0; - - if (getenv("OSSL_TEST_PROVIDER_NO_CACHE") != NULL) - *no_cache = 1; - switch (operation_id) { case OSSL_OP_DIGEST: return ossltest_digests; @@ -1884,12 +1773,6 @@ static const OSSL_ALGORITHM *ossltest_query(void *provctx, int operation_id, return ossltest_ciphers; case OSSL_OP_RAND: return ossltest_rands; - case OSSL_OP_DECODER: - return ossl_test_decoders; - case OSSL_OP_ENCODER: - return ossl_test_encoders; - case OSSL_OP_STORE: - return ossl_test_stores; } return NULL; } diff --git a/test/p_test.c b/test/p_test.c index 655cb7ce6f..1e38bee717 100644 --- a/test/p_test.c +++ b/test/p_test.c @@ -43,6 +43,7 @@ typedef struct p_test_ctx { OSSL_LIB_CTX *libctx; } P_TEST_CTX; +static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; static OSSL_FUNC_core_new_error_fn *c_new_error; static OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug; @@ -257,6 +258,9 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, for (; in->function_id != 0; in++) { switch (in->function_id) { + case OSSL_FUNC_CORE_GETTABLE_PARAMS: + c_gettable_params = OSSL_FUNC_core_gettable_params(in); + break; case OSSL_FUNC_CORE_GET_PARAMS: c_get_params = OSSL_FUNC_core_get_params(in); break; diff --git a/test/pairwise_fail_test.c b/test/pairwise_fail_test.c index 3446d23166..3173225a0c 100644 --- a/test/pairwise_fail_test.c +++ b/test/pairwise_fail_test.c @@ -99,6 +99,8 @@ static int test_keygen_pairwise_failure(void) if (!TEST_ptr_null(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", (size_t)2048))) goto err; } else if (strncmp(pairwise_name, "ec", 2) == 0) { + if (strcmp(pairwise_name, "eckat") == 0) + type = OSSL_SELF_TEST_TYPE_PCT_KAT; if (!TEST_true(setup_selftest_pairwise_failure(type))) goto err; if (!TEST_ptr_null(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-256"))) diff --git a/test/pbetest.c b/test/pbetest.c index 66c67e603d..42ae4a4da9 100644 --- a/test/pbetest.c +++ b/test/pbetest.c @@ -8,8 +8,6 @@ */ #include -#include -#include #include "testutil.h" @@ -19,7 +17,6 @@ #include #include #include -#include #if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5 \ || !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1 @@ -128,179 +125,6 @@ static int test_pkcs5_pbe_des_sha1(void) } #endif -/* - * Regression test for negative EVP_CIPHER_get_iv_length() return in - * PKCS5_pbe2_set_scrypt(). - * - * A malicious/buggy provider advertises SIZE_MAX as IV length. - * evp_cipher_cache_constants() casts (size_t)SIZE_MAX to int => -1. - * Without the ivlen > 0 guard, this -1 is implicitly converted to SIZE_MAX - * in the memcpy call, causing a stack buffer overflow. - * - * This test verifies that PKCS5_pbe2_set_scrypt() handles negative IV - * lengths gracefully (returns NULL, no crash). - */ -#ifndef OPENSSL_NO_SCRYPT - -static void *bad_iv_cipher_newctx(void *provctx) -{ - static int dummy; - return &dummy; -} - -static void bad_iv_cipher_freectx(void *vctx) -{ -} - -static int bad_iv_cipher_cipher(void *vctx, - unsigned char *out, size_t *outl, - size_t outsz, - const unsigned char *in, size_t inl) -{ - if (outl != NULL) - *outl = 0; - return 1; -} - -/* - * Advertise SIZE_MAX as IV length. After evp_cipher_cache_constants() - * stores (int)SIZE_MAX, EVP_CIPHER_get_iv_length() returns -1. - */ -static int bad_iv_cipher_get_params(OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); - if (p != NULL && !OSSL_PARAM_set_size_t(p, 16)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, 32)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); - if (p != NULL && !OSSL_PARAM_set_uint(p, EVP_CIPH_CBC_MODE)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, SIZE_MAX)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD); - if (p != NULL && !OSSL_PARAM_set_int(p, 0)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CUSTOM_IV); - if (p != NULL && !OSSL_PARAM_set_int(p, 0)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CTS); - if (p != NULL && !OSSL_PARAM_set_int(p, 0)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK); - if (p != NULL && !OSSL_PARAM_set_int(p, 0)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_HAS_RAND_KEY); - if (p != NULL && !OSSL_PARAM_set_int(p, 0)) - return 0; - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ENCRYPT_THEN_MAC); - if (p != NULL && !OSSL_PARAM_set_int(p, 0)) - return 0; - return 1; -} - -static const OSSL_DISPATCH bad_iv_cipher_fns[] = { - { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))bad_iv_cipher_newctx }, - { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))bad_iv_cipher_freectx }, - { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))bad_iv_cipher_cipher }, - { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))bad_iv_cipher_get_params }, - OSSL_DISPATCH_END -}; - -static const OSSL_ALGORITHM bad_iv_cipher_algs[] = { - { "AES-256-CBC:AES256", "provider=bad-iv-prov", bad_iv_cipher_fns, - "Bad IV length cipher for regression testing" }, - { NULL, NULL, NULL, NULL } -}; - -static const OSSL_ALGORITHM *bad_iv_query(void *provctx, - int operation_id, - int *no_cache) -{ - *no_cache = 0; - if (operation_id == OSSL_OP_CIPHER) - return bad_iv_cipher_algs; - return NULL; -} - -static void bad_iv_teardown(void *provctx) { } - -static const OSSL_DISPATCH bad_iv_provider_fns[] = { - { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))bad_iv_teardown }, - { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))bad_iv_query }, - OSSL_DISPATCH_END -}; - -static int bad_iv_provider_init(const OSSL_CORE_HANDLE *handle, - const OSSL_DISPATCH *in, - const OSSL_DISPATCH **out, - void **provctx) -{ - static int ctx; - - *provctx = &ctx; - *out = bad_iv_provider_fns; - return 1; -} - -/* - * Test that PKCS5_pbe2_set_scrypt() does not crash when - * EVP_CIPHER_get_iv_length() returns a negative value. - */ -static int test_pkcs5_scrypt_bad_iv_length(void) -{ - int ret = 0; - OSSL_LIB_CTX *libctx = NULL; - OSSL_PROVIDER *bad_prov = NULL; - EVP_CIPHER *cipher = NULL; - X509_ALGOR *alg = NULL; - unsigned char salt[16] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 - }; - unsigned char iv[16] = { 0xAA }; - - if (!TEST_ptr(libctx = OSSL_LIB_CTX_new())) - goto err; - - if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "bad-iv-prov", - bad_iv_provider_init))) - goto err; - - if (!TEST_ptr(bad_prov = OSSL_PROVIDER_load(libctx, "bad-iv-prov"))) - goto err; - - if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, "AES-256-CBC", - "provider=bad-iv-prov"))) - goto err; - - if (!TEST_int_lt(EVP_CIPHER_get_iv_length(cipher), 0)) - goto err; - - /* - * Before the fix, this would trigger memcpy(iv[16], aiv, SIZE_MAX) - * — a stack buffer overflow. After the fix, the function must - * return NULL. - */ - alg = PKCS5_pbe2_set_scrypt(cipher, salt, (int)sizeof(salt), - iv, 1024, 8, 1); - if (!TEST_ptr_null(alg)) - goto err; - - ret = 1; -err: - X509_ALGOR_free(alg); - EVP_CIPHER_free(cipher); - OSSL_PROVIDER_unload(bad_prov); - OSSL_LIB_CTX_free(libctx); - return ret; -} -#endif /* OPENSSL_NO_SCRYPT */ - #ifdef OPENSSL_NO_AUTOLOAD_CONFIG /* * For configurations where we are not autoloading configuration, we need @@ -328,9 +152,6 @@ int setup_tests(void) #if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1 ADD_TEST(test_pkcs5_pbe_des_sha1); #endif -#ifndef OPENSSL_NO_SCRYPT - ADD_TEST(test_pkcs5_scrypt_bad_iv_length); -#endif return 1; } diff --git a/test/pkcs7_test.c b/test/pkcs7_test.c index 8514101121..adf069695e 100644 --- a/test/pkcs7_test.c +++ b/test/pkcs7_test.c @@ -15,30 +15,6 @@ #include "internal/nelem.h" #include "testutil.h" -static int pkcs7_issuer_and_serial_negative_idx_test(void) -{ - PKCS7 *p7 = NULL; - PKCS7_RECIP_INFO *ri = NULL; - int ret = 0; - - if (!TEST_ptr(p7 = PKCS7_new()) - || !TEST_true(PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped)) - || !TEST_ptr(ri = PKCS7_RECIP_INFO_new()) - || !TEST_true(PKCS7_add_recipient_info(p7, ri))) - goto end; - ri = NULL; - - if (!TEST_ptr(PKCS7_get_issuer_and_serial(p7, 0)) - || !TEST_ptr_null(PKCS7_get_issuer_and_serial(p7, -1))) - goto end; - - ret = 1; -end: - PKCS7_RECIP_INFO_free(ri); - PKCS7_free(p7); - return ret; -} - #ifndef OPENSSL_NO_EC static const unsigned char cert_der[] = { 0x30, 0x82, 0x01, 0x51, 0x30, 0x81, 0xf7, 0xa0, 0x03, 0x02, 0x01, 0x02, @@ -385,10 +361,10 @@ static int pkcs7_inner_content_verify_test(void) 0x2D, 0x6F, 0x81 }; - if (!TEST_ptr(bio = BIO_new_mem_buf(sig_der, sizeof(sig_der)))) + if (!TEST_ptr(bio = BIO_new_mem_buf(sig_der, sizeof sig_der))) goto end; - ret = TEST_ptr(x509_bio = BIO_new_mem_buf(smroot_der, sizeof(smroot_der))) + ret = TEST_ptr(x509_bio = BIO_new_mem_buf(smroot_der, sizeof smroot_der)) && TEST_ptr(cert = d2i_X509_bio(x509_bio, NULL)) && TEST_int_eq(ERR_peek_error(), 0) && TEST_ptr(store = X509_STORE_new()) @@ -413,7 +389,6 @@ end: int setup_tests(void) { - ADD_TEST(pkcs7_issuer_and_serial_negative_idx_test); #ifndef OPENSSL_NO_EC ADD_TEST(pkcs7_verify_test); ADD_TEST(pkcs7_inner_content_verify_test); diff --git a/test/property_memfail.c b/test/property_memfail.c new file mode 100644 index 0000000000..caedc51c83 --- /dev/null +++ b/test/property_memfail.c @@ -0,0 +1,196 @@ +/* + * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include +#include "internal/hashtable.h" +#include "internal/property.h" +#include "internal/refcount.h" + +#define TEST_NID 1024 + +/* + * TEST_NID maps to shard zero with the property cache's current power-of-two + * shard count, so this partial view is enough to reach the cache table. + */ +typedef struct { + void *algs; + HT *cache; +} TEST_STORED_ALGORITHMS; + +struct ossl_method_store_st { + OSSL_LIB_CTX *ctx; + TEST_STORED_ALGORITHMS *algs; + CRYPTO_RWLOCK *biglock; +}; + +typedef struct { + HT_KEY key_header; +} QUERY_KEY; + +/* + * We make our OSSL_PROVIDER for testing purposes. The property cache only + * uses the provider pointer as a key, except when tracing asks for its name. + */ +struct ossl_provider_st { + unsigned int flag_initialized : 1; + unsigned int flag_activated : 1; + CRYPTO_RWLOCK *flag_lock; + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *activatecnt_lock; + int activatecnt; + char *name; +}; + +static long alloc_count; +static long fail_at; +static int fail_enabled; +static int method_refs; + +static void *test_malloc(size_t num, const char *file, int line) +{ + (void)file; + (void)line; + + if (fail_enabled && ++alloc_count == fail_at) + return NULL; + + return malloc(num); +} + +static void *test_realloc(void *ptr, size_t num, const char *file, int line) +{ + (void)file; + (void)line; + + if (fail_enabled && ++alloc_count == fail_at) + return NULL; + + return realloc(ptr, num); +} + +static void test_free(void *ptr, const char *file, int line) +{ + (void)file; + (void)line; + + free(ptr); +} + +static int up_ref(void *p) +{ + (void)p; + + method_refs++; + return 1; +} + +static void down_ref(void *p) +{ + (void)p; + + method_refs--; +} + +static int delete_providerless_cache_entry(OSSL_METHOD_STORE *store) +{ + QUERY_KEY key; + uint8_t keybuf[sizeof(int)]; + size_t keylen = 0; + int nid = TEST_NID; + + memcpy(&keybuf[keylen], &nid, sizeof(nid)); + keylen += sizeof(nid); + HT_INIT_KEY_EXTERNAL(&key, keybuf, keylen); + + return ossl_ht_delete(store->algs->cache, TO_HT_KEY(&key)); +} + +static int property_cache_workload(int expect_success) +{ + static struct ossl_provider_st prov = { + .flag_initialized = 1, + .flag_activated = 1, + .name = "property-memfail" + }; + OSSL_METHOD_STORE *store = NULL; + int method = 1; + void *result = NULL; + int ret = 0; + + method_refs = 0; + + if ((store = ossl_method_store_new(NULL)) == NULL) + goto end; + if (!ossl_method_store_add(store, (OSSL_PROVIDER *)&prov, TEST_NID, "", + &method, up_ref, down_ref)) + goto end; + /* + * Restrict failure injection to the cache paths. Store setup exercises + * unrelated global initialization and platform lock allocation. + */ + alloc_count = 0; + fail_enabled = 1; + if (!ossl_method_store_cache_set(store, (OSSL_PROVIDER *)&prov, TEST_NID, + "", &method, up_ref, down_ref)) + goto end; + if (!delete_providerless_cache_entry(store)) + goto end; + if (!ossl_method_store_cache_get(store, NULL, TEST_NID, "", &result) + || result != &method) + goto end; + ret = 1; + +end: + fail_enabled = 0; + if (result != NULL) + down_ref(result); + ossl_method_store_free(store); + + if (method_refs != 0) { + fprintf(stderr, "method reference leak: %d\n", method_refs); + return 0; + } + + return expect_success ? ret : 1; +} + +int main(int argc, char **argv) +{ + int ret = EXIT_FAILURE; + + if (argc < 2) { + fprintf(stderr, "usage: %s count | run \n", argv[0]); + return EXIT_FAILURE; + } + + if (!CRYPTO_set_mem_functions(test_malloc, test_realloc, test_free)) { + fprintf(stderr, "failed to set memory functions\n"); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "count") == 0) { + if (property_cache_workload(1)) { + fprintf(stderr, "skip: 0 count %ld\n", alloc_count); + ret = EXIT_SUCCESS; + } + } else if (strcmp(argv[1], "run") == 0 && argc == 3) { + fail_at = strtol(argv[2], NULL, 10); + if (fail_at > 0 && property_cache_workload(0)) + ret = EXIT_SUCCESS; + } else { + fprintf(stderr, "usage: %s count | run \n", argv[0]); + } + + OPENSSL_cleanup(); + return ret; +} diff --git a/test/property_test.c b/test/property_test.c index ed868dbe8c..f827d3c435 100644 --- a/test/property_test.c +++ b/test/property_test.c @@ -678,9 +678,7 @@ static int test_query_cache_set_duplicate(void) || !TEST_ptr_eq(result, &refs)) goto err; -#ifdef OPENSSL_NO_CACHED_FETCH counted_down_ref(result); -#endif result = NULL; res = 1; @@ -691,179 +689,6 @@ err: return res; } -/* - * When two providers cache the same nid and property query, the first one to - * do so must own the providerless ("any provider will do") cache entry, so - * that a NULL-provider lookup keeps resolving to that provider regardless of - * how many other providers subsequently cache the same nid. This matches the - * provider ossl_method_store_fetch would pick by implementation order. - */ -static int test_query_cache_provider_order(void) -{ - OSSL_METHOD_STORE *store = NULL; - int res = 0; - int method1 = 0, method2 = 0; - void *result = NULL; - OSSL_PROVIDER prov1 = { - .flag_initialized = 1, - .flag_activated = 1, - .name = "first-provider" - }; - OSSL_PROVIDER prov2 = { - .flag_initialized = 1, - .flag_activated = 1, - .name = "second-provider" - }; - - if (!TEST_ptr(store = ossl_method_store_new(NULL))) - goto err; - - /* prov1 caches the nid first, so it owns the providerless entry. */ - if (!TEST_true(ossl_method_store_cache_set(store, &prov1, 1, "", &method1, - up_ref, down_ref)) - || !TEST_true(ossl_method_store_cache_set(store, &prov2, 1, "", - &method2, up_ref, down_ref))) - goto err; - - /* A NULL-provider ("any provider") lookup must resolve to prov1. */ - if (!TEST_true(ossl_method_store_cache_get(store, NULL, 1, "", &result)) - || !TEST_ptr_eq(result, &method1)) - goto err; - - /* Provider-specific lookups must still return each provider's method. */ - result = NULL; - if (!TEST_true(ossl_method_store_cache_get(store, &prov1, 1, "", &result)) - || !TEST_ptr_eq(result, &method1)) - goto err; - result = NULL; - if (!TEST_true(ossl_method_store_cache_get(store, &prov2, 1, "", &result)) - || !TEST_ptr_eq(result, &method2)) - goto err; - - res = 1; - -err: - ossl_method_store_free(store); - return res; -} - -/* Memory-failure coverage for store creation. */ -static int test_query_store_new_mfail(void) -{ - OSSL_METHOD_STORE *store; - int rc; - - MFAIL_start(); - store = ossl_method_store_new(NULL); - MFAIL_end(); - - rc = store != NULL ? 1 : 0; - ossl_method_store_free(store); - return rc; -} - -/* Memory-failure coverage for method registration. */ -static int test_query_store_add_mfail(void) -{ - static OSSL_PROVIDER prov = { - .flag_initialized = 1, - .flag_activated = 1, - .name = "add-mfail-provider" - }; - OSSL_METHOD_STORE *store = NULL; - int refs = 0; - int rc = -1; - - if (!TEST_ptr(store = ossl_method_store_new(NULL))) - goto end; - - MFAIL_start(); - rc = ossl_method_store_add(store, &prov, 1, "", &refs, - counted_up_ref, counted_down_ref) - ? 1 - : 0; - MFAIL_end(); - -end: - ossl_method_store_free(store); - if (rc >= 0 && !TEST_int_eq(refs, 0)) - rc = -1; - return rc; -} - -/* A NULL method archives the matching entry instead of caching a new one. */ -static int test_query_cache_set_null(void) -{ - static OSSL_PROVIDER prov = { - .flag_initialized = 1, - .flag_activated = 1, - .name = "null-set-provider" - }; - OSSL_METHOD_STORE *store = NULL; - int refs = 0; - void *result = NULL; - int res = 0; - - if (!TEST_ptr(store = ossl_method_store_new(NULL)) - || !TEST_true(ossl_method_store_add(store, &prov, 1, "", &refs, - counted_up_ref, counted_down_ref)) - || !TEST_true(ossl_method_store_cache_set(store, &prov, 1, "", &refs, - counted_up_ref, counted_down_ref)) - || !TEST_true(ossl_method_store_cache_set(store, &prov, 1, "", NULL, - counted_up_ref, counted_down_ref)) - || !TEST_false(ossl_method_store_cache_get(store, &prov, 1, "", - &result))) - goto err; - - res = 1; - -err: - ossl_method_store_free(store); - if (!TEST_int_eq(refs, 0)) - res = 0; - return res; -} - -/* Memory-failure coverage for the cache set and providerless lookup. */ -static int test_query_cache_set_mfail(void) -{ - static OSSL_PROVIDER prov = { - .flag_initialized = 1, - .flag_activated = 1, - .name = "mfail-provider" - }; - OSSL_METHOD_STORE *store = NULL; - int refs = 0; - void *result = NULL; - int rc = -1; - - if (!TEST_ptr(store = ossl_method_store_new(NULL)) - || !TEST_true(ossl_method_store_add(store, &prov, 1, "", &refs, - counted_up_ref, counted_down_ref))) - goto end; - - /* Cache the method, then resolve it via the "any provider" (NULL) lookup. */ - MFAIL_start(); - rc = ossl_method_store_cache_set(store, &prov, 1, "", &refs, - counted_up_ref, counted_down_ref) - && ossl_method_store_cache_get(store, NULL, 1, "", &result) - && result == &refs - ? 1 - : 0; - MFAIL_end(); - -#ifdef OPENSSL_NO_CACHED_FETCH - if (result != NULL) - counted_down_ref(result); -#endif - -end: - ossl_method_store_free(store); - if (rc >= 0 && !TEST_int_eq(refs, 0)) - rc = -1; - return rc; -} - static int test_fips_mode(void) { int ret = 0; @@ -977,11 +802,6 @@ int setup_tests(void) ADD_TEST(test_property); ADD_TEST(test_query_cache_stochastic); ADD_TEST(test_query_cache_set_duplicate); - ADD_TEST(test_query_cache_provider_order); - ADD_TEST(test_query_cache_set_null); - ADD_MFAIL_TEST(test_query_store_new_mfail); - ADD_MFAIL_TEST(test_query_store_add_mfail); - ADD_MFAIL_TEST(test_query_cache_set_mfail); ADD_TEST(test_fips_mode); ADD_ALL_TESTS(test_property_list_to_string, OSSL_NELEM(to_string_tests)); ADD_TEST(test_property_list_to_string_bounds); diff --git a/test/quic_ackm_test.c b/test/quic_ackm_test.c index 8598bf8398..a4b488fafc 100644 --- a/test/quic_ackm_test.c +++ b/test/quic_ackm_test.c @@ -11,7 +11,6 @@ #include #include "internal/quic_ackm.h" #include "internal/quic_cc.h" -#include "internal/quic_vlint.h" static OSSL_TIME fake_time = { 0 }; @@ -148,26 +147,13 @@ struct tx_ack_test_case { const OSSL_QUIC_ACK_RANGE *ack_ranges; size_t num_ack_ranges; const char *expect_ack; /* 1=ack, 2=lost, 4=discarded */ - int expect_reject; /* if nonzero the ACK must be rejected (returns 0) */ }; #define DEFINE_TX_ACK_CASE(n, pntable) \ static const struct tx_ack_test_case tx_ack_case_##n = { \ (pntable), OSSL_NELEM(pntable), \ tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n), \ - tx_ack_expect_##n, 0 \ - } - -/* - * As DEFINE_TX_ACK_CASE, but the ACK acknowledges a packet number that was - * never sent and so must be rejected by ossl_ackm_on_rx_ack_frame() - * (RFC 9000 s. 13.1). - */ -#define DEFINE_TX_ACK_CASE_REJECT(n, pntable) \ - static const struct tx_ack_test_case tx_ack_case_##n = { \ - (pntable), OSSL_NELEM(pntable), \ - tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n), \ - tx_ack_expect_##n, 1 \ + tx_ack_expect_##n \ } /* One range, partial coverage of space */ @@ -221,32 +207,32 @@ static const char tx_ack_expect_5[] = { }; DEFINE_TX_ACK_CASE(5, linear_20); -/* One range covering the whole space (0..19, highest sent PN is 19): all acked */ +/* One range, covering entire space */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_6[] = { - { 0, 19 }, + { 0, 20 }, }; static const char tx_ack_expect_6[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; DEFINE_TX_ACK_CASE(6, linear_20); -/* One range above the highest sent PN (30 > 19): ACK rejected */ +/* One range, covering more space than exists */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_7[] = { { 0, 30 }, }; static const char tx_ack_expect_7[] = { - 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 }; -DEFINE_TX_ACK_CASE_REJECT(7, linear_20); +DEFINE_TX_ACK_CASE(7, linear_20); -/* One range entirely above the sent PNs (21..30): ACK rejected */ +/* One range, covering nothing (too high) */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_8[] = { { 21, 30 }, }; static const char tx_ack_expect_8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -DEFINE_TX_ACK_CASE_REJECT(8, linear_20); +DEFINE_TX_ACK_CASE(8, linear_20); /* One range, covering nothing (too low) */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_9[] = { @@ -303,20 +289,6 @@ static const char tx_ack_expect_13[] = { }; DEFINE_TX_ACK_CASE(13, high_linear_20); -/* - * Largest range claims the maximum PN (2**62 - 1, never sent) plus a second - * range over real packets so loss detection would otherwise run. ACK rejected; - * otherwise largest_acked_pkt pins at the maximum and every in-flight packet is - * declared lost. - */ -static const OSSL_QUIC_ACK_RANGE tx_ack_range_14[] = { - { OSSL_QUIC_VLINT_MAX, OSSL_QUIC_VLINT_MAX }, { 15, 19 } -}; -static const char tx_ack_expect_14[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; -DEFINE_TX_ACK_CASE_REJECT(14, linear_20); - static const struct tx_ack_test_case *const tx_ack_cases[] = { &tx_ack_case_1, &tx_ack_case_2, @@ -331,7 +303,6 @@ static const struct tx_ack_test_case *const tx_ack_cases[] = { &tx_ack_case_11, &tx_ack_case_12, &tx_ack_case_13, - &tx_ack_case_14, }; enum { @@ -431,25 +402,6 @@ static int test_tx_ack_case_actual(int tidx, int space, int mode) /* Try acknowledging. */ ack.ack_ranges = (OSSL_QUIC_ACK_RANGE *)c->ack_ranges; ack.num_ack_ranges = c->num_ack_ranges; - - if (c->expect_reject) { - /* ACK of an unsent PN: rejected without touching loss detection. */ - if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space, - fake_time), - 0)) - goto err; - - for (i = 0; i < c->pn_table_len; ++i) { - if (!TEST_int_eq(h.pkts[i].acked, 0) - || !TEST_int_eq(h.pkts[i].lost, 0) - || !TEST_int_eq(h.pkts[i].discarded, 0)) - goto err; - } - - testresult = 1; - goto err; - } - if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space, fake_time), 1)) goto err; @@ -625,7 +577,7 @@ static int test_tx_ack_time_script(int tidx) ack.num_ack_ranges = 1; ack_range.start = s->pn; - ack_range.end = s->pn + s->num_pn - 1; + ack_range.end = s->pn + s->num_pn; fake_time = ossl_time_add(fake_time, ossl_ticks2time(s->time_advance)); diff --git a/test/quic_client_test.c b/test/quic_client_test.c index 90e8498148..9edf3c18d8 100644 --- a/test/quic_client_test.c +++ b/test/quic_client_test.c @@ -172,7 +172,7 @@ err: static int test_quic_client(void) { - return test_quic_client_ex(INVALID_SOCKET); + return (test_quic_client_ex(INVALID_SOCKET)); } static int test_quic_client_connect_first(void) @@ -202,12 +202,12 @@ static int test_quic_client_connect_first(void) close(c_fd); - return rv; + return (rv); err: if (c_fd != INVALID_SOCKET) close(c_fd); - return 0; + return (0); } OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index a921f13610..de7ea27a49 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -356,12 +356,96 @@ static OSSL_TIME get_time(void *arg) return t; } +static int skip_time_ms(struct helper *h, struct helper_local *hl) +{ + if (!TEST_true(CRYPTO_THREAD_write_lock(h->time_lock))) + return 0; + + h->time_slip = ossl_time_add(h->time_slip, ossl_ms2time(hl->check_op->arg2)); + + CRYPTO_THREAD_unlock(h->time_lock); + return 1; +} + static QUIC_TSERVER *s_lock(struct helper *h, struct helper_local *hl); static void s_unlock(struct helper *h, struct helper_local *hl); #define ACQUIRE_S() s_lock(h, hl) #define ACQUIRE_S_NOHL() s_lock(h, NULL) +static int check_stream_reset(struct helper *h, struct helper_local *hl) +{ + uint64_t stream_id = hl->check_op->arg2, aec = 0; + + if (!ossl_quic_tserver_stream_has_peer_reset_stream(ACQUIRE_S(), stream_id, &aec)) { + h->check_spin_again = 1; + return 0; + } + + return TEST_uint64_t_eq(aec, 42); +} + +static int check_stream_stopped(struct helper *h, struct helper_local *hl) +{ + uint64_t stream_id = hl->check_op->arg2; + + if (!ossl_quic_tserver_stream_has_peer_stop_sending(ACQUIRE_S(), stream_id, NULL)) { + h->check_spin_again = 1; + return 0; + } + + return 1; +} + +static int override_key_update(struct helper *h, struct helper_local *hl) +{ + QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); + + ossl_quic_channel_set_txku_threshold_override(ch, hl->check_op->arg2); + return 1; +} + +static int trigger_key_update(struct helper *h, struct helper_local *hl) +{ + if (!TEST_true(SSL_key_update(h->c_conn, SSL_KEY_UPDATE_REQUESTED))) + return 0; + + return 1; +} + +static int check_key_update_ge(struct helper *h, struct helper_local *hl) +{ + QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); + int64_t txke = (int64_t)ossl_quic_channel_get_tx_key_epoch(ch); + int64_t rxke = (int64_t)ossl_quic_channel_get_rx_key_epoch(ch); + int64_t diff = txke - rxke; + + /* + * TXKE must always be equal to or ahead of RXKE. + * It can be ahead of RXKE by at most 1. + */ + if (!TEST_int64_t_ge(diff, 0) || !TEST_int64_t_le(diff, 1)) + return 0; + + /* Caller specifies a minimum number of RXKEs which must have happened. */ + if (!TEST_uint64_t_ge((uint64_t)rxke, hl->check_op->arg2)) + return 0; + + return 1; +} + +static int check_key_update_lt(struct helper *h, struct helper_local *hl) +{ + QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); + uint64_t txke = ossl_quic_channel_get_tx_key_epoch(ch); + + /* Caller specifies a maximum number of TXKEs which must have happened. */ + if (!TEST_uint64_t_lt(txke, hl->check_op->arg2)) + return 0; + + return 1; +} + static unsigned long stream_info_hash(const STREAM_INFO *info) { return OPENSSL_LH_strhash(info->name); @@ -1979,91 +2063,443 @@ static const struct script_op script_4[] = { /* 5. Test stream reset functionality */ static const struct script_op script_5[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + OP_C_NEW_STREAM_BIDI(a, C_BIDI_ID(0)), + OP_C_NEW_STREAM_BIDI(b, C_BIDI_ID(1)), + + OP_C_WRITE(a, "apple", 5), + OP_C_STREAM_RESET(a, 42), + + OP_C_WRITE(b, "strawberry", 10), + + OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)), + OP_S_BIND_STREAM_ID(b, C_BIDI_ID(1)), + OP_S_READ_EXPECT(b, "strawberry", 10), + /* Reset disrupts read of already sent data */ + OP_S_READ_FAIL(a, 0), + OP_CHECK(check_stream_reset, C_BIDI_ID(0)), + OP_END }; /* 6. Test STOP_SENDING functionality */ static const struct script_op script_6[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + OP_S_NEW_STREAM_BIDI(a, S_BIDI_ID(0)), + OP_S_WRITE(a, "apple", 5), + + OP_C_ACCEPT_STREAM_WAIT(a), + OP_C_FREE_STREAM(a), + OP_C_ACCEPT_STREAM_NONE(), + + OP_CHECK(check_stream_stopped, S_BIDI_ID(0)), + OP_END }; /* 7. Unidirectional default stream mode test (client sends first) */ static const struct script_op script_7[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_AUTO_UNI), + OP_C_WRITE(DEFAULT, "apple", 5), + + OP_S_BIND_STREAM_ID(a, C_UNI_ID(0)), + OP_S_READ_EXPECT(a, "apple", 5), + OP_S_WRITE_FAIL(a), + OP_END }; /* 8. Unidirectional default stream mode test (server sends first) */ static const struct script_op script_8[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_AUTO_UNI), + OP_S_NEW_STREAM_UNI(a, S_UNI_ID(0)), + OP_S_WRITE(a, "apple", 5), + OP_C_READ_EXPECT(DEFAULT, "apple", 5), + OP_C_WRITE_FAIL(DEFAULT), + OP_END }; /* 9. Unidirectional default stream mode test (server sends first on bidi) */ static const struct script_op script_9[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_AUTO_UNI), + OP_S_NEW_STREAM_BIDI(a, S_BIDI_ID(0)), + OP_S_WRITE(a, "apple", 5), + OP_C_READ_EXPECT(DEFAULT, "apple", 5), + OP_C_WRITE(DEFAULT, "orange", 6), + OP_S_READ_EXPECT(a, "orange", 6), + OP_END }; /* 10. Shutdown */ static const struct script_op script_10[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_WRITE(DEFAULT, "apple", 5), + OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)), + OP_S_READ_EXPECT(a, "apple", 5), + + OP_C_SHUTDOWN_WAIT(NULL, 0), + OP_C_EXPECT_CONN_CLOSE_INFO(0, 1, 0), + OP_S_EXPECT_CONN_CLOSE_INFO(0, 1, 1), + OP_END }; /* 11. Many threads accepted on the same client connection */ +static const struct script_op script_11_child[] = { + OP_C_ACCEPT_STREAM_WAIT(a), + OP_C_READ_EXPECT(a, "foo", 3), + OP_SLEEP(10), + OP_C_EXPECT_FIN(a), + + OP_END +}; + static const struct script_op script_11[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + + OP_NEW_THREAD(5, script_11_child), + + OP_S_NEW_STREAM_BIDI(a, ANY_ID), + OP_S_WRITE(a, "foo", 3), + OP_S_CONCLUDE(a), + + OP_S_NEW_STREAM_BIDI(b, ANY_ID), + OP_S_WRITE(b, "foo", 3), + OP_S_CONCLUDE(b), + + OP_S_NEW_STREAM_BIDI(c, ANY_ID), + OP_S_WRITE(c, "foo", 3), + OP_S_CONCLUDE(c), + + OP_S_NEW_STREAM_BIDI(d, ANY_ID), + OP_S_WRITE(d, "foo", 3), + OP_S_CONCLUDE(d), + + OP_S_NEW_STREAM_BIDI(e, ANY_ID), + OP_S_WRITE(e, "foo", 3), + OP_S_CONCLUDE(e), + OP_END }; /* 12. Many threads initiated on the same client connection */ +static const struct script_op script_12_child[] = { + OP_C_NEW_STREAM_BIDI(a, ANY_ID), + OP_C_WRITE(a, "foo", 3), + OP_C_CONCLUDE(a), + OP_C_FREE_STREAM(a), + + OP_END +}; + static const struct script_op script_12[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + + OP_NEW_THREAD(5, script_12_child), + + OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)), + OP_S_READ_EXPECT(a, "foo", 3), + OP_S_EXPECT_FIN(a), + OP_S_BIND_STREAM_ID(b, C_BIDI_ID(1)), + OP_S_READ_EXPECT(b, "foo", 3), + OP_S_EXPECT_FIN(b), + OP_S_BIND_STREAM_ID(c, C_BIDI_ID(2)), + OP_S_READ_EXPECT(c, "foo", 3), + OP_S_EXPECT_FIN(c), + OP_S_BIND_STREAM_ID(d, C_BIDI_ID(3)), + OP_S_READ_EXPECT(d, "foo", 3), + OP_S_EXPECT_FIN(d), + OP_S_BIND_STREAM_ID(e, C_BIDI_ID(4)), + OP_S_READ_EXPECT(e, "foo", 3), + OP_S_EXPECT_FIN(e), + OP_END }; /* 13. Many threads accepted on the same client connection (stress test) */ +static const struct script_op script_13_child[] = { + OP_BEGIN_REPEAT(10), + + OP_C_ACCEPT_STREAM_WAIT(a), + OP_C_READ_EXPECT(a, "foo", 3), + OP_C_EXPECT_FIN(a), + OP_C_FREE_STREAM(a), + + OP_END_REPEAT(), + + OP_END +}; + static const struct script_op script_13[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + + OP_NEW_THREAD(5, script_13_child), + + OP_BEGIN_REPEAT(50), + + OP_S_NEW_STREAM_BIDI(a, ANY_ID), + OP_S_WRITE(a, "foo", 3), + OP_S_CONCLUDE(a), + OP_S_UNBIND_STREAM_ID(a), + + OP_END_REPEAT(), + OP_END }; /* 14. Many threads initiating on the same client connection (stress test) */ +static const struct script_op script_14_child[] = { + OP_BEGIN_REPEAT(10), + + OP_C_NEW_STREAM_BIDI(a, ANY_ID), + OP_C_WRITE(a, "foo", 3), + OP_C_CONCLUDE(a), + OP_C_FREE_STREAM(a), + + OP_END_REPEAT(), + + OP_END +}; + static const struct script_op script_14[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + + OP_NEW_THREAD(5, script_14_child), + + OP_BEGIN_REPEAT(50), + + OP_S_ACCEPT_STREAM_WAIT(a), + OP_S_READ_EXPECT(a, "foo", 3), + OP_S_EXPECT_FIN(a), + OP_S_UNBIND_STREAM_ID(a), + + OP_END_REPEAT(), + OP_END }; /* 15. Client sending large number of streams, MAX_STREAMS test */ static const struct script_op script_15[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + + /* + * This will cause a protocol violation to be raised by the server if we are + * not handling the stream limit correctly on the TX side. + */ + OP_BEGIN_REPEAT(200), + + OP_C_NEW_STREAM_BIDI_EX(a, ANY_ID, SSL_STREAM_FLAG_ADVANCE), + OP_C_WRITE(a, "foo", 3), + OP_C_CONCLUDE(a), + OP_C_FREE_STREAM(a), + + OP_END_REPEAT(), + + /* Prove the connection is still good. */ + OP_S_NEW_STREAM_BIDI(a, S_BIDI_ID(0)), + OP_S_WRITE(a, "bar", 3), + OP_S_CONCLUDE(a), + + OP_C_ACCEPT_STREAM_WAIT(a), + OP_C_READ_EXPECT(a, "bar", 3), + OP_C_EXPECT_FIN(a), + + /* + * Drain the queue of incoming streams. We should be able to get all 200 + * even though only 100 can be initiated at a time. + */ + OP_BEGIN_REPEAT(200), + + OP_S_ACCEPT_STREAM_WAIT(b), + OP_S_READ_EXPECT(b, "foo", 3), + OP_S_EXPECT_FIN(b), + OP_S_UNBIND_STREAM_ID(b), + + OP_END_REPEAT(), + OP_END }; /* 16. Server sending large number of streams, MAX_STREAMS test */ static const struct script_op script_16[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE), + + /* + * This will cause a protocol violation to be raised by the client if we are + * not handling the stream limit correctly on the TX side. + */ + OP_BEGIN_REPEAT(200), + + OP_S_NEW_STREAM_BIDI(a, ANY_ID), + OP_S_WRITE(a, "foo", 3), + OP_S_CONCLUDE(a), + OP_S_UNBIND_STREAM_ID(a), + + OP_END_REPEAT(), + + /* Prove that the connection is still good. */ + OP_C_NEW_STREAM_BIDI(a, ANY_ID), + OP_C_WRITE(a, "bar", 3), + OP_C_CONCLUDE(a), + + OP_S_ACCEPT_STREAM_WAIT(b), + OP_S_READ_EXPECT(b, "bar", 3), + OP_S_EXPECT_FIN(b), + + /* Drain the queue of incoming streams. */ + OP_BEGIN_REPEAT(200), + + OP_C_ACCEPT_STREAM_WAIT(b), + OP_C_READ_EXPECT(b, "foo", 3), + OP_C_EXPECT_FIN(b), + OP_C_FREE_STREAM(b), + + OP_END_REPEAT(), + OP_END }; /* 17. Key update test - unlimited */ static const struct script_op script_17[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_WRITE(DEFAULT, "apple", 5), + + OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)), + OP_S_READ_EXPECT(a, "apple", 5), + + OP_CHECK(override_key_update, 1), + + OP_BEGIN_REPEAT(200), + + OP_C_WRITE(DEFAULT, "apple", 5), + OP_S_READ_EXPECT(a, "apple", 5), + + /* + * TXKU frequency is bounded by RTT because a previous TXKU needs to be + * acknowledged by the peer first before another one can be begin. By + * waiting this long, we eliminate any such concern and ensure as many key + * updates as possible can occur for the purposes of this test. + */ + OP_CHECK(skip_time_ms, 100), + + OP_END_REPEAT(), + + /* At least 5 RXKUs detected */ + OP_CHECK(check_key_update_ge, 5), + + /* + * Prove the connection is still healthy by sending something in both + * directions. + */ + OP_C_WRITE(DEFAULT, "xyzzy", 5), + OP_S_READ_EXPECT(a, "xyzzy", 5), + + OP_S_WRITE(a, "plugh", 5), + OP_C_READ_EXPECT(DEFAULT, "plugh", 5), + OP_END }; /* 18. Key update test - RTT-bounded */ static const struct script_op script_18[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_WRITE(DEFAULT, "apple", 5), + + OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)), + OP_S_READ_EXPECT(a, "apple", 5), + + OP_CHECK(override_key_update, 1), + + OP_BEGIN_REPEAT(200), + + OP_C_WRITE(DEFAULT, "apple", 5), + OP_S_READ_EXPECT(a, "apple", 5), + OP_CHECK(skip_time_ms, 8), + + OP_END_REPEAT(), + + /* + * This time we simulate far less time passing between writes, so there are + * fewer opportunities to initiate TXKUs. Note that we ask for a TXKU every + * 1 packet above, which is absurd; thus this ensures we only actually + * generate TXKUs when we are allowed to. + */ + OP_CHECK(check_key_update_lt, 240), + + /* + * Prove the connection is still healthy by sending something in both + * directions. + */ + OP_C_WRITE(DEFAULT, "xyzzy", 5), + OP_S_READ_EXPECT(a, "xyzzy", 5), + + OP_S_WRITE(a, "plugh", 5), + OP_C_READ_EXPECT(DEFAULT, "plugh", 5), + OP_END }; /* 19. Key update test - artificially triggered */ static const struct script_op script_19[] = { - /* test moved to test/radix/quic_tests.c */ + OP_C_SET_ALPN("ossltest"), + OP_C_CONNECT_WAIT(), + + OP_C_WRITE(DEFAULT, "apple", 5), + + OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)), + OP_S_READ_EXPECT(a, "apple", 5), + + OP_C_WRITE(DEFAULT, "orange", 6), + OP_S_READ_EXPECT(a, "orange", 6), + + OP_S_WRITE(a, "strawberry", 10), + OP_C_READ_EXPECT(DEFAULT, "strawberry", 10), + + OP_CHECK(check_key_update_lt, 1), + OP_CHECK(trigger_key_update, 0), + + OP_C_WRITE(DEFAULT, "orange", 6), + OP_S_READ_EXPECT(a, "orange", 6), + OP_S_WRITE(a, "ok", 2), + + OP_C_READ_EXPECT(DEFAULT, "ok", 2), + OP_CHECK(check_key_update_ge, 1), + OP_END }; @@ -3450,12 +3886,7 @@ static const struct script_op script_49[] = { OP_SET_INJECT_WORD(4, 0), OP_S_WRITE(a, "Strawberry", 10), - /* - * The injected ACK acknowledges a packet number we have not sent, which the - * peer is expected to treat as a PROTOCOL_VIOLATION, so the connection is - * closed rather than the stream data being delivered. - */ - OP_C_EXPECT_CONN_CLOSE_INFO(OSSL_QUIC_ERR_PROTOCOL_VIOLATION, 0, 0), + OP_C_READ_EXPECT(DEFAULT, "Strawberry", 10), OP_END }; @@ -4203,7 +4634,7 @@ static int script_68_inject_handshake(struct helper *h, unsigned char *msg, return 1; } -/* Send a CertificateRequest message post-handshake */ +/* Send a CerticateRequest message post-handshake */ static const struct script_op script_68[] = { OP_S_SET_INJECT_HANDSHAKE(script_68_inject_handshake), OP_C_SET_ALPN("ossltest"), diff --git a/test/quic_rcidm_test.c b/test/quic_rcidm_test.c index 1b966c93d3..619c4c3efe 100644 --- a/test/quic_rcidm_test.c +++ b/test/quic_rcidm_test.c @@ -125,41 +125,8 @@ err: return testresult; } -static int test_rcidm_mfail(void) -{ - int testresult = 0; - QUIC_RCIDM *rcidm = NULL; - OSSL_QUIC_FRAME_NEW_CONN_ID ncid = { 0 }; - uint64_t i; - - MFAIL_start(); - - rcidm = ossl_quic_rcidm_new(&cid8_1); - if (rcidm == NULL) - goto err; - - if (!ossl_quic_rcidm_add_from_initial(rcidm, &cid8_2)) - goto err; - - /* Push enough NCIDs to force at least one priority-queue grow/realloc. */ - ncid.conn_id.id_len = 8; - for (i = 2; i < 20; ++i) { - ncid.seq_num = i; - ncid.conn_id.id[0] = (unsigned char)i; - if (!ossl_quic_rcidm_add_from_ncid(rcidm, &ncid)) - goto err; - } - - testresult = 1; -err: - MFAIL_end(); - ossl_quic_rcidm_free(rcidm); - return testresult; -} - int setup_tests(void) { ADD_ALL_TESTS(test_rcidm, 3); - ADD_MFAIL_TEST(test_rcidm_mfail); return 1; } diff --git a/test/quic_record_test.c b/test/quic_record_test.c index 0c9fa3a098..85a97a9293 100644 --- a/test/quic_record_test.c +++ b/test/quic_record_test.c @@ -3883,37 +3883,6 @@ static int test_tx_script(int idx) return tx_run_script(tx_scripts[idx]); } -static int test_qrx_multipkt_alloc_failure(void) -{ - int testresult = 0; - struct rx_state s = { 0 }; - OSSL_QRX_PKT *pkt = NULL; - - s.args.short_conn_id_len = 0; - - if (!TEST_true(rx_state_ensure(&s))) - goto err; - - s.rx_dcid = empty_conn_id; - - if (!TEST_true(ossl_quic_provide_initial_secret(NULL, NULL, - &rx_script_5_c2s_init_dcid, 0, s.qrx, NULL))) - goto err; - - if (!TEST_true(ossl_quic_demux_inject(s.demux, rx_script_5_in, - sizeof(rx_script_5_in), NULL, NULL))) - goto err; - - MFAIL_start(); - testresult = ossl_qrx_read_pkt(s.qrx, &pkt); - MFAIL_end(); - -err: - ossl_qrx_pkt_release(pkt); - rx_state_teardown(&s); - return testresult; -} - int setup_tests(void) { ADD_ALL_TESTS(test_rx_script, OSSL_NELEM(rx_scripts)); @@ -3928,6 +3897,5 @@ int setup_tests(void) */ ADD_ALL_TESTS(test_wire_pkt_hdr, NUM_WIRE_PKT_HDR_TESTS + 1); ADD_ALL_TESTS(test_tx_script, OSSL_NELEM(tx_scripts)); - ADD_MFAIL_NO_CHECK_TEST(test_qrx_multipkt_alloc_failure); return 1; } diff --git a/test/quic_srt_gen_test.c b/test/quic_srt_gen_test.c index cfcee4a953..fcbf4aea22 100644 --- a/test/quic_srt_gen_test.c +++ b/test/quic_srt_gen_test.c @@ -70,26 +70,8 @@ err: return testresult; } -static int test_srt_gen_new_mfail(int idx) -{ - const struct test_case *t = &tests[idx]; - QUIC_SRT_GEN *srt_gen = NULL; - - MFAIL_start(); - srt_gen = ossl_quic_srt_gen_new(NULL, NULL, t->key, t->key_len); - MFAIL_end(); - - if (srt_gen == NULL) { - return 0; - } - - ossl_quic_srt_gen_free(srt_gen); - return 1; -} - int setup_tests(void) { ADD_ALL_TESTS(test_srt_gen, OSSL_NELEM(tests)); - ADD_MFAIL_ALL_TESTS(test_srt_gen_new_mfail, OSSL_NELEM(tests)); return 1; } diff --git a/test/quic_srtm_test.c b/test/quic_srtm_test.c index 7838d46a77..cbdf847632 100644 --- a/test/quic_srtm_test.c +++ b/test/quic_srtm_test.c @@ -22,17 +22,14 @@ static int test_srtm(void) QUIC_SRTM *srtm; void *opaque = NULL; uint64_t seq_num = 0; - uint8_t match; if (!TEST_ptr(srtm = ossl_quic_srtm_new(NULL, NULL))) goto err; if (!TEST_true(ossl_quic_srtm_add(srtm, ptrs + 0, 0, &token_1)) || !TEST_false(ossl_quic_srtm_add(srtm, ptrs + 0, 0, &token_1)) - || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 0, 1, &match)) - || !TEST_uint_eq(match, 0) - || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 3, 0, &match)) - || !TEST_uint_eq(match, 0) + || !TEST_false(ossl_quic_srtm_remove(srtm, ptrs + 0, 1)) + || !TEST_false(ossl_quic_srtm_remove(srtm, ptrs + 3, 0)) || !TEST_true(ossl_quic_srtm_cull(srtm, ptrs + 3)) || !TEST_true(ossl_quic_srtm_cull(srtm, ptrs + 3)) || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 0, 1, &token_1)) @@ -41,8 +38,7 @@ static int test_srtm(void) || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 1, 0, &token_1)) || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 2, 0, &token_2)) || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 3, 3, &token_2)) - || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 3, 3, &match)) - || !TEST_uint_eq(match, 1) + || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 3, 3)) || !TEST_true(ossl_quic_srtm_lookup(srtm, &token_1, 0, &opaque, &seq_num)) || !TEST_ptr_eq(opaque, ptrs + 1) || !TEST_uint64_t_eq(seq_num, 0) @@ -66,8 +62,7 @@ static int test_srtm(void) || !TEST_true(ossl_quic_srtm_lookup(srtm, &token_2, 0, &opaque, &seq_num)) || !TEST_ptr_eq(opaque, ptrs + 2) || !TEST_uint64_t_eq(seq_num, 0) - || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 2, 0, &match)) - || !TEST_uint_eq(match, 1) + || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 2, 0)) || !TEST_false(ossl_quic_srtm_lookup(srtm, &token_2, 0, &opaque, &seq_num))) goto err; @@ -77,54 +72,8 @@ err: return testresult; } -static int test_srtm_new_mfail(void) -{ - QUIC_SRTM *srtm; - - MFAIL_start(); - srtm = ossl_quic_srtm_new(NULL, NULL); - MFAIL_end(); - - ossl_quic_srtm_free(srtm); - return srtm != NULL; -} - -static int test_srtm_ops_mfail(void) -{ - int testresult = 0; - QUIC_SRTM *srtm; - void *opaque = NULL; - uint64_t seq_num = 0; - - if (!TEST_ptr(srtm = ossl_quic_srtm_new(NULL, NULL))) - goto err; - - MFAIL_start(); - - if (!ossl_quic_srtm_add(srtm, ptrs + 0, 0, &token_1) - || !ossl_quic_srtm_add(srtm, ptrs + 0, 1, &token_1) - || !ossl_quic_srtm_add(srtm, ptrs + 0, 2, &token_1) - || !ossl_quic_srtm_add(srtm, ptrs + 1, 0, &token_1) - || !ossl_quic_srtm_add(srtm, ptrs + 2, 0, &token_2) - || !ossl_quic_srtm_add(srtm, ptrs + 3, 3, &token_2) - || !ossl_quic_srtm_remove(srtm, ptrs + 3, 3, NULL) - || !ossl_quic_srtm_lookup(srtm, &token_1, 0, &opaque, &seq_num) - || !ossl_quic_srtm_cull(srtm, ptrs + 0) - || !ossl_quic_srtm_lookup(srtm, &token_2, 0, &opaque, &seq_num) - || !ossl_quic_srtm_remove(srtm, ptrs + 2, 0, NULL)) - goto err; - - testresult = 1; -err: - MFAIL_end(); - ossl_quic_srtm_free(srtm); - return testresult; -} - int setup_tests(void) { ADD_TEST(test_srtm); - ADD_MFAIL_TEST(test_srtm_new_mfail); - ADD_MFAIL_TEST(test_srtm_ops_mfail); return 1; } diff --git a/test/quic_tserver_test.c b/test/quic_tserver_test.c index b4e81f427f..0ef79035d2 100644 --- a/test/quic_tserver_test.c +++ b/test/quic_tserver_test.c @@ -331,38 +331,16 @@ static int do_test(int use_thread_assist, int use_fake_time, int use_inject) CRYPTO_THREAD_unlock(fake_time_lock); ++idle_units_done; + ossl_quic_conn_force_assist_thread_wake(c_ssl); /* - * The assist thread alone keeps the idle connection alive. It - * waits on real time internally, so advancing fake time can - * outrun it. Rather than race it, wait until it has caught up: - * the event timeout is computed against fake time, so once the - * next deadline is back in the future all events due up to now - * - including any keepalive - have been serviced. + * If the event timeout has expired then give the assistance + * thread a chance to catch up */ - for (;;) { - ossl_quic_conn_force_assist_thread_wake(c_ssl); - - if (!TEST_true(SSL_get_event_timeout(c_ssl, &tv, &isinf))) - goto err; - - if (isinf - || ossl_time_compare(ossl_time_from_timeval(tv), - ossl_time_zero()) - > 0) - break; - - if (ossl_time_compare(ossl_time_subtract(real_now(NULL), - start_time), - ossl_ms2time(limit_ms)) - >= 0) { - TEST_error("timeout waiting for assist thread to send " - "keepalive during idle test"); - goto err; - } - - OSSL_sleep(1); /* Yield so the assist thread can run. */ - } + if (!TEST_true(SSL_get_event_timeout(c_ssl, &tv, &isinf))) + goto err; + if (!isinf && ossl_time_compare(ossl_time_zero(), ossl_time_from_timeval(tv)) >= 0) + OSSL_sleep(10); /* Ensure CPU scheduling for test purposes */ } else { c_done_idle_test = 1; } diff --git a/test/quicapitest.c b/test/quicapitest.c index a8de8f9670..97c759dffc 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -21,7 +21,6 @@ #include "../ssl/ssl_local.h" #include "../ssl/quic/quic_channel_local.h" #include "internal/quic_error.h" -#include "internal/quic_ssl.h" static OSSL_LIB_CTX *libctx = NULL; static char *propq = NULL; @@ -40,9 +39,6 @@ static BIO_ADDR *create_addr(struct in_addr *ina, short int port); static int bio_addr_bind(BIO *bio, BIO_ADDR *addr); static SSL *ql_create(SSL_CTX *ssl_ctx, BIO *bio); static SSL_CTX *create_server_ctx(void); -static SSL_CTX *create_client_ctx(void); -static int create_quic_ssl_objects(SSL_CTX *sctx, SSL_CTX *cctx, - SSL **lssl, SSL **cssl); static int qc_init(SSL *qconn, BIO_ADDR *dst_addr); /* The ssltrace test assumes some options are switched on/off */ @@ -50,7 +46,7 @@ static int qc_init(SSL *qconn, BIO_ADDR *dst_addr); && defined(OPENSSL_NO_BROTLI) && defined(OPENSSL_NO_ZSTD) \ && !defined(OPENSSL_NO_ECX) && !defined(OPENSSL_NO_DH) \ && !defined(OPENSSL_NO_ML_DSA) && !defined(OPENSSL_NO_ML_KEM) \ - && !defined(OPENSSL_NO_SLH_DSA) && !defined(OPENSSL_NO_SM2) + && !defined(OPENSSL_NO_SM2) #define DO_SSL_TRACE_TEST #endif @@ -218,90 +214,6 @@ end: return ret; } -static int test_ssl_read_key_update_mfail(void) -{ - SSL_CTX *cctx = NULL, *sctx = NULL; - SSL *clientssl = NULL, *serverssl = NULL, *qlistener = NULL; - QUIC_CHANNEL *sch = NULL; - int ret = 0, i; - const char *msg = "ping"; - size_t msglen = strlen(msg); - size_t numbytes = 0; - unsigned char buf[64]; - - if (!TEST_ptr(sctx = create_server_ctx()) - || !TEST_ptr(cctx = create_client_ctx())) - goto err; - - if (!create_quic_ssl_objects(sctx, cctx, &qlistener, &clientssl)) - goto err; - - if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "localhost"))) - goto err; - - /* Send ClientHello and server retry. */ - for (i = 0; i < 2; i++) { - ret = SSL_connect(clientssl); - if (!TEST_int_le(ret, 0) - || !TEST_int_eq(SSL_get_error(clientssl, ret), SSL_ERROR_WANT_READ)) - goto err; - SSL_handle_events(qlistener); - } - - serverssl = SSL_accept_connection(qlistener, 0); - if (!TEST_ptr(serverssl) - || !TEST_true(create_bare_ssl_connection(serverssl, clientssl, - SSL_ERROR_NONE, 0, 0))) - goto err; - - if (!TEST_ptr(sch = ossl_quic_conn_get_channel(serverssl))) - goto err; - - /* Open the default stream so the server has something to write back on. */ - if (!TEST_true(SSL_write_ex(clientssl, msg, msglen, &numbytes)) - || !TEST_size_t_eq(numbytes, msglen)) - goto err; - - /* Route the datagram to the server connection and let it consume it. */ - SSL_handle_events(qlistener); - SSL_handle_events(serverssl); - if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &numbytes))) - goto err; - - /* - * Force the server's TX side to rotate keys. Its next outgoing packet - * will carry the flipped Key Phase bit. When the client decrypts that - * packet, qrx_key_update_initiated -> rxku_detected -> ch_trigger_txku - * fires on the client. - */ - if (!TEST_true(ossl_qtx_trigger_key_update(sch->qtx))) - goto err; - - if (!TEST_true(SSL_write_ex(serverssl, msg, msglen, &numbytes)) - || !TEST_size_t_eq(numbytes, msglen)) - goto err; - - /* - * Process the inbound packet (carrying the new Key Phase) under mfail. - * SSL_read_ex ticks the client, reads the datagram off its BIO and - * decrypts it, which is where the key update handling runs. - */ - MFAIL_start(); - ret = SSL_read_ex(clientssl, buf, sizeof(buf), &numbytes); - MFAIL_end(); - - ret = (ret > 0); - -err: - SSL_free(serverssl); - SSL_free(clientssl); - SSL_free(qlistener); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - - return ret; -} - /* * Test that sending FIN with no data to a client blocking in SSL_read_ex() will * wake up the client. @@ -2796,16 +2708,8 @@ end: return ret; } -/* Fake clock for tests that advance QUIC time without consuming real time. */ -static OSSL_TIME fake_now; - -static OSSL_TIME fake_now_cb(void *arg) -{ - return fake_now; -} - -static int create_quic_ssl_objects_ex(SSL_CTX *sctx, SSL_CTX *cctx, - SSL **lssl, SSL **cssl, int use_fake_time) +static int create_quic_ssl_objects(SSL_CTX *sctx, SSL_CTX *cctx, + SSL **lssl, SSL **cssl) { BIO_ADDR *addr = NULL; struct in_addr ina; @@ -2846,18 +2750,6 @@ static int create_quic_ssl_objects_ex(SSL_CTX *sctx, SSL_CTX *cctx, SSL_set_bio(*cssl, cbio, cbio); cbio = NULL; - if (use_fake_time) { - /* - * The base value does not matter but must be nonzero, as the ACK - * manager reads a zero packet timestamp as unset. Use real time to - * match the clock the engines were created with. - */ - fake_now = ossl_time_now(); - if (!TEST_true(ossl_quic_set_override_now_cb(*lssl, fake_now_cb, NULL)) - || !TEST_true(ossl_quic_set_override_now_cb(*cssl, fake_now_cb, NULL))) - goto err; - } - ret = 1; err: @@ -2873,12 +2765,6 @@ err: return ret; } -static int create_quic_ssl_objects(SSL_CTX *sctx, SSL_CTX *cctx, - SSL **lssl, SSL **cssl) -{ - return create_quic_ssl_objects_ex(sctx, cctx, lssl, cssl, 0); -} - static int test_ssl_client_as_ossl_quic_method(void) { SSL_CTX *cctx = NULL, *sctx = NULL; @@ -3518,146 +3404,6 @@ static int test_quic_peer_addr_v6(void) } #endif -/* - * Advance the fake clock to the next QUIC timer event when both endpoints are - * idle, consuming no real time. - */ -static void quic_advance_time(SSL *clientssl, SSL *serverssl) -{ - struct timeval tv; - int inf = 0; - OSSL_TIME delay = ossl_time_infinite(), t; - - /* If there is data waiting to be processed, do not wait - tick instead. */ - if (BIO_pending(SSL_get_rbio(clientssl)) > 0) - return; - - if (SSL_get_event_timeout(clientssl, &tv, &inf) && !inf) { - t = ossl_time_from_timeval(tv); - if (ossl_time_compare(t, delay) < 0) - delay = t; - } - if (SSL_get_event_timeout(serverssl, &tv, &inf) && !inf) { - t = ossl_time_from_timeval(tv); - if (ossl_time_compare(t, delay) < 0) - delay = t; - } - - if (!ossl_time_is_infinite(delay)) - fake_now = ossl_time_add(fake_now, delay); -} - -static int test_quic_handshake_multipkt_mfail(void) -{ - SSL_CTX *cctx = NULL, *sctx = NULL; - SSL *clientssl = NULL, *serverssl = NULL, *qlistener = NULL; - QUIC_CHANNEL *sch = NULL, *cch = NULL; - int ret = 0, rc = 0, err, i; - - if (!TEST_ptr(sctx = create_server_ctx()) - || !TEST_ptr(cctx = create_client_ctx())) - goto err; - - if (!create_quic_ssl_objects_ex(sctx, cctx, &qlistener, &clientssl, 1)) - goto err; - - if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "localhost"))) - goto err; - - /* Get the listener to bind a channel we can accept. */ - for (i = 0; i < 10; i++) { - rc = SSL_connect(clientssl); - if (rc <= 0) { - err = SSL_get_error(clientssl, rc); - if (!TEST_true(err == SSL_ERROR_WANT_READ - || err == SSL_ERROR_WANT_WRITE)) - goto err; - } - SSL_handle_events(qlistener); - - serverssl = SSL_accept_connection(qlistener, 0); - if (serverssl != NULL) - break; - } - if (!TEST_ptr(serverssl) - || !TEST_false(SSL_is_init_finished(serverssl))) - goto err; - - if (!TEST_ptr(sch = ossl_quic_conn_get_channel(serverssl))) - goto err; - - /* Do handshake until the server reaches the first flight. */ - for (i = 0; i < 10; i++) { - rc = SSL_do_handshake(clientssl); - if (rc <= 0) { - err = SSL_get_error(clientssl, rc); - if (!TEST_true(err == SSL_ERROR_WANT_READ - || err == SSL_ERROR_WANT_WRITE)) - goto err; - } - if (ossl_quic_channel_is_term_any(sch)) - goto err; - SSL_handle_events(serverssl); - if (sch->tx_enc_level >= QUIC_ENC_LEVEL_HANDSHAKE) - break; - quic_advance_time(clientssl, serverssl); - } - if (!TEST_int_lt(i, 10)) - goto err; - - /* Process the multi-packet datagram under mfail. */ - MFAIL_start(); - rc = SSL_do_handshake(clientssl); - MFAIL_end(); - - /* A fatal injected failure may terminate the connection - bail if so. */ - if (rc <= 0) { - err = SSL_get_error(clientssl, rc); - if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) - goto err; - } - - if (!TEST_ptr(cch = ossl_quic_conn_get_channel(clientssl))) - goto err; - - /* Connection still live so get the handshake to converge. */ - for (i = 0; i < 10; i++) { - rc = SSL_do_handshake(clientssl); - if (rc == 1) - break; - - err = SSL_get_error(clientssl, rc); - if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { - ret = -1; - goto err; - } - - if (ossl_quic_channel_is_term_any(cch) - || ossl_quic_channel_is_term_any(sch)) - goto err; - - SSL_handle_events(serverssl); - quic_advance_time(clientssl, serverssl); - } - if (!TEST_int_lt(i, 10)) { - ret = is_fips && fips_provider_version_match(libctx, ">=3.5.0 <4.1.0") - ? 0 - : -1; - goto err; - } - - ret = 1; - -err: - SSL_free(serverssl); - SSL_free(clientssl); - SSL_free(qlistener); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - - return ret; -} - /* Test ECH with quic */ static int test_ech(void) { @@ -3817,29 +3563,6 @@ end: return ret; } -static int test_ssl_new_mfail(void) -{ - int ret = 0; - SSL_CTX *cctx = NULL; - SSL *clientquic = NULL; - - if (!TEST_ptr(cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()))) - goto err; - - MFAIL_start(); - clientquic = SSL_new(cctx); - MFAIL_end(); - - if (clientquic != NULL) - ret = 1; - -err: - SSL_free(clientquic); - SSL_CTX_free(cctx); - - return ret; -} - /***********************************************************************************/ OPT_TEST_DECLARE_USAGE("provider config certsdir datadir\n") @@ -3909,7 +3632,6 @@ int setup_tests(void) goto err; ADD_ALL_TESTS(test_quic_write_read, 3); - ADD_MFAIL_NO_CHECK_TEST(test_ssl_read_key_update_mfail); ADD_TEST(test_fin_only_blocking); ADD_TEST(test_ciphersuites); ADD_TEST(test_cipher_find); @@ -3951,10 +3673,8 @@ int setup_tests(void) ADD_TEST(test_quic_peer_addr_v6); #endif ADD_TEST(test_quic_peer_addr_v4); - ADD_MFAIL_NO_CHECK_TEST(test_quic_handshake_multipkt_mfail); ADD_TEST(test_ech); ADD_TEST(test_quic_resize_txe); - ADD_MFAIL_TEST(test_ssl_new_mfail); return 1; err: diff --git a/test/radix/quic_bindings.c b/test/radix/quic_bindings.c index 63bcecad99..9f887d55c6 100644 --- a/test/radix/quic_bindings.c +++ b/test/radix/quic_bindings.c @@ -52,7 +52,6 @@ typedef struct radix_obj_st { SSL *ssl; /* owns one reference */ unsigned int registered : 1; /* in LHASH? */ unsigned int active : 1; /* tick? */ - CRYPTO_MUTEX *mx; } RADIX_OBJ; DEFINE_LHASH_OF_EX(RADIX_OBJ); @@ -67,12 +66,9 @@ typedef struct radix_process_st { /* Process-global state. */ CRYPTO_MUTEX *gm; /* global mutex */ LHASH_OF(RADIX_OBJ) *objs; /* protected by gm */ + OSSL_TIME time_slip; /* protected by gm */ BIO *keylog_out; /* protected by gm */ - CRYPTO_MUTEX *time_m; - OSSL_TIME base_time; /* set once at init, constant thereafter */ - OSSL_TIME time_slip; /* protected by time_m */ - int done_join_all_threads; /* @@ -108,11 +104,11 @@ typedef struct radix_thread_st { DEFINE_STACK_OF(RADIX_THREAD) /* ssl reference is transferred. name is copied and is required. */ -static RADIX_OBJ *RADIX_OBJ_new_empty(const char *name) +static RADIX_OBJ *RADIX_OBJ_new(const char *name, SSL *ssl) { RADIX_OBJ *obj; - if (!TEST_ptr(name)) + if (!TEST_ptr(name) || !TEST_ptr(ssl)) return NULL; if (!TEST_ptr(obj = OPENSSL_zalloc(sizeof(*obj)))) @@ -123,31 +119,7 @@ static RADIX_OBJ *RADIX_OBJ_new_empty(const char *name) return NULL; } - obj->mx = ossl_crypto_mutex_new(); -#if !defined(OPENSSL_THREADS_NONE) - if (obj->mx == NULL) { - OPENSSL_free(obj->name); - OPENSSL_free(obj); - return NULL; - } -#endif - - return obj; -} - -static RADIX_OBJ *RADIX_OBJ_new(const char *name, SSL *ssl) -{ - RADIX_OBJ *obj; - - if (!TEST_ptr(ssl)) - return NULL; - - obj = RADIX_OBJ_new_empty(name); - if (!TEST_ptr(obj)) - return NULL; - obj->ssl = ssl; - return obj; } @@ -160,7 +132,6 @@ static void RADIX_OBJ_free(RADIX_OBJ *obj) SSL_free(obj->ssl); OPENSSL_free(obj->name); - ossl_crypto_mutex_free(&obj->mx); OPENSSL_free(obj); } @@ -181,8 +152,6 @@ static int RADIX_PROCESS_init(RADIX_PROCESS *rp, size_t node_idx, size_t process #if defined(OPENSSL_THREADS) if (!TEST_ptr(rp->gm = ossl_crypto_mutex_new())) goto err; - if (!TEST_ptr(rp->time_m = ossl_crypto_mutex_new())) - goto err; #endif if (!TEST_ptr(rp->objs = lh_RADIX_OBJ_new(RADIX_OBJ_hash, RADIX_OBJ_cmp))) @@ -201,15 +170,12 @@ static int RADIX_PROCESS_init(RADIX_PROCESS *rp, size_t node_idx, size_t process rp->process_idx = process_idx; rp->done_join_all_threads = 0; rp->next_thread_idx = 0; - rp->base_time = ossl_time_now(); - rp->time_slip = ossl_time_zero(); return 1; err: lh_RADIX_OBJ_free(rp->objs); rp->objs = NULL; ossl_crypto_mutex_free(&rp->gm); - ossl_crypto_mutex_free(&rp->time_m); return 0; } @@ -464,7 +430,6 @@ static void RADIX_PROCESS_cleanup(RADIX_PROCESS *rp) BIO_free_all(rp->keylog_out); rp->keylog_out = NULL; ossl_crypto_mutex_free(&rp->gm); - ossl_crypto_mutex_free(&rp->time_m); } static RADIX_OBJ *RADIX_PROCESS_get_obj(RADIX_PROCESS *rp, const char *name) @@ -479,9 +444,6 @@ static int RADIX_PROCESS_set_obj(RADIX_PROCESS *rp, const char *name, RADIX_OBJ *obj) { RADIX_OBJ *existing; - SSL *existing_ssl = NULL; - RADIX_THREAD *rt; - int i, j; if (obj != NULL && !TEST_false(obj->registered)) return 0; @@ -493,10 +455,7 @@ static int RADIX_PROCESS_set_obj(RADIX_PROCESS *rp, lh_RADIX_OBJ_delete(rp->objs, existing); existing->registered = 0; - existing_ssl = existing->ssl; RADIX_OBJ_free(existing); - } else { - existing = NULL; } if (obj != NULL) { @@ -504,18 +463,6 @@ static int RADIX_PROCESS_set_obj(RADIX_PROCESS *rp, obj->registered = 1; } - if (existing != NULL) { - for (i = 0; i < sk_RADIX_THREAD_num(rp->threads); i++) { - rt = (RADIX_THREAD *)sk_RADIX_THREAD_value(rp->threads, i); - for (j = 0; j < NUM_SLOTS; j++) { - if (rt->slot[j] == existing) - rt->slot[j] = obj; - if (rt->ssl[j] == existing_ssl) - rt->ssl[j] = (obj == NULL) ? NULL : obj->ssl; - } - } - } - return 1; } @@ -671,9 +618,6 @@ static int bindings_process_finish(int testresult_main) radix_thread_cleanup(); /* cleanup main thread */ RADIX_PROCESS_cleanup(&radix_process); - if (!TEST_true(CRYPTO_THREAD_cleanup_local(&radix_thread))) - testresult = 0; - if (testresult) BIO_printf(bio_err, "==> OK\n\n"); else @@ -690,46 +634,36 @@ static OSSL_TIME get_time(void *arg) { OSSL_TIME time_slip; - ossl_crypto_mutex_lock(RP()->time_m); + ossl_crypto_mutex_lock(RP()->gm); time_slip = RP()->time_slip; - ossl_crypto_mutex_unlock(RP()->time_m); + ossl_crypto_mutex_unlock(RP()->gm); - return ossl_time_add(RP()->base_time, time_slip); + return ossl_time_add(ossl_time_now(), time_slip); } -static OSSL_TIME terp_now(void *arg) +ossl_unused static void radix_skip_time(OSSL_TIME t) { - return ossl_time_now(); -} - -static void radix_skip_time(OSSL_TIME t) -{ - ossl_crypto_mutex_lock(RP()->time_m); + ossl_crypto_mutex_lock(RP()->gm); RP()->time_slip = ossl_time_add(RP()->time_slip, t); - ossl_crypto_mutex_unlock(RP()->time_m); + ossl_crypto_mutex_unlock(RP()->gm); } static void per_op_tick_obj(RADIX_OBJ *obj) { - ossl_crypto_mutex_lock(obj->mx); - if (obj->active && obj->ssl) + if (obj->active) SSL_handle_events(obj->ssl); - ossl_crypto_mutex_unlock(obj->mx); } static int do_per_op(TERP *terp, void *arg) { - radix_skip_time(ossl_ms2time(1)); lh_RADIX_OBJ_doall(RP()->objs, per_op_tick_obj); return 1; } static int bindings_adjust_terp_config(TERP_CONFIG *cfg) { - cfg->now_cb = terp_now; + cfg->now_cb = get_time; cfg->per_op_cb = do_per_op; - - cfg->max_execution_time = ossl_ms2time(60000); return 1; } diff --git a/test/radix/quic_ops.c b/test/radix/quic_ops.c index ed129d0ff7..11cf93be30 100644 --- a/test/radix/quic_ops.c +++ b/test/radix/quic_ops.c @@ -27,24 +27,6 @@ err: return ok; } -DEF_FUNC(hf_bind) -{ - const char *name; - RADIX_OBJ *empty_obj; - - F_POP(name); - - empty_obj = RADIX_OBJ_new_empty(name); - if (empty_obj == NULL) - return 0; - - RADIX_PROCESS_set_obj(RP(), name, empty_obj); - - return 1; -err: - return 0; -} - static int ssl_ctx_select_alpn(SSL *ssl, const unsigned char **out, unsigned char *out_len, const unsigned char *in, unsigned int in_len, @@ -204,11 +186,6 @@ DEF_FUNC(hf_new_ssl) if (!is_domain && !TEST_true(ssl_attach_bio_dgram(ssl, 0, NULL))) goto err; - if (!TEST_true(ossl_quic_set_override_now_cb(ssl, get_time, NULL))) { - SSL_free(ssl); - goto err; - } - if (!TEST_true(RADIX_PROCESS_set_ssl(RP(), name, ssl))) { SSL_free(ssl); goto err; @@ -271,37 +248,27 @@ err: return ok; } -#define OP_F_REPLACE_STREAM 0x8000000000000000 -#define OP_F_MASK 0x7fffffffffffffff - DEF_FUNC(hf_new_stream) { int ok = 0; - int replace; - RADIX_OBJ *stream_obj; const char *stream_name; - SSL *conn, *stream, *old; + SSL *conn, *stream; uint64_t flags, do_accept; F_POP2(flags, do_accept); F_POP(stream_name); REQUIRE_SSL(conn); - replace = ((OP_F_REPLACE_STREAM & flags) != 0); - stream_obj = RADIX_PROCESS_get_obj(RP(), stream_name); - if (replace == 0) { - if (!TEST_ptr_null(stream_obj)) - goto err; - } else if (TEST_ptr_null(stream_obj)) + if (!TEST_ptr_null(RADIX_PROCESS_get_obj(RP(), stream_name))) goto err; if (do_accept) { - stream = SSL_accept_stream(conn, flags & OP_F_MASK); + stream = SSL_accept_stream(conn, flags); if (stream == NULL) F_SPIN_AGAIN(); } else { - stream = SSL_new_stream(conn, flags & OP_F_MASK); + stream = SSL_new_stream(conn, flags); } if (!TEST_ptr(stream)) @@ -309,14 +276,8 @@ DEF_FUNC(hf_new_stream) /* TODO(QUIC RADIX): Implement wait behaviour */ - if (stream_obj != NULL) { - ossl_crypto_mutex_lock(stream_obj->mx); - old = stream_obj->ssl; - stream_obj->ssl = stream; - stream = NULL; - ossl_crypto_mutex_unlock(stream_obj->mx); - SSL_free(old); - } else if (!TEST_true(RADIX_PROCESS_set_ssl(RP(), stream_name, stream))) { + if (stream != NULL + && !TEST_true(RADIX_PROCESS_set_ssl(RP(), stream_name, stream))) { SSL_free(stream); goto err; } @@ -347,7 +308,6 @@ DEF_FUNC(hf_accept_conn) SSL_free(conn); goto err; } - radix_activate_obj(RADIX_PROCESS_get_obj(RP(), conn_name)); ok = 1; err: @@ -964,99 +924,10 @@ err: return ok; } -DEF_FUNC(hf_override_key_update) -{ - int ok = 0; - SSL *ssl; - uint64_t threshold; - QUIC_CHANNEL *ch; - - F_POP(threshold); - REQUIRE_SSL(ssl); - ch = ossl_quic_conn_get_channel(ssl); - ossl_quic_channel_set_txku_threshold_override(ch, threshold); - ok = 1; -err: - return ok; -} - -DEF_FUNC(hf_check_key_update_ge) -{ - int ok = 0; - SSL *ssl; - uint64_t min_rxke, txke, rxke; - int64_t diff; - QUIC_CHANNEL *ch; - - F_POP(min_rxke); - REQUIRE_SSL(ssl); - ch = ossl_quic_conn_get_channel(ssl); - txke = ossl_quic_channel_get_tx_key_epoch(ch); - rxke = ossl_quic_channel_get_rx_key_epoch(ch); - diff = (int64_t)txke - (int64_t)rxke; - - /* - * TXKE must always be equal to or ahead of RXKE. - * It can be ahead of RXKE by at most 1. - */ - if (!TEST_int64_t_ge(diff, 0) || !TEST_int64_t_le(diff, 1)) - goto err; - - /* Caller specifies a minimum number of RXKEs which must have happened. */ - if (!TEST_uint64_t_ge(rxke, min_rxke)) - goto err; - - ok = 1; -err: - return ok; -} - -DEF_FUNC(hf_check_key_update_lt) -{ - int ok = 0; - SSL *ssl; - uint64_t max_txke, txke; - QUIC_CHANNEL *ch; - - F_POP(max_txke); - REQUIRE_SSL(ssl); - ch = ossl_quic_conn_get_channel(ssl); - txke = ossl_quic_channel_get_tx_key_epoch(ch); - - /* Caller specifies a maximum number of TXKEs which must not be exceeded. */ - if (!TEST_uint64_t_lt(txke, max_txke)) - goto err; - - ok = 1; -err: - return ok; -} - -DEF_FUNC(hf_trigger_key_update) -{ - int ok = 0; - SSL *ssl; - uint64_t update_type; - - F_POP(update_type); - REQUIRE_SSL(ssl); - - if (!TEST_true(SSL_key_update(ssl, (int)update_type))) - goto err; - - ok = 1; -err: - return ok; -} - #define OP_UNBIND(name) \ (OP_PUSH_PZ(#name), \ OP_FUNC(hf_unbind)) -#define OP_BIND(name) \ - (OP_PUSH_PZ(#name), \ - OP_FUNC(hf_bind)) - #define OP_SELECT_SSL(slot, name) \ (OP_PUSH_U64(slot), \ OP_PUSH_PZ(#name), \ @@ -1208,9 +1079,9 @@ err: OP_FUNC(hf_read_fail)) #define OP_READ_FAIL_WAIT(name) \ - (OP_SELECT_SSL(0, name), \ - OP_PUSH_U64(1), \ - OP_FUNC(hf_read_fail)) + (OP_SELECT_SSL(0, name), \ + OP_PUSH_U64(1), \ + OP_FUNC(hf_read_fail) #define OP_POP_ERR() \ OP_FUNC(hf_pop_err) @@ -1228,7 +1099,7 @@ err: #define OP_STREAM_RESET(name, error_code) \ (OP_SELECT_SSL(0, name), \ - OP_PUSH_PZ(#name), \ + OP_PUSH_U64(flags), \ OP_PUSH_U64(error_code), \ OP_FUNC(hf_stream_reset)) @@ -1275,23 +1146,3 @@ err: #define OP_SLEEP(ms) \ (OP_PUSH_U64(ms), \ OP_FUNC(hf_sleep)) - -#define OP_OVERRIDE_KEY_UPDATE(name, threshold) \ - (OP_SELECT_SSL(0, name), \ - OP_PUSH_U64(threshold), \ - OP_FUNC(hf_override_key_update)) - -#define OP_CHECK_KEY_UPDATE_GE(name, min_rxke) \ - (OP_SELECT_SSL(0, name), \ - OP_PUSH_U64(min_rxke), \ - OP_FUNC(hf_check_key_update_ge)) - -#define OP_CHECK_KEY_UPDATE_LT(name, max_txke) \ - (OP_SELECT_SSL(0, name), \ - OP_PUSH_U64(max_txke), \ - OP_FUNC(hf_check_key_update_lt)) - -#define OP_TRIGGER_KEY_UPDATE(name, update_type) \ - (OP_SELECT_SSL(0, name), \ - OP_PUSH_U64(update_type), \ - OP_FUNC(hf_trigger_key_update)) diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index 154926a16f..ed2685d14c 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -765,1038 +765,6 @@ DEF_SCRIPT(check_ctx_cbks, "Check new_pending and client_hello callbacks") OP_FUNC(check_pending); } -DEF_FUNC(check_stream_reset_5) -{ - int ok = 0; - SSL *ssl; - uint64_t aec = 0; - int state; - - REQUIRE_SSL(ssl); - - state = SSL_get_stream_read_state(ssl); - if (state != SSL_STREAM_STATE_RESET_REMOTE) - F_SPIN_AGAIN(); - - if (!TEST_true(SSL_get_stream_read_error_code(ssl, &aec))) - goto err; - - if (!TEST_uint64_t_eq(aec, 42)) - goto err; - - ok = 1; -err: - return ok; -} - -/* - * script_5 - script_106 are place holders for tests we - * currently keep in test/quic_multistream_test.c. - * We need to move those here so we can get rid off - * QUIC T-server mock-up. - * - * there should be one PR for each script being moved here, - * to make reviewer's life easier. Once all scripts will be - * moved we can find better names for script_5, ..., script_106. - * - * The scaffolding here hopes to avoid conflicts in 'scripts' - * array below when more PRs will be in flight. - */ - -/* 5. Test stream reset functionality */ -DEF_SCRIPT(script_5, "Test stream reset functionality") -{ - OP_SIMPLE_PAIR_CONN_ND(); - - OP_NEW_STREAM(C, Ca, 0 /* bidirectional */); - OP_NEW_STREAM(C, Cb, 0 /* bidirectional */); - - OP_WRITE(Ca, "apple", 5); - OP_STREAM_RESET(Ca, 42); - - OP_WRITE(Cb, "strawberry", 10); - - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - OP_ACCEPT_STREAM_WAIT(S, Sa, 0); /* first stream = Ca */ - OP_ACCEPT_STREAM_WAIT(S, Sb, 0); /* second stream = Cb */ - - /* Reset disrupts read of already-sent data */ - OP_SELECT_SSL(0, Sa); - OP_FUNC(check_stream_reset_5); - - OP_READ_EXPECT(Sb, "strawberry", 10); -} - -DEF_FUNC(check_stream_stopped_6) -{ - int ok = 0; - SSL *ssl; - - REQUIRE_SSL(ssl); - - if (SSL_get_stream_write_state(ssl) != SSL_STREAM_STATE_RESET_LOCAL) - F_SPIN_AGAIN(); - - ok = 1; -err: - return ok; -} - -/* 6. Test STOP_SENDING functionality */ -DEF_SCRIPT(script_6, "Test STOP_SENDING functionality") -{ - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - - OP_NEW_STREAM(S, Sa, 0 /* bidirectional */); - OP_WRITE(Sa, "apple", 5); - - OP_ACCEPT_STREAM_WAIT(C, Ca, 0); - OP_UNBIND(Ca); - OP_ACCEPT_STREAM_NONE(C, 0); - - OP_SELECT_SSL(0, Sa); - OP_FUNC(check_stream_stopped_6); -} - -/* 7. Unidirectional default stream mode test (client sends first) */ -DEF_SCRIPT(script_7, "Unidirectional default stream mode (client sends first)") -{ - OP_SIMPLE_PAIR_CONN(); - OP_SET_DEFAULT_STREAM_MODE(C, SSL_DEFAULT_STREAM_MODE_AUTO_UNI); - OP_WRITE(C, "apple", 5); - - OP_ACCEPT_CONN_WAIT(L, S, 0); - OP_READ_EXPECT(S, "apple", 5); - OP_WRITE_FAIL(S); -} - -/* 8. Unidirectional default stream mode test (server sends first) */ -DEF_SCRIPT(script_8, "Unidirectional default stream mode (server sends first)") -{ - OP_SIMPLE_PAIR_CONN(); - OP_SET_DEFAULT_STREAM_MODE(C, SSL_DEFAULT_STREAM_MODE_AUTO_UNI); - - OP_ACCEPT_CONN_WAIT(L, S, 0); - OP_NEW_STREAM(S, Sa, SSL_STREAM_FLAG_UNI); - OP_WRITE(Sa, "apple", 5); - - OP_READ_EXPECT(C, "apple", 5); - OP_WRITE_FAIL(C); -} - -/* 9. Unidirectional default stream mode test (server sends first on bidi) */ -DEF_SCRIPT(script_9, "Unidirectional default stream mode (server sends bidi first)") -{ - OP_SIMPLE_PAIR_CONN(); - OP_SET_DEFAULT_STREAM_MODE(C, SSL_DEFAULT_STREAM_MODE_AUTO_UNI); - - OP_ACCEPT_CONN_WAIT(L, S, 0); - OP_NEW_STREAM(S, Sa, 0 /* bidirectional */); - OP_WRITE(Sa, "apple", 5); - - OP_READ_EXPECT(C, "apple", 5); - OP_WRITE(C, "orange", 6); - OP_READ_EXPECT(Sa, "orange", 6); -} - -/* 10. Shutdown */ -DEF_SCRIPT(script_10, "Shutdown test") -{ - OP_SIMPLE_PAIR_CONN(); - - OP_WRITE(C, "apple", 5); - OP_ACCEPT_CONN_WAIT(L, S, 0); - OP_READ_EXPECT(S, "apple", 5); - - OP_SHUTDOWN_WAIT(C, 0, 0, NULL); - OP_EXPECT_CONN_CLOSE_INFO(C, 0, 1, 0); - OP_EXPECT_CONN_CLOSE_INFO(S, 0, 1, 1); -} - -/* 11. Many threads accepted on the same client connection */ -DEF_SCRIPT(script_11_child_0, - "child: accept stream from C, read, sleep, expect FIN") -{ - OP_ACCEPT_STREAM_WAIT(C, C0, OP_F_REPLACE_STREAM /* bidirectional */); - OP_READ_EXPECT_B(C0, "foo"); - OP_SLEEP(10); - OP_EXPECT_FIN(C0); -} - -DEF_SCRIPT(script_11_child_1, - "child: accept stream from C, read, sleep, expect FIN") -{ - OP_ACCEPT_STREAM_WAIT(C, C1, OP_F_REPLACE_STREAM /* bidirectional */); - OP_READ_EXPECT_B(C1, "foo"); - OP_SLEEP(10); - OP_EXPECT_FIN(C1); -} - -DEF_SCRIPT(script_11_child_2, - "child: accept stream from C, read, sleep, expect FIN") -{ - OP_ACCEPT_STREAM_WAIT(C, C2, OP_F_REPLACE_STREAM /* bidirectional */); - OP_READ_EXPECT_B(C2, "foo"); - OP_SLEEP(10); - OP_EXPECT_FIN(C2); -} - -DEF_SCRIPT(script_11_child_3, - "child: accept stream from C, read, sleep, expect FIN") -{ - OP_ACCEPT_STREAM_WAIT(C, C3, OP_F_REPLACE_STREAM /* bidirectional */); - OP_READ_EXPECT_B(C3, "foo"); - OP_SLEEP(10); - OP_EXPECT_FIN(C3); -} - -DEF_SCRIPT(script_11_child_4, - "child: accept stream from C, read, sleep, expect FIN") -{ - OP_ACCEPT_STREAM_WAIT(C, C4, OP_F_REPLACE_STREAM /* bidirectional */); - OP_READ_EXPECT_B(C4, "foo"); - OP_SLEEP(10); - OP_EXPECT_FIN(C4); -} - -DEF_SCRIPT(script_11, "Many threads accepted on the same client connection") -{ - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT(L, S, 0); - - OP_BIND(C0); - OP_BIND(C1); - OP_BIND(C2); - OP_BIND(C3); - OP_BIND(C4); - OP_BIND(Sa); - OP_BIND(Sb); - OP_BIND(Sc); - OP_BIND(Sd); - OP_BIND(Se); - - OP_SPAWN_THREAD(script_11_child_0); - OP_SPAWN_THREAD(script_11_child_1); - OP_SPAWN_THREAD(script_11_child_2); - OP_SPAWN_THREAD(script_11_child_3); - OP_SPAWN_THREAD(script_11_child_4); - - OP_NEW_STREAM(S, Sa, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(Sa, "foo"); - OP_CONCLUDE(Sa); - - OP_NEW_STREAM(S, Sb, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(Sb, "foo"); - OP_CONCLUDE(Sb); - - OP_NEW_STREAM(S, Sc, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(Sc, "foo"); - OP_CONCLUDE(Sc); - - OP_NEW_STREAM(S, Sd, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(Sd, "foo"); - OP_CONCLUDE(Sd); - - OP_NEW_STREAM(S, Se, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(Se, "foo"); - OP_CONCLUDE(Se); - OP_SLEEP(10); -} - -/* 12. Many threads initiated on the same client connection */ -DEF_SCRIPT(script_12_child_0, - "child: create stream on C, write, conclude") -{ - OP_NEW_STREAM(C, C0, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(C0, "foo"); - OP_CONCLUDE(C0); -} - -DEF_SCRIPT(script_12_child_1, - "child: create stream on C, write, conclude") -{ - OP_NEW_STREAM(C, C1, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(C1, "foo"); - OP_CONCLUDE(C1); -} - -DEF_SCRIPT(script_12_child_2, - "child: create stream on C, write, conclude") -{ - OP_NEW_STREAM(C, C2, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(C2, "foo"); - OP_CONCLUDE(C2); -} - -DEF_SCRIPT(script_12_child_3, - "child: create stream on C, write, conclude") -{ - OP_NEW_STREAM(C, C3, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(C3, "foo"); - OP_CONCLUDE(C3); -} - -DEF_SCRIPT(script_12_child_4, - "child: create stream on C, write, conclude") -{ - OP_NEW_STREAM(C, C4, OP_F_REPLACE_STREAM /* bidirectional */); - OP_WRITE_B(C4, "foo"); - OP_CONCLUDE(C4); -} - -DEF_SCRIPT(script_12, "Many threads initiated on the same client connection") -{ - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - - OP_BIND(C0); - OP_BIND(C1); - OP_BIND(C2); - OP_BIND(C3); - OP_BIND(C4); - OP_BIND(Sa); - OP_BIND(Sb); - OP_BIND(Sc); - OP_BIND(Sd); - OP_BIND(Se); - - OP_SPAWN_THREAD(script_12_child_0); - OP_SPAWN_THREAD(script_12_child_1); - OP_SPAWN_THREAD(script_12_child_2); - OP_SPAWN_THREAD(script_12_child_3); - OP_SPAWN_THREAD(script_12_child_4); - - OP_ACCEPT_STREAM_WAIT(S, Sa, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(Sa, "foo"); - OP_EXPECT_FIN(Sa); - OP_ACCEPT_STREAM_WAIT(S, Sb, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(Sb, "foo"); - OP_EXPECT_FIN(Sb); - OP_ACCEPT_STREAM_WAIT(S, Sc, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(Sc, "foo"); - OP_EXPECT_FIN(Sc); - OP_ACCEPT_STREAM_WAIT(S, Sd, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(Sd, "foo"); - OP_EXPECT_FIN(Sd); - OP_ACCEPT_STREAM_WAIT(S, Se, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(Se, "foo"); - OP_EXPECT_FIN(Se); - OP_SLEEP(10); -} - -/* 13. Many threads accepted on the same client connection (stress test) */ -DEF_SCRIPT(script_13_child_1, - "child: 10x accept stream from C, read, expect FIN, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_ACCEPT_STREAM_WAIT(C, C1, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(C1, "foo"); - OP_EXPECT_FIN(C1); - } -} - -DEF_SCRIPT(script_13_child_2, - "child: 10x accept stream from C, read, expect FIN, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_ACCEPT_STREAM_WAIT(C, C2, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(C2, "foo"); - OP_EXPECT_FIN(C2); - } -} - -DEF_SCRIPT(script_13_child_3, - "child: 10x accept stream from C, read, expect FIN, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_ACCEPT_STREAM_WAIT(C, C3, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(C3, "foo"); - OP_EXPECT_FIN(C3); - } -} - -DEF_SCRIPT(script_13_child_4, - "child: 10x accept stream from C, read, expect FIN, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_ACCEPT_STREAM_WAIT(C, C4, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(C4, "foo"); - OP_EXPECT_FIN(C4); - } -} - -DEF_SCRIPT(script_13_child_5, - "child: 10x accept stream from C, read, expect FIN, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_ACCEPT_STREAM_WAIT(C, C5, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(C5, "foo"); - OP_EXPECT_FIN(C5); - } -} - -DEF_SCRIPT(script_13, - "Many threads accepted on same client connection (stress test)") -{ - size_t i; - - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - - /* - * put empty objects to radix process cache. - * objects C1 - C5 are going to be used for - * SSL streams in _child_1 - _child_5 threads. - */ - OP_BIND(C1); - OP_BIND(C2); - OP_BIND(C3); - OP_BIND(C4); - OP_BIND(C5); - OP_BIND(Sa); - - OP_SPAWN_THREAD(script_13_child_1); - OP_SPAWN_THREAD(script_13_child_2); - OP_SPAWN_THREAD(script_13_child_3); - OP_SPAWN_THREAD(script_13_child_4); - OP_SPAWN_THREAD(script_13_child_5); - - for (i = 0; i < 50; ++i) { - OP_NEW_STREAM(S, Sa, OP_F_REPLACE_STREAM); - OP_WRITE_B(Sa, "foo"); - OP_CONCLUDE(Sa); - } -} - -/* 14. Many threads initiating on the same client connection (stress test) */ -DEF_SCRIPT(script_14_child_1, - "child: 10x create stream on C, write, conclude, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_NEW_STREAM(C, C1, OP_F_REPLACE_STREAM); - OP_WRITE_B(C1, "foo"); - OP_CONCLUDE(C1); - } -} - -DEF_SCRIPT(script_14_child_2, - "child: 10x create stream on C, write, conclude, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_NEW_STREAM(C, C2, OP_F_REPLACE_STREAM); - OP_WRITE_B(C2, "foo"); - OP_CONCLUDE(C2); - } -} - -DEF_SCRIPT(script_14_child_3, - "child: 10x create stream on C, write, conclude, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_NEW_STREAM(C, C3, OP_F_REPLACE_STREAM); - OP_WRITE_B(C3, "foo"); - OP_CONCLUDE(C3); - } -} - -DEF_SCRIPT(script_14_child_4, - "child: 10x create stream on C, write, conclude, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_NEW_STREAM(C, C4, OP_F_REPLACE_STREAM); - OP_WRITE_B(C4, "foo"); - OP_CONCLUDE(C4); - } -} - -DEF_SCRIPT(script_14_child_5, - "child: 10x create stream on C, write, conclude, free") -{ - size_t i; - - for (i = 0; i < 10; i++) { - OP_NEW_STREAM(C, C5, OP_F_REPLACE_STREAM); - OP_WRITE_B(C5, "foo"); - OP_CONCLUDE(C5); - } -} - -DEF_SCRIPT(script_14, - "Many threads initiating on same client connection (stress test)") -{ - size_t i; - - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - - OP_BIND(C1); - OP_BIND(C2); - OP_BIND(C3); - OP_BIND(C4); - OP_BIND(C5); - OP_BIND(Sa); - - OP_SPAWN_THREAD(script_14_child_1); - OP_SPAWN_THREAD(script_14_child_2); - OP_SPAWN_THREAD(script_14_child_3); - OP_SPAWN_THREAD(script_14_child_4); - OP_SPAWN_THREAD(script_14_child_5); - - for (i = 0; i < 50; ++i) { - OP_ACCEPT_STREAM_WAIT(S, Sa, OP_F_REPLACE_STREAM); - OP_READ_EXPECT_B(Sa, "foo"); - OP_EXPECT_FIN(Sa); - } -} - -/* 15. Client sending large number of streams, MAX_STREAMS test */ -DEF_SCRIPT(script_15, "Client sending large number of streams, MAX_STREAMS test") -{ - size_t i; - - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - - /* - * This will cause a protocol violation to be raised by the server if we are - * not handling the stream limit correctly on the TX side. - */ - for (i = 0; i < 200; ++i) { - OP_NEW_STREAM(C, Ca, SSL_STREAM_FLAG_ADVANCE); - OP_WRITE(Ca, "foo", 3); - OP_CONCLUDE(Ca); - OP_UNBIND(Ca); - } - - /* Prove the connection is still good. */ - OP_NEW_STREAM(S, Sa, 0); - OP_WRITE(Sa, "bar", 3); - OP_CONCLUDE(Sa); - - OP_ACCEPT_STREAM_WAIT(C, Ca, 0); - OP_READ_EXPECT(Ca, "bar", 3); - OP_EXPECT_FIN(Ca); - - /* - * Drain the queue of incoming streams. We should be able to get all 200 - * even though only 100 can be initiated at a time. - */ - for (i = 0; i < 200; ++i) { - OP_ACCEPT_STREAM_WAIT(S, Sb, 0); - OP_READ_EXPECT(Sb, "foo", 3); - OP_EXPECT_FIN(Sb); - OP_UNBIND(Sb); - } -} - -/* 16. Server sending large number of streams, MAX_STREAMS test */ -DEF_SCRIPT(script_16, "Server sending large number of streams, MAX_STREAMS test") -{ - size_t i; - - OP_SIMPLE_PAIR_CONN_ND(); - OP_ACCEPT_CONN_WAIT_ND(L, S, 0); - - /* - * This will cause a protocol violation to be raised by the client if we are - * not handling the stream limit correctly on the TX side. - */ - for (i = 0; i < 200; ++i) { - OP_NEW_STREAM(S, Sa, SSL_STREAM_FLAG_ADVANCE); - OP_WRITE(Sa, "foo", 3); - OP_CONCLUDE(Sa); - OP_UNBIND(Sa); - } - - /* Prove that the connection is still good. */ - OP_NEW_STREAM(C, Ca, 0); - OP_WRITE(Ca, "bar", 3); - OP_CONCLUDE(Ca); - - OP_ACCEPT_STREAM_WAIT(S, Sb, 0); - OP_READ_EXPECT(Sb, "bar", 3); - OP_EXPECT_FIN(Sb); - - /* Drain the queue of incoming streams. */ - for (i = 0; i < 200; ++i) { - OP_ACCEPT_STREAM_WAIT(C, Cb, 0); - OP_READ_EXPECT(Cb, "foo", 3); - OP_EXPECT_FIN(Cb); - OP_UNBIND(Cb); - } -} - -/* 17. Key update test - unlimited */ -DEF_SCRIPT(script_17, "Key update test - unlimited") -{ - size_t i; - - OP_SIMPLE_PAIR_CONN(); - OP_ACCEPT_CONN_WAIT(L, S, 0); - - OP_WRITE(C, "apple", 5); - OP_READ_EXPECT(S, "apple", 5); - - OP_OVERRIDE_KEY_UPDATE(C, 1); - - for (i = 0; i < 200; ++i) { - OP_WRITE(C, "apple", 5); - OP_READ_EXPECT(S, "apple", 5); - /* - * TXKU frequency is bounded by RTT because a previous TXKU needs to be - * acknowledged by the peer first before another one can begin. By - * waiting this long, we eliminate any such concern and ensure as many key - * updates as possible can occur for the purposes of this test. - */ - OP_SKIP_TIME(100); - } - - /* At least 5 RXKUs detected */ - OP_CHECK_KEY_UPDATE_GE(C, 5); - - /* - * Prove the connection is still healthy by sending something in both - * directions. - */ - OP_WRITE(C, "xyzzy", 5); - OP_READ_EXPECT(S, "xyzzy", 5); - - OP_WRITE(S, "plugh", 5); - OP_READ_EXPECT(C, "plugh", 5); -} - -/* 18. Key update test - RTT-bounded */ -DEF_SCRIPT(script_18, "Key update test - RTT-bounded") -{ - size_t i; - - OP_SIMPLE_PAIR_CONN(); - OP_ACCEPT_CONN_WAIT(L, S, 0); - - OP_WRITE(C, "apple", 5); - OP_READ_EXPECT(S, "apple", 5); - - OP_OVERRIDE_KEY_UPDATE(C, 1); - - for (i = 0; i < 200; ++i) { - OP_WRITE(C, "apple", 5); - OP_READ_EXPECT(S, "apple", 5); - OP_SKIP_TIME(8); - } - - /* - * This time we simulate far less time passing between writes, so there are - * fewer opportunities to initiate TXKUs. Note that we ask for a TXKU every - * 1 packet above, which is absurd; thus this ensures we only actually - * generate TXKUs when we are allowed to. - */ - OP_CHECK_KEY_UPDATE_LT(C, 240); - - /* - * Prove the connection is still healthy by sending something in both - * directions. - */ - OP_WRITE(C, "xyzzy", 5); - OP_READ_EXPECT(S, "xyzzy", 5); - - OP_WRITE(S, "plugh", 5); - OP_READ_EXPECT(C, "plugh", 5); -} - -/* 19. Key update test - artificially triggered */ -DEF_SCRIPT(script_19, "Key update test - artificially triggered") -{ - OP_SIMPLE_PAIR_CONN(); - OP_ACCEPT_CONN_WAIT(L, S, 0); - - OP_WRITE(C, "apple", 5); - OP_READ_EXPECT(S, "apple", 5); - - OP_WRITE(C, "orange", 6); - OP_READ_EXPECT(S, "orange", 6); - - OP_WRITE(S, "strawberry", 10); - OP_READ_EXPECT(C, "strawberry", 10); - - OP_CHECK_KEY_UPDATE_LT(C, 1); - - OP_TRIGGER_KEY_UPDATE(C, SSL_KEY_UPDATE_REQUESTED); - - OP_WRITE(C, "orange", 6); - OP_READ_EXPECT(S, "orange", 6); - OP_WRITE(S, "ok", 2); - - OP_READ_EXPECT(C, "ok", 2); - OP_CHECK_KEY_UPDATE_GE(C, 1); -} - -DEF_SCRIPT(script_20, "place holder for multistrem script_20") -{ -} - -DEF_SCRIPT(script_21, "place holder for multistrem script_21") -{ -} - -DEF_SCRIPT(script_22, "place holder for multistrem script_22") -{ -} - -DEF_SCRIPT(script_23, "place holder for multistrem script_23") -{ -} - -DEF_SCRIPT(script_24, "place holder for multistrem script_24") -{ -} - -DEF_SCRIPT(script_25, "place holder for multistrem script_25") -{ -} - -DEF_SCRIPT(script_26, "place holder for multistrem script_26") -{ -} - -DEF_SCRIPT(script_27, "place holder for multistrem script_27") -{ -} - -DEF_SCRIPT(script_28, "place holder for multistrem script_28") -{ -} - -DEF_SCRIPT(script_29, "place holder for multistrem script_29") -{ -} - -DEF_SCRIPT(script_30, "place holder for multistrem script_30") -{ -} - -DEF_SCRIPT(script_31, "place holder for multistrem script_31") -{ -} - -DEF_SCRIPT(script_32, "place holder for multistrem script_32") -{ -} - -DEF_SCRIPT(script_33, "place holder for multistrem script_33") -{ -} - -DEF_SCRIPT(script_34, "place holder for multistrem script_34") -{ -} - -DEF_SCRIPT(script_35, "place holder for multistrem script_35") -{ -} - -DEF_SCRIPT(script_36, "place holder for multistrem script_36") -{ -} - -DEF_SCRIPT(script_37, "place holder for multistrem script_37") -{ -} - -DEF_SCRIPT(script_38, "place holder for multistrem script_38") -{ -} - -DEF_SCRIPT(script_39, "place holder for multistrem script_39") -{ -} - -DEF_SCRIPT(script_40, "place holder for multistrem script_40") -{ -} - -DEF_SCRIPT(script_41, "place holder for multistrem script_41") -{ -} - -DEF_SCRIPT(script_42, "place holder for multistrem script_42") -{ -} - -DEF_SCRIPT(script_43, "place holder for multistrem script_43") -{ -} - -DEF_SCRIPT(script_44, "place holder for multistrem script_44") -{ -} - -DEF_SCRIPT(script_45, "place holder for multistrem script_45") -{ -} - -DEF_SCRIPT(script_46, "place holder for multistrem script_46") -{ -} - -DEF_SCRIPT(script_47, "place holder for multistrem script_47") -{ -} - -DEF_SCRIPT(script_48, "place holder for multistrem script_48") -{ -} - -DEF_SCRIPT(script_49, "place holder for multistrem script_49") -{ -} - -DEF_SCRIPT(script_50, "place holder for multistrem script_50") -{ -} - -DEF_SCRIPT(script_51, "place holder for multistrem script_51") -{ -} - -DEF_SCRIPT(script_52, "place holder for multistrem script_52") -{ -} - -DEF_SCRIPT(script_53, "place holder for multistrem script_53") -{ -} - -DEF_SCRIPT(script_54, "place holder for multistrem script_54") -{ -} - -DEF_SCRIPT(script_55, "place holder for multistrem script_55") -{ -} - -DEF_SCRIPT(script_56, "place holder for multistrem script_56") -{ -} - -DEF_SCRIPT(script_57, "place holder for multistrem script_57") -{ -} - -DEF_SCRIPT(script_58, "place holder for multistrem script_58") -{ -} - -DEF_SCRIPT(script_59, "place holder for multistrem script_59") -{ -} - -DEF_SCRIPT(script_60, "place holder for multistrem script_60") -{ -} - -DEF_SCRIPT(script_61, "place holder for multistrem script_61") -{ -} - -DEF_SCRIPT(script_62, "place holder for multistrem script_62") -{ -} - -DEF_SCRIPT(script_63, "place holder for multistrem script_63") -{ -} - -DEF_SCRIPT(script_64, "place holder for multistrem script_64") -{ -} - -DEF_SCRIPT(script_65, "place holder for multistrem script_65") -{ -} - -DEF_SCRIPT(script_66, "place holder for multistrem script_66") -{ -} - -DEF_SCRIPT(script_67, "place holder for multistrem script_67") -{ -} - -DEF_SCRIPT(script_68, "place holder for multistrem script_68") -{ -} - -DEF_SCRIPT(script_69, "place holder for multistrem script_69") -{ -} - -DEF_SCRIPT(script_70, "place holder for multistrem script_70") -{ -} - -DEF_SCRIPT(script_71, "place holder for multistrem script_71") -{ -} - -DEF_SCRIPT(script_72, "place holder for multistrem script_72") -{ -} - -DEF_SCRIPT(script_73, "place holder for multistrem script_73") -{ -} - -DEF_SCRIPT(script_74, "place holder for multistrem script_74") -{ -} - -DEF_SCRIPT(script_75, "place holder for multistrem script_75") -{ -} - -DEF_SCRIPT(script_76, "place holder for multistrem script_76") -{ -} - -DEF_SCRIPT(script_77, "place holder for multistrem script_77") -{ -} - -DEF_SCRIPT(script_78, "place holder for multistrem script_78") -{ -} - -DEF_SCRIPT(script_79, "place holder for multistrem script_79") -{ -} - -DEF_SCRIPT(script_80, "place holder for multistrem script_80") -{ -} - -DEF_SCRIPT(script_81, "place holder for multistrem script_81") -{ -} - -DEF_SCRIPT(script_82, "place holder for multistrem script_82") -{ -} - -DEF_SCRIPT(script_83, "place holder for multistrem script_83") -{ -} - -DEF_SCRIPT(script_84, "place holder for multistrem script_84") -{ -} - -DEF_SCRIPT(script_85, "place holder for multistrem script_85") -{ -} - -DEF_SCRIPT(script_86, "place holder for multistrem script_86") -{ -} - -DEF_SCRIPT(script_87, "place holder for multistrem script_87") -{ -} - -DEF_SCRIPT(script_88, "place holder for multistrem script_88") -{ -} - -DEF_SCRIPT(script_89, "place holder for multistrem script_89") -{ -} - -DEF_SCRIPT(script_90, "place holder for multistrem script_90") -{ -} - -DEF_SCRIPT(script_91, "place holder for multistrem script_91") -{ -} - -DEF_SCRIPT(script_92, "place holder for multistrem script_92") -{ -} - -DEF_SCRIPT(script_93, "place holder for multistrem script_93") -{ -} - -DEF_SCRIPT(script_94, "place holder for multistrem script_94") -{ -} - -DEF_SCRIPT(script_95, "place holder for multistrem script_95") -{ -} - -DEF_SCRIPT(script_96, "place holder for multistrem script_96") -{ -} - -DEF_SCRIPT(script_97, "place holder for multistrem script_97") -{ -} - -DEF_SCRIPT(script_98, "place holder for multistrem script_98") -{ -} - -DEF_SCRIPT(script_99, "place holder for multistrem script_99") -{ -} - -DEF_SCRIPT(script_100, "place holder for multistrem script_100") -{ -} - -DEF_SCRIPT(script_101, "place holder for multistrem script_101") -{ -} - -DEF_SCRIPT(script_102, "place holder for multistrem script_102") -{ -} - -DEF_SCRIPT(script_103, "place holder for multistrem script_103") -{ -} - -DEF_SCRIPT(script_104, "place holder for multistrem script_104") -{ -} - -DEF_SCRIPT(script_105, "place holder for multistrem script_105") -{ -} - -DEF_SCRIPT(script_106, "place holder for multistrem script_106") -{ -} - /* * List of Test Scripts * ============================================================================ @@ -1810,106 +778,4 @@ static SCRIPT_INFO *const scripts[] = { USE(check_cwm), USE(check_pc_flood), USE(check_ctx_cbks), - USE(script_5), - USE(script_6), - USE(script_7), - USE(script_8), - USE(script_9), - USE(script_10), - USE(script_11), - USE(script_12), - USE(script_13), - USE(script_14), - USE(script_15), - USE(script_16), - USE(script_17), - USE(script_18), - USE(script_19), - USE(script_20), - USE(script_21), - USE(script_22), - USE(script_23), - USE(script_24), - USE(script_25), - USE(script_26), - USE(script_27), - USE(script_28), - USE(script_29), - USE(script_30), - USE(script_31), - USE(script_32), - USE(script_33), - USE(script_34), - USE(script_35), - USE(script_36), - USE(script_37), - USE(script_38), - USE(script_39), - USE(script_40), - USE(script_41), - USE(script_42), - USE(script_43), - USE(script_44), - USE(script_45), - USE(script_46), - USE(script_47), - USE(script_48), - USE(script_49), - USE(script_50), - USE(script_51), - USE(script_52), - USE(script_53), - USE(script_54), - USE(script_55), - USE(script_56), - USE(script_57), - USE(script_58), - USE(script_59), - USE(script_60), - USE(script_61), - USE(script_62), - USE(script_63), - USE(script_64), - USE(script_65), - USE(script_66), - USE(script_67), - USE(script_68), - USE(script_69), - USE(script_70), - USE(script_71), - USE(script_72), - USE(script_73), - USE(script_74), - USE(script_75), - USE(script_76), - USE(script_77), - USE(script_78), - USE(script_79), - USE(script_80), - USE(script_81), - USE(script_82), - USE(script_83), - USE(script_84), - USE(script_85), - USE(script_86), - USE(script_87), - USE(script_88), - USE(script_89), - USE(script_90), - USE(script_91), - USE(script_92), - USE(script_93), - USE(script_94), - USE(script_95), - USE(script_96), - USE(script_97), - USE(script_98), - USE(script_99), - USE(script_100), - USE(script_101), - USE(script_102), - USE(script_103), - USE(script_104), - USE(script_105), - USE(script_106), }; diff --git a/test/rand_test.c b/test/rand_test.c index 5b2270cb4e..0fbd89542f 100644 --- a/test/rand_test.c +++ b/test/rand_test.c @@ -275,142 +275,6 @@ err: return res; } -/* Warm up the DRBG cipher fetch caches outside the mfail injection window */ -static int rand_drbg_fetch_warmup(EVP_RAND *drbg_alg) -{ - EVP_RAND_CTX *warm; - OSSL_PARAM params[3]; - int ret; - - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, - (char *)"AES-256-CTR", 0); - params[1] = OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_CORE_PROV_NAME, - (char *)"default", 0); - params[2] = OSSL_PARAM_construct_end(); - - if (!TEST_ptr(warm = EVP_RAND_CTX_new(drbg_alg, NULL))) - return 0; - ret = TEST_true(EVP_RAND_CTX_set_params(warm, params)); - EVP_RAND_CTX_free(warm); - return ret; -} - -/* - * Memory-failure coverage for the whole random generation stack on a fresh - * library context: the seed source and DRBG chain creation and seeding. - */ -static int test_rand_bytes_mfail(int idx) -{ - OSSL_LIB_CTX *ctx = NULL; - EVP_RAND *drbg = NULL, *seed = NULL; - unsigned char buf[16]; - int rc = -1; - - if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) - || !TEST_ptr(drbg = EVP_RAND_fetch(ctx, "CTR-DRBG", NULL)) - || !rand_drbg_fetch_warmup(drbg)) - goto end; - /* The default seed source may be unavailable in some configurations */ - ERR_set_mark(); - seed = EVP_RAND_fetch(ctx, OPENSSL_SEED_SRC_NAME, NULL); - ERR_pop_to_mark(); - - MFAIL_start(); - rc = (idx == 0 ? RAND_bytes_ex(ctx, buf, sizeof(buf), 0) - : RAND_priv_bytes_ex(ctx, buf, sizeof(buf), 0)) - > 0; - MFAIL_end(); - -end: - EVP_RAND_free(seed); - EVP_RAND_free(drbg); - OSSL_LIB_CTX_free(ctx); - return rc; -} - -/* Memory-failure coverage for the seed source entropy acquisition. */ -static int test_rand_seed_src_mfail(void) -{ - OSSL_LIB_CTX *ctx = NULL; - EVP_RAND *rand = NULL; - EVP_RAND_CTX *seed = NULL; - unsigned char buf[64]; - int rc = -1; - - if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) - || !TEST_ptr(rand = EVP_RAND_fetch(ctx, OPENSSL_SEED_SRC_NAME, NULL))) - goto end; - - MFAIL_start(); - rc = (seed = EVP_RAND_CTX_new(rand, NULL)) != NULL - && EVP_RAND_instantiate(seed, 0, 0, NULL, 0, NULL) - && EVP_RAND_generate(seed, buf, sizeof(buf), 0, 0, NULL, 0); - MFAIL_end(); - -end: - EVP_RAND_CTX_free(seed); - EVP_RAND_free(rand); - OSSL_LIB_CTX_free(ctx); - return rc; -} - -/* Memory-failure coverage for the DRBG operations with a TEST-RAND parent */ -static int test_rand_drbg_mfail(void) -{ - OSSL_LIB_CTX *ctx = NULL; - EVP_RAND *parent_alg = NULL, *drbg_alg = NULL; - EVP_RAND_CTX *parent = NULL, *drbg = NULL; - unsigned int strength = 256, generate = 1; - unsigned char entropy[128]; - unsigned char buf[32]; - OSSL_PARAM parent_params[4], drbg_params[3]; - size_t i; - int rc = -1; - - for (i = 0; i < sizeof(entropy); i++) - entropy[i] = 0xff & i; - parent_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, - &strength); - parent_params[1] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_GENERATE, - &generate); - parent_params[2] = OSSL_PARAM_construct_octet_string( - OSSL_RAND_PARAM_TEST_ENTROPY, entropy, sizeof(entropy)); - parent_params[3] = OSSL_PARAM_construct_end(); - - drbg_params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, - (char *)"AES-256-CTR", 0); - drbg_params[1] = OSSL_PARAM_construct_utf8_string( - OSSL_PROV_PARAM_CORE_PROV_NAME, (char *)"default", 0); - drbg_params[2] = OSSL_PARAM_construct_end(); - - if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) - || !TEST_ptr(parent_alg = EVP_RAND_fetch(ctx, "TEST-RAND", NULL)) - || !TEST_ptr(drbg_alg = EVP_RAND_fetch(ctx, "CTR-DRBG", NULL)) - || !rand_drbg_fetch_warmup(drbg_alg) - || !TEST_ptr(parent = EVP_RAND_CTX_new(parent_alg, NULL)) - || !TEST_true(EVP_RAND_instantiate(parent, 0, 0, NULL, 0, - parent_params))) - goto end; - - MFAIL_start(); - rc = (drbg = EVP_RAND_CTX_new(drbg_alg, parent)) != NULL - && EVP_RAND_instantiate(drbg, 0, 0, (unsigned char *)"abc", 3, - drbg_params) - && EVP_RAND_generate(drbg, buf, sizeof(buf), 0, 0, NULL, 0) - && EVP_RAND_reseed(drbg, 0, NULL, 0, (unsigned char *)"xyz", 3) - && EVP_RAND_generate(drbg, buf, sizeof(buf), 0, 0, - (unsigned char *)"adin", 4); - MFAIL_end(); - -end: - EVP_RAND_CTX_free(drbg); - EVP_RAND_CTX_free(parent); - EVP_RAND_free(parent_alg); - EVP_RAND_free(drbg_alg); - OSSL_LIB_CTX_free(ctx); - return rc; -} - int setup_tests(void) { if (!test_skip_common_options()) { @@ -437,9 +301,5 @@ int setup_tests(void) if (!OSSL_PROVIDER_available(NULL, "fips") || fips_provider_version_ge(NULL, 3, 5, 1)) ADD_TEST(test_rand_get0_primary); - - ADD_MFAIL_ALL_TESTS(test_rand_bytes_mfail, 2); - ADD_MFAIL_TEST(test_rand_seed_src_mfail); - ADD_MFAIL_TEST(test_rand_drbg_mfail); return 1; } diff --git a/test/recipes/02-test_unit.t b/test/recipes/02-test_unit.t deleted file mode 100644 index d88c3dcf31..0000000000 --- a/test/recipes/02-test_unit.t +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use strict; -use warnings; - -use File::Find; -use File::Spec::Functions qw(abs2rel); - -use OpenSSL::Test qw(:DEFAULT bldtop_dir); -use OpenSSL::Test::Utils; - -setup("test_unit"); - -my $unit_dir = bldtop_dir('test', 'unit'); -my $exeext = ''; - -if ($^O eq 'MSWin32') { - $exeext = '.exe'; - # The shared libraries (libcrypto/libssl DLLs) are only placed at the - # build top and copied into apps/, test/ and fuzz/. The unit test - # executables live in nested directories under test/unit/, so add the - # build top to PATH to let the loader find the DLLs. - $ENV{PATH} = bldtop_dir() . ';' . ($ENV{PATH} // ''); -} - -my @tests = (); -if (-d $unit_dir) { - find({ - wanted => sub { - return unless -f $_; - my $base = $_; - if ($exeext ne '') { - # require + strip .exe - return unless $base =~ s/\Q$exeext\E$//; - } else { - return unless -x $_; - } - return unless $base =~ m|/test_[^/]*$|; - # reject .pdb/.obj/etc - return if $base =~ m|\.\w+$|; - push @tests, $_; - }, - no_chdir => 1, - }, $unit_dir); -} - -@tests = sort @tests; - -plan skip_all => "No unit tests built (enable-unit-tests not set?)" - unless @tests; - -plan tests => scalar @tests; - -foreach my $test_bin (@tests) { - my $name = abs2rel($test_bin, $unit_dir); - ok(run(cmd([$test_bin])), "unit: $name"); -} diff --git a/test/recipes/03-test_internal_fn.t b/test/recipes/03-test_internal_fn.t new file mode 100644 index 0000000000..46a477f000 --- /dev/null +++ b/test/recipes/03-test_internal_fn.t @@ -0,0 +1,19 @@ +#! /usr/bin/env perl +# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use OpenSSL::Test; # get 'plan' +use OpenSSL::Test::Simple; +use OpenSSL::Test::Utils; + +setup("test_internal_fn"); + +plan skip_all => "This test is unsupported in a shared library build on Windows" + if $^O eq 'MSWin32' && !disabled("shared"); + +simple_test("test_internal_fn", "fn_internal_test"); diff --git a/test/recipes/10-test_bn.t b/test/recipes/10-test_bn.t index bdccce14d3..4a76930f2a 100644 --- a/test/recipes/10-test_bn.t +++ b/test/recipes/10-test_bn.t @@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT data_file/; setup("test_bn"); -my @files = qw( bnexp.txt bnmod.txt bnmul.txt bnshift.txt bnsum.txt bngcd.txt ); +my @files = qw( bnexp.txt bnmod.txt bnmodinv.txt bnmul.txt bnshift.txt bnsum.txt bngcd.txt ); plan tests => 1 + scalar(@files); diff --git a/test/recipes/10-test_bn_data/bnmodinv.txt b/test/recipes/10-test_bn_data/bnmodinv.txt new file mode 100644 index 0000000000..6ab0f66d76 --- /dev/null +++ b/test/recipes/10-test_bn_data/bnmodinv.txt @@ -0,0 +1,69180 @@ +# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# These test vectors satisfy A * ModInv = 1 (mod M) and 1 <= ModInv < M. +# ModInv = -1 denotes a negative test where A has no inverse mod M. +# This includes the degenerate moduli M = 0 and M = 1. + +Title = ModInv positive tests (manual) + +# I assure you, this is hex +ModInv = 10668 +A = 3 +M = 31337 + +ModInv = ba9b69 +A = -beef +M = c0ffee + +ModInv = d1e25270e36d6cd4f2cc145e216cbd50d8127bc013df4c4a8803cf48d59c2af6 +A = 72ea74f57cde544391e2a4f9e9eef63c9876b67650b6fa310b40a0b7eb47a41e1046a5fc40d212df3c0a724c17d540e5212c6652a920604719bed8c79b568aeb +M = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d + +ModInv = fade56a040340d441acd6f2a3ef1bd0d4290e9dbdee3328c82b41b90fa86ddf8 +A = c5098aead5db1636886be39c8db47c82908a256c632dd41973a1129749e201bf +M = fdcb43c7eb582feebf97ecc44b52cd98fbd5cb03f9e276cba91007cd6a9b070f + +ModInv = 56266432e45a996b832f5cfdb8ff9e55b2d89f028dcff9f5e01431e83a5b1ee7e3024c9cb59 +A = c61e8b534be55c9d300c8de4b559f280cb3e080c647ca41ab4a050aad80d815179c983562eb +M = 7f586b20e780700c327cb4b9125c8653a3930dd74118b6cfc8785561a0ed550161c7bca9c5a + +ModInv = 2d06f3c1b2d5c458d6543e07360ad49f219794289144e5effbb95b2b452dfd075126a697e638e1fda3c13e82176256d6 +A = -bfc018675ff4398180f5a6d286a3afb128f47b3b5333f6ede83b1bd67ee642923634ffe0354678219e68d527c0bb661 +M = cb75ab61fc05aa3f5d842cb32a86f529376d1523a9b888978e35614b51755a419ee04c55396abb1941f271eee30fab47 + +# RFC 4754 8.1 ECDSA-256: kinv = k^-1 mod q +ModInv = afa278945af74b1e295008e03a8984e2e1c69d9bbbc74af14e3ac4e421abfa61 +A = 9e56f509196784d963d1c0a401510ee7ada3dcc5dee04b154bf61af1d5a6dece +M = ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + +# RFC 4754 8.1 ECDSA-256: sinv = s^-1 mod q +ModInv = 33bdc294e90cfad62a9f2fd1f8741da77c02a573e1b53ba17a60ba904f491952 +A = 86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0315 +M = ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + +# RFC 4754 8.2 ECDSA-384: kinv = k^-1 mod q +ModInv = eb12876bf6191a291aa5780a3887c3bfe7a5c7e321cca674886b1228d9bb3d52918ef19fe5ce67e980bedc1e613d39c0 +A = b4b74e44d71a13d568003d7489908d564c7761e229c58cbfa18950096eb7463b854d7fa992f934d927376285e63414fa +M = ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 + +# RFC 4754 8.2 ECDSA-384: sinv = s^-1 mod q +ModInv = 6efacee8a657f77584c5a039f7e2720d61df84c8fac6fa49a06f6c46e8cda286add7d3b90e1cda479bd899bee14b99d +A = b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9f +M = ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 + +# RFC 4754 8.3 ECDSA-521: kinv = k^-1 mod q +ModInv = e90ef3ce52f8d1e5a4eebd0905f4252400b0ae73b49e3323bce258a55f507d7c45f3a2de3a3ea2e51d934346d71593a80c8c62fe229ddf5d2b64b7af4a08370d32 +A = c1c2b305419f5a41344d7e4359933d734096f556197a9b244342b8b62f46f9373778f9de6b6497b1ef825ff24f42f9b4a4bd7382cfc3378a540b1b7f0c1b956c2f +M = 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 + +# RFC 4754 8.3 ECDSA-521: sinv = s^-1 mod q +ModInv = dda6b883cb36bfcb21d5b0b7d1f4439d3c7797b23a8d7358032d5cc917142e3f6778bd977d8460867853ae9c74ef5e417cfa96f7c937c1418d9343738a1ba878e0 +A = 17705a7030290d1ceb605a9a1bb03ff9cdd521e87a696ec926c8c10c8362df4975367101f67d1cf9bccbf2f3d239534fa509e70aac851ae01aac68d62f866472660 +M = 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 + +# GOST R 34.10 verification step v = e^-1 mod q +# Identical KAT in RFC 7091 S7.3 and RFC 5832 S7.3 +ModInv = 271a4ee429f84ebc423e388964555bb29d3ba53c7bf945e5fac8f381706354c2 +A = 2dfbc1b372d89a1188c09c52e0eec61fce52032ab1022e8e67ece6672b043ee5 +M = 8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3 + +Title = ModInv negative tests (manual) + +ModInv = -1 +A = 0 +M = 31337 + +ModInv = -1 +A = 31337 +M = 31337 + +ModInv = -1 +A = a +M = c0ffee + +ModInv = -1 +A = 4 +M = 8 + +ModInv = -1 +A = C +M = 8 + +ModInv = -1 +A = 14 +M = 8 + +ModInv = -1 +A = 12a24ee7bdafe19a20fd2f7d27a076b38b132e2f57aa3c724737e398a44f97776 +M = 2df40a1d3a5bebe10a4a29d6e58fb17a2b77ddd8aa8b20f78f08b79956e4b4e6 + +ModInv = -1 +A = 2fee14d4f0c663afa6b45741c0732e6b2b10a4538a1e55dff37 +M = 26e0818494fd1cfe5304d5d017791a634416b43f5e24f62e019 + +ModInv = -1 +A = 31337 +M = 1 + +ModInv = -1 +A = 5 +M = 0 + +Title = ModInv positive tests (auto) + +ModInv = 1 +A = -63 +M = 2 + +ModInv = 1 +A = -61 +M = 2 + +ModInv = 1 +A = -5f +M = 2 + +ModInv = 1 +A = -5d +M = 2 + +ModInv = 1 +A = -5b +M = 2 + +ModInv = 1 +A = -59 +M = 2 + +ModInv = 1 +A = -57 +M = 2 + +ModInv = 1 +A = -55 +M = 2 + +ModInv = 1 +A = -53 +M = 2 + +ModInv = 1 +A = -51 +M = 2 + +ModInv = 1 +A = -4f +M = 2 + +ModInv = 1 +A = -4d +M = 2 + +ModInv = 1 +A = -4b +M = 2 + +ModInv = 1 +A = -49 +M = 2 + +ModInv = 1 +A = -47 +M = 2 + +ModInv = 1 +A = -45 +M = 2 + +ModInv = 1 +A = -43 +M = 2 + +ModInv = 1 +A = -41 +M = 2 + +ModInv = 1 +A = -3f +M = 2 + +ModInv = 1 +A = -3d +M = 2 + +ModInv = 1 +A = -3b +M = 2 + +ModInv = 1 +A = -39 +M = 2 + +ModInv = 1 +A = -37 +M = 2 + +ModInv = 1 +A = -35 +M = 2 + +ModInv = 1 +A = -33 +M = 2 + +ModInv = 1 +A = -31 +M = 2 + +ModInv = 1 +A = -2f +M = 2 + +ModInv = 1 +A = -2d +M = 2 + +ModInv = 1 +A = -2b +M = 2 + +ModInv = 1 +A = -29 +M = 2 + +ModInv = 1 +A = -27 +M = 2 + +ModInv = 1 +A = -25 +M = 2 + +ModInv = 1 +A = -23 +M = 2 + +ModInv = 1 +A = -21 +M = 2 + +ModInv = 1 +A = -1f +M = 2 + +ModInv = 1 +A = -1d +M = 2 + +ModInv = 1 +A = -1b +M = 2 + +ModInv = 1 +A = -19 +M = 2 + +ModInv = 1 +A = -17 +M = 2 + +ModInv = 1 +A = -15 +M = 2 + +ModInv = 1 +A = -13 +M = 2 + +ModInv = 1 +A = -11 +M = 2 + +ModInv = 1 +A = -f +M = 2 + +ModInv = 1 +A = -d +M = 2 + +ModInv = 1 +A = -b +M = 2 + +ModInv = 1 +A = -9 +M = 2 + +ModInv = 1 +A = -7 +M = 2 + +ModInv = 1 +A = -5 +M = 2 + +ModInv = 1 +A = -3 +M = 2 + +ModInv = 1 +A = -1 +M = 2 + +ModInv = 1 +A = 1 +M = 2 + +ModInv = 1 +A = 3 +M = 2 + +ModInv = 1 +A = 5 +M = 2 + +ModInv = 1 +A = 7 +M = 2 + +ModInv = 1 +A = 9 +M = 2 + +ModInv = 1 +A = b +M = 2 + +ModInv = 1 +A = d +M = 2 + +ModInv = 1 +A = f +M = 2 + +ModInv = 1 +A = 11 +M = 2 + +ModInv = 1 +A = 13 +M = 2 + +ModInv = 1 +A = 15 +M = 2 + +ModInv = 1 +A = 17 +M = 2 + +ModInv = 1 +A = 19 +M = 2 + +ModInv = 1 +A = 1b +M = 2 + +ModInv = 1 +A = 1d +M = 2 + +ModInv = 1 +A = 1f +M = 2 + +ModInv = 1 +A = 21 +M = 2 + +ModInv = 1 +A = 23 +M = 2 + +ModInv = 1 +A = 25 +M = 2 + +ModInv = 1 +A = 27 +M = 2 + +ModInv = 1 +A = 29 +M = 2 + +ModInv = 1 +A = 2b +M = 2 + +ModInv = 1 +A = 2d +M = 2 + +ModInv = 1 +A = 2f +M = 2 + +ModInv = 1 +A = 31 +M = 2 + +ModInv = 1 +A = 33 +M = 2 + +ModInv = 1 +A = 35 +M = 2 + +ModInv = 1 +A = 37 +M = 2 + +ModInv = 1 +A = 39 +M = 2 + +ModInv = 1 +A = 3b +M = 2 + +ModInv = 1 +A = 3d +M = 2 + +ModInv = 1 +A = 3f +M = 2 + +ModInv = 1 +A = 41 +M = 2 + +ModInv = 1 +A = 43 +M = 2 + +ModInv = 1 +A = 45 +M = 2 + +ModInv = 1 +A = 47 +M = 2 + +ModInv = 1 +A = 49 +M = 2 + +ModInv = 1 +A = 4b +M = 2 + +ModInv = 1 +A = 4d +M = 2 + +ModInv = 1 +A = 4f +M = 2 + +ModInv = 1 +A = 51 +M = 2 + +ModInv = 1 +A = 53 +M = 2 + +ModInv = 1 +A = 55 +M = 2 + +ModInv = 1 +A = 57 +M = 2 + +ModInv = 1 +A = 59 +M = 2 + +ModInv = 1 +A = 5b +M = 2 + +ModInv = 1 +A = 5d +M = 2 + +ModInv = 1 +A = 5f +M = 2 + +ModInv = 1 +A = 61 +M = 2 + +ModInv = 1 +A = 63 +M = 2 + +ModInv = 2 +A = -64 +M = 3 + +ModInv = 1 +A = -62 +M = 3 + +ModInv = 2 +A = -61 +M = 3 + +ModInv = 1 +A = -5f +M = 3 + +ModInv = 2 +A = -5e +M = 3 + +ModInv = 1 +A = -5c +M = 3 + +ModInv = 2 +A = -5b +M = 3 + +ModInv = 1 +A = -59 +M = 3 + +ModInv = 2 +A = -58 +M = 3 + +ModInv = 1 +A = -56 +M = 3 + +ModInv = 2 +A = -55 +M = 3 + +ModInv = 1 +A = -53 +M = 3 + +ModInv = 2 +A = -52 +M = 3 + +ModInv = 1 +A = -50 +M = 3 + +ModInv = 2 +A = -4f +M = 3 + +ModInv = 1 +A = -4d +M = 3 + +ModInv = 2 +A = -4c +M = 3 + +ModInv = 1 +A = -4a +M = 3 + +ModInv = 2 +A = -49 +M = 3 + +ModInv = 1 +A = -47 +M = 3 + +ModInv = 2 +A = -46 +M = 3 + +ModInv = 1 +A = -44 +M = 3 + +ModInv = 2 +A = -43 +M = 3 + +ModInv = 1 +A = -41 +M = 3 + +ModInv = 2 +A = -40 +M = 3 + +ModInv = 1 +A = -3e +M = 3 + +ModInv = 2 +A = -3d +M = 3 + +ModInv = 1 +A = -3b +M = 3 + +ModInv = 2 +A = -3a +M = 3 + +ModInv = 1 +A = -38 +M = 3 + +ModInv = 2 +A = -37 +M = 3 + +ModInv = 1 +A = -35 +M = 3 + +ModInv = 2 +A = -34 +M = 3 + +ModInv = 1 +A = -32 +M = 3 + +ModInv = 2 +A = -31 +M = 3 + +ModInv = 1 +A = -2f +M = 3 + +ModInv = 2 +A = -2e +M = 3 + +ModInv = 1 +A = -2c +M = 3 + +ModInv = 2 +A = -2b +M = 3 + +ModInv = 1 +A = -29 +M = 3 + +ModInv = 2 +A = -28 +M = 3 + +ModInv = 1 +A = -26 +M = 3 + +ModInv = 2 +A = -25 +M = 3 + +ModInv = 1 +A = -23 +M = 3 + +ModInv = 2 +A = -22 +M = 3 + +ModInv = 1 +A = -20 +M = 3 + +ModInv = 2 +A = -1f +M = 3 + +ModInv = 1 +A = -1d +M = 3 + +ModInv = 2 +A = -1c +M = 3 + +ModInv = 1 +A = -1a +M = 3 + +ModInv = 2 +A = -19 +M = 3 + +ModInv = 1 +A = -17 +M = 3 + +ModInv = 2 +A = -16 +M = 3 + +ModInv = 1 +A = -14 +M = 3 + +ModInv = 2 +A = -13 +M = 3 + +ModInv = 1 +A = -11 +M = 3 + +ModInv = 2 +A = -10 +M = 3 + +ModInv = 1 +A = -e +M = 3 + +ModInv = 2 +A = -d +M = 3 + +ModInv = 1 +A = -b +M = 3 + +ModInv = 2 +A = -a +M = 3 + +ModInv = 1 +A = -8 +M = 3 + +ModInv = 2 +A = -7 +M = 3 + +ModInv = 1 +A = -5 +M = 3 + +ModInv = 2 +A = -4 +M = 3 + +ModInv = 1 +A = -2 +M = 3 + +ModInv = 2 +A = -1 +M = 3 + +ModInv = 1 +A = 1 +M = 3 + +ModInv = 2 +A = 2 +M = 3 + +ModInv = 1 +A = 4 +M = 3 + +ModInv = 2 +A = 5 +M = 3 + +ModInv = 1 +A = 7 +M = 3 + +ModInv = 2 +A = 8 +M = 3 + +ModInv = 1 +A = a +M = 3 + +ModInv = 2 +A = b +M = 3 + +ModInv = 1 +A = d +M = 3 + +ModInv = 2 +A = e +M = 3 + +ModInv = 1 +A = 10 +M = 3 + +ModInv = 2 +A = 11 +M = 3 + +ModInv = 1 +A = 13 +M = 3 + +ModInv = 2 +A = 14 +M = 3 + +ModInv = 1 +A = 16 +M = 3 + +ModInv = 2 +A = 17 +M = 3 + +ModInv = 1 +A = 19 +M = 3 + +ModInv = 2 +A = 1a +M = 3 + +ModInv = 1 +A = 1c +M = 3 + +ModInv = 2 +A = 1d +M = 3 + +ModInv = 1 +A = 1f +M = 3 + +ModInv = 2 +A = 20 +M = 3 + +ModInv = 1 +A = 22 +M = 3 + +ModInv = 2 +A = 23 +M = 3 + +ModInv = 1 +A = 25 +M = 3 + +ModInv = 2 +A = 26 +M = 3 + +ModInv = 1 +A = 28 +M = 3 + +ModInv = 2 +A = 29 +M = 3 + +ModInv = 1 +A = 2b +M = 3 + +ModInv = 2 +A = 2c +M = 3 + +ModInv = 1 +A = 2e +M = 3 + +ModInv = 2 +A = 2f +M = 3 + +ModInv = 1 +A = 31 +M = 3 + +ModInv = 2 +A = 32 +M = 3 + +ModInv = 1 +A = 34 +M = 3 + +ModInv = 2 +A = 35 +M = 3 + +ModInv = 1 +A = 37 +M = 3 + +ModInv = 2 +A = 38 +M = 3 + +ModInv = 1 +A = 3a +M = 3 + +ModInv = 2 +A = 3b +M = 3 + +ModInv = 1 +A = 3d +M = 3 + +ModInv = 2 +A = 3e +M = 3 + +ModInv = 1 +A = 40 +M = 3 + +ModInv = 2 +A = 41 +M = 3 + +ModInv = 1 +A = 43 +M = 3 + +ModInv = 2 +A = 44 +M = 3 + +ModInv = 1 +A = 46 +M = 3 + +ModInv = 2 +A = 47 +M = 3 + +ModInv = 1 +A = 49 +M = 3 + +ModInv = 2 +A = 4a +M = 3 + +ModInv = 1 +A = 4c +M = 3 + +ModInv = 2 +A = 4d +M = 3 + +ModInv = 1 +A = 4f +M = 3 + +ModInv = 2 +A = 50 +M = 3 + +ModInv = 1 +A = 52 +M = 3 + +ModInv = 2 +A = 53 +M = 3 + +ModInv = 1 +A = 55 +M = 3 + +ModInv = 2 +A = 56 +M = 3 + +ModInv = 1 +A = 58 +M = 3 + +ModInv = 2 +A = 59 +M = 3 + +ModInv = 1 +A = 5b +M = 3 + +ModInv = 2 +A = 5c +M = 3 + +ModInv = 1 +A = 5e +M = 3 + +ModInv = 2 +A = 5f +M = 3 + +ModInv = 1 +A = 61 +M = 3 + +ModInv = 2 +A = 62 +M = 3 + +ModInv = 1 +A = -63 +M = 4 + +ModInv = 3 +A = -61 +M = 4 + +ModInv = 1 +A = -5f +M = 4 + +ModInv = 3 +A = -5d +M = 4 + +ModInv = 1 +A = -5b +M = 4 + +ModInv = 3 +A = -59 +M = 4 + +ModInv = 1 +A = -57 +M = 4 + +ModInv = 3 +A = -55 +M = 4 + +ModInv = 1 +A = -53 +M = 4 + +ModInv = 3 +A = -51 +M = 4 + +ModInv = 1 +A = -4f +M = 4 + +ModInv = 3 +A = -4d +M = 4 + +ModInv = 1 +A = -4b +M = 4 + +ModInv = 3 +A = -49 +M = 4 + +ModInv = 1 +A = -47 +M = 4 + +ModInv = 3 +A = -45 +M = 4 + +ModInv = 1 +A = -43 +M = 4 + +ModInv = 3 +A = -41 +M = 4 + +ModInv = 1 +A = -3f +M = 4 + +ModInv = 3 +A = -3d +M = 4 + +ModInv = 1 +A = -3b +M = 4 + +ModInv = 3 +A = -39 +M = 4 + +ModInv = 1 +A = -37 +M = 4 + +ModInv = 3 +A = -35 +M = 4 + +ModInv = 1 +A = -33 +M = 4 + +ModInv = 3 +A = -31 +M = 4 + +ModInv = 1 +A = -2f +M = 4 + +ModInv = 3 +A = -2d +M = 4 + +ModInv = 1 +A = -2b +M = 4 + +ModInv = 3 +A = -29 +M = 4 + +ModInv = 1 +A = -27 +M = 4 + +ModInv = 3 +A = -25 +M = 4 + +ModInv = 1 +A = -23 +M = 4 + +ModInv = 3 +A = -21 +M = 4 + +ModInv = 1 +A = -1f +M = 4 + +ModInv = 3 +A = -1d +M = 4 + +ModInv = 1 +A = -1b +M = 4 + +ModInv = 3 +A = -19 +M = 4 + +ModInv = 1 +A = -17 +M = 4 + +ModInv = 3 +A = -15 +M = 4 + +ModInv = 1 +A = -13 +M = 4 + +ModInv = 3 +A = -11 +M = 4 + +ModInv = 1 +A = -f +M = 4 + +ModInv = 3 +A = -d +M = 4 + +ModInv = 1 +A = -b +M = 4 + +ModInv = 3 +A = -9 +M = 4 + +ModInv = 1 +A = -7 +M = 4 + +ModInv = 3 +A = -5 +M = 4 + +ModInv = 1 +A = -3 +M = 4 + +ModInv = 3 +A = -1 +M = 4 + +ModInv = 1 +A = 1 +M = 4 + +ModInv = 3 +A = 3 +M = 4 + +ModInv = 1 +A = 5 +M = 4 + +ModInv = 3 +A = 7 +M = 4 + +ModInv = 1 +A = 9 +M = 4 + +ModInv = 3 +A = b +M = 4 + +ModInv = 1 +A = d +M = 4 + +ModInv = 3 +A = f +M = 4 + +ModInv = 1 +A = 11 +M = 4 + +ModInv = 3 +A = 13 +M = 4 + +ModInv = 1 +A = 15 +M = 4 + +ModInv = 3 +A = 17 +M = 4 + +ModInv = 1 +A = 19 +M = 4 + +ModInv = 3 +A = 1b +M = 4 + +ModInv = 1 +A = 1d +M = 4 + +ModInv = 3 +A = 1f +M = 4 + +ModInv = 1 +A = 21 +M = 4 + +ModInv = 3 +A = 23 +M = 4 + +ModInv = 1 +A = 25 +M = 4 + +ModInv = 3 +A = 27 +M = 4 + +ModInv = 1 +A = 29 +M = 4 + +ModInv = 3 +A = 2b +M = 4 + +ModInv = 1 +A = 2d +M = 4 + +ModInv = 3 +A = 2f +M = 4 + +ModInv = 1 +A = 31 +M = 4 + +ModInv = 3 +A = 33 +M = 4 + +ModInv = 1 +A = 35 +M = 4 + +ModInv = 3 +A = 37 +M = 4 + +ModInv = 1 +A = 39 +M = 4 + +ModInv = 3 +A = 3b +M = 4 + +ModInv = 1 +A = 3d +M = 4 + +ModInv = 3 +A = 3f +M = 4 + +ModInv = 1 +A = 41 +M = 4 + +ModInv = 3 +A = 43 +M = 4 + +ModInv = 1 +A = 45 +M = 4 + +ModInv = 3 +A = 47 +M = 4 + +ModInv = 1 +A = 49 +M = 4 + +ModInv = 3 +A = 4b +M = 4 + +ModInv = 1 +A = 4d +M = 4 + +ModInv = 3 +A = 4f +M = 4 + +ModInv = 1 +A = 51 +M = 4 + +ModInv = 3 +A = 53 +M = 4 + +ModInv = 1 +A = 55 +M = 4 + +ModInv = 3 +A = 57 +M = 4 + +ModInv = 1 +A = 59 +M = 4 + +ModInv = 3 +A = 5b +M = 4 + +ModInv = 1 +A = 5d +M = 4 + +ModInv = 3 +A = 5f +M = 4 + +ModInv = 1 +A = 61 +M = 4 + +ModInv = 3 +A = 63 +M = 4 + +ModInv = 1 +A = -63 +M = 5 + +ModInv = 3 +A = -62 +M = 5 + +ModInv = 2 +A = -61 +M = 5 + +ModInv = 4 +A = -60 +M = 5 + +ModInv = 1 +A = -5e +M = 5 + +ModInv = 3 +A = -5d +M = 5 + +ModInv = 2 +A = -5c +M = 5 + +ModInv = 4 +A = -5b +M = 5 + +ModInv = 1 +A = -59 +M = 5 + +ModInv = 3 +A = -58 +M = 5 + +ModInv = 2 +A = -57 +M = 5 + +ModInv = 4 +A = -56 +M = 5 + +ModInv = 1 +A = -54 +M = 5 + +ModInv = 3 +A = -53 +M = 5 + +ModInv = 2 +A = -52 +M = 5 + +ModInv = 4 +A = -51 +M = 5 + +ModInv = 1 +A = -4f +M = 5 + +ModInv = 3 +A = -4e +M = 5 + +ModInv = 2 +A = -4d +M = 5 + +ModInv = 4 +A = -4c +M = 5 + +ModInv = 1 +A = -4a +M = 5 + +ModInv = 3 +A = -49 +M = 5 + +ModInv = 2 +A = -48 +M = 5 + +ModInv = 4 +A = -47 +M = 5 + +ModInv = 1 +A = -45 +M = 5 + +ModInv = 3 +A = -44 +M = 5 + +ModInv = 2 +A = -43 +M = 5 + +ModInv = 4 +A = -42 +M = 5 + +ModInv = 1 +A = -40 +M = 5 + +ModInv = 3 +A = -3f +M = 5 + +ModInv = 2 +A = -3e +M = 5 + +ModInv = 4 +A = -3d +M = 5 + +ModInv = 1 +A = -3b +M = 5 + +ModInv = 3 +A = -3a +M = 5 + +ModInv = 2 +A = -39 +M = 5 + +ModInv = 4 +A = -38 +M = 5 + +ModInv = 1 +A = -36 +M = 5 + +ModInv = 3 +A = -35 +M = 5 + +ModInv = 2 +A = -34 +M = 5 + +ModInv = 4 +A = -33 +M = 5 + +ModInv = 1 +A = -31 +M = 5 + +ModInv = 3 +A = -30 +M = 5 + +ModInv = 2 +A = -2f +M = 5 + +ModInv = 4 +A = -2e +M = 5 + +ModInv = 1 +A = -2c +M = 5 + +ModInv = 3 +A = -2b +M = 5 + +ModInv = 2 +A = -2a +M = 5 + +ModInv = 4 +A = -29 +M = 5 + +ModInv = 1 +A = -27 +M = 5 + +ModInv = 3 +A = -26 +M = 5 + +ModInv = 2 +A = -25 +M = 5 + +ModInv = 4 +A = -24 +M = 5 + +ModInv = 1 +A = -22 +M = 5 + +ModInv = 3 +A = -21 +M = 5 + +ModInv = 2 +A = -20 +M = 5 + +ModInv = 4 +A = -1f +M = 5 + +ModInv = 1 +A = -1d +M = 5 + +ModInv = 3 +A = -1c +M = 5 + +ModInv = 2 +A = -1b +M = 5 + +ModInv = 4 +A = -1a +M = 5 + +ModInv = 1 +A = -18 +M = 5 + +ModInv = 3 +A = -17 +M = 5 + +ModInv = 2 +A = -16 +M = 5 + +ModInv = 4 +A = -15 +M = 5 + +ModInv = 1 +A = -13 +M = 5 + +ModInv = 3 +A = -12 +M = 5 + +ModInv = 2 +A = -11 +M = 5 + +ModInv = 4 +A = -10 +M = 5 + +ModInv = 1 +A = -e +M = 5 + +ModInv = 3 +A = -d +M = 5 + +ModInv = 2 +A = -c +M = 5 + +ModInv = 4 +A = -b +M = 5 + +ModInv = 1 +A = -9 +M = 5 + +ModInv = 3 +A = -8 +M = 5 + +ModInv = 2 +A = -7 +M = 5 + +ModInv = 4 +A = -6 +M = 5 + +ModInv = 1 +A = -4 +M = 5 + +ModInv = 3 +A = -3 +M = 5 + +ModInv = 2 +A = -2 +M = 5 + +ModInv = 4 +A = -1 +M = 5 + +ModInv = 1 +A = 1 +M = 5 + +ModInv = 3 +A = 2 +M = 5 + +ModInv = 2 +A = 3 +M = 5 + +ModInv = 4 +A = 4 +M = 5 + +ModInv = 1 +A = 6 +M = 5 + +ModInv = 3 +A = 7 +M = 5 + +ModInv = 2 +A = 8 +M = 5 + +ModInv = 4 +A = 9 +M = 5 + +ModInv = 1 +A = b +M = 5 + +ModInv = 3 +A = c +M = 5 + +ModInv = 2 +A = d +M = 5 + +ModInv = 4 +A = e +M = 5 + +ModInv = 1 +A = 10 +M = 5 + +ModInv = 3 +A = 11 +M = 5 + +ModInv = 2 +A = 12 +M = 5 + +ModInv = 4 +A = 13 +M = 5 + +ModInv = 1 +A = 15 +M = 5 + +ModInv = 3 +A = 16 +M = 5 + +ModInv = 2 +A = 17 +M = 5 + +ModInv = 4 +A = 18 +M = 5 + +ModInv = 1 +A = 1a +M = 5 + +ModInv = 3 +A = 1b +M = 5 + +ModInv = 2 +A = 1c +M = 5 + +ModInv = 4 +A = 1d +M = 5 + +ModInv = 1 +A = 1f +M = 5 + +ModInv = 3 +A = 20 +M = 5 + +ModInv = 2 +A = 21 +M = 5 + +ModInv = 4 +A = 22 +M = 5 + +ModInv = 1 +A = 24 +M = 5 + +ModInv = 3 +A = 25 +M = 5 + +ModInv = 2 +A = 26 +M = 5 + +ModInv = 4 +A = 27 +M = 5 + +ModInv = 1 +A = 29 +M = 5 + +ModInv = 3 +A = 2a +M = 5 + +ModInv = 2 +A = 2b +M = 5 + +ModInv = 4 +A = 2c +M = 5 + +ModInv = 1 +A = 2e +M = 5 + +ModInv = 3 +A = 2f +M = 5 + +ModInv = 2 +A = 30 +M = 5 + +ModInv = 4 +A = 31 +M = 5 + +ModInv = 1 +A = 33 +M = 5 + +ModInv = 3 +A = 34 +M = 5 + +ModInv = 2 +A = 35 +M = 5 + +ModInv = 4 +A = 36 +M = 5 + +ModInv = 1 +A = 38 +M = 5 + +ModInv = 3 +A = 39 +M = 5 + +ModInv = 2 +A = 3a +M = 5 + +ModInv = 4 +A = 3b +M = 5 + +ModInv = 1 +A = 3d +M = 5 + +ModInv = 3 +A = 3e +M = 5 + +ModInv = 2 +A = 3f +M = 5 + +ModInv = 4 +A = 40 +M = 5 + +ModInv = 1 +A = 42 +M = 5 + +ModInv = 3 +A = 43 +M = 5 + +ModInv = 2 +A = 44 +M = 5 + +ModInv = 4 +A = 45 +M = 5 + +ModInv = 1 +A = 47 +M = 5 + +ModInv = 3 +A = 48 +M = 5 + +ModInv = 2 +A = 49 +M = 5 + +ModInv = 4 +A = 4a +M = 5 + +ModInv = 1 +A = 4c +M = 5 + +ModInv = 3 +A = 4d +M = 5 + +ModInv = 2 +A = 4e +M = 5 + +ModInv = 4 +A = 4f +M = 5 + +ModInv = 1 +A = 51 +M = 5 + +ModInv = 3 +A = 52 +M = 5 + +ModInv = 2 +A = 53 +M = 5 + +ModInv = 4 +A = 54 +M = 5 + +ModInv = 1 +A = 56 +M = 5 + +ModInv = 3 +A = 57 +M = 5 + +ModInv = 2 +A = 58 +M = 5 + +ModInv = 4 +A = 59 +M = 5 + +ModInv = 1 +A = 5b +M = 5 + +ModInv = 3 +A = 5c +M = 5 + +ModInv = 2 +A = 5d +M = 5 + +ModInv = 4 +A = 5e +M = 5 + +ModInv = 1 +A = 60 +M = 5 + +ModInv = 3 +A = 61 +M = 5 + +ModInv = 2 +A = 62 +M = 5 + +ModInv = 4 +A = 63 +M = 5 + +ModInv = 5 +A = -61 +M = 6 + +ModInv = 1 +A = -5f +M = 6 + +ModInv = 5 +A = -5b +M = 6 + +ModInv = 1 +A = -59 +M = 6 + +ModInv = 5 +A = -55 +M = 6 + +ModInv = 1 +A = -53 +M = 6 + +ModInv = 5 +A = -4f +M = 6 + +ModInv = 1 +A = -4d +M = 6 + +ModInv = 5 +A = -49 +M = 6 + +ModInv = 1 +A = -47 +M = 6 + +ModInv = 5 +A = -43 +M = 6 + +ModInv = 1 +A = -41 +M = 6 + +ModInv = 5 +A = -3d +M = 6 + +ModInv = 1 +A = -3b +M = 6 + +ModInv = 5 +A = -37 +M = 6 + +ModInv = 1 +A = -35 +M = 6 + +ModInv = 5 +A = -31 +M = 6 + +ModInv = 1 +A = -2f +M = 6 + +ModInv = 5 +A = -2b +M = 6 + +ModInv = 1 +A = -29 +M = 6 + +ModInv = 5 +A = -25 +M = 6 + +ModInv = 1 +A = -23 +M = 6 + +ModInv = 5 +A = -1f +M = 6 + +ModInv = 1 +A = -1d +M = 6 + +ModInv = 5 +A = -19 +M = 6 + +ModInv = 1 +A = -17 +M = 6 + +ModInv = 5 +A = -13 +M = 6 + +ModInv = 1 +A = -11 +M = 6 + +ModInv = 5 +A = -d +M = 6 + +ModInv = 1 +A = -b +M = 6 + +ModInv = 5 +A = -7 +M = 6 + +ModInv = 1 +A = -5 +M = 6 + +ModInv = 5 +A = -1 +M = 6 + +ModInv = 1 +A = 1 +M = 6 + +ModInv = 5 +A = 5 +M = 6 + +ModInv = 1 +A = 7 +M = 6 + +ModInv = 5 +A = b +M = 6 + +ModInv = 1 +A = d +M = 6 + +ModInv = 5 +A = 11 +M = 6 + +ModInv = 1 +A = 13 +M = 6 + +ModInv = 5 +A = 17 +M = 6 + +ModInv = 1 +A = 19 +M = 6 + +ModInv = 5 +A = 1d +M = 6 + +ModInv = 1 +A = 1f +M = 6 + +ModInv = 5 +A = 23 +M = 6 + +ModInv = 1 +A = 25 +M = 6 + +ModInv = 5 +A = 29 +M = 6 + +ModInv = 1 +A = 2b +M = 6 + +ModInv = 5 +A = 2f +M = 6 + +ModInv = 1 +A = 31 +M = 6 + +ModInv = 5 +A = 35 +M = 6 + +ModInv = 1 +A = 37 +M = 6 + +ModInv = 5 +A = 3b +M = 6 + +ModInv = 1 +A = 3d +M = 6 + +ModInv = 5 +A = 41 +M = 6 + +ModInv = 1 +A = 43 +M = 6 + +ModInv = 5 +A = 47 +M = 6 + +ModInv = 1 +A = 49 +M = 6 + +ModInv = 5 +A = 4d +M = 6 + +ModInv = 1 +A = 4f +M = 6 + +ModInv = 5 +A = 53 +M = 6 + +ModInv = 1 +A = 55 +M = 6 + +ModInv = 5 +A = 59 +M = 6 + +ModInv = 1 +A = 5b +M = 6 + +ModInv = 5 +A = 5f +M = 6 + +ModInv = 1 +A = 61 +M = 6 + +ModInv = 3 +A = -64 +M = 7 + +ModInv = 6 +A = -63 +M = 7 + +ModInv = 1 +A = -61 +M = 7 + +ModInv = 4 +A = -60 +M = 7 + +ModInv = 5 +A = -5f +M = 7 + +ModInv = 2 +A = -5e +M = 7 + +ModInv = 3 +A = -5d +M = 7 + +ModInv = 6 +A = -5c +M = 7 + +ModInv = 1 +A = -5a +M = 7 + +ModInv = 4 +A = -59 +M = 7 + +ModInv = 5 +A = -58 +M = 7 + +ModInv = 2 +A = -57 +M = 7 + +ModInv = 3 +A = -56 +M = 7 + +ModInv = 6 +A = -55 +M = 7 + +ModInv = 1 +A = -53 +M = 7 + +ModInv = 4 +A = -52 +M = 7 + +ModInv = 5 +A = -51 +M = 7 + +ModInv = 2 +A = -50 +M = 7 + +ModInv = 3 +A = -4f +M = 7 + +ModInv = 6 +A = -4e +M = 7 + +ModInv = 1 +A = -4c +M = 7 + +ModInv = 4 +A = -4b +M = 7 + +ModInv = 5 +A = -4a +M = 7 + +ModInv = 2 +A = -49 +M = 7 + +ModInv = 3 +A = -48 +M = 7 + +ModInv = 6 +A = -47 +M = 7 + +ModInv = 1 +A = -45 +M = 7 + +ModInv = 4 +A = -44 +M = 7 + +ModInv = 5 +A = -43 +M = 7 + +ModInv = 2 +A = -42 +M = 7 + +ModInv = 3 +A = -41 +M = 7 + +ModInv = 6 +A = -40 +M = 7 + +ModInv = 1 +A = -3e +M = 7 + +ModInv = 4 +A = -3d +M = 7 + +ModInv = 5 +A = -3c +M = 7 + +ModInv = 2 +A = -3b +M = 7 + +ModInv = 3 +A = -3a +M = 7 + +ModInv = 6 +A = -39 +M = 7 + +ModInv = 1 +A = -37 +M = 7 + +ModInv = 4 +A = -36 +M = 7 + +ModInv = 5 +A = -35 +M = 7 + +ModInv = 2 +A = -34 +M = 7 + +ModInv = 3 +A = -33 +M = 7 + +ModInv = 6 +A = -32 +M = 7 + +ModInv = 1 +A = -30 +M = 7 + +ModInv = 4 +A = -2f +M = 7 + +ModInv = 5 +A = -2e +M = 7 + +ModInv = 2 +A = -2d +M = 7 + +ModInv = 3 +A = -2c +M = 7 + +ModInv = 6 +A = -2b +M = 7 + +ModInv = 1 +A = -29 +M = 7 + +ModInv = 4 +A = -28 +M = 7 + +ModInv = 5 +A = -27 +M = 7 + +ModInv = 2 +A = -26 +M = 7 + +ModInv = 3 +A = -25 +M = 7 + +ModInv = 6 +A = -24 +M = 7 + +ModInv = 1 +A = -22 +M = 7 + +ModInv = 4 +A = -21 +M = 7 + +ModInv = 5 +A = -20 +M = 7 + +ModInv = 2 +A = -1f +M = 7 + +ModInv = 3 +A = -1e +M = 7 + +ModInv = 6 +A = -1d +M = 7 + +ModInv = 1 +A = -1b +M = 7 + +ModInv = 4 +A = -1a +M = 7 + +ModInv = 5 +A = -19 +M = 7 + +ModInv = 2 +A = -18 +M = 7 + +ModInv = 3 +A = -17 +M = 7 + +ModInv = 6 +A = -16 +M = 7 + +ModInv = 1 +A = -14 +M = 7 + +ModInv = 4 +A = -13 +M = 7 + +ModInv = 5 +A = -12 +M = 7 + +ModInv = 2 +A = -11 +M = 7 + +ModInv = 3 +A = -10 +M = 7 + +ModInv = 6 +A = -f +M = 7 + +ModInv = 1 +A = -d +M = 7 + +ModInv = 4 +A = -c +M = 7 + +ModInv = 5 +A = -b +M = 7 + +ModInv = 2 +A = -a +M = 7 + +ModInv = 3 +A = -9 +M = 7 + +ModInv = 6 +A = -8 +M = 7 + +ModInv = 1 +A = -6 +M = 7 + +ModInv = 4 +A = -5 +M = 7 + +ModInv = 5 +A = -4 +M = 7 + +ModInv = 2 +A = -3 +M = 7 + +ModInv = 3 +A = -2 +M = 7 + +ModInv = 6 +A = -1 +M = 7 + +ModInv = 1 +A = 1 +M = 7 + +ModInv = 4 +A = 2 +M = 7 + +ModInv = 5 +A = 3 +M = 7 + +ModInv = 2 +A = 4 +M = 7 + +ModInv = 3 +A = 5 +M = 7 + +ModInv = 6 +A = 6 +M = 7 + +ModInv = 1 +A = 8 +M = 7 + +ModInv = 4 +A = 9 +M = 7 + +ModInv = 5 +A = a +M = 7 + +ModInv = 2 +A = b +M = 7 + +ModInv = 3 +A = c +M = 7 + +ModInv = 6 +A = d +M = 7 + +ModInv = 1 +A = f +M = 7 + +ModInv = 4 +A = 10 +M = 7 + +ModInv = 5 +A = 11 +M = 7 + +ModInv = 2 +A = 12 +M = 7 + +ModInv = 3 +A = 13 +M = 7 + +ModInv = 6 +A = 14 +M = 7 + +ModInv = 1 +A = 16 +M = 7 + +ModInv = 4 +A = 17 +M = 7 + +ModInv = 5 +A = 18 +M = 7 + +ModInv = 2 +A = 19 +M = 7 + +ModInv = 3 +A = 1a +M = 7 + +ModInv = 6 +A = 1b +M = 7 + +ModInv = 1 +A = 1d +M = 7 + +ModInv = 4 +A = 1e +M = 7 + +ModInv = 5 +A = 1f +M = 7 + +ModInv = 2 +A = 20 +M = 7 + +ModInv = 3 +A = 21 +M = 7 + +ModInv = 6 +A = 22 +M = 7 + +ModInv = 1 +A = 24 +M = 7 + +ModInv = 4 +A = 25 +M = 7 + +ModInv = 5 +A = 26 +M = 7 + +ModInv = 2 +A = 27 +M = 7 + +ModInv = 3 +A = 28 +M = 7 + +ModInv = 6 +A = 29 +M = 7 + +ModInv = 1 +A = 2b +M = 7 + +ModInv = 4 +A = 2c +M = 7 + +ModInv = 5 +A = 2d +M = 7 + +ModInv = 2 +A = 2e +M = 7 + +ModInv = 3 +A = 2f +M = 7 + +ModInv = 6 +A = 30 +M = 7 + +ModInv = 1 +A = 32 +M = 7 + +ModInv = 4 +A = 33 +M = 7 + +ModInv = 5 +A = 34 +M = 7 + +ModInv = 2 +A = 35 +M = 7 + +ModInv = 3 +A = 36 +M = 7 + +ModInv = 6 +A = 37 +M = 7 + +ModInv = 1 +A = 39 +M = 7 + +ModInv = 4 +A = 3a +M = 7 + +ModInv = 5 +A = 3b +M = 7 + +ModInv = 2 +A = 3c +M = 7 + +ModInv = 3 +A = 3d +M = 7 + +ModInv = 6 +A = 3e +M = 7 + +ModInv = 1 +A = 40 +M = 7 + +ModInv = 4 +A = 41 +M = 7 + +ModInv = 5 +A = 42 +M = 7 + +ModInv = 2 +A = 43 +M = 7 + +ModInv = 3 +A = 44 +M = 7 + +ModInv = 6 +A = 45 +M = 7 + +ModInv = 1 +A = 47 +M = 7 + +ModInv = 4 +A = 48 +M = 7 + +ModInv = 5 +A = 49 +M = 7 + +ModInv = 2 +A = 4a +M = 7 + +ModInv = 3 +A = 4b +M = 7 + +ModInv = 6 +A = 4c +M = 7 + +ModInv = 1 +A = 4e +M = 7 + +ModInv = 4 +A = 4f +M = 7 + +ModInv = 5 +A = 50 +M = 7 + +ModInv = 2 +A = 51 +M = 7 + +ModInv = 3 +A = 52 +M = 7 + +ModInv = 6 +A = 53 +M = 7 + +ModInv = 1 +A = 55 +M = 7 + +ModInv = 4 +A = 56 +M = 7 + +ModInv = 5 +A = 57 +M = 7 + +ModInv = 2 +A = 58 +M = 7 + +ModInv = 3 +A = 59 +M = 7 + +ModInv = 6 +A = 5a +M = 7 + +ModInv = 1 +A = 5c +M = 7 + +ModInv = 4 +A = 5d +M = 7 + +ModInv = 5 +A = 5e +M = 7 + +ModInv = 2 +A = 5f +M = 7 + +ModInv = 3 +A = 60 +M = 7 + +ModInv = 6 +A = 61 +M = 7 + +ModInv = 1 +A = 63 +M = 7 + +ModInv = 5 +A = -63 +M = 8 + +ModInv = 7 +A = -61 +M = 8 + +ModInv = 1 +A = -5f +M = 8 + +ModInv = 3 +A = -5d +M = 8 + +ModInv = 5 +A = -5b +M = 8 + +ModInv = 7 +A = -59 +M = 8 + +ModInv = 1 +A = -57 +M = 8 + +ModInv = 3 +A = -55 +M = 8 + +ModInv = 5 +A = -53 +M = 8 + +ModInv = 7 +A = -51 +M = 8 + +ModInv = 1 +A = -4f +M = 8 + +ModInv = 3 +A = -4d +M = 8 + +ModInv = 5 +A = -4b +M = 8 + +ModInv = 7 +A = -49 +M = 8 + +ModInv = 1 +A = -47 +M = 8 + +ModInv = 3 +A = -45 +M = 8 + +ModInv = 5 +A = -43 +M = 8 + +ModInv = 7 +A = -41 +M = 8 + +ModInv = 1 +A = -3f +M = 8 + +ModInv = 3 +A = -3d +M = 8 + +ModInv = 5 +A = -3b +M = 8 + +ModInv = 7 +A = -39 +M = 8 + +ModInv = 1 +A = -37 +M = 8 + +ModInv = 3 +A = -35 +M = 8 + +ModInv = 5 +A = -33 +M = 8 + +ModInv = 7 +A = -31 +M = 8 + +ModInv = 1 +A = -2f +M = 8 + +ModInv = 3 +A = -2d +M = 8 + +ModInv = 5 +A = -2b +M = 8 + +ModInv = 7 +A = -29 +M = 8 + +ModInv = 1 +A = -27 +M = 8 + +ModInv = 3 +A = -25 +M = 8 + +ModInv = 5 +A = -23 +M = 8 + +ModInv = 7 +A = -21 +M = 8 + +ModInv = 1 +A = -1f +M = 8 + +ModInv = 3 +A = -1d +M = 8 + +ModInv = 5 +A = -1b +M = 8 + +ModInv = 7 +A = -19 +M = 8 + +ModInv = 1 +A = -17 +M = 8 + +ModInv = 3 +A = -15 +M = 8 + +ModInv = 5 +A = -13 +M = 8 + +ModInv = 7 +A = -11 +M = 8 + +ModInv = 1 +A = -f +M = 8 + +ModInv = 3 +A = -d +M = 8 + +ModInv = 5 +A = -b +M = 8 + +ModInv = 7 +A = -9 +M = 8 + +ModInv = 1 +A = -7 +M = 8 + +ModInv = 3 +A = -5 +M = 8 + +ModInv = 5 +A = -3 +M = 8 + +ModInv = 7 +A = -1 +M = 8 + +ModInv = 1 +A = 1 +M = 8 + +ModInv = 3 +A = 3 +M = 8 + +ModInv = 5 +A = 5 +M = 8 + +ModInv = 7 +A = 7 +M = 8 + +ModInv = 1 +A = 9 +M = 8 + +ModInv = 3 +A = b +M = 8 + +ModInv = 5 +A = d +M = 8 + +ModInv = 7 +A = f +M = 8 + +ModInv = 1 +A = 11 +M = 8 + +ModInv = 3 +A = 13 +M = 8 + +ModInv = 5 +A = 15 +M = 8 + +ModInv = 7 +A = 17 +M = 8 + +ModInv = 1 +A = 19 +M = 8 + +ModInv = 3 +A = 1b +M = 8 + +ModInv = 5 +A = 1d +M = 8 + +ModInv = 7 +A = 1f +M = 8 + +ModInv = 1 +A = 21 +M = 8 + +ModInv = 3 +A = 23 +M = 8 + +ModInv = 5 +A = 25 +M = 8 + +ModInv = 7 +A = 27 +M = 8 + +ModInv = 1 +A = 29 +M = 8 + +ModInv = 3 +A = 2b +M = 8 + +ModInv = 5 +A = 2d +M = 8 + +ModInv = 7 +A = 2f +M = 8 + +ModInv = 1 +A = 31 +M = 8 + +ModInv = 3 +A = 33 +M = 8 + +ModInv = 5 +A = 35 +M = 8 + +ModInv = 7 +A = 37 +M = 8 + +ModInv = 1 +A = 39 +M = 8 + +ModInv = 3 +A = 3b +M = 8 + +ModInv = 5 +A = 3d +M = 8 + +ModInv = 7 +A = 3f +M = 8 + +ModInv = 1 +A = 41 +M = 8 + +ModInv = 3 +A = 43 +M = 8 + +ModInv = 5 +A = 45 +M = 8 + +ModInv = 7 +A = 47 +M = 8 + +ModInv = 1 +A = 49 +M = 8 + +ModInv = 3 +A = 4b +M = 8 + +ModInv = 5 +A = 4d +M = 8 + +ModInv = 7 +A = 4f +M = 8 + +ModInv = 1 +A = 51 +M = 8 + +ModInv = 3 +A = 53 +M = 8 + +ModInv = 5 +A = 55 +M = 8 + +ModInv = 7 +A = 57 +M = 8 + +ModInv = 1 +A = 59 +M = 8 + +ModInv = 3 +A = 5b +M = 8 + +ModInv = 5 +A = 5d +M = 8 + +ModInv = 7 +A = 5f +M = 8 + +ModInv = 1 +A = 61 +M = 8 + +ModInv = 3 +A = 63 +M = 8 + +ModInv = 8 +A = -64 +M = 9 + +ModInv = 1 +A = -62 +M = 9 + +ModInv = 5 +A = -61 +M = 9 + +ModInv = 7 +A = -5f +M = 9 + +ModInv = 2 +A = -5e +M = 9 + +ModInv = 4 +A = -5c +M = 9 + +ModInv = 8 +A = -5b +M = 9 + +ModInv = 1 +A = -59 +M = 9 + +ModInv = 5 +A = -58 +M = 9 + +ModInv = 7 +A = -56 +M = 9 + +ModInv = 2 +A = -55 +M = 9 + +ModInv = 4 +A = -53 +M = 9 + +ModInv = 8 +A = -52 +M = 9 + +ModInv = 1 +A = -50 +M = 9 + +ModInv = 5 +A = -4f +M = 9 + +ModInv = 7 +A = -4d +M = 9 + +ModInv = 2 +A = -4c +M = 9 + +ModInv = 4 +A = -4a +M = 9 + +ModInv = 8 +A = -49 +M = 9 + +ModInv = 1 +A = -47 +M = 9 + +ModInv = 5 +A = -46 +M = 9 + +ModInv = 7 +A = -44 +M = 9 + +ModInv = 2 +A = -43 +M = 9 + +ModInv = 4 +A = -41 +M = 9 + +ModInv = 8 +A = -40 +M = 9 + +ModInv = 1 +A = -3e +M = 9 + +ModInv = 5 +A = -3d +M = 9 + +ModInv = 7 +A = -3b +M = 9 + +ModInv = 2 +A = -3a +M = 9 + +ModInv = 4 +A = -38 +M = 9 + +ModInv = 8 +A = -37 +M = 9 + +ModInv = 1 +A = -35 +M = 9 + +ModInv = 5 +A = -34 +M = 9 + +ModInv = 7 +A = -32 +M = 9 + +ModInv = 2 +A = -31 +M = 9 + +ModInv = 4 +A = -2f +M = 9 + +ModInv = 8 +A = -2e +M = 9 + +ModInv = 1 +A = -2c +M = 9 + +ModInv = 5 +A = -2b +M = 9 + +ModInv = 7 +A = -29 +M = 9 + +ModInv = 2 +A = -28 +M = 9 + +ModInv = 4 +A = -26 +M = 9 + +ModInv = 8 +A = -25 +M = 9 + +ModInv = 1 +A = -23 +M = 9 + +ModInv = 5 +A = -22 +M = 9 + +ModInv = 7 +A = -20 +M = 9 + +ModInv = 2 +A = -1f +M = 9 + +ModInv = 4 +A = -1d +M = 9 + +ModInv = 8 +A = -1c +M = 9 + +ModInv = 1 +A = -1a +M = 9 + +ModInv = 5 +A = -19 +M = 9 + +ModInv = 7 +A = -17 +M = 9 + +ModInv = 2 +A = -16 +M = 9 + +ModInv = 4 +A = -14 +M = 9 + +ModInv = 8 +A = -13 +M = 9 + +ModInv = 1 +A = -11 +M = 9 + +ModInv = 5 +A = -10 +M = 9 + +ModInv = 7 +A = -e +M = 9 + +ModInv = 2 +A = -d +M = 9 + +ModInv = 4 +A = -b +M = 9 + +ModInv = 8 +A = -a +M = 9 + +ModInv = 1 +A = -8 +M = 9 + +ModInv = 5 +A = -7 +M = 9 + +ModInv = 7 +A = -5 +M = 9 + +ModInv = 2 +A = -4 +M = 9 + +ModInv = 4 +A = -2 +M = 9 + +ModInv = 8 +A = -1 +M = 9 + +ModInv = 1 +A = 1 +M = 9 + +ModInv = 5 +A = 2 +M = 9 + +ModInv = 7 +A = 4 +M = 9 + +ModInv = 2 +A = 5 +M = 9 + +ModInv = 4 +A = 7 +M = 9 + +ModInv = 8 +A = 8 +M = 9 + +ModInv = 1 +A = a +M = 9 + +ModInv = 5 +A = b +M = 9 + +ModInv = 7 +A = d +M = 9 + +ModInv = 2 +A = e +M = 9 + +ModInv = 4 +A = 10 +M = 9 + +ModInv = 8 +A = 11 +M = 9 + +ModInv = 1 +A = 13 +M = 9 + +ModInv = 5 +A = 14 +M = 9 + +ModInv = 7 +A = 16 +M = 9 + +ModInv = 2 +A = 17 +M = 9 + +ModInv = 4 +A = 19 +M = 9 + +ModInv = 8 +A = 1a +M = 9 + +ModInv = 1 +A = 1c +M = 9 + +ModInv = 5 +A = 1d +M = 9 + +ModInv = 7 +A = 1f +M = 9 + +ModInv = 2 +A = 20 +M = 9 + +ModInv = 4 +A = 22 +M = 9 + +ModInv = 8 +A = 23 +M = 9 + +ModInv = 1 +A = 25 +M = 9 + +ModInv = 5 +A = 26 +M = 9 + +ModInv = 7 +A = 28 +M = 9 + +ModInv = 2 +A = 29 +M = 9 + +ModInv = 4 +A = 2b +M = 9 + +ModInv = 8 +A = 2c +M = 9 + +ModInv = 1 +A = 2e +M = 9 + +ModInv = 5 +A = 2f +M = 9 + +ModInv = 7 +A = 31 +M = 9 + +ModInv = 2 +A = 32 +M = 9 + +ModInv = 4 +A = 34 +M = 9 + +ModInv = 8 +A = 35 +M = 9 + +ModInv = 1 +A = 37 +M = 9 + +ModInv = 5 +A = 38 +M = 9 + +ModInv = 7 +A = 3a +M = 9 + +ModInv = 2 +A = 3b +M = 9 + +ModInv = 4 +A = 3d +M = 9 + +ModInv = 8 +A = 3e +M = 9 + +ModInv = 1 +A = 40 +M = 9 + +ModInv = 5 +A = 41 +M = 9 + +ModInv = 7 +A = 43 +M = 9 + +ModInv = 2 +A = 44 +M = 9 + +ModInv = 4 +A = 46 +M = 9 + +ModInv = 8 +A = 47 +M = 9 + +ModInv = 1 +A = 49 +M = 9 + +ModInv = 5 +A = 4a +M = 9 + +ModInv = 7 +A = 4c +M = 9 + +ModInv = 2 +A = 4d +M = 9 + +ModInv = 4 +A = 4f +M = 9 + +ModInv = 8 +A = 50 +M = 9 + +ModInv = 1 +A = 52 +M = 9 + +ModInv = 5 +A = 53 +M = 9 + +ModInv = 7 +A = 55 +M = 9 + +ModInv = 2 +A = 56 +M = 9 + +ModInv = 4 +A = 58 +M = 9 + +ModInv = 8 +A = 59 +M = 9 + +ModInv = 1 +A = 5b +M = 9 + +ModInv = 5 +A = 5c +M = 9 + +ModInv = 7 +A = 5e +M = 9 + +ModInv = 2 +A = 5f +M = 9 + +ModInv = 4 +A = 61 +M = 9 + +ModInv = 8 +A = 62 +M = 9 + +ModInv = 1 +A = -63 +M = a + +ModInv = 7 +A = -61 +M = a + +ModInv = 3 +A = -5d +M = a + +ModInv = 9 +A = -5b +M = a + +ModInv = 1 +A = -59 +M = a + +ModInv = 7 +A = -57 +M = a + +ModInv = 3 +A = -53 +M = a + +ModInv = 9 +A = -51 +M = a + +ModInv = 1 +A = -4f +M = a + +ModInv = 7 +A = -4d +M = a + +ModInv = 3 +A = -49 +M = a + +ModInv = 9 +A = -47 +M = a + +ModInv = 1 +A = -45 +M = a + +ModInv = 7 +A = -43 +M = a + +ModInv = 3 +A = -3f +M = a + +ModInv = 9 +A = -3d +M = a + +ModInv = 1 +A = -3b +M = a + +ModInv = 7 +A = -39 +M = a + +ModInv = 3 +A = -35 +M = a + +ModInv = 9 +A = -33 +M = a + +ModInv = 1 +A = -31 +M = a + +ModInv = 7 +A = -2f +M = a + +ModInv = 3 +A = -2b +M = a + +ModInv = 9 +A = -29 +M = a + +ModInv = 1 +A = -27 +M = a + +ModInv = 7 +A = -25 +M = a + +ModInv = 3 +A = -21 +M = a + +ModInv = 9 +A = -1f +M = a + +ModInv = 1 +A = -1d +M = a + +ModInv = 7 +A = -1b +M = a + +ModInv = 3 +A = -17 +M = a + +ModInv = 9 +A = -15 +M = a + +ModInv = 1 +A = -13 +M = a + +ModInv = 7 +A = -11 +M = a + +ModInv = 3 +A = -d +M = a + +ModInv = 9 +A = -b +M = a + +ModInv = 1 +A = -9 +M = a + +ModInv = 7 +A = -7 +M = a + +ModInv = 3 +A = -3 +M = a + +ModInv = 9 +A = -1 +M = a + +ModInv = 1 +A = 1 +M = a + +ModInv = 7 +A = 3 +M = a + +ModInv = 3 +A = 7 +M = a + +ModInv = 9 +A = 9 +M = a + +ModInv = 1 +A = b +M = a + +ModInv = 7 +A = d +M = a + +ModInv = 3 +A = 11 +M = a + +ModInv = 9 +A = 13 +M = a + +ModInv = 1 +A = 15 +M = a + +ModInv = 7 +A = 17 +M = a + +ModInv = 3 +A = 1b +M = a + +ModInv = 9 +A = 1d +M = a + +ModInv = 1 +A = 1f +M = a + +ModInv = 7 +A = 21 +M = a + +ModInv = 3 +A = 25 +M = a + +ModInv = 9 +A = 27 +M = a + +ModInv = 1 +A = 29 +M = a + +ModInv = 7 +A = 2b +M = a + +ModInv = 3 +A = 2f +M = a + +ModInv = 9 +A = 31 +M = a + +ModInv = 1 +A = 33 +M = a + +ModInv = 7 +A = 35 +M = a + +ModInv = 3 +A = 39 +M = a + +ModInv = 9 +A = 3b +M = a + +ModInv = 1 +A = 3d +M = a + +ModInv = 7 +A = 3f +M = a + +ModInv = 3 +A = 43 +M = a + +ModInv = 9 +A = 45 +M = a + +ModInv = 1 +A = 47 +M = a + +ModInv = 7 +A = 49 +M = a + +ModInv = 3 +A = 4d +M = a + +ModInv = 9 +A = 4f +M = a + +ModInv = 1 +A = 51 +M = a + +ModInv = 7 +A = 53 +M = a + +ModInv = 3 +A = 57 +M = a + +ModInv = 9 +A = 59 +M = a + +ModInv = 1 +A = 5b +M = a + +ModInv = 7 +A = 5d +M = a + +ModInv = 3 +A = 61 +M = a + +ModInv = 9 +A = 63 +M = a + +ModInv = a +A = -64 +M = b + +ModInv = 1 +A = -62 +M = b + +ModInv = 6 +A = -61 +M = b + +ModInv = 4 +A = -60 +M = b + +ModInv = 3 +A = -5f +M = b + +ModInv = 9 +A = -5e +M = b + +ModInv = 2 +A = -5d +M = b + +ModInv = 8 +A = -5c +M = b + +ModInv = 7 +A = -5b +M = b + +ModInv = 5 +A = -5a +M = b + +ModInv = a +A = -59 +M = b + +ModInv = 1 +A = -57 +M = b + +ModInv = 6 +A = -56 +M = b + +ModInv = 4 +A = -55 +M = b + +ModInv = 3 +A = -54 +M = b + +ModInv = 9 +A = -53 +M = b + +ModInv = 2 +A = -52 +M = b + +ModInv = 8 +A = -51 +M = b + +ModInv = 7 +A = -50 +M = b + +ModInv = 5 +A = -4f +M = b + +ModInv = a +A = -4e +M = b + +ModInv = 1 +A = -4c +M = b + +ModInv = 6 +A = -4b +M = b + +ModInv = 4 +A = -4a +M = b + +ModInv = 3 +A = -49 +M = b + +ModInv = 9 +A = -48 +M = b + +ModInv = 2 +A = -47 +M = b + +ModInv = 8 +A = -46 +M = b + +ModInv = 7 +A = -45 +M = b + +ModInv = 5 +A = -44 +M = b + +ModInv = a +A = -43 +M = b + +ModInv = 1 +A = -41 +M = b + +ModInv = 6 +A = -40 +M = b + +ModInv = 4 +A = -3f +M = b + +ModInv = 3 +A = -3e +M = b + +ModInv = 9 +A = -3d +M = b + +ModInv = 2 +A = -3c +M = b + +ModInv = 8 +A = -3b +M = b + +ModInv = 7 +A = -3a +M = b + +ModInv = 5 +A = -39 +M = b + +ModInv = a +A = -38 +M = b + +ModInv = 1 +A = -36 +M = b + +ModInv = 6 +A = -35 +M = b + +ModInv = 4 +A = -34 +M = b + +ModInv = 3 +A = -33 +M = b + +ModInv = 9 +A = -32 +M = b + +ModInv = 2 +A = -31 +M = b + +ModInv = 8 +A = -30 +M = b + +ModInv = 7 +A = -2f +M = b + +ModInv = 5 +A = -2e +M = b + +ModInv = a +A = -2d +M = b + +ModInv = 1 +A = -2b +M = b + +ModInv = 6 +A = -2a +M = b + +ModInv = 4 +A = -29 +M = b + +ModInv = 3 +A = -28 +M = b + +ModInv = 9 +A = -27 +M = b + +ModInv = 2 +A = -26 +M = b + +ModInv = 8 +A = -25 +M = b + +ModInv = 7 +A = -24 +M = b + +ModInv = 5 +A = -23 +M = b + +ModInv = a +A = -22 +M = b + +ModInv = 1 +A = -20 +M = b + +ModInv = 6 +A = -1f +M = b + +ModInv = 4 +A = -1e +M = b + +ModInv = 3 +A = -1d +M = b + +ModInv = 9 +A = -1c +M = b + +ModInv = 2 +A = -1b +M = b + +ModInv = 8 +A = -1a +M = b + +ModInv = 7 +A = -19 +M = b + +ModInv = 5 +A = -18 +M = b + +ModInv = a +A = -17 +M = b + +ModInv = 1 +A = -15 +M = b + +ModInv = 6 +A = -14 +M = b + +ModInv = 4 +A = -13 +M = b + +ModInv = 3 +A = -12 +M = b + +ModInv = 9 +A = -11 +M = b + +ModInv = 2 +A = -10 +M = b + +ModInv = 8 +A = -f +M = b + +ModInv = 7 +A = -e +M = b + +ModInv = 5 +A = -d +M = b + +ModInv = a +A = -c +M = b + +ModInv = 1 +A = -a +M = b + +ModInv = 6 +A = -9 +M = b + +ModInv = 4 +A = -8 +M = b + +ModInv = 3 +A = -7 +M = b + +ModInv = 9 +A = -6 +M = b + +ModInv = 2 +A = -5 +M = b + +ModInv = 8 +A = -4 +M = b + +ModInv = 7 +A = -3 +M = b + +ModInv = 5 +A = -2 +M = b + +ModInv = a +A = -1 +M = b + +ModInv = 1 +A = 1 +M = b + +ModInv = 6 +A = 2 +M = b + +ModInv = 4 +A = 3 +M = b + +ModInv = 3 +A = 4 +M = b + +ModInv = 9 +A = 5 +M = b + +ModInv = 2 +A = 6 +M = b + +ModInv = 8 +A = 7 +M = b + +ModInv = 7 +A = 8 +M = b + +ModInv = 5 +A = 9 +M = b + +ModInv = a +A = a +M = b + +ModInv = 1 +A = c +M = b + +ModInv = 6 +A = d +M = b + +ModInv = 4 +A = e +M = b + +ModInv = 3 +A = f +M = b + +ModInv = 9 +A = 10 +M = b + +ModInv = 2 +A = 11 +M = b + +ModInv = 8 +A = 12 +M = b + +ModInv = 7 +A = 13 +M = b + +ModInv = 5 +A = 14 +M = b + +ModInv = a +A = 15 +M = b + +ModInv = 1 +A = 17 +M = b + +ModInv = 6 +A = 18 +M = b + +ModInv = 4 +A = 19 +M = b + +ModInv = 3 +A = 1a +M = b + +ModInv = 9 +A = 1b +M = b + +ModInv = 2 +A = 1c +M = b + +ModInv = 8 +A = 1d +M = b + +ModInv = 7 +A = 1e +M = b + +ModInv = 5 +A = 1f +M = b + +ModInv = a +A = 20 +M = b + +ModInv = 1 +A = 22 +M = b + +ModInv = 6 +A = 23 +M = b + +ModInv = 4 +A = 24 +M = b + +ModInv = 3 +A = 25 +M = b + +ModInv = 9 +A = 26 +M = b + +ModInv = 2 +A = 27 +M = b + +ModInv = 8 +A = 28 +M = b + +ModInv = 7 +A = 29 +M = b + +ModInv = 5 +A = 2a +M = b + +ModInv = a +A = 2b +M = b + +ModInv = 1 +A = 2d +M = b + +ModInv = 6 +A = 2e +M = b + +ModInv = 4 +A = 2f +M = b + +ModInv = 3 +A = 30 +M = b + +ModInv = 9 +A = 31 +M = b + +ModInv = 2 +A = 32 +M = b + +ModInv = 8 +A = 33 +M = b + +ModInv = 7 +A = 34 +M = b + +ModInv = 5 +A = 35 +M = b + +ModInv = a +A = 36 +M = b + +ModInv = 1 +A = 38 +M = b + +ModInv = 6 +A = 39 +M = b + +ModInv = 4 +A = 3a +M = b + +ModInv = 3 +A = 3b +M = b + +ModInv = 9 +A = 3c +M = b + +ModInv = 2 +A = 3d +M = b + +ModInv = 8 +A = 3e +M = b + +ModInv = 7 +A = 3f +M = b + +ModInv = 5 +A = 40 +M = b + +ModInv = a +A = 41 +M = b + +ModInv = 1 +A = 43 +M = b + +ModInv = 6 +A = 44 +M = b + +ModInv = 4 +A = 45 +M = b + +ModInv = 3 +A = 46 +M = b + +ModInv = 9 +A = 47 +M = b + +ModInv = 2 +A = 48 +M = b + +ModInv = 8 +A = 49 +M = b + +ModInv = 7 +A = 4a +M = b + +ModInv = 5 +A = 4b +M = b + +ModInv = a +A = 4c +M = b + +ModInv = 1 +A = 4e +M = b + +ModInv = 6 +A = 4f +M = b + +ModInv = 4 +A = 50 +M = b + +ModInv = 3 +A = 51 +M = b + +ModInv = 9 +A = 52 +M = b + +ModInv = 2 +A = 53 +M = b + +ModInv = 8 +A = 54 +M = b + +ModInv = 7 +A = 55 +M = b + +ModInv = 5 +A = 56 +M = b + +ModInv = a +A = 57 +M = b + +ModInv = 1 +A = 59 +M = b + +ModInv = 6 +A = 5a +M = b + +ModInv = 4 +A = 5b +M = b + +ModInv = 3 +A = 5c +M = b + +ModInv = 9 +A = 5d +M = b + +ModInv = 2 +A = 5e +M = b + +ModInv = 8 +A = 5f +M = b + +ModInv = 7 +A = 60 +M = b + +ModInv = 5 +A = 61 +M = b + +ModInv = a +A = 62 +M = b + +ModInv = b +A = -61 +M = c + +ModInv = 1 +A = -5f +M = c + +ModInv = 5 +A = -5b +M = c + +ModInv = 7 +A = -59 +M = c + +ModInv = b +A = -55 +M = c + +ModInv = 1 +A = -53 +M = c + +ModInv = 5 +A = -4f +M = c + +ModInv = 7 +A = -4d +M = c + +ModInv = b +A = -49 +M = c + +ModInv = 1 +A = -47 +M = c + +ModInv = 5 +A = -43 +M = c + +ModInv = 7 +A = -41 +M = c + +ModInv = b +A = -3d +M = c + +ModInv = 1 +A = -3b +M = c + +ModInv = 5 +A = -37 +M = c + +ModInv = 7 +A = -35 +M = c + +ModInv = b +A = -31 +M = c + +ModInv = 1 +A = -2f +M = c + +ModInv = 5 +A = -2b +M = c + +ModInv = 7 +A = -29 +M = c + +ModInv = b +A = -25 +M = c + +ModInv = 1 +A = -23 +M = c + +ModInv = 5 +A = -1f +M = c + +ModInv = 7 +A = -1d +M = c + +ModInv = b +A = -19 +M = c + +ModInv = 1 +A = -17 +M = c + +ModInv = 5 +A = -13 +M = c + +ModInv = 7 +A = -11 +M = c + +ModInv = b +A = -d +M = c + +ModInv = 1 +A = -b +M = c + +ModInv = 5 +A = -7 +M = c + +ModInv = 7 +A = -5 +M = c + +ModInv = b +A = -1 +M = c + +ModInv = 1 +A = 1 +M = c + +ModInv = 5 +A = 5 +M = c + +ModInv = 7 +A = 7 +M = c + +ModInv = b +A = b +M = c + +ModInv = 1 +A = d +M = c + +ModInv = 5 +A = 11 +M = c + +ModInv = 7 +A = 13 +M = c + +ModInv = b +A = 17 +M = c + +ModInv = 1 +A = 19 +M = c + +ModInv = 5 +A = 1d +M = c + +ModInv = 7 +A = 1f +M = c + +ModInv = b +A = 23 +M = c + +ModInv = 1 +A = 25 +M = c + +ModInv = 5 +A = 29 +M = c + +ModInv = 7 +A = 2b +M = c + +ModInv = b +A = 2f +M = c + +ModInv = 1 +A = 31 +M = c + +ModInv = 5 +A = 35 +M = c + +ModInv = 7 +A = 37 +M = c + +ModInv = b +A = 3b +M = c + +ModInv = 1 +A = 3d +M = c + +ModInv = 5 +A = 41 +M = c + +ModInv = 7 +A = 43 +M = c + +ModInv = b +A = 47 +M = c + +ModInv = 1 +A = 49 +M = c + +ModInv = 5 +A = 4d +M = c + +ModInv = 7 +A = 4f +M = c + +ModInv = b +A = 53 +M = c + +ModInv = 1 +A = 55 +M = c + +ModInv = 5 +A = 59 +M = c + +ModInv = 7 +A = 5b +M = c + +ModInv = b +A = 5f +M = c + +ModInv = 1 +A = 61 +M = c + +ModInv = a +A = -64 +M = d + +ModInv = 8 +A = -63 +M = d + +ModInv = b +A = -62 +M = d + +ModInv = 2 +A = -61 +M = d + +ModInv = 5 +A = -60 +M = d + +ModInv = 3 +A = -5f +M = d + +ModInv = 4 +A = -5e +M = d + +ModInv = 6 +A = -5d +M = d + +ModInv = c +A = -5c +M = d + +ModInv = 1 +A = -5a +M = d + +ModInv = 7 +A = -59 +M = d + +ModInv = 9 +A = -58 +M = d + +ModInv = a +A = -57 +M = d + +ModInv = 8 +A = -56 +M = d + +ModInv = b +A = -55 +M = d + +ModInv = 2 +A = -54 +M = d + +ModInv = 5 +A = -53 +M = d + +ModInv = 3 +A = -52 +M = d + +ModInv = 4 +A = -51 +M = d + +ModInv = 6 +A = -50 +M = d + +ModInv = c +A = -4f +M = d + +ModInv = 1 +A = -4d +M = d + +ModInv = 7 +A = -4c +M = d + +ModInv = 9 +A = -4b +M = d + +ModInv = a +A = -4a +M = d + +ModInv = 8 +A = -49 +M = d + +ModInv = b +A = -48 +M = d + +ModInv = 2 +A = -47 +M = d + +ModInv = 5 +A = -46 +M = d + +ModInv = 3 +A = -45 +M = d + +ModInv = 4 +A = -44 +M = d + +ModInv = 6 +A = -43 +M = d + +ModInv = c +A = -42 +M = d + +ModInv = 1 +A = -40 +M = d + +ModInv = 7 +A = -3f +M = d + +ModInv = 9 +A = -3e +M = d + +ModInv = a +A = -3d +M = d + +ModInv = 8 +A = -3c +M = d + +ModInv = b +A = -3b +M = d + +ModInv = 2 +A = -3a +M = d + +ModInv = 5 +A = -39 +M = d + +ModInv = 3 +A = -38 +M = d + +ModInv = 4 +A = -37 +M = d + +ModInv = 6 +A = -36 +M = d + +ModInv = c +A = -35 +M = d + +ModInv = 1 +A = -33 +M = d + +ModInv = 7 +A = -32 +M = d + +ModInv = 9 +A = -31 +M = d + +ModInv = a +A = -30 +M = d + +ModInv = 8 +A = -2f +M = d + +ModInv = b +A = -2e +M = d + +ModInv = 2 +A = -2d +M = d + +ModInv = 5 +A = -2c +M = d + +ModInv = 3 +A = -2b +M = d + +ModInv = 4 +A = -2a +M = d + +ModInv = 6 +A = -29 +M = d + +ModInv = c +A = -28 +M = d + +ModInv = 1 +A = -26 +M = d + +ModInv = 7 +A = -25 +M = d + +ModInv = 9 +A = -24 +M = d + +ModInv = a +A = -23 +M = d + +ModInv = 8 +A = -22 +M = d + +ModInv = b +A = -21 +M = d + +ModInv = 2 +A = -20 +M = d + +ModInv = 5 +A = -1f +M = d + +ModInv = 3 +A = -1e +M = d + +ModInv = 4 +A = -1d +M = d + +ModInv = 6 +A = -1c +M = d + +ModInv = c +A = -1b +M = d + +ModInv = 1 +A = -19 +M = d + +ModInv = 7 +A = -18 +M = d + +ModInv = 9 +A = -17 +M = d + +ModInv = a +A = -16 +M = d + +ModInv = 8 +A = -15 +M = d + +ModInv = b +A = -14 +M = d + +ModInv = 2 +A = -13 +M = d + +ModInv = 5 +A = -12 +M = d + +ModInv = 3 +A = -11 +M = d + +ModInv = 4 +A = -10 +M = d + +ModInv = 6 +A = -f +M = d + +ModInv = c +A = -e +M = d + +ModInv = 1 +A = -c +M = d + +ModInv = 7 +A = -b +M = d + +ModInv = 9 +A = -a +M = d + +ModInv = a +A = -9 +M = d + +ModInv = 8 +A = -8 +M = d + +ModInv = b +A = -7 +M = d + +ModInv = 2 +A = -6 +M = d + +ModInv = 5 +A = -5 +M = d + +ModInv = 3 +A = -4 +M = d + +ModInv = 4 +A = -3 +M = d + +ModInv = 6 +A = -2 +M = d + +ModInv = c +A = -1 +M = d + +ModInv = 1 +A = 1 +M = d + +ModInv = 7 +A = 2 +M = d + +ModInv = 9 +A = 3 +M = d + +ModInv = a +A = 4 +M = d + +ModInv = 8 +A = 5 +M = d + +ModInv = b +A = 6 +M = d + +ModInv = 2 +A = 7 +M = d + +ModInv = 5 +A = 8 +M = d + +ModInv = 3 +A = 9 +M = d + +ModInv = 4 +A = a +M = d + +ModInv = 6 +A = b +M = d + +ModInv = c +A = c +M = d + +ModInv = 1 +A = e +M = d + +ModInv = 7 +A = f +M = d + +ModInv = 9 +A = 10 +M = d + +ModInv = a +A = 11 +M = d + +ModInv = 8 +A = 12 +M = d + +ModInv = b +A = 13 +M = d + +ModInv = 2 +A = 14 +M = d + +ModInv = 5 +A = 15 +M = d + +ModInv = 3 +A = 16 +M = d + +ModInv = 4 +A = 17 +M = d + +ModInv = 6 +A = 18 +M = d + +ModInv = c +A = 19 +M = d + +ModInv = 1 +A = 1b +M = d + +ModInv = 7 +A = 1c +M = d + +ModInv = 9 +A = 1d +M = d + +ModInv = a +A = 1e +M = d + +ModInv = 8 +A = 1f +M = d + +ModInv = b +A = 20 +M = d + +ModInv = 2 +A = 21 +M = d + +ModInv = 5 +A = 22 +M = d + +ModInv = 3 +A = 23 +M = d + +ModInv = 4 +A = 24 +M = d + +ModInv = 6 +A = 25 +M = d + +ModInv = c +A = 26 +M = d + +ModInv = 1 +A = 28 +M = d + +ModInv = 7 +A = 29 +M = d + +ModInv = 9 +A = 2a +M = d + +ModInv = a +A = 2b +M = d + +ModInv = 8 +A = 2c +M = d + +ModInv = b +A = 2d +M = d + +ModInv = 2 +A = 2e +M = d + +ModInv = 5 +A = 2f +M = d + +ModInv = 3 +A = 30 +M = d + +ModInv = 4 +A = 31 +M = d + +ModInv = 6 +A = 32 +M = d + +ModInv = c +A = 33 +M = d + +ModInv = 1 +A = 35 +M = d + +ModInv = 7 +A = 36 +M = d + +ModInv = 9 +A = 37 +M = d + +ModInv = a +A = 38 +M = d + +ModInv = 8 +A = 39 +M = d + +ModInv = b +A = 3a +M = d + +ModInv = 2 +A = 3b +M = d + +ModInv = 5 +A = 3c +M = d + +ModInv = 3 +A = 3d +M = d + +ModInv = 4 +A = 3e +M = d + +ModInv = 6 +A = 3f +M = d + +ModInv = c +A = 40 +M = d + +ModInv = 1 +A = 42 +M = d + +ModInv = 7 +A = 43 +M = d + +ModInv = 9 +A = 44 +M = d + +ModInv = a +A = 45 +M = d + +ModInv = 8 +A = 46 +M = d + +ModInv = b +A = 47 +M = d + +ModInv = 2 +A = 48 +M = d + +ModInv = 5 +A = 49 +M = d + +ModInv = 3 +A = 4a +M = d + +ModInv = 4 +A = 4b +M = d + +ModInv = 6 +A = 4c +M = d + +ModInv = c +A = 4d +M = d + +ModInv = 1 +A = 4f +M = d + +ModInv = 7 +A = 50 +M = d + +ModInv = 9 +A = 51 +M = d + +ModInv = a +A = 52 +M = d + +ModInv = 8 +A = 53 +M = d + +ModInv = b +A = 54 +M = d + +ModInv = 2 +A = 55 +M = d + +ModInv = 5 +A = 56 +M = d + +ModInv = 3 +A = 57 +M = d + +ModInv = 4 +A = 58 +M = d + +ModInv = 6 +A = 59 +M = d + +ModInv = c +A = 5a +M = d + +ModInv = 1 +A = 5c +M = d + +ModInv = 7 +A = 5d +M = d + +ModInv = 9 +A = 5e +M = d + +ModInv = a +A = 5f +M = d + +ModInv = 8 +A = 60 +M = d + +ModInv = b +A = 61 +M = d + +ModInv = 2 +A = 62 +M = d + +ModInv = 5 +A = 63 +M = d + +ModInv = d +A = -63 +M = e + +ModInv = 1 +A = -61 +M = e + +ModInv = 5 +A = -5f +M = e + +ModInv = 3 +A = -5d +M = e + +ModInv = b +A = -59 +M = e + +ModInv = 9 +A = -57 +M = e + +ModInv = d +A = -55 +M = e + +ModInv = 1 +A = -53 +M = e + +ModInv = 5 +A = -51 +M = e + +ModInv = 3 +A = -4f +M = e + +ModInv = b +A = -4b +M = e + +ModInv = 9 +A = -49 +M = e + +ModInv = d +A = -47 +M = e + +ModInv = 1 +A = -45 +M = e + +ModInv = 5 +A = -43 +M = e + +ModInv = 3 +A = -41 +M = e + +ModInv = b +A = -3d +M = e + +ModInv = 9 +A = -3b +M = e + +ModInv = d +A = -39 +M = e + +ModInv = 1 +A = -37 +M = e + +ModInv = 5 +A = -35 +M = e + +ModInv = 3 +A = -33 +M = e + +ModInv = b +A = -2f +M = e + +ModInv = 9 +A = -2d +M = e + +ModInv = d +A = -2b +M = e + +ModInv = 1 +A = -29 +M = e + +ModInv = 5 +A = -27 +M = e + +ModInv = 3 +A = -25 +M = e + +ModInv = b +A = -21 +M = e + +ModInv = 9 +A = -1f +M = e + +ModInv = d +A = -1d +M = e + +ModInv = 1 +A = -1b +M = e + +ModInv = 5 +A = -19 +M = e + +ModInv = 3 +A = -17 +M = e + +ModInv = b +A = -13 +M = e + +ModInv = 9 +A = -11 +M = e + +ModInv = d +A = -f +M = e + +ModInv = 1 +A = -d +M = e + +ModInv = 5 +A = -b +M = e + +ModInv = 3 +A = -9 +M = e + +ModInv = b +A = -5 +M = e + +ModInv = 9 +A = -3 +M = e + +ModInv = d +A = -1 +M = e + +ModInv = 1 +A = 1 +M = e + +ModInv = 5 +A = 3 +M = e + +ModInv = 3 +A = 5 +M = e + +ModInv = b +A = 9 +M = e + +ModInv = 9 +A = b +M = e + +ModInv = d +A = d +M = e + +ModInv = 1 +A = f +M = e + +ModInv = 5 +A = 11 +M = e + +ModInv = 3 +A = 13 +M = e + +ModInv = b +A = 17 +M = e + +ModInv = 9 +A = 19 +M = e + +ModInv = d +A = 1b +M = e + +ModInv = 1 +A = 1d +M = e + +ModInv = 5 +A = 1f +M = e + +ModInv = 3 +A = 21 +M = e + +ModInv = b +A = 25 +M = e + +ModInv = 9 +A = 27 +M = e + +ModInv = d +A = 29 +M = e + +ModInv = 1 +A = 2b +M = e + +ModInv = 5 +A = 2d +M = e + +ModInv = 3 +A = 2f +M = e + +ModInv = b +A = 33 +M = e + +ModInv = 9 +A = 35 +M = e + +ModInv = d +A = 37 +M = e + +ModInv = 1 +A = 39 +M = e + +ModInv = 5 +A = 3b +M = e + +ModInv = 3 +A = 3d +M = e + +ModInv = b +A = 41 +M = e + +ModInv = 9 +A = 43 +M = e + +ModInv = d +A = 45 +M = e + +ModInv = 1 +A = 47 +M = e + +ModInv = 5 +A = 49 +M = e + +ModInv = 3 +A = 4b +M = e + +ModInv = b +A = 4f +M = e + +ModInv = 9 +A = 51 +M = e + +ModInv = d +A = 53 +M = e + +ModInv = 1 +A = 55 +M = e + +ModInv = 5 +A = 57 +M = e + +ModInv = 3 +A = 59 +M = e + +ModInv = b +A = 5d +M = e + +ModInv = 9 +A = 5f +M = e + +ModInv = d +A = 61 +M = e + +ModInv = 1 +A = 63 +M = e + +ModInv = d +A = -62 +M = f + +ModInv = 2 +A = -61 +M = f + +ModInv = b +A = -5e +M = f + +ModInv = 7 +A = -5c +M = f + +ModInv = e +A = -5b +M = f + +ModInv = 1 +A = -59 +M = f + +ModInv = 8 +A = -58 +M = f + +ModInv = 4 +A = -56 +M = f + +ModInv = d +A = -53 +M = f + +ModInv = 2 +A = -52 +M = f + +ModInv = b +A = -4f +M = f + +ModInv = 7 +A = -4d +M = f + +ModInv = e +A = -4c +M = f + +ModInv = 1 +A = -4a +M = f + +ModInv = 8 +A = -49 +M = f + +ModInv = 4 +A = -47 +M = f + +ModInv = d +A = -44 +M = f + +ModInv = 2 +A = -43 +M = f + +ModInv = b +A = -40 +M = f + +ModInv = 7 +A = -3e +M = f + +ModInv = e +A = -3d +M = f + +ModInv = 1 +A = -3b +M = f + +ModInv = 8 +A = -3a +M = f + +ModInv = 4 +A = -38 +M = f + +ModInv = d +A = -35 +M = f + +ModInv = 2 +A = -34 +M = f + +ModInv = b +A = -31 +M = f + +ModInv = 7 +A = -2f +M = f + +ModInv = e +A = -2e +M = f + +ModInv = 1 +A = -2c +M = f + +ModInv = 8 +A = -2b +M = f + +ModInv = 4 +A = -29 +M = f + +ModInv = d +A = -26 +M = f + +ModInv = 2 +A = -25 +M = f + +ModInv = b +A = -22 +M = f + +ModInv = 7 +A = -20 +M = f + +ModInv = e +A = -1f +M = f + +ModInv = 1 +A = -1d +M = f + +ModInv = 8 +A = -1c +M = f + +ModInv = 4 +A = -1a +M = f + +ModInv = d +A = -17 +M = f + +ModInv = 2 +A = -16 +M = f + +ModInv = b +A = -13 +M = f + +ModInv = 7 +A = -11 +M = f + +ModInv = e +A = -10 +M = f + +ModInv = 1 +A = -e +M = f + +ModInv = 8 +A = -d +M = f + +ModInv = 4 +A = -b +M = f + +ModInv = d +A = -8 +M = f + +ModInv = 2 +A = -7 +M = f + +ModInv = b +A = -4 +M = f + +ModInv = 7 +A = -2 +M = f + +ModInv = e +A = -1 +M = f + +ModInv = 1 +A = 1 +M = f + +ModInv = 8 +A = 2 +M = f + +ModInv = 4 +A = 4 +M = f + +ModInv = d +A = 7 +M = f + +ModInv = 2 +A = 8 +M = f + +ModInv = b +A = b +M = f + +ModInv = 7 +A = d +M = f + +ModInv = e +A = e +M = f + +ModInv = 1 +A = 10 +M = f + +ModInv = 8 +A = 11 +M = f + +ModInv = 4 +A = 13 +M = f + +ModInv = d +A = 16 +M = f + +ModInv = 2 +A = 17 +M = f + +ModInv = b +A = 1a +M = f + +ModInv = 7 +A = 1c +M = f + +ModInv = e +A = 1d +M = f + +ModInv = 1 +A = 1f +M = f + +ModInv = 8 +A = 20 +M = f + +ModInv = 4 +A = 22 +M = f + +ModInv = d +A = 25 +M = f + +ModInv = 2 +A = 26 +M = f + +ModInv = b +A = 29 +M = f + +ModInv = 7 +A = 2b +M = f + +ModInv = e +A = 2c +M = f + +ModInv = 1 +A = 2e +M = f + +ModInv = 8 +A = 2f +M = f + +ModInv = 4 +A = 31 +M = f + +ModInv = d +A = 34 +M = f + +ModInv = 2 +A = 35 +M = f + +ModInv = b +A = 38 +M = f + +ModInv = 7 +A = 3a +M = f + +ModInv = e +A = 3b +M = f + +ModInv = 1 +A = 3d +M = f + +ModInv = 8 +A = 3e +M = f + +ModInv = 4 +A = 40 +M = f + +ModInv = d +A = 43 +M = f + +ModInv = 2 +A = 44 +M = f + +ModInv = b +A = 47 +M = f + +ModInv = 7 +A = 49 +M = f + +ModInv = e +A = 4a +M = f + +ModInv = 1 +A = 4c +M = f + +ModInv = 8 +A = 4d +M = f + +ModInv = 4 +A = 4f +M = f + +ModInv = d +A = 52 +M = f + +ModInv = 2 +A = 53 +M = f + +ModInv = b +A = 56 +M = f + +ModInv = 7 +A = 58 +M = f + +ModInv = e +A = 59 +M = f + +ModInv = 1 +A = 5b +M = f + +ModInv = 8 +A = 5c +M = f + +ModInv = 4 +A = 5e +M = f + +ModInv = d +A = 61 +M = f + +ModInv = 2 +A = 62 +M = f + +ModInv = 5 +A = -63 +M = 10 + +ModInv = f +A = -61 +M = 10 + +ModInv = 1 +A = -5f +M = 10 + +ModInv = b +A = -5d +M = 10 + +ModInv = d +A = -5b +M = 10 + +ModInv = 7 +A = -59 +M = 10 + +ModInv = 9 +A = -57 +M = 10 + +ModInv = 3 +A = -55 +M = 10 + +ModInv = 5 +A = -53 +M = 10 + +ModInv = f +A = -51 +M = 10 + +ModInv = 1 +A = -4f +M = 10 + +ModInv = b +A = -4d +M = 10 + +ModInv = d +A = -4b +M = 10 + +ModInv = 7 +A = -49 +M = 10 + +ModInv = 9 +A = -47 +M = 10 + +ModInv = 3 +A = -45 +M = 10 + +ModInv = 5 +A = -43 +M = 10 + +ModInv = f +A = -41 +M = 10 + +ModInv = 1 +A = -3f +M = 10 + +ModInv = b +A = -3d +M = 10 + +ModInv = d +A = -3b +M = 10 + +ModInv = 7 +A = -39 +M = 10 + +ModInv = 9 +A = -37 +M = 10 + +ModInv = 3 +A = -35 +M = 10 + +ModInv = 5 +A = -33 +M = 10 + +ModInv = f +A = -31 +M = 10 + +ModInv = 1 +A = -2f +M = 10 + +ModInv = b +A = -2d +M = 10 + +ModInv = d +A = -2b +M = 10 + +ModInv = 7 +A = -29 +M = 10 + +ModInv = 9 +A = -27 +M = 10 + +ModInv = 3 +A = -25 +M = 10 + +ModInv = 5 +A = -23 +M = 10 + +ModInv = f +A = -21 +M = 10 + +ModInv = 1 +A = -1f +M = 10 + +ModInv = b +A = -1d +M = 10 + +ModInv = d +A = -1b +M = 10 + +ModInv = 7 +A = -19 +M = 10 + +ModInv = 9 +A = -17 +M = 10 + +ModInv = 3 +A = -15 +M = 10 + +ModInv = 5 +A = -13 +M = 10 + +ModInv = f +A = -11 +M = 10 + +ModInv = 1 +A = -f +M = 10 + +ModInv = b +A = -d +M = 10 + +ModInv = d +A = -b +M = 10 + +ModInv = 7 +A = -9 +M = 10 + +ModInv = 9 +A = -7 +M = 10 + +ModInv = 3 +A = -5 +M = 10 + +ModInv = 5 +A = -3 +M = 10 + +ModInv = f +A = -1 +M = 10 + +ModInv = 1 +A = 1 +M = 10 + +ModInv = b +A = 3 +M = 10 + +ModInv = d +A = 5 +M = 10 + +ModInv = 7 +A = 7 +M = 10 + +ModInv = 9 +A = 9 +M = 10 + +ModInv = 3 +A = b +M = 10 + +ModInv = 5 +A = d +M = 10 + +ModInv = f +A = f +M = 10 + +ModInv = 1 +A = 11 +M = 10 + +ModInv = b +A = 13 +M = 10 + +ModInv = d +A = 15 +M = 10 + +ModInv = 7 +A = 17 +M = 10 + +ModInv = 9 +A = 19 +M = 10 + +ModInv = 3 +A = 1b +M = 10 + +ModInv = 5 +A = 1d +M = 10 + +ModInv = f +A = 1f +M = 10 + +ModInv = 1 +A = 21 +M = 10 + +ModInv = b +A = 23 +M = 10 + +ModInv = d +A = 25 +M = 10 + +ModInv = 7 +A = 27 +M = 10 + +ModInv = 9 +A = 29 +M = 10 + +ModInv = 3 +A = 2b +M = 10 + +ModInv = 5 +A = 2d +M = 10 + +ModInv = f +A = 2f +M = 10 + +ModInv = 1 +A = 31 +M = 10 + +ModInv = b +A = 33 +M = 10 + +ModInv = d +A = 35 +M = 10 + +ModInv = 7 +A = 37 +M = 10 + +ModInv = 9 +A = 39 +M = 10 + +ModInv = 3 +A = 3b +M = 10 + +ModInv = 5 +A = 3d +M = 10 + +ModInv = f +A = 3f +M = 10 + +ModInv = 1 +A = 41 +M = 10 + +ModInv = b +A = 43 +M = 10 + +ModInv = d +A = 45 +M = 10 + +ModInv = 7 +A = 47 +M = 10 + +ModInv = 9 +A = 49 +M = 10 + +ModInv = 3 +A = 4b +M = 10 + +ModInv = 5 +A = 4d +M = 10 + +ModInv = f +A = 4f +M = 10 + +ModInv = 1 +A = 51 +M = 10 + +ModInv = b +A = 53 +M = 10 + +ModInv = d +A = 55 +M = 10 + +ModInv = 7 +A = 57 +M = 10 + +ModInv = 9 +A = 59 +M = 10 + +ModInv = 3 +A = 5b +M = 10 + +ModInv = 5 +A = 5d +M = 10 + +ModInv = f +A = 5f +M = 10 + +ModInv = 1 +A = 61 +M = 10 + +ModInv = b +A = 63 +M = 10 + +ModInv = 9 +A = -64 +M = 11 + +ModInv = 6 +A = -63 +M = 11 + +ModInv = d +A = -62 +M = 11 + +ModInv = 7 +A = -61 +M = 11 + +ModInv = 3 +A = -60 +M = 11 + +ModInv = 5 +A = -5f +M = 11 + +ModInv = f +A = -5e +M = 11 + +ModInv = 2 +A = -5d +M = 11 + +ModInv = c +A = -5c +M = 11 + +ModInv = e +A = -5b +M = 11 + +ModInv = a +A = -5a +M = 11 + +ModInv = 4 +A = -59 +M = 11 + +ModInv = b +A = -58 +M = 11 + +ModInv = 8 +A = -57 +M = 11 + +ModInv = 10 +A = -56 +M = 11 + +ModInv = 1 +A = -54 +M = 11 + +ModInv = 9 +A = -53 +M = 11 + +ModInv = 6 +A = -52 +M = 11 + +ModInv = d +A = -51 +M = 11 + +ModInv = 7 +A = -50 +M = 11 + +ModInv = 3 +A = -4f +M = 11 + +ModInv = 5 +A = -4e +M = 11 + +ModInv = f +A = -4d +M = 11 + +ModInv = 2 +A = -4c +M = 11 + +ModInv = c +A = -4b +M = 11 + +ModInv = e +A = -4a +M = 11 + +ModInv = a +A = -49 +M = 11 + +ModInv = 4 +A = -48 +M = 11 + +ModInv = b +A = -47 +M = 11 + +ModInv = 8 +A = -46 +M = 11 + +ModInv = 10 +A = -45 +M = 11 + +ModInv = 1 +A = -43 +M = 11 + +ModInv = 9 +A = -42 +M = 11 + +ModInv = 6 +A = -41 +M = 11 + +ModInv = d +A = -40 +M = 11 + +ModInv = 7 +A = -3f +M = 11 + +ModInv = 3 +A = -3e +M = 11 + +ModInv = 5 +A = -3d +M = 11 + +ModInv = f +A = -3c +M = 11 + +ModInv = 2 +A = -3b +M = 11 + +ModInv = c +A = -3a +M = 11 + +ModInv = e +A = -39 +M = 11 + +ModInv = a +A = -38 +M = 11 + +ModInv = 4 +A = -37 +M = 11 + +ModInv = b +A = -36 +M = 11 + +ModInv = 8 +A = -35 +M = 11 + +ModInv = 10 +A = -34 +M = 11 + +ModInv = 1 +A = -32 +M = 11 + +ModInv = 9 +A = -31 +M = 11 + +ModInv = 6 +A = -30 +M = 11 + +ModInv = d +A = -2f +M = 11 + +ModInv = 7 +A = -2e +M = 11 + +ModInv = 3 +A = -2d +M = 11 + +ModInv = 5 +A = -2c +M = 11 + +ModInv = f +A = -2b +M = 11 + +ModInv = 2 +A = -2a +M = 11 + +ModInv = c +A = -29 +M = 11 + +ModInv = e +A = -28 +M = 11 + +ModInv = a +A = -27 +M = 11 + +ModInv = 4 +A = -26 +M = 11 + +ModInv = b +A = -25 +M = 11 + +ModInv = 8 +A = -24 +M = 11 + +ModInv = 10 +A = -23 +M = 11 + +ModInv = 1 +A = -21 +M = 11 + +ModInv = 9 +A = -20 +M = 11 + +ModInv = 6 +A = -1f +M = 11 + +ModInv = d +A = -1e +M = 11 + +ModInv = 7 +A = -1d +M = 11 + +ModInv = 3 +A = -1c +M = 11 + +ModInv = 5 +A = -1b +M = 11 + +ModInv = f +A = -1a +M = 11 + +ModInv = 2 +A = -19 +M = 11 + +ModInv = c +A = -18 +M = 11 + +ModInv = e +A = -17 +M = 11 + +ModInv = a +A = -16 +M = 11 + +ModInv = 4 +A = -15 +M = 11 + +ModInv = b +A = -14 +M = 11 + +ModInv = 8 +A = -13 +M = 11 + +ModInv = 10 +A = -12 +M = 11 + +ModInv = 1 +A = -10 +M = 11 + +ModInv = 9 +A = -f +M = 11 + +ModInv = 6 +A = -e +M = 11 + +ModInv = d +A = -d +M = 11 + +ModInv = 7 +A = -c +M = 11 + +ModInv = 3 +A = -b +M = 11 + +ModInv = 5 +A = -a +M = 11 + +ModInv = f +A = -9 +M = 11 + +ModInv = 2 +A = -8 +M = 11 + +ModInv = c +A = -7 +M = 11 + +ModInv = e +A = -6 +M = 11 + +ModInv = a +A = -5 +M = 11 + +ModInv = 4 +A = -4 +M = 11 + +ModInv = b +A = -3 +M = 11 + +ModInv = 8 +A = -2 +M = 11 + +ModInv = 10 +A = -1 +M = 11 + +ModInv = 1 +A = 1 +M = 11 + +ModInv = 9 +A = 2 +M = 11 + +ModInv = 6 +A = 3 +M = 11 + +ModInv = d +A = 4 +M = 11 + +ModInv = 7 +A = 5 +M = 11 + +ModInv = 3 +A = 6 +M = 11 + +ModInv = 5 +A = 7 +M = 11 + +ModInv = f +A = 8 +M = 11 + +ModInv = 2 +A = 9 +M = 11 + +ModInv = c +A = a +M = 11 + +ModInv = e +A = b +M = 11 + +ModInv = a +A = c +M = 11 + +ModInv = 4 +A = d +M = 11 + +ModInv = b +A = e +M = 11 + +ModInv = 8 +A = f +M = 11 + +ModInv = 10 +A = 10 +M = 11 + +ModInv = 1 +A = 12 +M = 11 + +ModInv = 9 +A = 13 +M = 11 + +ModInv = 6 +A = 14 +M = 11 + +ModInv = d +A = 15 +M = 11 + +ModInv = 7 +A = 16 +M = 11 + +ModInv = 3 +A = 17 +M = 11 + +ModInv = 5 +A = 18 +M = 11 + +ModInv = f +A = 19 +M = 11 + +ModInv = 2 +A = 1a +M = 11 + +ModInv = c +A = 1b +M = 11 + +ModInv = e +A = 1c +M = 11 + +ModInv = a +A = 1d +M = 11 + +ModInv = 4 +A = 1e +M = 11 + +ModInv = b +A = 1f +M = 11 + +ModInv = 8 +A = 20 +M = 11 + +ModInv = 10 +A = 21 +M = 11 + +ModInv = 1 +A = 23 +M = 11 + +ModInv = 9 +A = 24 +M = 11 + +ModInv = 6 +A = 25 +M = 11 + +ModInv = d +A = 26 +M = 11 + +ModInv = 7 +A = 27 +M = 11 + +ModInv = 3 +A = 28 +M = 11 + +ModInv = 5 +A = 29 +M = 11 + +ModInv = f +A = 2a +M = 11 + +ModInv = 2 +A = 2b +M = 11 + +ModInv = c +A = 2c +M = 11 + +ModInv = e +A = 2d +M = 11 + +ModInv = a +A = 2e +M = 11 + +ModInv = 4 +A = 2f +M = 11 + +ModInv = b +A = 30 +M = 11 + +ModInv = 8 +A = 31 +M = 11 + +ModInv = 10 +A = 32 +M = 11 + +ModInv = 1 +A = 34 +M = 11 + +ModInv = 9 +A = 35 +M = 11 + +ModInv = 6 +A = 36 +M = 11 + +ModInv = d +A = 37 +M = 11 + +ModInv = 7 +A = 38 +M = 11 + +ModInv = 3 +A = 39 +M = 11 + +ModInv = 5 +A = 3a +M = 11 + +ModInv = f +A = 3b +M = 11 + +ModInv = 2 +A = 3c +M = 11 + +ModInv = c +A = 3d +M = 11 + +ModInv = e +A = 3e +M = 11 + +ModInv = a +A = 3f +M = 11 + +ModInv = 4 +A = 40 +M = 11 + +ModInv = b +A = 41 +M = 11 + +ModInv = 8 +A = 42 +M = 11 + +ModInv = 10 +A = 43 +M = 11 + +ModInv = 1 +A = 45 +M = 11 + +ModInv = 9 +A = 46 +M = 11 + +ModInv = 6 +A = 47 +M = 11 + +ModInv = d +A = 48 +M = 11 + +ModInv = 7 +A = 49 +M = 11 + +ModInv = 3 +A = 4a +M = 11 + +ModInv = 5 +A = 4b +M = 11 + +ModInv = f +A = 4c +M = 11 + +ModInv = 2 +A = 4d +M = 11 + +ModInv = c +A = 4e +M = 11 + +ModInv = e +A = 4f +M = 11 + +ModInv = a +A = 50 +M = 11 + +ModInv = 4 +A = 51 +M = 11 + +ModInv = b +A = 52 +M = 11 + +ModInv = 8 +A = 53 +M = 11 + +ModInv = 10 +A = 54 +M = 11 + +ModInv = 1 +A = 56 +M = 11 + +ModInv = 9 +A = 57 +M = 11 + +ModInv = 6 +A = 58 +M = 11 + +ModInv = d +A = 59 +M = 11 + +ModInv = 7 +A = 5a +M = 11 + +ModInv = 3 +A = 5b +M = 11 + +ModInv = 5 +A = 5c +M = 11 + +ModInv = f +A = 5d +M = 11 + +ModInv = 2 +A = 5e +M = 11 + +ModInv = c +A = 5f +M = 11 + +ModInv = e +A = 60 +M = 11 + +ModInv = a +A = 61 +M = 11 + +ModInv = 4 +A = 62 +M = 11 + +ModInv = b +A = 63 +M = 11 + +ModInv = 5 +A = -61 +M = 12 + +ModInv = 7 +A = -5f +M = 12 + +ModInv = 11 +A = -5b +M = 12 + +ModInv = 1 +A = -59 +M = 12 + +ModInv = b +A = -55 +M = 12 + +ModInv = d +A = -53 +M = 12 + +ModInv = 5 +A = -4f +M = 12 + +ModInv = 7 +A = -4d +M = 12 + +ModInv = 11 +A = -49 +M = 12 + +ModInv = 1 +A = -47 +M = 12 + +ModInv = b +A = -43 +M = 12 + +ModInv = d +A = -41 +M = 12 + +ModInv = 5 +A = -3d +M = 12 + +ModInv = 7 +A = -3b +M = 12 + +ModInv = 11 +A = -37 +M = 12 + +ModInv = 1 +A = -35 +M = 12 + +ModInv = b +A = -31 +M = 12 + +ModInv = d +A = -2f +M = 12 + +ModInv = 5 +A = -2b +M = 12 + +ModInv = 7 +A = -29 +M = 12 + +ModInv = 11 +A = -25 +M = 12 + +ModInv = 1 +A = -23 +M = 12 + +ModInv = b +A = -1f +M = 12 + +ModInv = d +A = -1d +M = 12 + +ModInv = 5 +A = -19 +M = 12 + +ModInv = 7 +A = -17 +M = 12 + +ModInv = 11 +A = -13 +M = 12 + +ModInv = 1 +A = -11 +M = 12 + +ModInv = b +A = -d +M = 12 + +ModInv = d +A = -b +M = 12 + +ModInv = 5 +A = -7 +M = 12 + +ModInv = 7 +A = -5 +M = 12 + +ModInv = 11 +A = -1 +M = 12 + +ModInv = 1 +A = 1 +M = 12 + +ModInv = b +A = 5 +M = 12 + +ModInv = d +A = 7 +M = 12 + +ModInv = 5 +A = b +M = 12 + +ModInv = 7 +A = d +M = 12 + +ModInv = 11 +A = 11 +M = 12 + +ModInv = 1 +A = 13 +M = 12 + +ModInv = b +A = 17 +M = 12 + +ModInv = d +A = 19 +M = 12 + +ModInv = 5 +A = 1d +M = 12 + +ModInv = 7 +A = 1f +M = 12 + +ModInv = 11 +A = 23 +M = 12 + +ModInv = 1 +A = 25 +M = 12 + +ModInv = b +A = 29 +M = 12 + +ModInv = d +A = 2b +M = 12 + +ModInv = 5 +A = 2f +M = 12 + +ModInv = 7 +A = 31 +M = 12 + +ModInv = 11 +A = 35 +M = 12 + +ModInv = 1 +A = 37 +M = 12 + +ModInv = b +A = 3b +M = 12 + +ModInv = d +A = 3d +M = 12 + +ModInv = 5 +A = 41 +M = 12 + +ModInv = 7 +A = 43 +M = 12 + +ModInv = 11 +A = 47 +M = 12 + +ModInv = 1 +A = 49 +M = 12 + +ModInv = b +A = 4d +M = 12 + +ModInv = d +A = 4f +M = 12 + +ModInv = 5 +A = 53 +M = 12 + +ModInv = 7 +A = 55 +M = 12 + +ModInv = 11 +A = 59 +M = 12 + +ModInv = 1 +A = 5b +M = 12 + +ModInv = b +A = 5f +M = 12 + +ModInv = d +A = 61 +M = 12 + +ModInv = f +A = -64 +M = 13 + +ModInv = e +A = -63 +M = 13 + +ModInv = 6 +A = -62 +M = 13 + +ModInv = 9 +A = -61 +M = 13 + +ModInv = 12 +A = -60 +M = 13 + +ModInv = 1 +A = -5e +M = 13 + +ModInv = a +A = -5d +M = 13 + +ModInv = d +A = -5c +M = 13 + +ModInv = 5 +A = -5b +M = 13 + +ModInv = 4 +A = -5a +M = 13 + +ModInv = 10 +A = -59 +M = 13 + +ModInv = b +A = -58 +M = 13 + +ModInv = c +A = -57 +M = 13 + +ModInv = 11 +A = -56 +M = 13 + +ModInv = 2 +A = -55 +M = 13 + +ModInv = 7 +A = -54 +M = 13 + +ModInv = 8 +A = -53 +M = 13 + +ModInv = 3 +A = -52 +M = 13 + +ModInv = f +A = -51 +M = 13 + +ModInv = e +A = -50 +M = 13 + +ModInv = 6 +A = -4f +M = 13 + +ModInv = 9 +A = -4e +M = 13 + +ModInv = 12 +A = -4d +M = 13 + +ModInv = 1 +A = -4b +M = 13 + +ModInv = a +A = -4a +M = 13 + +ModInv = d +A = -49 +M = 13 + +ModInv = 5 +A = -48 +M = 13 + +ModInv = 4 +A = -47 +M = 13 + +ModInv = 10 +A = -46 +M = 13 + +ModInv = b +A = -45 +M = 13 + +ModInv = c +A = -44 +M = 13 + +ModInv = 11 +A = -43 +M = 13 + +ModInv = 2 +A = -42 +M = 13 + +ModInv = 7 +A = -41 +M = 13 + +ModInv = 8 +A = -40 +M = 13 + +ModInv = 3 +A = -3f +M = 13 + +ModInv = f +A = -3e +M = 13 + +ModInv = e +A = -3d +M = 13 + +ModInv = 6 +A = -3c +M = 13 + +ModInv = 9 +A = -3b +M = 13 + +ModInv = 12 +A = -3a +M = 13 + +ModInv = 1 +A = -38 +M = 13 + +ModInv = a +A = -37 +M = 13 + +ModInv = d +A = -36 +M = 13 + +ModInv = 5 +A = -35 +M = 13 + +ModInv = 4 +A = -34 +M = 13 + +ModInv = 10 +A = -33 +M = 13 + +ModInv = b +A = -32 +M = 13 + +ModInv = c +A = -31 +M = 13 + +ModInv = 11 +A = -30 +M = 13 + +ModInv = 2 +A = -2f +M = 13 + +ModInv = 7 +A = -2e +M = 13 + +ModInv = 8 +A = -2d +M = 13 + +ModInv = 3 +A = -2c +M = 13 + +ModInv = f +A = -2b +M = 13 + +ModInv = e +A = -2a +M = 13 + +ModInv = 6 +A = -29 +M = 13 + +ModInv = 9 +A = -28 +M = 13 + +ModInv = 12 +A = -27 +M = 13 + +ModInv = 1 +A = -25 +M = 13 + +ModInv = a +A = -24 +M = 13 + +ModInv = d +A = -23 +M = 13 + +ModInv = 5 +A = -22 +M = 13 + +ModInv = 4 +A = -21 +M = 13 + +ModInv = 10 +A = -20 +M = 13 + +ModInv = b +A = -1f +M = 13 + +ModInv = c +A = -1e +M = 13 + +ModInv = 11 +A = -1d +M = 13 + +ModInv = 2 +A = -1c +M = 13 + +ModInv = 7 +A = -1b +M = 13 + +ModInv = 8 +A = -1a +M = 13 + +ModInv = 3 +A = -19 +M = 13 + +ModInv = f +A = -18 +M = 13 + +ModInv = e +A = -17 +M = 13 + +ModInv = 6 +A = -16 +M = 13 + +ModInv = 9 +A = -15 +M = 13 + +ModInv = 12 +A = -14 +M = 13 + +ModInv = 1 +A = -12 +M = 13 + +ModInv = a +A = -11 +M = 13 + +ModInv = d +A = -10 +M = 13 + +ModInv = 5 +A = -f +M = 13 + +ModInv = 4 +A = -e +M = 13 + +ModInv = 10 +A = -d +M = 13 + +ModInv = b +A = -c +M = 13 + +ModInv = c +A = -b +M = 13 + +ModInv = 11 +A = -a +M = 13 + +ModInv = 2 +A = -9 +M = 13 + +ModInv = 7 +A = -8 +M = 13 + +ModInv = 8 +A = -7 +M = 13 + +ModInv = 3 +A = -6 +M = 13 + +ModInv = f +A = -5 +M = 13 + +ModInv = e +A = -4 +M = 13 + +ModInv = 6 +A = -3 +M = 13 + +ModInv = 9 +A = -2 +M = 13 + +ModInv = 12 +A = -1 +M = 13 + +ModInv = 1 +A = 1 +M = 13 + +ModInv = a +A = 2 +M = 13 + +ModInv = d +A = 3 +M = 13 + +ModInv = 5 +A = 4 +M = 13 + +ModInv = 4 +A = 5 +M = 13 + +ModInv = 10 +A = 6 +M = 13 + +ModInv = b +A = 7 +M = 13 + +ModInv = c +A = 8 +M = 13 + +ModInv = 11 +A = 9 +M = 13 + +ModInv = 2 +A = a +M = 13 + +ModInv = 7 +A = b +M = 13 + +ModInv = 8 +A = c +M = 13 + +ModInv = 3 +A = d +M = 13 + +ModInv = f +A = e +M = 13 + +ModInv = e +A = f +M = 13 + +ModInv = 6 +A = 10 +M = 13 + +ModInv = 9 +A = 11 +M = 13 + +ModInv = 12 +A = 12 +M = 13 + +ModInv = 1 +A = 14 +M = 13 + +ModInv = a +A = 15 +M = 13 + +ModInv = d +A = 16 +M = 13 + +ModInv = 5 +A = 17 +M = 13 + +ModInv = 4 +A = 18 +M = 13 + +ModInv = 10 +A = 19 +M = 13 + +ModInv = b +A = 1a +M = 13 + +ModInv = c +A = 1b +M = 13 + +ModInv = 11 +A = 1c +M = 13 + +ModInv = 2 +A = 1d +M = 13 + +ModInv = 7 +A = 1e +M = 13 + +ModInv = 8 +A = 1f +M = 13 + +ModInv = 3 +A = 20 +M = 13 + +ModInv = f +A = 21 +M = 13 + +ModInv = e +A = 22 +M = 13 + +ModInv = 6 +A = 23 +M = 13 + +ModInv = 9 +A = 24 +M = 13 + +ModInv = 12 +A = 25 +M = 13 + +ModInv = 1 +A = 27 +M = 13 + +ModInv = a +A = 28 +M = 13 + +ModInv = d +A = 29 +M = 13 + +ModInv = 5 +A = 2a +M = 13 + +ModInv = 4 +A = 2b +M = 13 + +ModInv = 10 +A = 2c +M = 13 + +ModInv = b +A = 2d +M = 13 + +ModInv = c +A = 2e +M = 13 + +ModInv = 11 +A = 2f +M = 13 + +ModInv = 2 +A = 30 +M = 13 + +ModInv = 7 +A = 31 +M = 13 + +ModInv = 8 +A = 32 +M = 13 + +ModInv = 3 +A = 33 +M = 13 + +ModInv = f +A = 34 +M = 13 + +ModInv = e +A = 35 +M = 13 + +ModInv = 6 +A = 36 +M = 13 + +ModInv = 9 +A = 37 +M = 13 + +ModInv = 12 +A = 38 +M = 13 + +ModInv = 1 +A = 3a +M = 13 + +ModInv = a +A = 3b +M = 13 + +ModInv = d +A = 3c +M = 13 + +ModInv = 5 +A = 3d +M = 13 + +ModInv = 4 +A = 3e +M = 13 + +ModInv = 10 +A = 3f +M = 13 + +ModInv = b +A = 40 +M = 13 + +ModInv = c +A = 41 +M = 13 + +ModInv = 11 +A = 42 +M = 13 + +ModInv = 2 +A = 43 +M = 13 + +ModInv = 7 +A = 44 +M = 13 + +ModInv = 8 +A = 45 +M = 13 + +ModInv = 3 +A = 46 +M = 13 + +ModInv = f +A = 47 +M = 13 + +ModInv = e +A = 48 +M = 13 + +ModInv = 6 +A = 49 +M = 13 + +ModInv = 9 +A = 4a +M = 13 + +ModInv = 12 +A = 4b +M = 13 + +ModInv = 1 +A = 4d +M = 13 + +ModInv = a +A = 4e +M = 13 + +ModInv = d +A = 4f +M = 13 + +ModInv = 5 +A = 50 +M = 13 + +ModInv = 4 +A = 51 +M = 13 + +ModInv = 10 +A = 52 +M = 13 + +ModInv = b +A = 53 +M = 13 + +ModInv = c +A = 54 +M = 13 + +ModInv = 11 +A = 55 +M = 13 + +ModInv = 2 +A = 56 +M = 13 + +ModInv = 7 +A = 57 +M = 13 + +ModInv = 8 +A = 58 +M = 13 + +ModInv = 3 +A = 59 +M = 13 + +ModInv = f +A = 5a +M = 13 + +ModInv = e +A = 5b +M = 13 + +ModInv = 6 +A = 5c +M = 13 + +ModInv = 9 +A = 5d +M = 13 + +ModInv = 12 +A = 5e +M = 13 + +ModInv = 1 +A = 60 +M = 13 + +ModInv = a +A = 61 +M = 13 + +ModInv = d +A = 62 +M = 13 + +ModInv = 5 +A = 63 +M = 13 + +ModInv = 1 +A = -63 +M = 14 + +ModInv = 7 +A = -61 +M = 14 + +ModInv = 3 +A = -5d +M = 14 + +ModInv = 9 +A = -5b +M = 14 + +ModInv = b +A = -59 +M = 14 + +ModInv = 11 +A = -57 +M = 14 + +ModInv = d +A = -53 +M = 14 + +ModInv = 13 +A = -51 +M = 14 + +ModInv = 1 +A = -4f +M = 14 + +ModInv = 7 +A = -4d +M = 14 + +ModInv = 3 +A = -49 +M = 14 + +ModInv = 9 +A = -47 +M = 14 + +ModInv = b +A = -45 +M = 14 + +ModInv = 11 +A = -43 +M = 14 + +ModInv = d +A = -3f +M = 14 + +ModInv = 13 +A = -3d +M = 14 + +ModInv = 1 +A = -3b +M = 14 + +ModInv = 7 +A = -39 +M = 14 + +ModInv = 3 +A = -35 +M = 14 + +ModInv = 9 +A = -33 +M = 14 + +ModInv = b +A = -31 +M = 14 + +ModInv = 11 +A = -2f +M = 14 + +ModInv = d +A = -2b +M = 14 + +ModInv = 13 +A = -29 +M = 14 + +ModInv = 1 +A = -27 +M = 14 + +ModInv = 7 +A = -25 +M = 14 + +ModInv = 3 +A = -21 +M = 14 + +ModInv = 9 +A = -1f +M = 14 + +ModInv = b +A = -1d +M = 14 + +ModInv = 11 +A = -1b +M = 14 + +ModInv = d +A = -17 +M = 14 + +ModInv = 13 +A = -15 +M = 14 + +ModInv = 1 +A = -13 +M = 14 + +ModInv = 7 +A = -11 +M = 14 + +ModInv = 3 +A = -d +M = 14 + +ModInv = 9 +A = -b +M = 14 + +ModInv = b +A = -9 +M = 14 + +ModInv = 11 +A = -7 +M = 14 + +ModInv = d +A = -3 +M = 14 + +ModInv = 13 +A = -1 +M = 14 + +ModInv = 1 +A = 1 +M = 14 + +ModInv = 7 +A = 3 +M = 14 + +ModInv = 3 +A = 7 +M = 14 + +ModInv = 9 +A = 9 +M = 14 + +ModInv = b +A = b +M = 14 + +ModInv = 11 +A = d +M = 14 + +ModInv = d +A = 11 +M = 14 + +ModInv = 13 +A = 13 +M = 14 + +ModInv = 1 +A = 15 +M = 14 + +ModInv = 7 +A = 17 +M = 14 + +ModInv = 3 +A = 1b +M = 14 + +ModInv = 9 +A = 1d +M = 14 + +ModInv = b +A = 1f +M = 14 + +ModInv = 11 +A = 21 +M = 14 + +ModInv = d +A = 25 +M = 14 + +ModInv = 13 +A = 27 +M = 14 + +ModInv = 1 +A = 29 +M = 14 + +ModInv = 7 +A = 2b +M = 14 + +ModInv = 3 +A = 2f +M = 14 + +ModInv = 9 +A = 31 +M = 14 + +ModInv = b +A = 33 +M = 14 + +ModInv = 11 +A = 35 +M = 14 + +ModInv = d +A = 39 +M = 14 + +ModInv = 13 +A = 3b +M = 14 + +ModInv = 1 +A = 3d +M = 14 + +ModInv = 7 +A = 3f +M = 14 + +ModInv = 3 +A = 43 +M = 14 + +ModInv = 9 +A = 45 +M = 14 + +ModInv = b +A = 47 +M = 14 + +ModInv = 11 +A = 49 +M = 14 + +ModInv = d +A = 4d +M = 14 + +ModInv = 13 +A = 4f +M = 14 + +ModInv = 1 +A = 51 +M = 14 + +ModInv = 7 +A = 53 +M = 14 + +ModInv = 3 +A = 57 +M = 14 + +ModInv = 9 +A = 59 +M = 14 + +ModInv = b +A = 5b +M = 14 + +ModInv = 11 +A = 5d +M = 14 + +ModInv = d +A = 61 +M = 14 + +ModInv = 13 +A = 63 +M = 14 + +ModInv = 11 +A = -64 +M = 15 + +ModInv = 8 +A = -61 +M = 15 + +ModInv = 13 +A = -5f +M = 15 + +ModInv = 2 +A = -5e +M = 15 + +ModInv = d +A = -5c +M = 15 + +ModInv = 4 +A = -59 +M = 15 + +ModInv = 5 +A = -58 +M = 15 + +ModInv = a +A = -56 +M = 15 + +ModInv = 14 +A = -55 +M = 15 + +ModInv = 1 +A = -53 +M = 15 + +ModInv = b +A = -52 +M = 15 + +ModInv = 10 +A = -50 +M = 15 + +ModInv = 11 +A = -4f +M = 15 + +ModInv = 8 +A = -4c +M = 15 + +ModInv = 13 +A = -4a +M = 15 + +ModInv = 2 +A = -49 +M = 15 + +ModInv = d +A = -47 +M = 15 + +ModInv = 4 +A = -44 +M = 15 + +ModInv = 5 +A = -43 +M = 15 + +ModInv = a +A = -41 +M = 15 + +ModInv = 14 +A = -40 +M = 15 + +ModInv = 1 +A = -3e +M = 15 + +ModInv = b +A = -3d +M = 15 + +ModInv = 10 +A = -3b +M = 15 + +ModInv = 11 +A = -3a +M = 15 + +ModInv = 8 +A = -37 +M = 15 + +ModInv = 13 +A = -35 +M = 15 + +ModInv = 2 +A = -34 +M = 15 + +ModInv = d +A = -32 +M = 15 + +ModInv = 4 +A = -2f +M = 15 + +ModInv = 5 +A = -2e +M = 15 + +ModInv = a +A = -2c +M = 15 + +ModInv = 14 +A = -2b +M = 15 + +ModInv = 1 +A = -29 +M = 15 + +ModInv = b +A = -28 +M = 15 + +ModInv = 10 +A = -26 +M = 15 + +ModInv = 11 +A = -25 +M = 15 + +ModInv = 8 +A = -22 +M = 15 + +ModInv = 13 +A = -20 +M = 15 + +ModInv = 2 +A = -1f +M = 15 + +ModInv = d +A = -1d +M = 15 + +ModInv = 4 +A = -1a +M = 15 + +ModInv = 5 +A = -19 +M = 15 + +ModInv = a +A = -17 +M = 15 + +ModInv = 14 +A = -16 +M = 15 + +ModInv = 1 +A = -14 +M = 15 + +ModInv = b +A = -13 +M = 15 + +ModInv = 10 +A = -11 +M = 15 + +ModInv = 11 +A = -10 +M = 15 + +ModInv = 8 +A = -d +M = 15 + +ModInv = 13 +A = -b +M = 15 + +ModInv = 2 +A = -a +M = 15 + +ModInv = d +A = -8 +M = 15 + +ModInv = 4 +A = -5 +M = 15 + +ModInv = 5 +A = -4 +M = 15 + +ModInv = a +A = -2 +M = 15 + +ModInv = 14 +A = -1 +M = 15 + +ModInv = 1 +A = 1 +M = 15 + +ModInv = b +A = 2 +M = 15 + +ModInv = 10 +A = 4 +M = 15 + +ModInv = 11 +A = 5 +M = 15 + +ModInv = 8 +A = 8 +M = 15 + +ModInv = 13 +A = a +M = 15 + +ModInv = 2 +A = b +M = 15 + +ModInv = d +A = d +M = 15 + +ModInv = 4 +A = 10 +M = 15 + +ModInv = 5 +A = 11 +M = 15 + +ModInv = a +A = 13 +M = 15 + +ModInv = 14 +A = 14 +M = 15 + +ModInv = 1 +A = 16 +M = 15 + +ModInv = b +A = 17 +M = 15 + +ModInv = 10 +A = 19 +M = 15 + +ModInv = 11 +A = 1a +M = 15 + +ModInv = 8 +A = 1d +M = 15 + +ModInv = 13 +A = 1f +M = 15 + +ModInv = 2 +A = 20 +M = 15 + +ModInv = d +A = 22 +M = 15 + +ModInv = 4 +A = 25 +M = 15 + +ModInv = 5 +A = 26 +M = 15 + +ModInv = a +A = 28 +M = 15 + +ModInv = 14 +A = 29 +M = 15 + +ModInv = 1 +A = 2b +M = 15 + +ModInv = b +A = 2c +M = 15 + +ModInv = 10 +A = 2e +M = 15 + +ModInv = 11 +A = 2f +M = 15 + +ModInv = 8 +A = 32 +M = 15 + +ModInv = 13 +A = 34 +M = 15 + +ModInv = 2 +A = 35 +M = 15 + +ModInv = d +A = 37 +M = 15 + +ModInv = 4 +A = 3a +M = 15 + +ModInv = 5 +A = 3b +M = 15 + +ModInv = a +A = 3d +M = 15 + +ModInv = 14 +A = 3e +M = 15 + +ModInv = 1 +A = 40 +M = 15 + +ModInv = b +A = 41 +M = 15 + +ModInv = 10 +A = 43 +M = 15 + +ModInv = 11 +A = 44 +M = 15 + +ModInv = 8 +A = 47 +M = 15 + +ModInv = 13 +A = 49 +M = 15 + +ModInv = 2 +A = 4a +M = 15 + +ModInv = d +A = 4c +M = 15 + +ModInv = 4 +A = 4f +M = 15 + +ModInv = 5 +A = 50 +M = 15 + +ModInv = a +A = 52 +M = 15 + +ModInv = 14 +A = 53 +M = 15 + +ModInv = 1 +A = 55 +M = 15 + +ModInv = b +A = 56 +M = 15 + +ModInv = 10 +A = 58 +M = 15 + +ModInv = 11 +A = 59 +M = 15 + +ModInv = 8 +A = 5c +M = 15 + +ModInv = 13 +A = 5e +M = 15 + +ModInv = 2 +A = 5f +M = 15 + +ModInv = d +A = 61 +M = 15 + +ModInv = 11 +A = -61 +M = 16 + +ModInv = 3 +A = -5f +M = 16 + +ModInv = d +A = -5d +M = 16 + +ModInv = 7 +A = -5b +M = 16 + +ModInv = 15 +A = -59 +M = 16 + +ModInv = 1 +A = -57 +M = 16 + +ModInv = f +A = -55 +M = 16 + +ModInv = 9 +A = -53 +M = 16 + +ModInv = 13 +A = -51 +M = 16 + +ModInv = 5 +A = -4f +M = 16 + +ModInv = 11 +A = -4b +M = 16 + +ModInv = 3 +A = -49 +M = 16 + +ModInv = d +A = -47 +M = 16 + +ModInv = 7 +A = -45 +M = 16 + +ModInv = 15 +A = -43 +M = 16 + +ModInv = 1 +A = -41 +M = 16 + +ModInv = f +A = -3f +M = 16 + +ModInv = 9 +A = -3d +M = 16 + +ModInv = 13 +A = -3b +M = 16 + +ModInv = 5 +A = -39 +M = 16 + +ModInv = 11 +A = -35 +M = 16 + +ModInv = 3 +A = -33 +M = 16 + +ModInv = d +A = -31 +M = 16 + +ModInv = 7 +A = -2f +M = 16 + +ModInv = 15 +A = -2d +M = 16 + +ModInv = 1 +A = -2b +M = 16 + +ModInv = f +A = -29 +M = 16 + +ModInv = 9 +A = -27 +M = 16 + +ModInv = 13 +A = -25 +M = 16 + +ModInv = 5 +A = -23 +M = 16 + +ModInv = 11 +A = -1f +M = 16 + +ModInv = 3 +A = -1d +M = 16 + +ModInv = d +A = -1b +M = 16 + +ModInv = 7 +A = -19 +M = 16 + +ModInv = 15 +A = -17 +M = 16 + +ModInv = 1 +A = -15 +M = 16 + +ModInv = f +A = -13 +M = 16 + +ModInv = 9 +A = -11 +M = 16 + +ModInv = 13 +A = -f +M = 16 + +ModInv = 5 +A = -d +M = 16 + +ModInv = 11 +A = -9 +M = 16 + +ModInv = 3 +A = -7 +M = 16 + +ModInv = d +A = -5 +M = 16 + +ModInv = 7 +A = -3 +M = 16 + +ModInv = 15 +A = -1 +M = 16 + +ModInv = 1 +A = 1 +M = 16 + +ModInv = f +A = 3 +M = 16 + +ModInv = 9 +A = 5 +M = 16 + +ModInv = 13 +A = 7 +M = 16 + +ModInv = 5 +A = 9 +M = 16 + +ModInv = 11 +A = d +M = 16 + +ModInv = 3 +A = f +M = 16 + +ModInv = d +A = 11 +M = 16 + +ModInv = 7 +A = 13 +M = 16 + +ModInv = 15 +A = 15 +M = 16 + +ModInv = 1 +A = 17 +M = 16 + +ModInv = f +A = 19 +M = 16 + +ModInv = 9 +A = 1b +M = 16 + +ModInv = 13 +A = 1d +M = 16 + +ModInv = 5 +A = 1f +M = 16 + +ModInv = 11 +A = 23 +M = 16 + +ModInv = 3 +A = 25 +M = 16 + +ModInv = d +A = 27 +M = 16 + +ModInv = 7 +A = 29 +M = 16 + +ModInv = 15 +A = 2b +M = 16 + +ModInv = 1 +A = 2d +M = 16 + +ModInv = f +A = 2f +M = 16 + +ModInv = 9 +A = 31 +M = 16 + +ModInv = 13 +A = 33 +M = 16 + +ModInv = 5 +A = 35 +M = 16 + +ModInv = 11 +A = 39 +M = 16 + +ModInv = 3 +A = 3b +M = 16 + +ModInv = d +A = 3d +M = 16 + +ModInv = 7 +A = 3f +M = 16 + +ModInv = 15 +A = 41 +M = 16 + +ModInv = 1 +A = 43 +M = 16 + +ModInv = f +A = 45 +M = 16 + +ModInv = 9 +A = 47 +M = 16 + +ModInv = 13 +A = 49 +M = 16 + +ModInv = 5 +A = 4b +M = 16 + +ModInv = 11 +A = 4f +M = 16 + +ModInv = 3 +A = 51 +M = 16 + +ModInv = d +A = 53 +M = 16 + +ModInv = 7 +A = 55 +M = 16 + +ModInv = 15 +A = 57 +M = 16 + +ModInv = 1 +A = 59 +M = 16 + +ModInv = f +A = 5b +M = 16 + +ModInv = 9 +A = 5d +M = 16 + +ModInv = 13 +A = 5f +M = 16 + +ModInv = 5 +A = 61 +M = 16 + +ModInv = 14 +A = -64 +M = 17 + +ModInv = d +A = -63 +M = 17 + +ModInv = 13 +A = -62 +M = 17 + +ModInv = 9 +A = -61 +M = 17 + +ModInv = 11 +A = -60 +M = 17 + +ModInv = f +A = -5f +M = 17 + +ModInv = b +A = -5e +M = 17 + +ModInv = 16 +A = -5d +M = 17 + +ModInv = 1 +A = -5b +M = 17 + +ModInv = c +A = -5a +M = 17 + +ModInv = 8 +A = -59 +M = 17 + +ModInv = 6 +A = -58 +M = 17 + +ModInv = e +A = -57 +M = 17 + +ModInv = 4 +A = -56 +M = 17 + +ModInv = a +A = -55 +M = 17 + +ModInv = 3 +A = -54 +M = 17 + +ModInv = 12 +A = -53 +M = 17 + +ModInv = 7 +A = -52 +M = 17 + +ModInv = 15 +A = -51 +M = 17 + +ModInv = 2 +A = -50 +M = 17 + +ModInv = 10 +A = -4f +M = 17 + +ModInv = 5 +A = -4e +M = 17 + +ModInv = 14 +A = -4d +M = 17 + +ModInv = d +A = -4c +M = 17 + +ModInv = 13 +A = -4b +M = 17 + +ModInv = 9 +A = -4a +M = 17 + +ModInv = 11 +A = -49 +M = 17 + +ModInv = f +A = -48 +M = 17 + +ModInv = b +A = -47 +M = 17 + +ModInv = 16 +A = -46 +M = 17 + +ModInv = 1 +A = -44 +M = 17 + +ModInv = c +A = -43 +M = 17 + +ModInv = 8 +A = -42 +M = 17 + +ModInv = 6 +A = -41 +M = 17 + +ModInv = e +A = -40 +M = 17 + +ModInv = 4 +A = -3f +M = 17 + +ModInv = a +A = -3e +M = 17 + +ModInv = 3 +A = -3d +M = 17 + +ModInv = 12 +A = -3c +M = 17 + +ModInv = 7 +A = -3b +M = 17 + +ModInv = 15 +A = -3a +M = 17 + +ModInv = 2 +A = -39 +M = 17 + +ModInv = 10 +A = -38 +M = 17 + +ModInv = 5 +A = -37 +M = 17 + +ModInv = 14 +A = -36 +M = 17 + +ModInv = d +A = -35 +M = 17 + +ModInv = 13 +A = -34 +M = 17 + +ModInv = 9 +A = -33 +M = 17 + +ModInv = 11 +A = -32 +M = 17 + +ModInv = f +A = -31 +M = 17 + +ModInv = b +A = -30 +M = 17 + +ModInv = 16 +A = -2f +M = 17 + +ModInv = 1 +A = -2d +M = 17 + +ModInv = c +A = -2c +M = 17 + +ModInv = 8 +A = -2b +M = 17 + +ModInv = 6 +A = -2a +M = 17 + +ModInv = e +A = -29 +M = 17 + +ModInv = 4 +A = -28 +M = 17 + +ModInv = a +A = -27 +M = 17 + +ModInv = 3 +A = -26 +M = 17 + +ModInv = 12 +A = -25 +M = 17 + +ModInv = 7 +A = -24 +M = 17 + +ModInv = 15 +A = -23 +M = 17 + +ModInv = 2 +A = -22 +M = 17 + +ModInv = 10 +A = -21 +M = 17 + +ModInv = 5 +A = -20 +M = 17 + +ModInv = 14 +A = -1f +M = 17 + +ModInv = d +A = -1e +M = 17 + +ModInv = 13 +A = -1d +M = 17 + +ModInv = 9 +A = -1c +M = 17 + +ModInv = 11 +A = -1b +M = 17 + +ModInv = f +A = -1a +M = 17 + +ModInv = b +A = -19 +M = 17 + +ModInv = 16 +A = -18 +M = 17 + +ModInv = 1 +A = -16 +M = 17 + +ModInv = c +A = -15 +M = 17 + +ModInv = 8 +A = -14 +M = 17 + +ModInv = 6 +A = -13 +M = 17 + +ModInv = e +A = -12 +M = 17 + +ModInv = 4 +A = -11 +M = 17 + +ModInv = a +A = -10 +M = 17 + +ModInv = 3 +A = -f +M = 17 + +ModInv = 12 +A = -e +M = 17 + +ModInv = 7 +A = -d +M = 17 + +ModInv = 15 +A = -c +M = 17 + +ModInv = 2 +A = -b +M = 17 + +ModInv = 10 +A = -a +M = 17 + +ModInv = 5 +A = -9 +M = 17 + +ModInv = 14 +A = -8 +M = 17 + +ModInv = d +A = -7 +M = 17 + +ModInv = 13 +A = -6 +M = 17 + +ModInv = 9 +A = -5 +M = 17 + +ModInv = 11 +A = -4 +M = 17 + +ModInv = f +A = -3 +M = 17 + +ModInv = b +A = -2 +M = 17 + +ModInv = 16 +A = -1 +M = 17 + +ModInv = 1 +A = 1 +M = 17 + +ModInv = c +A = 2 +M = 17 + +ModInv = 8 +A = 3 +M = 17 + +ModInv = 6 +A = 4 +M = 17 + +ModInv = e +A = 5 +M = 17 + +ModInv = 4 +A = 6 +M = 17 + +ModInv = a +A = 7 +M = 17 + +ModInv = 3 +A = 8 +M = 17 + +ModInv = 12 +A = 9 +M = 17 + +ModInv = 7 +A = a +M = 17 + +ModInv = 15 +A = b +M = 17 + +ModInv = 2 +A = c +M = 17 + +ModInv = 10 +A = d +M = 17 + +ModInv = 5 +A = e +M = 17 + +ModInv = 14 +A = f +M = 17 + +ModInv = d +A = 10 +M = 17 + +ModInv = 13 +A = 11 +M = 17 + +ModInv = 9 +A = 12 +M = 17 + +ModInv = 11 +A = 13 +M = 17 + +ModInv = f +A = 14 +M = 17 + +ModInv = b +A = 15 +M = 17 + +ModInv = 16 +A = 16 +M = 17 + +ModInv = 1 +A = 18 +M = 17 + +ModInv = c +A = 19 +M = 17 + +ModInv = 8 +A = 1a +M = 17 + +ModInv = 6 +A = 1b +M = 17 + +ModInv = e +A = 1c +M = 17 + +ModInv = 4 +A = 1d +M = 17 + +ModInv = a +A = 1e +M = 17 + +ModInv = 3 +A = 1f +M = 17 + +ModInv = 12 +A = 20 +M = 17 + +ModInv = 7 +A = 21 +M = 17 + +ModInv = 15 +A = 22 +M = 17 + +ModInv = 2 +A = 23 +M = 17 + +ModInv = 10 +A = 24 +M = 17 + +ModInv = 5 +A = 25 +M = 17 + +ModInv = 14 +A = 26 +M = 17 + +ModInv = d +A = 27 +M = 17 + +ModInv = 13 +A = 28 +M = 17 + +ModInv = 9 +A = 29 +M = 17 + +ModInv = 11 +A = 2a +M = 17 + +ModInv = f +A = 2b +M = 17 + +ModInv = b +A = 2c +M = 17 + +ModInv = 16 +A = 2d +M = 17 + +ModInv = 1 +A = 2f +M = 17 + +ModInv = c +A = 30 +M = 17 + +ModInv = 8 +A = 31 +M = 17 + +ModInv = 6 +A = 32 +M = 17 + +ModInv = e +A = 33 +M = 17 + +ModInv = 4 +A = 34 +M = 17 + +ModInv = a +A = 35 +M = 17 + +ModInv = 3 +A = 36 +M = 17 + +ModInv = 12 +A = 37 +M = 17 + +ModInv = 7 +A = 38 +M = 17 + +ModInv = 15 +A = 39 +M = 17 + +ModInv = 2 +A = 3a +M = 17 + +ModInv = 10 +A = 3b +M = 17 + +ModInv = 5 +A = 3c +M = 17 + +ModInv = 14 +A = 3d +M = 17 + +ModInv = d +A = 3e +M = 17 + +ModInv = 13 +A = 3f +M = 17 + +ModInv = 9 +A = 40 +M = 17 + +ModInv = 11 +A = 41 +M = 17 + +ModInv = f +A = 42 +M = 17 + +ModInv = b +A = 43 +M = 17 + +ModInv = 16 +A = 44 +M = 17 + +ModInv = 1 +A = 46 +M = 17 + +ModInv = c +A = 47 +M = 17 + +ModInv = 8 +A = 48 +M = 17 + +ModInv = 6 +A = 49 +M = 17 + +ModInv = e +A = 4a +M = 17 + +ModInv = 4 +A = 4b +M = 17 + +ModInv = a +A = 4c +M = 17 + +ModInv = 3 +A = 4d +M = 17 + +ModInv = 12 +A = 4e +M = 17 + +ModInv = 7 +A = 4f +M = 17 + +ModInv = 15 +A = 50 +M = 17 + +ModInv = 2 +A = 51 +M = 17 + +ModInv = 10 +A = 52 +M = 17 + +ModInv = 5 +A = 53 +M = 17 + +ModInv = 14 +A = 54 +M = 17 + +ModInv = d +A = 55 +M = 17 + +ModInv = 13 +A = 56 +M = 17 + +ModInv = 9 +A = 57 +M = 17 + +ModInv = 11 +A = 58 +M = 17 + +ModInv = f +A = 59 +M = 17 + +ModInv = b +A = 5a +M = 17 + +ModInv = 16 +A = 5b +M = 17 + +ModInv = 1 +A = 5d +M = 17 + +ModInv = c +A = 5e +M = 17 + +ModInv = 8 +A = 5f +M = 17 + +ModInv = 6 +A = 60 +M = 17 + +ModInv = e +A = 61 +M = 17 + +ModInv = 4 +A = 62 +M = 17 + +ModInv = a +A = 63 +M = 17 + +ModInv = 17 +A = -61 +M = 18 + +ModInv = 1 +A = -5f +M = 18 + +ModInv = 5 +A = -5b +M = 18 + +ModInv = 7 +A = -59 +M = 18 + +ModInv = b +A = -55 +M = 18 + +ModInv = d +A = -53 +M = 18 + +ModInv = 11 +A = -4f +M = 18 + +ModInv = 13 +A = -4d +M = 18 + +ModInv = 17 +A = -49 +M = 18 + +ModInv = 1 +A = -47 +M = 18 + +ModInv = 5 +A = -43 +M = 18 + +ModInv = 7 +A = -41 +M = 18 + +ModInv = b +A = -3d +M = 18 + +ModInv = d +A = -3b +M = 18 + +ModInv = 11 +A = -37 +M = 18 + +ModInv = 13 +A = -35 +M = 18 + +ModInv = 17 +A = -31 +M = 18 + +ModInv = 1 +A = -2f +M = 18 + +ModInv = 5 +A = -2b +M = 18 + +ModInv = 7 +A = -29 +M = 18 + +ModInv = b +A = -25 +M = 18 + +ModInv = d +A = -23 +M = 18 + +ModInv = 11 +A = -1f +M = 18 + +ModInv = 13 +A = -1d +M = 18 + +ModInv = 17 +A = -19 +M = 18 + +ModInv = 1 +A = -17 +M = 18 + +ModInv = 5 +A = -13 +M = 18 + +ModInv = 7 +A = -11 +M = 18 + +ModInv = b +A = -d +M = 18 + +ModInv = d +A = -b +M = 18 + +ModInv = 11 +A = -7 +M = 18 + +ModInv = 13 +A = -5 +M = 18 + +ModInv = 17 +A = -1 +M = 18 + +ModInv = 1 +A = 1 +M = 18 + +ModInv = 5 +A = 5 +M = 18 + +ModInv = 7 +A = 7 +M = 18 + +ModInv = b +A = b +M = 18 + +ModInv = d +A = d +M = 18 + +ModInv = 11 +A = 11 +M = 18 + +ModInv = 13 +A = 13 +M = 18 + +ModInv = 17 +A = 17 +M = 18 + +ModInv = 1 +A = 19 +M = 18 + +ModInv = 5 +A = 1d +M = 18 + +ModInv = 7 +A = 1f +M = 18 + +ModInv = b +A = 23 +M = 18 + +ModInv = d +A = 25 +M = 18 + +ModInv = 11 +A = 29 +M = 18 + +ModInv = 13 +A = 2b +M = 18 + +ModInv = 17 +A = 2f +M = 18 + +ModInv = 1 +A = 31 +M = 18 + +ModInv = 5 +A = 35 +M = 18 + +ModInv = 7 +A = 37 +M = 18 + +ModInv = b +A = 3b +M = 18 + +ModInv = d +A = 3d +M = 18 + +ModInv = 11 +A = 41 +M = 18 + +ModInv = 13 +A = 43 +M = 18 + +ModInv = 17 +A = 47 +M = 18 + +ModInv = 1 +A = 49 +M = 18 + +ModInv = 5 +A = 4d +M = 18 + +ModInv = 7 +A = 4f +M = 18 + +ModInv = b +A = 53 +M = 18 + +ModInv = d +A = 55 +M = 18 + +ModInv = 11 +A = 59 +M = 18 + +ModInv = 13 +A = 5b +M = 18 + +ModInv = 17 +A = 5f +M = 18 + +ModInv = 1 +A = 61 +M = 18 + +ModInv = 1 +A = -63 +M = 19 + +ModInv = d +A = -62 +M = 19 + +ModInv = 11 +A = -61 +M = 19 + +ModInv = 13 +A = -60 +M = 19 + +ModInv = 15 +A = -5e +M = 19 + +ModInv = 12 +A = -5d +M = 19 + +ModInv = 16 +A = -5c +M = 19 + +ModInv = e +A = -5b +M = 19 + +ModInv = 10 +A = -59 +M = 19 + +ModInv = 17 +A = -58 +M = 19 + +ModInv = 2 +A = -57 +M = 19 + +ModInv = 9 +A = -56 +M = 19 + +ModInv = b +A = -54 +M = 19 + +ModInv = 3 +A = -53 +M = 19 + +ModInv = 7 +A = -52 +M = 19 + +ModInv = 4 +A = -51 +M = 19 + +ModInv = 6 +A = -4f +M = 19 + +ModInv = 8 +A = -4e +M = 19 + +ModInv = c +A = -4d +M = 19 + +ModInv = 18 +A = -4c +M = 19 + +ModInv = 1 +A = -4a +M = 19 + +ModInv = d +A = -49 +M = 19 + +ModInv = 11 +A = -48 +M = 19 + +ModInv = 13 +A = -47 +M = 19 + +ModInv = 15 +A = -45 +M = 19 + +ModInv = 12 +A = -44 +M = 19 + +ModInv = 16 +A = -43 +M = 19 + +ModInv = e +A = -42 +M = 19 + +ModInv = 10 +A = -40 +M = 19 + +ModInv = 17 +A = -3f +M = 19 + +ModInv = 2 +A = -3e +M = 19 + +ModInv = 9 +A = -3d +M = 19 + +ModInv = b +A = -3b +M = 19 + +ModInv = 3 +A = -3a +M = 19 + +ModInv = 7 +A = -39 +M = 19 + +ModInv = 4 +A = -38 +M = 19 + +ModInv = 6 +A = -36 +M = 19 + +ModInv = 8 +A = -35 +M = 19 + +ModInv = c +A = -34 +M = 19 + +ModInv = 18 +A = -33 +M = 19 + +ModInv = 1 +A = -31 +M = 19 + +ModInv = d +A = -30 +M = 19 + +ModInv = 11 +A = -2f +M = 19 + +ModInv = 13 +A = -2e +M = 19 + +ModInv = 15 +A = -2c +M = 19 + +ModInv = 12 +A = -2b +M = 19 + +ModInv = 16 +A = -2a +M = 19 + +ModInv = e +A = -29 +M = 19 + +ModInv = 10 +A = -27 +M = 19 + +ModInv = 17 +A = -26 +M = 19 + +ModInv = 2 +A = -25 +M = 19 + +ModInv = 9 +A = -24 +M = 19 + +ModInv = b +A = -22 +M = 19 + +ModInv = 3 +A = -21 +M = 19 + +ModInv = 7 +A = -20 +M = 19 + +ModInv = 4 +A = -1f +M = 19 + +ModInv = 6 +A = -1d +M = 19 + +ModInv = 8 +A = -1c +M = 19 + +ModInv = c +A = -1b +M = 19 + +ModInv = 18 +A = -1a +M = 19 + +ModInv = 1 +A = -18 +M = 19 + +ModInv = d +A = -17 +M = 19 + +ModInv = 11 +A = -16 +M = 19 + +ModInv = 13 +A = -15 +M = 19 + +ModInv = 15 +A = -13 +M = 19 + +ModInv = 12 +A = -12 +M = 19 + +ModInv = 16 +A = -11 +M = 19 + +ModInv = e +A = -10 +M = 19 + +ModInv = 10 +A = -e +M = 19 + +ModInv = 17 +A = -d +M = 19 + +ModInv = 2 +A = -c +M = 19 + +ModInv = 9 +A = -b +M = 19 + +ModInv = b +A = -9 +M = 19 + +ModInv = 3 +A = -8 +M = 19 + +ModInv = 7 +A = -7 +M = 19 + +ModInv = 4 +A = -6 +M = 19 + +ModInv = 6 +A = -4 +M = 19 + +ModInv = 8 +A = -3 +M = 19 + +ModInv = c +A = -2 +M = 19 + +ModInv = 18 +A = -1 +M = 19 + +ModInv = 1 +A = 1 +M = 19 + +ModInv = d +A = 2 +M = 19 + +ModInv = 11 +A = 3 +M = 19 + +ModInv = 13 +A = 4 +M = 19 + +ModInv = 15 +A = 6 +M = 19 + +ModInv = 12 +A = 7 +M = 19 + +ModInv = 16 +A = 8 +M = 19 + +ModInv = e +A = 9 +M = 19 + +ModInv = 10 +A = b +M = 19 + +ModInv = 17 +A = c +M = 19 + +ModInv = 2 +A = d +M = 19 + +ModInv = 9 +A = e +M = 19 + +ModInv = b +A = 10 +M = 19 + +ModInv = 3 +A = 11 +M = 19 + +ModInv = 7 +A = 12 +M = 19 + +ModInv = 4 +A = 13 +M = 19 + +ModInv = 6 +A = 15 +M = 19 + +ModInv = 8 +A = 16 +M = 19 + +ModInv = c +A = 17 +M = 19 + +ModInv = 18 +A = 18 +M = 19 + +ModInv = 1 +A = 1a +M = 19 + +ModInv = d +A = 1b +M = 19 + +ModInv = 11 +A = 1c +M = 19 + +ModInv = 13 +A = 1d +M = 19 + +ModInv = 15 +A = 1f +M = 19 + +ModInv = 12 +A = 20 +M = 19 + +ModInv = 16 +A = 21 +M = 19 + +ModInv = e +A = 22 +M = 19 + +ModInv = 10 +A = 24 +M = 19 + +ModInv = 17 +A = 25 +M = 19 + +ModInv = 2 +A = 26 +M = 19 + +ModInv = 9 +A = 27 +M = 19 + +ModInv = b +A = 29 +M = 19 + +ModInv = 3 +A = 2a +M = 19 + +ModInv = 7 +A = 2b +M = 19 + +ModInv = 4 +A = 2c +M = 19 + +ModInv = 6 +A = 2e +M = 19 + +ModInv = 8 +A = 2f +M = 19 + +ModInv = c +A = 30 +M = 19 + +ModInv = 18 +A = 31 +M = 19 + +ModInv = 1 +A = 33 +M = 19 + +ModInv = d +A = 34 +M = 19 + +ModInv = 11 +A = 35 +M = 19 + +ModInv = 13 +A = 36 +M = 19 + +ModInv = 15 +A = 38 +M = 19 + +ModInv = 12 +A = 39 +M = 19 + +ModInv = 16 +A = 3a +M = 19 + +ModInv = e +A = 3b +M = 19 + +ModInv = 10 +A = 3d +M = 19 + +ModInv = 17 +A = 3e +M = 19 + +ModInv = 2 +A = 3f +M = 19 + +ModInv = 9 +A = 40 +M = 19 + +ModInv = b +A = 42 +M = 19 + +ModInv = 3 +A = 43 +M = 19 + +ModInv = 7 +A = 44 +M = 19 + +ModInv = 4 +A = 45 +M = 19 + +ModInv = 6 +A = 47 +M = 19 + +ModInv = 8 +A = 48 +M = 19 + +ModInv = c +A = 49 +M = 19 + +ModInv = 18 +A = 4a +M = 19 + +ModInv = 1 +A = 4c +M = 19 + +ModInv = d +A = 4d +M = 19 + +ModInv = 11 +A = 4e +M = 19 + +ModInv = 13 +A = 4f +M = 19 + +ModInv = 15 +A = 51 +M = 19 + +ModInv = 12 +A = 52 +M = 19 + +ModInv = 16 +A = 53 +M = 19 + +ModInv = e +A = 54 +M = 19 + +ModInv = 10 +A = 56 +M = 19 + +ModInv = 17 +A = 57 +M = 19 + +ModInv = 2 +A = 58 +M = 19 + +ModInv = 9 +A = 59 +M = 19 + +ModInv = b +A = 5b +M = 19 + +ModInv = 3 +A = 5c +M = 19 + +ModInv = 7 +A = 5d +M = 19 + +ModInv = 4 +A = 5e +M = 19 + +ModInv = 6 +A = 60 +M = 19 + +ModInv = 8 +A = 61 +M = 19 + +ModInv = c +A = 62 +M = 19 + +ModInv = 18 +A = 63 +M = 19 + +ModInv = 15 +A = -63 +M = 1a + +ModInv = f +A = -61 +M = 1a + +ModInv = 3 +A = -5f +M = 1a + +ModInv = 13 +A = -5d +M = 1a + +ModInv = 7 +A = -59 +M = 1a + +ModInv = 17 +A = -57 +M = 1a + +ModInv = b +A = -55 +M = 1a + +ModInv = 5 +A = -53 +M = 1a + +ModInv = 11 +A = -51 +M = 1a + +ModInv = 19 +A = -4f +M = 1a + +ModInv = 1 +A = -4d +M = 1a + +ModInv = 9 +A = -4b +M = 1a + +ModInv = 15 +A = -49 +M = 1a + +ModInv = f +A = -47 +M = 1a + +ModInv = 3 +A = -45 +M = 1a + +ModInv = 13 +A = -43 +M = 1a + +ModInv = 7 +A = -3f +M = 1a + +ModInv = 17 +A = -3d +M = 1a + +ModInv = b +A = -3b +M = 1a + +ModInv = 5 +A = -39 +M = 1a + +ModInv = 11 +A = -37 +M = 1a + +ModInv = 19 +A = -35 +M = 1a + +ModInv = 1 +A = -33 +M = 1a + +ModInv = 9 +A = -31 +M = 1a + +ModInv = 15 +A = -2f +M = 1a + +ModInv = f +A = -2d +M = 1a + +ModInv = 3 +A = -2b +M = 1a + +ModInv = 13 +A = -29 +M = 1a + +ModInv = 7 +A = -25 +M = 1a + +ModInv = 17 +A = -23 +M = 1a + +ModInv = b +A = -21 +M = 1a + +ModInv = 5 +A = -1f +M = 1a + +ModInv = 11 +A = -1d +M = 1a + +ModInv = 19 +A = -1b +M = 1a + +ModInv = 1 +A = -19 +M = 1a + +ModInv = 9 +A = -17 +M = 1a + +ModInv = 15 +A = -15 +M = 1a + +ModInv = f +A = -13 +M = 1a + +ModInv = 3 +A = -11 +M = 1a + +ModInv = 13 +A = -f +M = 1a + +ModInv = 7 +A = -b +M = 1a + +ModInv = 17 +A = -9 +M = 1a + +ModInv = b +A = -7 +M = 1a + +ModInv = 5 +A = -5 +M = 1a + +ModInv = 11 +A = -3 +M = 1a + +ModInv = 19 +A = -1 +M = 1a + +ModInv = 1 +A = 1 +M = 1a + +ModInv = 9 +A = 3 +M = 1a + +ModInv = 15 +A = 5 +M = 1a + +ModInv = f +A = 7 +M = 1a + +ModInv = 3 +A = 9 +M = 1a + +ModInv = 13 +A = b +M = 1a + +ModInv = 7 +A = f +M = 1a + +ModInv = 17 +A = 11 +M = 1a + +ModInv = b +A = 13 +M = 1a + +ModInv = 5 +A = 15 +M = 1a + +ModInv = 11 +A = 17 +M = 1a + +ModInv = 19 +A = 19 +M = 1a + +ModInv = 1 +A = 1b +M = 1a + +ModInv = 9 +A = 1d +M = 1a + +ModInv = 15 +A = 1f +M = 1a + +ModInv = f +A = 21 +M = 1a + +ModInv = 3 +A = 23 +M = 1a + +ModInv = 13 +A = 25 +M = 1a + +ModInv = 7 +A = 29 +M = 1a + +ModInv = 17 +A = 2b +M = 1a + +ModInv = b +A = 2d +M = 1a + +ModInv = 5 +A = 2f +M = 1a + +ModInv = 11 +A = 31 +M = 1a + +ModInv = 19 +A = 33 +M = 1a + +ModInv = 1 +A = 35 +M = 1a + +ModInv = 9 +A = 37 +M = 1a + +ModInv = 15 +A = 39 +M = 1a + +ModInv = f +A = 3b +M = 1a + +ModInv = 3 +A = 3d +M = 1a + +ModInv = 13 +A = 3f +M = 1a + +ModInv = 7 +A = 43 +M = 1a + +ModInv = 17 +A = 45 +M = 1a + +ModInv = b +A = 47 +M = 1a + +ModInv = 5 +A = 49 +M = 1a + +ModInv = 11 +A = 4b +M = 1a + +ModInv = 19 +A = 4d +M = 1a + +ModInv = 1 +A = 4f +M = 1a + +ModInv = 9 +A = 51 +M = 1a + +ModInv = 15 +A = 53 +M = 1a + +ModInv = f +A = 55 +M = 1a + +ModInv = 3 +A = 57 +M = 1a + +ModInv = 13 +A = 59 +M = 1a + +ModInv = 7 +A = 5d +M = 1a + +ModInv = 17 +A = 5f +M = 1a + +ModInv = b +A = 61 +M = 1a + +ModInv = 5 +A = 63 +M = 1a + +ModInv = 11 +A = -64 +M = 1b + +ModInv = 13 +A = -62 +M = 1b + +ModInv = 5 +A = -61 +M = 1b + +ModInv = 19 +A = -5f +M = 1b + +ModInv = 2 +A = -5e +M = 1b + +ModInv = 16 +A = -5c +M = 1b + +ModInv = 8 +A = -5b +M = 1b + +ModInv = a +A = -59 +M = 1b + +ModInv = 17 +A = -58 +M = 1b + +ModInv = 10 +A = -56 +M = 1b + +ModInv = 14 +A = -55 +M = 1b + +ModInv = d +A = -53 +M = 1b + +ModInv = 1a +A = -52 +M = 1b + +ModInv = 1 +A = -50 +M = 1b + +ModInv = e +A = -4f +M = 1b + +ModInv = 7 +A = -4d +M = 1b + +ModInv = b +A = -4c +M = 1b + +ModInv = 4 +A = -4a +M = 1b + +ModInv = 11 +A = -49 +M = 1b + +ModInv = 13 +A = -47 +M = 1b + +ModInv = 5 +A = -46 +M = 1b + +ModInv = 19 +A = -44 +M = 1b + +ModInv = 2 +A = -43 +M = 1b + +ModInv = 16 +A = -41 +M = 1b + +ModInv = 8 +A = -40 +M = 1b + +ModInv = a +A = -3e +M = 1b + +ModInv = 17 +A = -3d +M = 1b + +ModInv = 10 +A = -3b +M = 1b + +ModInv = 14 +A = -3a +M = 1b + +ModInv = d +A = -38 +M = 1b + +ModInv = 1a +A = -37 +M = 1b + +ModInv = 1 +A = -35 +M = 1b + +ModInv = e +A = -34 +M = 1b + +ModInv = 7 +A = -32 +M = 1b + +ModInv = b +A = -31 +M = 1b + +ModInv = 4 +A = -2f +M = 1b + +ModInv = 11 +A = -2e +M = 1b + +ModInv = 13 +A = -2c +M = 1b + +ModInv = 5 +A = -2b +M = 1b + +ModInv = 19 +A = -29 +M = 1b + +ModInv = 2 +A = -28 +M = 1b + +ModInv = 16 +A = -26 +M = 1b + +ModInv = 8 +A = -25 +M = 1b + +ModInv = a +A = -23 +M = 1b + +ModInv = 17 +A = -22 +M = 1b + +ModInv = 10 +A = -20 +M = 1b + +ModInv = 14 +A = -1f +M = 1b + +ModInv = d +A = -1d +M = 1b + +ModInv = 1a +A = -1c +M = 1b + +ModInv = 1 +A = -1a +M = 1b + +ModInv = e +A = -19 +M = 1b + +ModInv = 7 +A = -17 +M = 1b + +ModInv = b +A = -16 +M = 1b + +ModInv = 4 +A = -14 +M = 1b + +ModInv = 11 +A = -13 +M = 1b + +ModInv = 13 +A = -11 +M = 1b + +ModInv = 5 +A = -10 +M = 1b + +ModInv = 19 +A = -e +M = 1b + +ModInv = 2 +A = -d +M = 1b + +ModInv = 16 +A = -b +M = 1b + +ModInv = 8 +A = -a +M = 1b + +ModInv = a +A = -8 +M = 1b + +ModInv = 17 +A = -7 +M = 1b + +ModInv = 10 +A = -5 +M = 1b + +ModInv = 14 +A = -4 +M = 1b + +ModInv = d +A = -2 +M = 1b + +ModInv = 1a +A = -1 +M = 1b + +ModInv = 1 +A = 1 +M = 1b + +ModInv = e +A = 2 +M = 1b + +ModInv = 7 +A = 4 +M = 1b + +ModInv = b +A = 5 +M = 1b + +ModInv = 4 +A = 7 +M = 1b + +ModInv = 11 +A = 8 +M = 1b + +ModInv = 13 +A = a +M = 1b + +ModInv = 5 +A = b +M = 1b + +ModInv = 19 +A = d +M = 1b + +ModInv = 2 +A = e +M = 1b + +ModInv = 16 +A = 10 +M = 1b + +ModInv = 8 +A = 11 +M = 1b + +ModInv = a +A = 13 +M = 1b + +ModInv = 17 +A = 14 +M = 1b + +ModInv = 10 +A = 16 +M = 1b + +ModInv = 14 +A = 17 +M = 1b + +ModInv = d +A = 19 +M = 1b + +ModInv = 1a +A = 1a +M = 1b + +ModInv = 1 +A = 1c +M = 1b + +ModInv = e +A = 1d +M = 1b + +ModInv = 7 +A = 1f +M = 1b + +ModInv = b +A = 20 +M = 1b + +ModInv = 4 +A = 22 +M = 1b + +ModInv = 11 +A = 23 +M = 1b + +ModInv = 13 +A = 25 +M = 1b + +ModInv = 5 +A = 26 +M = 1b + +ModInv = 19 +A = 28 +M = 1b + +ModInv = 2 +A = 29 +M = 1b + +ModInv = 16 +A = 2b +M = 1b + +ModInv = 8 +A = 2c +M = 1b + +ModInv = a +A = 2e +M = 1b + +ModInv = 17 +A = 2f +M = 1b + +ModInv = 10 +A = 31 +M = 1b + +ModInv = 14 +A = 32 +M = 1b + +ModInv = d +A = 34 +M = 1b + +ModInv = 1a +A = 35 +M = 1b + +ModInv = 1 +A = 37 +M = 1b + +ModInv = e +A = 38 +M = 1b + +ModInv = 7 +A = 3a +M = 1b + +ModInv = b +A = 3b +M = 1b + +ModInv = 4 +A = 3d +M = 1b + +ModInv = 11 +A = 3e +M = 1b + +ModInv = 13 +A = 40 +M = 1b + +ModInv = 5 +A = 41 +M = 1b + +ModInv = 19 +A = 43 +M = 1b + +ModInv = 2 +A = 44 +M = 1b + +ModInv = 16 +A = 46 +M = 1b + +ModInv = 8 +A = 47 +M = 1b + +ModInv = a +A = 49 +M = 1b + +ModInv = 17 +A = 4a +M = 1b + +ModInv = 10 +A = 4c +M = 1b + +ModInv = 14 +A = 4d +M = 1b + +ModInv = d +A = 4f +M = 1b + +ModInv = 1a +A = 50 +M = 1b + +ModInv = 1 +A = 52 +M = 1b + +ModInv = e +A = 53 +M = 1b + +ModInv = 7 +A = 55 +M = 1b + +ModInv = b +A = 56 +M = 1b + +ModInv = 4 +A = 58 +M = 1b + +ModInv = 11 +A = 59 +M = 1b + +ModInv = 13 +A = 5b +M = 1b + +ModInv = 5 +A = 5c +M = 1b + +ModInv = 19 +A = 5e +M = 1b + +ModInv = 2 +A = 5f +M = 1b + +ModInv = 16 +A = 61 +M = 1b + +ModInv = 8 +A = 62 +M = 1b + +ModInv = d +A = -63 +M = 1c + +ModInv = f +A = -61 +M = 1c + +ModInv = 5 +A = -5f +M = 1c + +ModInv = 3 +A = -5d +M = 1c + +ModInv = b +A = -59 +M = 1c + +ModInv = 9 +A = -57 +M = 1c + +ModInv = 1b +A = -55 +M = 1c + +ModInv = 1 +A = -53 +M = 1c + +ModInv = 13 +A = -51 +M = 1c + +ModInv = 11 +A = -4f +M = 1c + +ModInv = 19 +A = -4b +M = 1c + +ModInv = 17 +A = -49 +M = 1c + +ModInv = d +A = -47 +M = 1c + +ModInv = f +A = -45 +M = 1c + +ModInv = 5 +A = -43 +M = 1c + +ModInv = 3 +A = -41 +M = 1c + +ModInv = b +A = -3d +M = 1c + +ModInv = 9 +A = -3b +M = 1c + +ModInv = 1b +A = -39 +M = 1c + +ModInv = 1 +A = -37 +M = 1c + +ModInv = 13 +A = -35 +M = 1c + +ModInv = 11 +A = -33 +M = 1c + +ModInv = 19 +A = -2f +M = 1c + +ModInv = 17 +A = -2d +M = 1c + +ModInv = d +A = -2b +M = 1c + +ModInv = f +A = -29 +M = 1c + +ModInv = 5 +A = -27 +M = 1c + +ModInv = 3 +A = -25 +M = 1c + +ModInv = b +A = -21 +M = 1c + +ModInv = 9 +A = -1f +M = 1c + +ModInv = 1b +A = -1d +M = 1c + +ModInv = 1 +A = -1b +M = 1c + +ModInv = 13 +A = -19 +M = 1c + +ModInv = 11 +A = -17 +M = 1c + +ModInv = 19 +A = -13 +M = 1c + +ModInv = 17 +A = -11 +M = 1c + +ModInv = d +A = -f +M = 1c + +ModInv = f +A = -d +M = 1c + +ModInv = 5 +A = -b +M = 1c + +ModInv = 3 +A = -9 +M = 1c + +ModInv = b +A = -5 +M = 1c + +ModInv = 9 +A = -3 +M = 1c + +ModInv = 1b +A = -1 +M = 1c + +ModInv = 1 +A = 1 +M = 1c + +ModInv = 13 +A = 3 +M = 1c + +ModInv = 11 +A = 5 +M = 1c + +ModInv = 19 +A = 9 +M = 1c + +ModInv = 17 +A = b +M = 1c + +ModInv = d +A = d +M = 1c + +ModInv = f +A = f +M = 1c + +ModInv = 5 +A = 11 +M = 1c + +ModInv = 3 +A = 13 +M = 1c + +ModInv = b +A = 17 +M = 1c + +ModInv = 9 +A = 19 +M = 1c + +ModInv = 1b +A = 1b +M = 1c + +ModInv = 1 +A = 1d +M = 1c + +ModInv = 13 +A = 1f +M = 1c + +ModInv = 11 +A = 21 +M = 1c + +ModInv = 19 +A = 25 +M = 1c + +ModInv = 17 +A = 27 +M = 1c + +ModInv = d +A = 29 +M = 1c + +ModInv = f +A = 2b +M = 1c + +ModInv = 5 +A = 2d +M = 1c + +ModInv = 3 +A = 2f +M = 1c + +ModInv = b +A = 33 +M = 1c + +ModInv = 9 +A = 35 +M = 1c + +ModInv = 1b +A = 37 +M = 1c + +ModInv = 1 +A = 39 +M = 1c + +ModInv = 13 +A = 3b +M = 1c + +ModInv = 11 +A = 3d +M = 1c + +ModInv = 19 +A = 41 +M = 1c + +ModInv = 17 +A = 43 +M = 1c + +ModInv = d +A = 45 +M = 1c + +ModInv = f +A = 47 +M = 1c + +ModInv = 5 +A = 49 +M = 1c + +ModInv = 3 +A = 4b +M = 1c + +ModInv = b +A = 4f +M = 1c + +ModInv = 9 +A = 51 +M = 1c + +ModInv = 1b +A = 53 +M = 1c + +ModInv = 1 +A = 55 +M = 1c + +ModInv = 13 +A = 57 +M = 1c + +ModInv = 11 +A = 59 +M = 1c + +ModInv = 19 +A = 5d +M = 1c + +ModInv = 17 +A = 5f +M = 1c + +ModInv = d +A = 61 +M = 1c + +ModInv = f +A = 63 +M = 1c + +ModInv = 14 +A = -64 +M = 1d + +ModInv = c +A = -63 +M = 1d + +ModInv = 15 +A = -62 +M = 1d + +ModInv = 1a +A = -61 +M = 1d + +ModInv = 10 +A = -60 +M = 1d + +ModInv = 12 +A = -5f +M = 1d + +ModInv = 4 +A = -5e +M = 1d + +ModInv = 18 +A = -5d +M = 1d + +ModInv = 17 +A = -5c +M = 1d + +ModInv = 7 +A = -5b +M = 1d + +ModInv = 13 +A = -5a +M = 1d + +ModInv = e +A = -59 +M = 1d + +ModInv = 1c +A = -58 +M = 1d + +ModInv = 1 +A = -56 +M = 1d + +ModInv = f +A = -55 +M = 1d + +ModInv = a +A = -54 +M = 1d + +ModInv = 16 +A = -53 +M = 1d + +ModInv = 6 +A = -52 +M = 1d + +ModInv = 5 +A = -51 +M = 1d + +ModInv = 19 +A = -50 +M = 1d + +ModInv = b +A = -4f +M = 1d + +ModInv = d +A = -4e +M = 1d + +ModInv = 3 +A = -4d +M = 1d + +ModInv = 8 +A = -4c +M = 1d + +ModInv = 11 +A = -4b +M = 1d + +ModInv = 9 +A = -4a +M = 1d + +ModInv = 1b +A = -49 +M = 1d + +ModInv = 2 +A = -48 +M = 1d + +ModInv = 14 +A = -47 +M = 1d + +ModInv = c +A = -46 +M = 1d + +ModInv = 15 +A = -45 +M = 1d + +ModInv = 1a +A = -44 +M = 1d + +ModInv = 10 +A = -43 +M = 1d + +ModInv = 12 +A = -42 +M = 1d + +ModInv = 4 +A = -41 +M = 1d + +ModInv = 18 +A = -40 +M = 1d + +ModInv = 17 +A = -3f +M = 1d + +ModInv = 7 +A = -3e +M = 1d + +ModInv = 13 +A = -3d +M = 1d + +ModInv = e +A = -3c +M = 1d + +ModInv = 1c +A = -3b +M = 1d + +ModInv = 1 +A = -39 +M = 1d + +ModInv = f +A = -38 +M = 1d + +ModInv = a +A = -37 +M = 1d + +ModInv = 16 +A = -36 +M = 1d + +ModInv = 6 +A = -35 +M = 1d + +ModInv = 5 +A = -34 +M = 1d + +ModInv = 19 +A = -33 +M = 1d + +ModInv = b +A = -32 +M = 1d + +ModInv = d +A = -31 +M = 1d + +ModInv = 3 +A = -30 +M = 1d + +ModInv = 8 +A = -2f +M = 1d + +ModInv = 11 +A = -2e +M = 1d + +ModInv = 9 +A = -2d +M = 1d + +ModInv = 1b +A = -2c +M = 1d + +ModInv = 2 +A = -2b +M = 1d + +ModInv = 14 +A = -2a +M = 1d + +ModInv = c +A = -29 +M = 1d + +ModInv = 15 +A = -28 +M = 1d + +ModInv = 1a +A = -27 +M = 1d + +ModInv = 10 +A = -26 +M = 1d + +ModInv = 12 +A = -25 +M = 1d + +ModInv = 4 +A = -24 +M = 1d + +ModInv = 18 +A = -23 +M = 1d + +ModInv = 17 +A = -22 +M = 1d + +ModInv = 7 +A = -21 +M = 1d + +ModInv = 13 +A = -20 +M = 1d + +ModInv = e +A = -1f +M = 1d + +ModInv = 1c +A = -1e +M = 1d + +ModInv = 1 +A = -1c +M = 1d + +ModInv = f +A = -1b +M = 1d + +ModInv = a +A = -1a +M = 1d + +ModInv = 16 +A = -19 +M = 1d + +ModInv = 6 +A = -18 +M = 1d + +ModInv = 5 +A = -17 +M = 1d + +ModInv = 19 +A = -16 +M = 1d + +ModInv = b +A = -15 +M = 1d + +ModInv = d +A = -14 +M = 1d + +ModInv = 3 +A = -13 +M = 1d + +ModInv = 8 +A = -12 +M = 1d + +ModInv = 11 +A = -11 +M = 1d + +ModInv = 9 +A = -10 +M = 1d + +ModInv = 1b +A = -f +M = 1d + +ModInv = 2 +A = -e +M = 1d + +ModInv = 14 +A = -d +M = 1d + +ModInv = c +A = -c +M = 1d + +ModInv = 15 +A = -b +M = 1d + +ModInv = 1a +A = -a +M = 1d + +ModInv = 10 +A = -9 +M = 1d + +ModInv = 12 +A = -8 +M = 1d + +ModInv = 4 +A = -7 +M = 1d + +ModInv = 18 +A = -6 +M = 1d + +ModInv = 17 +A = -5 +M = 1d + +ModInv = 7 +A = -4 +M = 1d + +ModInv = 13 +A = -3 +M = 1d + +ModInv = e +A = -2 +M = 1d + +ModInv = 1c +A = -1 +M = 1d + +ModInv = 1 +A = 1 +M = 1d + +ModInv = f +A = 2 +M = 1d + +ModInv = a +A = 3 +M = 1d + +ModInv = 16 +A = 4 +M = 1d + +ModInv = 6 +A = 5 +M = 1d + +ModInv = 5 +A = 6 +M = 1d + +ModInv = 19 +A = 7 +M = 1d + +ModInv = b +A = 8 +M = 1d + +ModInv = d +A = 9 +M = 1d + +ModInv = 3 +A = a +M = 1d + +ModInv = 8 +A = b +M = 1d + +ModInv = 11 +A = c +M = 1d + +ModInv = 9 +A = d +M = 1d + +ModInv = 1b +A = e +M = 1d + +ModInv = 2 +A = f +M = 1d + +ModInv = 14 +A = 10 +M = 1d + +ModInv = c +A = 11 +M = 1d + +ModInv = 15 +A = 12 +M = 1d + +ModInv = 1a +A = 13 +M = 1d + +ModInv = 10 +A = 14 +M = 1d + +ModInv = 12 +A = 15 +M = 1d + +ModInv = 4 +A = 16 +M = 1d + +ModInv = 18 +A = 17 +M = 1d + +ModInv = 17 +A = 18 +M = 1d + +ModInv = 7 +A = 19 +M = 1d + +ModInv = 13 +A = 1a +M = 1d + +ModInv = e +A = 1b +M = 1d + +ModInv = 1c +A = 1c +M = 1d + +ModInv = 1 +A = 1e +M = 1d + +ModInv = f +A = 1f +M = 1d + +ModInv = a +A = 20 +M = 1d + +ModInv = 16 +A = 21 +M = 1d + +ModInv = 6 +A = 22 +M = 1d + +ModInv = 5 +A = 23 +M = 1d + +ModInv = 19 +A = 24 +M = 1d + +ModInv = b +A = 25 +M = 1d + +ModInv = d +A = 26 +M = 1d + +ModInv = 3 +A = 27 +M = 1d + +ModInv = 8 +A = 28 +M = 1d + +ModInv = 11 +A = 29 +M = 1d + +ModInv = 9 +A = 2a +M = 1d + +ModInv = 1b +A = 2b +M = 1d + +ModInv = 2 +A = 2c +M = 1d + +ModInv = 14 +A = 2d +M = 1d + +ModInv = c +A = 2e +M = 1d + +ModInv = 15 +A = 2f +M = 1d + +ModInv = 1a +A = 30 +M = 1d + +ModInv = 10 +A = 31 +M = 1d + +ModInv = 12 +A = 32 +M = 1d + +ModInv = 4 +A = 33 +M = 1d + +ModInv = 18 +A = 34 +M = 1d + +ModInv = 17 +A = 35 +M = 1d + +ModInv = 7 +A = 36 +M = 1d + +ModInv = 13 +A = 37 +M = 1d + +ModInv = e +A = 38 +M = 1d + +ModInv = 1c +A = 39 +M = 1d + +ModInv = 1 +A = 3b +M = 1d + +ModInv = f +A = 3c +M = 1d + +ModInv = a +A = 3d +M = 1d + +ModInv = 16 +A = 3e +M = 1d + +ModInv = 6 +A = 3f +M = 1d + +ModInv = 5 +A = 40 +M = 1d + +ModInv = 19 +A = 41 +M = 1d + +ModInv = b +A = 42 +M = 1d + +ModInv = d +A = 43 +M = 1d + +ModInv = 3 +A = 44 +M = 1d + +ModInv = 8 +A = 45 +M = 1d + +ModInv = 11 +A = 46 +M = 1d + +ModInv = 9 +A = 47 +M = 1d + +ModInv = 1b +A = 48 +M = 1d + +ModInv = 2 +A = 49 +M = 1d + +ModInv = 14 +A = 4a +M = 1d + +ModInv = c +A = 4b +M = 1d + +ModInv = 15 +A = 4c +M = 1d + +ModInv = 1a +A = 4d +M = 1d + +ModInv = 10 +A = 4e +M = 1d + +ModInv = 12 +A = 4f +M = 1d + +ModInv = 4 +A = 50 +M = 1d + +ModInv = 18 +A = 51 +M = 1d + +ModInv = 17 +A = 52 +M = 1d + +ModInv = 7 +A = 53 +M = 1d + +ModInv = 13 +A = 54 +M = 1d + +ModInv = e +A = 55 +M = 1d + +ModInv = 1c +A = 56 +M = 1d + +ModInv = 1 +A = 58 +M = 1d + +ModInv = f +A = 59 +M = 1d + +ModInv = a +A = 5a +M = 1d + +ModInv = 16 +A = 5b +M = 1d + +ModInv = 6 +A = 5c +M = 1d + +ModInv = 5 +A = 5d +M = 1d + +ModInv = 19 +A = 5e +M = 1d + +ModInv = b +A = 5f +M = 1d + +ModInv = d +A = 60 +M = 1d + +ModInv = 3 +A = 61 +M = 1d + +ModInv = 8 +A = 62 +M = 1d + +ModInv = 11 +A = 63 +M = 1d + +ModInv = 11 +A = -61 +M = 1e + +ModInv = 1d +A = -5b +M = 1e + +ModInv = 1 +A = -59 +M = 1e + +ModInv = d +A = -53 +M = 1e + +ModInv = b +A = -4f +M = 1e + +ModInv = 7 +A = -4d +M = 1e + +ModInv = 17 +A = -49 +M = 1e + +ModInv = 13 +A = -47 +M = 1e + +ModInv = 11 +A = -43 +M = 1e + +ModInv = 1d +A = -3d +M = 1e + +ModInv = 1 +A = -3b +M = 1e + +ModInv = d +A = -35 +M = 1e + +ModInv = b +A = -31 +M = 1e + +ModInv = 7 +A = -2f +M = 1e + +ModInv = 17 +A = -2b +M = 1e + +ModInv = 13 +A = -29 +M = 1e + +ModInv = 11 +A = -25 +M = 1e + +ModInv = 1d +A = -1f +M = 1e + +ModInv = 1 +A = -1d +M = 1e + +ModInv = d +A = -17 +M = 1e + +ModInv = b +A = -13 +M = 1e + +ModInv = 7 +A = -11 +M = 1e + +ModInv = 17 +A = -d +M = 1e + +ModInv = 13 +A = -b +M = 1e + +ModInv = 11 +A = -7 +M = 1e + +ModInv = 1d +A = -1 +M = 1e + +ModInv = 1 +A = 1 +M = 1e + +ModInv = d +A = 7 +M = 1e + +ModInv = b +A = b +M = 1e + +ModInv = 7 +A = d +M = 1e + +ModInv = 17 +A = 11 +M = 1e + +ModInv = 13 +A = 13 +M = 1e + +ModInv = 11 +A = 17 +M = 1e + +ModInv = 1d +A = 1d +M = 1e + +ModInv = 1 +A = 1f +M = 1e + +ModInv = d +A = 25 +M = 1e + +ModInv = b +A = 29 +M = 1e + +ModInv = 7 +A = 2b +M = 1e + +ModInv = 17 +A = 2f +M = 1e + +ModInv = 13 +A = 31 +M = 1e + +ModInv = 11 +A = 35 +M = 1e + +ModInv = 1d +A = 3b +M = 1e + +ModInv = 1 +A = 3d +M = 1e + +ModInv = d +A = 43 +M = 1e + +ModInv = b +A = 47 +M = 1e + +ModInv = 7 +A = 49 +M = 1e + +ModInv = 17 +A = 4d +M = 1e + +ModInv = 13 +A = 4f +M = 1e + +ModInv = 11 +A = 53 +M = 1e + +ModInv = 1d +A = 59 +M = 1e + +ModInv = 1 +A = 5b +M = 1e + +ModInv = d +A = 61 +M = 1e + +ModInv = 16 +A = -64 +M = 1f + +ModInv = 5 +A = -63 +M = 1f + +ModInv = 6 +A = -62 +M = 1f + +ModInv = 17 +A = -61 +M = 1f + +ModInv = a +A = -60 +M = 1f + +ModInv = f +A = -5f +M = 1f + +ModInv = 1e +A = -5e +M = 1f + +ModInv = 1 +A = -5c +M = 1f + +ModInv = 10 +A = -5b +M = 1f + +ModInv = 15 +A = -5a +M = 1f + +ModInv = 8 +A = -59 +M = 1f + +ModInv = 19 +A = -58 +M = 1f + +ModInv = 1a +A = -57 +M = 1f + +ModInv = 9 +A = -56 +M = 1f + +ModInv = 4 +A = -55 +M = 1f + +ModInv = 7 +A = -54 +M = 1f + +ModInv = 1c +A = -53 +M = 1f + +ModInv = 11 +A = -52 +M = 1f + +ModInv = d +A = -51 +M = 1f + +ModInv = c +A = -50 +M = 1f + +ModInv = 14 +A = -4f +M = 1f + +ModInv = 1d +A = -4e +M = 1f + +ModInv = 2 +A = -4d +M = 1f + +ModInv = b +A = -4c +M = 1f + +ModInv = 13 +A = -4b +M = 1f + +ModInv = 12 +A = -4a +M = 1f + +ModInv = e +A = -49 +M = 1f + +ModInv = 3 +A = -48 +M = 1f + +ModInv = 18 +A = -47 +M = 1f + +ModInv = 1b +A = -46 +M = 1f + +ModInv = 16 +A = -45 +M = 1f + +ModInv = 5 +A = -44 +M = 1f + +ModInv = 6 +A = -43 +M = 1f + +ModInv = 17 +A = -42 +M = 1f + +ModInv = a +A = -41 +M = 1f + +ModInv = f +A = -40 +M = 1f + +ModInv = 1e +A = -3f +M = 1f + +ModInv = 1 +A = -3d +M = 1f + +ModInv = 10 +A = -3c +M = 1f + +ModInv = 15 +A = -3b +M = 1f + +ModInv = 8 +A = -3a +M = 1f + +ModInv = 19 +A = -39 +M = 1f + +ModInv = 1a +A = -38 +M = 1f + +ModInv = 9 +A = -37 +M = 1f + +ModInv = 4 +A = -36 +M = 1f + +ModInv = 7 +A = -35 +M = 1f + +ModInv = 1c +A = -34 +M = 1f + +ModInv = 11 +A = -33 +M = 1f + +ModInv = d +A = -32 +M = 1f + +ModInv = c +A = -31 +M = 1f + +ModInv = 14 +A = -30 +M = 1f + +ModInv = 1d +A = -2f +M = 1f + +ModInv = 2 +A = -2e +M = 1f + +ModInv = b +A = -2d +M = 1f + +ModInv = 13 +A = -2c +M = 1f + +ModInv = 12 +A = -2b +M = 1f + +ModInv = e +A = -2a +M = 1f + +ModInv = 3 +A = -29 +M = 1f + +ModInv = 18 +A = -28 +M = 1f + +ModInv = 1b +A = -27 +M = 1f + +ModInv = 16 +A = -26 +M = 1f + +ModInv = 5 +A = -25 +M = 1f + +ModInv = 6 +A = -24 +M = 1f + +ModInv = 17 +A = -23 +M = 1f + +ModInv = a +A = -22 +M = 1f + +ModInv = f +A = -21 +M = 1f + +ModInv = 1e +A = -20 +M = 1f + +ModInv = 1 +A = -1e +M = 1f + +ModInv = 10 +A = -1d +M = 1f + +ModInv = 15 +A = -1c +M = 1f + +ModInv = 8 +A = -1b +M = 1f + +ModInv = 19 +A = -1a +M = 1f + +ModInv = 1a +A = -19 +M = 1f + +ModInv = 9 +A = -18 +M = 1f + +ModInv = 4 +A = -17 +M = 1f + +ModInv = 7 +A = -16 +M = 1f + +ModInv = 1c +A = -15 +M = 1f + +ModInv = 11 +A = -14 +M = 1f + +ModInv = d +A = -13 +M = 1f + +ModInv = c +A = -12 +M = 1f + +ModInv = 14 +A = -11 +M = 1f + +ModInv = 1d +A = -10 +M = 1f + +ModInv = 2 +A = -f +M = 1f + +ModInv = b +A = -e +M = 1f + +ModInv = 13 +A = -d +M = 1f + +ModInv = 12 +A = -c +M = 1f + +ModInv = e +A = -b +M = 1f + +ModInv = 3 +A = -a +M = 1f + +ModInv = 18 +A = -9 +M = 1f + +ModInv = 1b +A = -8 +M = 1f + +ModInv = 16 +A = -7 +M = 1f + +ModInv = 5 +A = -6 +M = 1f + +ModInv = 6 +A = -5 +M = 1f + +ModInv = 17 +A = -4 +M = 1f + +ModInv = a +A = -3 +M = 1f + +ModInv = f +A = -2 +M = 1f + +ModInv = 1e +A = -1 +M = 1f + +ModInv = 1 +A = 1 +M = 1f + +ModInv = 10 +A = 2 +M = 1f + +ModInv = 15 +A = 3 +M = 1f + +ModInv = 8 +A = 4 +M = 1f + +ModInv = 19 +A = 5 +M = 1f + +ModInv = 1a +A = 6 +M = 1f + +ModInv = 9 +A = 7 +M = 1f + +ModInv = 4 +A = 8 +M = 1f + +ModInv = 7 +A = 9 +M = 1f + +ModInv = 1c +A = a +M = 1f + +ModInv = 11 +A = b +M = 1f + +ModInv = d +A = c +M = 1f + +ModInv = c +A = d +M = 1f + +ModInv = 14 +A = e +M = 1f + +ModInv = 1d +A = f +M = 1f + +ModInv = 2 +A = 10 +M = 1f + +ModInv = b +A = 11 +M = 1f + +ModInv = 13 +A = 12 +M = 1f + +ModInv = 12 +A = 13 +M = 1f + +ModInv = e +A = 14 +M = 1f + +ModInv = 3 +A = 15 +M = 1f + +ModInv = 18 +A = 16 +M = 1f + +ModInv = 1b +A = 17 +M = 1f + +ModInv = 16 +A = 18 +M = 1f + +ModInv = 5 +A = 19 +M = 1f + +ModInv = 6 +A = 1a +M = 1f + +ModInv = 17 +A = 1b +M = 1f + +ModInv = a +A = 1c +M = 1f + +ModInv = f +A = 1d +M = 1f + +ModInv = 1e +A = 1e +M = 1f + +ModInv = 1 +A = 20 +M = 1f + +ModInv = 10 +A = 21 +M = 1f + +ModInv = 15 +A = 22 +M = 1f + +ModInv = 8 +A = 23 +M = 1f + +ModInv = 19 +A = 24 +M = 1f + +ModInv = 1a +A = 25 +M = 1f + +ModInv = 9 +A = 26 +M = 1f + +ModInv = 4 +A = 27 +M = 1f + +ModInv = 7 +A = 28 +M = 1f + +ModInv = 1c +A = 29 +M = 1f + +ModInv = 11 +A = 2a +M = 1f + +ModInv = d +A = 2b +M = 1f + +ModInv = c +A = 2c +M = 1f + +ModInv = 14 +A = 2d +M = 1f + +ModInv = 1d +A = 2e +M = 1f + +ModInv = 2 +A = 2f +M = 1f + +ModInv = b +A = 30 +M = 1f + +ModInv = 13 +A = 31 +M = 1f + +ModInv = 12 +A = 32 +M = 1f + +ModInv = e +A = 33 +M = 1f + +ModInv = 3 +A = 34 +M = 1f + +ModInv = 18 +A = 35 +M = 1f + +ModInv = 1b +A = 36 +M = 1f + +ModInv = 16 +A = 37 +M = 1f + +ModInv = 5 +A = 38 +M = 1f + +ModInv = 6 +A = 39 +M = 1f + +ModInv = 17 +A = 3a +M = 1f + +ModInv = a +A = 3b +M = 1f + +ModInv = f +A = 3c +M = 1f + +ModInv = 1e +A = 3d +M = 1f + +ModInv = 1 +A = 3f +M = 1f + +ModInv = 10 +A = 40 +M = 1f + +ModInv = 15 +A = 41 +M = 1f + +ModInv = 8 +A = 42 +M = 1f + +ModInv = 19 +A = 43 +M = 1f + +ModInv = 1a +A = 44 +M = 1f + +ModInv = 9 +A = 45 +M = 1f + +ModInv = 4 +A = 46 +M = 1f + +ModInv = 7 +A = 47 +M = 1f + +ModInv = 1c +A = 48 +M = 1f + +ModInv = 11 +A = 49 +M = 1f + +ModInv = d +A = 4a +M = 1f + +ModInv = c +A = 4b +M = 1f + +ModInv = 14 +A = 4c +M = 1f + +ModInv = 1d +A = 4d +M = 1f + +ModInv = 2 +A = 4e +M = 1f + +ModInv = b +A = 4f +M = 1f + +ModInv = 13 +A = 50 +M = 1f + +ModInv = 12 +A = 51 +M = 1f + +ModInv = e +A = 52 +M = 1f + +ModInv = 3 +A = 53 +M = 1f + +ModInv = 18 +A = 54 +M = 1f + +ModInv = 1b +A = 55 +M = 1f + +ModInv = 16 +A = 56 +M = 1f + +ModInv = 5 +A = 57 +M = 1f + +ModInv = 6 +A = 58 +M = 1f + +ModInv = 17 +A = 59 +M = 1f + +ModInv = a +A = 5a +M = 1f + +ModInv = f +A = 5b +M = 1f + +ModInv = 1e +A = 5c +M = 1f + +ModInv = 1 +A = 5e +M = 1f + +ModInv = 10 +A = 5f +M = 1f + +ModInv = 15 +A = 60 +M = 1f + +ModInv = 8 +A = 61 +M = 1f + +ModInv = 19 +A = 62 +M = 1f + +ModInv = 1a +A = 63 +M = 1f + +ModInv = 15 +A = -63 +M = 20 + +ModInv = 1f +A = -61 +M = 20 + +ModInv = 1 +A = -5f +M = 20 + +ModInv = b +A = -5d +M = 20 + +ModInv = d +A = -5b +M = 20 + +ModInv = 17 +A = -59 +M = 20 + +ModInv = 19 +A = -57 +M = 20 + +ModInv = 3 +A = -55 +M = 20 + +ModInv = 5 +A = -53 +M = 20 + +ModInv = f +A = -51 +M = 20 + +ModInv = 11 +A = -4f +M = 20 + +ModInv = 1b +A = -4d +M = 20 + +ModInv = 1d +A = -4b +M = 20 + +ModInv = 7 +A = -49 +M = 20 + +ModInv = 9 +A = -47 +M = 20 + +ModInv = 13 +A = -45 +M = 20 + +ModInv = 15 +A = -43 +M = 20 + +ModInv = 1f +A = -41 +M = 20 + +ModInv = 1 +A = -3f +M = 20 + +ModInv = b +A = -3d +M = 20 + +ModInv = d +A = -3b +M = 20 + +ModInv = 17 +A = -39 +M = 20 + +ModInv = 19 +A = -37 +M = 20 + +ModInv = 3 +A = -35 +M = 20 + +ModInv = 5 +A = -33 +M = 20 + +ModInv = f +A = -31 +M = 20 + +ModInv = 11 +A = -2f +M = 20 + +ModInv = 1b +A = -2d +M = 20 + +ModInv = 1d +A = -2b +M = 20 + +ModInv = 7 +A = -29 +M = 20 + +ModInv = 9 +A = -27 +M = 20 + +ModInv = 13 +A = -25 +M = 20 + +ModInv = 15 +A = -23 +M = 20 + +ModInv = 1f +A = -21 +M = 20 + +ModInv = 1 +A = -1f +M = 20 + +ModInv = b +A = -1d +M = 20 + +ModInv = d +A = -1b +M = 20 + +ModInv = 17 +A = -19 +M = 20 + +ModInv = 19 +A = -17 +M = 20 + +ModInv = 3 +A = -15 +M = 20 + +ModInv = 5 +A = -13 +M = 20 + +ModInv = f +A = -11 +M = 20 + +ModInv = 11 +A = -f +M = 20 + +ModInv = 1b +A = -d +M = 20 + +ModInv = 1d +A = -b +M = 20 + +ModInv = 7 +A = -9 +M = 20 + +ModInv = 9 +A = -7 +M = 20 + +ModInv = 13 +A = -5 +M = 20 + +ModInv = 15 +A = -3 +M = 20 + +ModInv = 1f +A = -1 +M = 20 + +ModInv = 1 +A = 1 +M = 20 + +ModInv = b +A = 3 +M = 20 + +ModInv = d +A = 5 +M = 20 + +ModInv = 17 +A = 7 +M = 20 + +ModInv = 19 +A = 9 +M = 20 + +ModInv = 3 +A = b +M = 20 + +ModInv = 5 +A = d +M = 20 + +ModInv = f +A = f +M = 20 + +ModInv = 11 +A = 11 +M = 20 + +ModInv = 1b +A = 13 +M = 20 + +ModInv = 1d +A = 15 +M = 20 + +ModInv = 7 +A = 17 +M = 20 + +ModInv = 9 +A = 19 +M = 20 + +ModInv = 13 +A = 1b +M = 20 + +ModInv = 15 +A = 1d +M = 20 + +ModInv = 1f +A = 1f +M = 20 + +ModInv = 1 +A = 21 +M = 20 + +ModInv = b +A = 23 +M = 20 + +ModInv = d +A = 25 +M = 20 + +ModInv = 17 +A = 27 +M = 20 + +ModInv = 19 +A = 29 +M = 20 + +ModInv = 3 +A = 2b +M = 20 + +ModInv = 5 +A = 2d +M = 20 + +ModInv = f +A = 2f +M = 20 + +ModInv = 11 +A = 31 +M = 20 + +ModInv = 1b +A = 33 +M = 20 + +ModInv = 1d +A = 35 +M = 20 + +ModInv = 7 +A = 37 +M = 20 + +ModInv = 9 +A = 39 +M = 20 + +ModInv = 13 +A = 3b +M = 20 + +ModInv = 15 +A = 3d +M = 20 + +ModInv = 1f +A = 3f +M = 20 + +ModInv = 1 +A = 41 +M = 20 + +ModInv = b +A = 43 +M = 20 + +ModInv = d +A = 45 +M = 20 + +ModInv = 17 +A = 47 +M = 20 + +ModInv = 19 +A = 49 +M = 20 + +ModInv = 3 +A = 4b +M = 20 + +ModInv = 5 +A = 4d +M = 20 + +ModInv = f +A = 4f +M = 20 + +ModInv = 11 +A = 51 +M = 20 + +ModInv = 1b +A = 53 +M = 20 + +ModInv = 1d +A = 55 +M = 20 + +ModInv = 7 +A = 57 +M = 20 + +ModInv = 9 +A = 59 +M = 20 + +ModInv = 13 +A = 5b +M = 20 + +ModInv = 15 +A = 5d +M = 20 + +ModInv = 1f +A = 5f +M = 20 + +ModInv = 1 +A = 61 +M = 20 + +ModInv = b +A = 63 +M = 20 + +ModInv = 20 +A = -64 +M = 21 + +ModInv = 1 +A = -62 +M = 21 + +ModInv = 11 +A = -61 +M = 21 + +ModInv = 19 +A = -5f +M = 21 + +ModInv = 14 +A = -5e +M = 21 + +ModInv = 13 +A = -5c +M = 21 + +ModInv = 1d +A = -5b +M = 21 + +ModInv = a +A = -59 +M = 21 + +ModInv = 1c +A = -56 +M = 21 + +ModInv = 1a +A = -55 +M = 21 + +ModInv = 1f +A = -53 +M = 21 + +ModInv = 2 +A = -52 +M = 21 + +ModInv = 7 +A = -50 +M = 21 + +ModInv = 5 +A = -4f +M = 21 + +ModInv = 17 +A = -4c +M = 21 + +ModInv = 4 +A = -4a +M = 21 + +ModInv = e +A = -49 +M = 21 + +ModInv = d +A = -47 +M = 21 + +ModInv = 8 +A = -46 +M = 21 + +ModInv = 10 +A = -44 +M = 21 + +ModInv = 20 +A = -43 +M = 21 + +ModInv = 1 +A = -41 +M = 21 + +ModInv = 11 +A = -40 +M = 21 + +ModInv = 19 +A = -3e +M = 21 + +ModInv = 14 +A = -3d +M = 21 + +ModInv = 13 +A = -3b +M = 21 + +ModInv = 1d +A = -3a +M = 21 + +ModInv = a +A = -38 +M = 21 + +ModInv = 1c +A = -35 +M = 21 + +ModInv = 1a +A = -34 +M = 21 + +ModInv = 1f +A = -32 +M = 21 + +ModInv = 2 +A = -31 +M = 21 + +ModInv = 7 +A = -2f +M = 21 + +ModInv = 5 +A = -2e +M = 21 + +ModInv = 17 +A = -2b +M = 21 + +ModInv = 4 +A = -29 +M = 21 + +ModInv = e +A = -28 +M = 21 + +ModInv = d +A = -26 +M = 21 + +ModInv = 8 +A = -25 +M = 21 + +ModInv = 10 +A = -23 +M = 21 + +ModInv = 20 +A = -22 +M = 21 + +ModInv = 1 +A = -20 +M = 21 + +ModInv = 11 +A = -1f +M = 21 + +ModInv = 19 +A = -1d +M = 21 + +ModInv = 14 +A = -1c +M = 21 + +ModInv = 13 +A = -1a +M = 21 + +ModInv = 1d +A = -19 +M = 21 + +ModInv = a +A = -17 +M = 21 + +ModInv = 1c +A = -14 +M = 21 + +ModInv = 1a +A = -13 +M = 21 + +ModInv = 1f +A = -11 +M = 21 + +ModInv = 2 +A = -10 +M = 21 + +ModInv = 7 +A = -e +M = 21 + +ModInv = 5 +A = -d +M = 21 + +ModInv = 17 +A = -a +M = 21 + +ModInv = 4 +A = -8 +M = 21 + +ModInv = e +A = -7 +M = 21 + +ModInv = d +A = -5 +M = 21 + +ModInv = 8 +A = -4 +M = 21 + +ModInv = 10 +A = -2 +M = 21 + +ModInv = 20 +A = -1 +M = 21 + +ModInv = 1 +A = 1 +M = 21 + +ModInv = 11 +A = 2 +M = 21 + +ModInv = 19 +A = 4 +M = 21 + +ModInv = 14 +A = 5 +M = 21 + +ModInv = 13 +A = 7 +M = 21 + +ModInv = 1d +A = 8 +M = 21 + +ModInv = a +A = a +M = 21 + +ModInv = 1c +A = d +M = 21 + +ModInv = 1a +A = e +M = 21 + +ModInv = 1f +A = 10 +M = 21 + +ModInv = 2 +A = 11 +M = 21 + +ModInv = 7 +A = 13 +M = 21 + +ModInv = 5 +A = 14 +M = 21 + +ModInv = 17 +A = 17 +M = 21 + +ModInv = 4 +A = 19 +M = 21 + +ModInv = e +A = 1a +M = 21 + +ModInv = d +A = 1c +M = 21 + +ModInv = 8 +A = 1d +M = 21 + +ModInv = 10 +A = 1f +M = 21 + +ModInv = 20 +A = 20 +M = 21 + +ModInv = 1 +A = 22 +M = 21 + +ModInv = 11 +A = 23 +M = 21 + +ModInv = 19 +A = 25 +M = 21 + +ModInv = 14 +A = 26 +M = 21 + +ModInv = 13 +A = 28 +M = 21 + +ModInv = 1d +A = 29 +M = 21 + +ModInv = a +A = 2b +M = 21 + +ModInv = 1c +A = 2e +M = 21 + +ModInv = 1a +A = 2f +M = 21 + +ModInv = 1f +A = 31 +M = 21 + +ModInv = 2 +A = 32 +M = 21 + +ModInv = 7 +A = 34 +M = 21 + +ModInv = 5 +A = 35 +M = 21 + +ModInv = 17 +A = 38 +M = 21 + +ModInv = 4 +A = 3a +M = 21 + +ModInv = e +A = 3b +M = 21 + +ModInv = d +A = 3d +M = 21 + +ModInv = 8 +A = 3e +M = 21 + +ModInv = 10 +A = 40 +M = 21 + +ModInv = 20 +A = 41 +M = 21 + +ModInv = 1 +A = 43 +M = 21 + +ModInv = 11 +A = 44 +M = 21 + +ModInv = 19 +A = 46 +M = 21 + +ModInv = 14 +A = 47 +M = 21 + +ModInv = 13 +A = 49 +M = 21 + +ModInv = 1d +A = 4a +M = 21 + +ModInv = a +A = 4c +M = 21 + +ModInv = 1c +A = 4f +M = 21 + +ModInv = 1a +A = 50 +M = 21 + +ModInv = 1f +A = 52 +M = 21 + +ModInv = 2 +A = 53 +M = 21 + +ModInv = 7 +A = 55 +M = 21 + +ModInv = 5 +A = 56 +M = 21 + +ModInv = 17 +A = 59 +M = 21 + +ModInv = 4 +A = 5b +M = 21 + +ModInv = e +A = 5c +M = 21 + +ModInv = d +A = 5e +M = 21 + +ModInv = 8 +A = 5f +M = 21 + +ModInv = 10 +A = 61 +M = 21 + +ModInv = 20 +A = 62 +M = 21 + +ModInv = 17 +A = -63 +M = 22 + +ModInv = 7 +A = -61 +M = 22 + +ModInv = 5 +A = -5f +M = 22 + +ModInv = 13 +A = -5d +M = 22 + +ModInv = 1f +A = -5b +M = 22 + +ModInv = 15 +A = -59 +M = 22 + +ModInv = 19 +A = -57 +M = 22 + +ModInv = 9 +A = -53 +M = 22 + +ModInv = d +A = -51 +M = 22 + +ModInv = 3 +A = -4f +M = 22 + +ModInv = f +A = -4d +M = 22 + +ModInv = 1d +A = -4b +M = 22 + +ModInv = 1b +A = -49 +M = 22 + +ModInv = b +A = -47 +M = 22 + +ModInv = 21 +A = -45 +M = 22 + +ModInv = 1 +A = -43 +M = 22 + +ModInv = 17 +A = -41 +M = 22 + +ModInv = 7 +A = -3f +M = 22 + +ModInv = 5 +A = -3d +M = 22 + +ModInv = 13 +A = -3b +M = 22 + +ModInv = 1f +A = -39 +M = 22 + +ModInv = 15 +A = -37 +M = 22 + +ModInv = 19 +A = -35 +M = 22 + +ModInv = 9 +A = -31 +M = 22 + +ModInv = d +A = -2f +M = 22 + +ModInv = 3 +A = -2d +M = 22 + +ModInv = f +A = -2b +M = 22 + +ModInv = 1d +A = -29 +M = 22 + +ModInv = 1b +A = -27 +M = 22 + +ModInv = b +A = -25 +M = 22 + +ModInv = 21 +A = -23 +M = 22 + +ModInv = 1 +A = -21 +M = 22 + +ModInv = 17 +A = -1f +M = 22 + +ModInv = 7 +A = -1d +M = 22 + +ModInv = 5 +A = -1b +M = 22 + +ModInv = 13 +A = -19 +M = 22 + +ModInv = 1f +A = -17 +M = 22 + +ModInv = 15 +A = -15 +M = 22 + +ModInv = 19 +A = -13 +M = 22 + +ModInv = 9 +A = -f +M = 22 + +ModInv = d +A = -d +M = 22 + +ModInv = 3 +A = -b +M = 22 + +ModInv = f +A = -9 +M = 22 + +ModInv = 1d +A = -7 +M = 22 + +ModInv = 1b +A = -5 +M = 22 + +ModInv = b +A = -3 +M = 22 + +ModInv = 21 +A = -1 +M = 22 + +ModInv = 1 +A = 1 +M = 22 + +ModInv = 17 +A = 3 +M = 22 + +ModInv = 7 +A = 5 +M = 22 + +ModInv = 5 +A = 7 +M = 22 + +ModInv = 13 +A = 9 +M = 22 + +ModInv = 1f +A = b +M = 22 + +ModInv = 15 +A = d +M = 22 + +ModInv = 19 +A = f +M = 22 + +ModInv = 9 +A = 13 +M = 22 + +ModInv = d +A = 15 +M = 22 + +ModInv = 3 +A = 17 +M = 22 + +ModInv = f +A = 19 +M = 22 + +ModInv = 1d +A = 1b +M = 22 + +ModInv = 1b +A = 1d +M = 22 + +ModInv = b +A = 1f +M = 22 + +ModInv = 21 +A = 21 +M = 22 + +ModInv = 1 +A = 23 +M = 22 + +ModInv = 17 +A = 25 +M = 22 + +ModInv = 7 +A = 27 +M = 22 + +ModInv = 5 +A = 29 +M = 22 + +ModInv = 13 +A = 2b +M = 22 + +ModInv = 1f +A = 2d +M = 22 + +ModInv = 15 +A = 2f +M = 22 + +ModInv = 19 +A = 31 +M = 22 + +ModInv = 9 +A = 35 +M = 22 + +ModInv = d +A = 37 +M = 22 + +ModInv = 3 +A = 39 +M = 22 + +ModInv = f +A = 3b +M = 22 + +ModInv = 1d +A = 3d +M = 22 + +ModInv = 1b +A = 3f +M = 22 + +ModInv = b +A = 41 +M = 22 + +ModInv = 21 +A = 43 +M = 22 + +ModInv = 1 +A = 45 +M = 22 + +ModInv = 17 +A = 47 +M = 22 + +ModInv = 7 +A = 49 +M = 22 + +ModInv = 5 +A = 4b +M = 22 + +ModInv = 13 +A = 4d +M = 22 + +ModInv = 1f +A = 4f +M = 22 + +ModInv = 15 +A = 51 +M = 22 + +ModInv = 19 +A = 53 +M = 22 + +ModInv = 9 +A = 57 +M = 22 + +ModInv = d +A = 59 +M = 22 + +ModInv = 3 +A = 5b +M = 22 + +ModInv = f +A = 5d +M = 22 + +ModInv = 1d +A = 5f +M = 22 + +ModInv = 1b +A = 61 +M = 22 + +ModInv = b +A = 63 +M = 22 + +ModInv = 6 +A = -63 +M = 23 + +ModInv = 16 +A = -61 +M = 23 + +ModInv = 4 +A = -60 +M = 23 + +ModInv = 10 +A = -5e +M = 23 + +ModInv = 3 +A = -5d +M = 23 + +ModInv = 1b +A = -5c +M = 23 + +ModInv = b +A = -59 +M = 23 + +ModInv = 21 +A = -58 +M = 23 + +ModInv = 2 +A = -57 +M = 23 + +ModInv = 18 +A = -56 +M = 23 + +ModInv = 8 +A = -53 +M = 23 + +ModInv = 20 +A = -52 +M = 23 + +ModInv = 13 +A = -51 +M = 23 + +ModInv = 1f +A = -4f +M = 23 + +ModInv = d +A = -4e +M = 23 + +ModInv = 1d +A = -4c +M = 23 + +ModInv = 1a +A = -4a +M = 23 + +ModInv = 17 +A = -49 +M = 23 + +ModInv = 11 +A = -48 +M = 23 + +ModInv = 22 +A = -47 +M = 23 + +ModInv = 1 +A = -45 +M = 23 + +ModInv = 12 +A = -44 +M = 23 + +ModInv = c +A = -43 +M = 23 + +ModInv = 9 +A = -42 +M = 23 + +ModInv = 6 +A = -40 +M = 23 + +ModInv = 16 +A = -3e +M = 23 + +ModInv = 4 +A = -3d +M = 23 + +ModInv = 10 +A = -3b +M = 23 + +ModInv = 3 +A = -3a +M = 23 + +ModInv = 1b +A = -39 +M = 23 + +ModInv = b +A = -36 +M = 23 + +ModInv = 21 +A = -35 +M = 23 + +ModInv = 2 +A = -34 +M = 23 + +ModInv = 18 +A = -33 +M = 23 + +ModInv = 8 +A = -30 +M = 23 + +ModInv = 20 +A = -2f +M = 23 + +ModInv = 13 +A = -2e +M = 23 + +ModInv = 1f +A = -2c +M = 23 + +ModInv = d +A = -2b +M = 23 + +ModInv = 1d +A = -29 +M = 23 + +ModInv = 1a +A = -27 +M = 23 + +ModInv = 17 +A = -26 +M = 23 + +ModInv = 11 +A = -25 +M = 23 + +ModInv = 22 +A = -24 +M = 23 + +ModInv = 1 +A = -22 +M = 23 + +ModInv = 12 +A = -21 +M = 23 + +ModInv = c +A = -20 +M = 23 + +ModInv = 9 +A = -1f +M = 23 + +ModInv = 6 +A = -1d +M = 23 + +ModInv = 16 +A = -1b +M = 23 + +ModInv = 4 +A = -1a +M = 23 + +ModInv = 10 +A = -18 +M = 23 + +ModInv = 3 +A = -17 +M = 23 + +ModInv = 1b +A = -16 +M = 23 + +ModInv = b +A = -13 +M = 23 + +ModInv = 21 +A = -12 +M = 23 + +ModInv = 2 +A = -11 +M = 23 + +ModInv = 18 +A = -10 +M = 23 + +ModInv = 8 +A = -d +M = 23 + +ModInv = 20 +A = -c +M = 23 + +ModInv = 13 +A = -b +M = 23 + +ModInv = 1f +A = -9 +M = 23 + +ModInv = d +A = -8 +M = 23 + +ModInv = 1d +A = -6 +M = 23 + +ModInv = 1a +A = -4 +M = 23 + +ModInv = 17 +A = -3 +M = 23 + +ModInv = 11 +A = -2 +M = 23 + +ModInv = 22 +A = -1 +M = 23 + +ModInv = 1 +A = 1 +M = 23 + +ModInv = 12 +A = 2 +M = 23 + +ModInv = c +A = 3 +M = 23 + +ModInv = 9 +A = 4 +M = 23 + +ModInv = 6 +A = 6 +M = 23 + +ModInv = 16 +A = 8 +M = 23 + +ModInv = 4 +A = 9 +M = 23 + +ModInv = 10 +A = b +M = 23 + +ModInv = 3 +A = c +M = 23 + +ModInv = 1b +A = d +M = 23 + +ModInv = b +A = 10 +M = 23 + +ModInv = 21 +A = 11 +M = 23 + +ModInv = 2 +A = 12 +M = 23 + +ModInv = 18 +A = 13 +M = 23 + +ModInv = 8 +A = 16 +M = 23 + +ModInv = 20 +A = 17 +M = 23 + +ModInv = 13 +A = 18 +M = 23 + +ModInv = 1f +A = 1a +M = 23 + +ModInv = d +A = 1b +M = 23 + +ModInv = 1d +A = 1d +M = 23 + +ModInv = 1a +A = 1f +M = 23 + +ModInv = 17 +A = 20 +M = 23 + +ModInv = 11 +A = 21 +M = 23 + +ModInv = 22 +A = 22 +M = 23 + +ModInv = 1 +A = 24 +M = 23 + +ModInv = 12 +A = 25 +M = 23 + +ModInv = c +A = 26 +M = 23 + +ModInv = 9 +A = 27 +M = 23 + +ModInv = 6 +A = 29 +M = 23 + +ModInv = 16 +A = 2b +M = 23 + +ModInv = 4 +A = 2c +M = 23 + +ModInv = 10 +A = 2e +M = 23 + +ModInv = 3 +A = 2f +M = 23 + +ModInv = 1b +A = 30 +M = 23 + +ModInv = b +A = 33 +M = 23 + +ModInv = 21 +A = 34 +M = 23 + +ModInv = 2 +A = 35 +M = 23 + +ModInv = 18 +A = 36 +M = 23 + +ModInv = 8 +A = 39 +M = 23 + +ModInv = 20 +A = 3a +M = 23 + +ModInv = 13 +A = 3b +M = 23 + +ModInv = 1f +A = 3d +M = 23 + +ModInv = d +A = 3e +M = 23 + +ModInv = 1d +A = 40 +M = 23 + +ModInv = 1a +A = 42 +M = 23 + +ModInv = 17 +A = 43 +M = 23 + +ModInv = 11 +A = 44 +M = 23 + +ModInv = 22 +A = 45 +M = 23 + +ModInv = 1 +A = 47 +M = 23 + +ModInv = 12 +A = 48 +M = 23 + +ModInv = c +A = 49 +M = 23 + +ModInv = 9 +A = 4a +M = 23 + +ModInv = 6 +A = 4c +M = 23 + +ModInv = 16 +A = 4e +M = 23 + +ModInv = 4 +A = 4f +M = 23 + +ModInv = 10 +A = 51 +M = 23 + +ModInv = 3 +A = 52 +M = 23 + +ModInv = 1b +A = 53 +M = 23 + +ModInv = b +A = 56 +M = 23 + +ModInv = 21 +A = 57 +M = 23 + +ModInv = 2 +A = 58 +M = 23 + +ModInv = 18 +A = 59 +M = 23 + +ModInv = 8 +A = 5c +M = 23 + +ModInv = 20 +A = 5d +M = 23 + +ModInv = 13 +A = 5e +M = 23 + +ModInv = 1f +A = 60 +M = 23 + +ModInv = d +A = 61 +M = 23 + +ModInv = 1d +A = 63 +M = 23 + +ModInv = 17 +A = -61 +M = 24 + +ModInv = 19 +A = -5f +M = 24 + +ModInv = 11 +A = -5b +M = 24 + +ModInv = 13 +A = -59 +M = 24 + +ModInv = b +A = -55 +M = 24 + +ModInv = d +A = -53 +M = 24 + +ModInv = 5 +A = -4f +M = 24 + +ModInv = 7 +A = -4d +M = 24 + +ModInv = 23 +A = -49 +M = 24 + +ModInv = 1 +A = -47 +M = 24 + +ModInv = 1d +A = -43 +M = 24 + +ModInv = 1f +A = -41 +M = 24 + +ModInv = 17 +A = -3d +M = 24 + +ModInv = 19 +A = -3b +M = 24 + +ModInv = 11 +A = -37 +M = 24 + +ModInv = 13 +A = -35 +M = 24 + +ModInv = b +A = -31 +M = 24 + +ModInv = d +A = -2f +M = 24 + +ModInv = 5 +A = -2b +M = 24 + +ModInv = 7 +A = -29 +M = 24 + +ModInv = 23 +A = -25 +M = 24 + +ModInv = 1 +A = -23 +M = 24 + +ModInv = 1d +A = -1f +M = 24 + +ModInv = 1f +A = -1d +M = 24 + +ModInv = 17 +A = -19 +M = 24 + +ModInv = 19 +A = -17 +M = 24 + +ModInv = 11 +A = -13 +M = 24 + +ModInv = 13 +A = -11 +M = 24 + +ModInv = b +A = -d +M = 24 + +ModInv = d +A = -b +M = 24 + +ModInv = 5 +A = -7 +M = 24 + +ModInv = 7 +A = -5 +M = 24 + +ModInv = 23 +A = -1 +M = 24 + +ModInv = 1 +A = 1 +M = 24 + +ModInv = 1d +A = 5 +M = 24 + +ModInv = 1f +A = 7 +M = 24 + +ModInv = 17 +A = b +M = 24 + +ModInv = 19 +A = d +M = 24 + +ModInv = 11 +A = 11 +M = 24 + +ModInv = 13 +A = 13 +M = 24 + +ModInv = b +A = 17 +M = 24 + +ModInv = d +A = 19 +M = 24 + +ModInv = 5 +A = 1d +M = 24 + +ModInv = 7 +A = 1f +M = 24 + +ModInv = 23 +A = 23 +M = 24 + +ModInv = 1 +A = 25 +M = 24 + +ModInv = 1d +A = 29 +M = 24 + +ModInv = 1f +A = 2b +M = 24 + +ModInv = 17 +A = 2f +M = 24 + +ModInv = 19 +A = 31 +M = 24 + +ModInv = 11 +A = 35 +M = 24 + +ModInv = 13 +A = 37 +M = 24 + +ModInv = b +A = 3b +M = 24 + +ModInv = d +A = 3d +M = 24 + +ModInv = 5 +A = 41 +M = 24 + +ModInv = 7 +A = 43 +M = 24 + +ModInv = 23 +A = 47 +M = 24 + +ModInv = 1 +A = 49 +M = 24 + +ModInv = 1d +A = 4d +M = 24 + +ModInv = 1f +A = 4f +M = 24 + +ModInv = 17 +A = 53 +M = 24 + +ModInv = 19 +A = 55 +M = 24 + +ModInv = 11 +A = 59 +M = 24 + +ModInv = 13 +A = 5b +M = 24 + +ModInv = b +A = 5f +M = 24 + +ModInv = d +A = 61 +M = 24 + +ModInv = 1b +A = -64 +M = 25 + +ModInv = 22 +A = -63 +M = 25 + +ModInv = 14 +A = -62 +M = 25 + +ModInv = 8 +A = -61 +M = 25 + +ModInv = 5 +A = -60 +M = 25 + +ModInv = 7 +A = -5f +M = 25 + +ModInv = 18 +A = -5e +M = 25 + +ModInv = 23 +A = -5d +M = 25 + +ModInv = 2 +A = -5c +M = 25 + +ModInv = d +A = -5b +M = 25 + +ModInv = 1e +A = -5a +M = 25 + +ModInv = 20 +A = -59 +M = 25 + +ModInv = 1d +A = -58 +M = 25 + +ModInv = 11 +A = -57 +M = 25 + +ModInv = 3 +A = -56 +M = 25 + +ModInv = a +A = -55 +M = 25 + +ModInv = b +A = -54 +M = 25 + +ModInv = 4 +A = -53 +M = 25 + +ModInv = 17 +A = -52 +M = 25 + +ModInv = 15 +A = -51 +M = 25 + +ModInv = 6 +A = -50 +M = 25 + +ModInv = 16 +A = -4f +M = 25 + +ModInv = 9 +A = -4e +M = 25 + +ModInv = c +A = -4d +M = 25 + +ModInv = 12 +A = -4c +M = 25 + +ModInv = 24 +A = -4b +M = 25 + +ModInv = 1 +A = -49 +M = 25 + +ModInv = 13 +A = -48 +M = 25 + +ModInv = 19 +A = -47 +M = 25 + +ModInv = 1c +A = -46 +M = 25 + +ModInv = f +A = -45 +M = 25 + +ModInv = 1f +A = -44 +M = 25 + +ModInv = 10 +A = -43 +M = 25 + +ModInv = e +A = -42 +M = 25 + +ModInv = 21 +A = -41 +M = 25 + +ModInv = 1a +A = -40 +M = 25 + +ModInv = 1b +A = -3f +M = 25 + +ModInv = 22 +A = -3e +M = 25 + +ModInv = 14 +A = -3d +M = 25 + +ModInv = 8 +A = -3c +M = 25 + +ModInv = 5 +A = -3b +M = 25 + +ModInv = 7 +A = -3a +M = 25 + +ModInv = 18 +A = -39 +M = 25 + +ModInv = 23 +A = -38 +M = 25 + +ModInv = 2 +A = -37 +M = 25 + +ModInv = d +A = -36 +M = 25 + +ModInv = 1e +A = -35 +M = 25 + +ModInv = 20 +A = -34 +M = 25 + +ModInv = 1d +A = -33 +M = 25 + +ModInv = 11 +A = -32 +M = 25 + +ModInv = 3 +A = -31 +M = 25 + +ModInv = a +A = -30 +M = 25 + +ModInv = b +A = -2f +M = 25 + +ModInv = 4 +A = -2e +M = 25 + +ModInv = 17 +A = -2d +M = 25 + +ModInv = 15 +A = -2c +M = 25 + +ModInv = 6 +A = -2b +M = 25 + +ModInv = 16 +A = -2a +M = 25 + +ModInv = 9 +A = -29 +M = 25 + +ModInv = c +A = -28 +M = 25 + +ModInv = 12 +A = -27 +M = 25 + +ModInv = 24 +A = -26 +M = 25 + +ModInv = 1 +A = -24 +M = 25 + +ModInv = 13 +A = -23 +M = 25 + +ModInv = 19 +A = -22 +M = 25 + +ModInv = 1c +A = -21 +M = 25 + +ModInv = f +A = -20 +M = 25 + +ModInv = 1f +A = -1f +M = 25 + +ModInv = 10 +A = -1e +M = 25 + +ModInv = e +A = -1d +M = 25 + +ModInv = 21 +A = -1c +M = 25 + +ModInv = 1a +A = -1b +M = 25 + +ModInv = 1b +A = -1a +M = 25 + +ModInv = 22 +A = -19 +M = 25 + +ModInv = 14 +A = -18 +M = 25 + +ModInv = 8 +A = -17 +M = 25 + +ModInv = 5 +A = -16 +M = 25 + +ModInv = 7 +A = -15 +M = 25 + +ModInv = 18 +A = -14 +M = 25 + +ModInv = 23 +A = -13 +M = 25 + +ModInv = 2 +A = -12 +M = 25 + +ModInv = d +A = -11 +M = 25 + +ModInv = 1e +A = -10 +M = 25 + +ModInv = 20 +A = -f +M = 25 + +ModInv = 1d +A = -e +M = 25 + +ModInv = 11 +A = -d +M = 25 + +ModInv = 3 +A = -c +M = 25 + +ModInv = a +A = -b +M = 25 + +ModInv = b +A = -a +M = 25 + +ModInv = 4 +A = -9 +M = 25 + +ModInv = 17 +A = -8 +M = 25 + +ModInv = 15 +A = -7 +M = 25 + +ModInv = 6 +A = -6 +M = 25 + +ModInv = 16 +A = -5 +M = 25 + +ModInv = 9 +A = -4 +M = 25 + +ModInv = c +A = -3 +M = 25 + +ModInv = 12 +A = -2 +M = 25 + +ModInv = 24 +A = -1 +M = 25 + +ModInv = 1 +A = 1 +M = 25 + +ModInv = 13 +A = 2 +M = 25 + +ModInv = 19 +A = 3 +M = 25 + +ModInv = 1c +A = 4 +M = 25 + +ModInv = f +A = 5 +M = 25 + +ModInv = 1f +A = 6 +M = 25 + +ModInv = 10 +A = 7 +M = 25 + +ModInv = e +A = 8 +M = 25 + +ModInv = 21 +A = 9 +M = 25 + +ModInv = 1a +A = a +M = 25 + +ModInv = 1b +A = b +M = 25 + +ModInv = 22 +A = c +M = 25 + +ModInv = 14 +A = d +M = 25 + +ModInv = 8 +A = e +M = 25 + +ModInv = 5 +A = f +M = 25 + +ModInv = 7 +A = 10 +M = 25 + +ModInv = 18 +A = 11 +M = 25 + +ModInv = 23 +A = 12 +M = 25 + +ModInv = 2 +A = 13 +M = 25 + +ModInv = d +A = 14 +M = 25 + +ModInv = 1e +A = 15 +M = 25 + +ModInv = 20 +A = 16 +M = 25 + +ModInv = 1d +A = 17 +M = 25 + +ModInv = 11 +A = 18 +M = 25 + +ModInv = 3 +A = 19 +M = 25 + +ModInv = a +A = 1a +M = 25 + +ModInv = b +A = 1b +M = 25 + +ModInv = 4 +A = 1c +M = 25 + +ModInv = 17 +A = 1d +M = 25 + +ModInv = 15 +A = 1e +M = 25 + +ModInv = 6 +A = 1f +M = 25 + +ModInv = 16 +A = 20 +M = 25 + +ModInv = 9 +A = 21 +M = 25 + +ModInv = c +A = 22 +M = 25 + +ModInv = 12 +A = 23 +M = 25 + +ModInv = 24 +A = 24 +M = 25 + +ModInv = 1 +A = 26 +M = 25 + +ModInv = 13 +A = 27 +M = 25 + +ModInv = 19 +A = 28 +M = 25 + +ModInv = 1c +A = 29 +M = 25 + +ModInv = f +A = 2a +M = 25 + +ModInv = 1f +A = 2b +M = 25 + +ModInv = 10 +A = 2c +M = 25 + +ModInv = e +A = 2d +M = 25 + +ModInv = 21 +A = 2e +M = 25 + +ModInv = 1a +A = 2f +M = 25 + +ModInv = 1b +A = 30 +M = 25 + +ModInv = 22 +A = 31 +M = 25 + +ModInv = 14 +A = 32 +M = 25 + +ModInv = 8 +A = 33 +M = 25 + +ModInv = 5 +A = 34 +M = 25 + +ModInv = 7 +A = 35 +M = 25 + +ModInv = 18 +A = 36 +M = 25 + +ModInv = 23 +A = 37 +M = 25 + +ModInv = 2 +A = 38 +M = 25 + +ModInv = d +A = 39 +M = 25 + +ModInv = 1e +A = 3a +M = 25 + +ModInv = 20 +A = 3b +M = 25 + +ModInv = 1d +A = 3c +M = 25 + +ModInv = 11 +A = 3d +M = 25 + +ModInv = 3 +A = 3e +M = 25 + +ModInv = a +A = 3f +M = 25 + +ModInv = b +A = 40 +M = 25 + +ModInv = 4 +A = 41 +M = 25 + +ModInv = 17 +A = 42 +M = 25 + +ModInv = 15 +A = 43 +M = 25 + +ModInv = 6 +A = 44 +M = 25 + +ModInv = 16 +A = 45 +M = 25 + +ModInv = 9 +A = 46 +M = 25 + +ModInv = c +A = 47 +M = 25 + +ModInv = 12 +A = 48 +M = 25 + +ModInv = 24 +A = 49 +M = 25 + +ModInv = 1 +A = 4b +M = 25 + +ModInv = 13 +A = 4c +M = 25 + +ModInv = 19 +A = 4d +M = 25 + +ModInv = 1c +A = 4e +M = 25 + +ModInv = f +A = 4f +M = 25 + +ModInv = 1f +A = 50 +M = 25 + +ModInv = 10 +A = 51 +M = 25 + +ModInv = e +A = 52 +M = 25 + +ModInv = 21 +A = 53 +M = 25 + +ModInv = 1a +A = 54 +M = 25 + +ModInv = 1b +A = 55 +M = 25 + +ModInv = 22 +A = 56 +M = 25 + +ModInv = 14 +A = 57 +M = 25 + +ModInv = 8 +A = 58 +M = 25 + +ModInv = 5 +A = 59 +M = 25 + +ModInv = 7 +A = 5a +M = 25 + +ModInv = 18 +A = 5b +M = 25 + +ModInv = 23 +A = 5c +M = 25 + +ModInv = 2 +A = 5d +M = 25 + +ModInv = d +A = 5e +M = 25 + +ModInv = 1e +A = 5f +M = 25 + +ModInv = 20 +A = 60 +M = 25 + +ModInv = 1d +A = 61 +M = 25 + +ModInv = 11 +A = 62 +M = 25 + +ModInv = 3 +A = 63 +M = 25 + +ModInv = 21 +A = -63 +M = 26 + +ModInv = 9 +A = -61 +M = 26 + +ModInv = 1d +A = -5d +M = 26 + +ModInv = 5 +A = -5b +M = 26 + +ModInv = 23 +A = -59 +M = 26 + +ModInv = 1f +A = -57 +M = 26 + +ModInv = 15 +A = -55 +M = 26 + +ModInv = 1b +A = -53 +M = 26 + +ModInv = f +A = -51 +M = 26 + +ModInv = 19 +A = -4f +M = 26 + +ModInv = 25 +A = -4d +M = 26 + +ModInv = 1 +A = -4b +M = 26 + +ModInv = d +A = -49 +M = 26 + +ModInv = 17 +A = -47 +M = 26 + +ModInv = b +A = -45 +M = 26 + +ModInv = 11 +A = -43 +M = 26 + +ModInv = 7 +A = -41 +M = 26 + +ModInv = 3 +A = -3f +M = 26 + +ModInv = 21 +A = -3d +M = 26 + +ModInv = 9 +A = -3b +M = 26 + +ModInv = 1d +A = -37 +M = 26 + +ModInv = 5 +A = -35 +M = 26 + +ModInv = 23 +A = -33 +M = 26 + +ModInv = 1f +A = -31 +M = 26 + +ModInv = 15 +A = -2f +M = 26 + +ModInv = 1b +A = -2d +M = 26 + +ModInv = f +A = -2b +M = 26 + +ModInv = 19 +A = -29 +M = 26 + +ModInv = 25 +A = -27 +M = 26 + +ModInv = 1 +A = -25 +M = 26 + +ModInv = d +A = -23 +M = 26 + +ModInv = 17 +A = -21 +M = 26 + +ModInv = b +A = -1f +M = 26 + +ModInv = 11 +A = -1d +M = 26 + +ModInv = 7 +A = -1b +M = 26 + +ModInv = 3 +A = -19 +M = 26 + +ModInv = 21 +A = -17 +M = 26 + +ModInv = 9 +A = -15 +M = 26 + +ModInv = 1d +A = -11 +M = 26 + +ModInv = 5 +A = -f +M = 26 + +ModInv = 23 +A = -d +M = 26 + +ModInv = 1f +A = -b +M = 26 + +ModInv = 15 +A = -9 +M = 26 + +ModInv = 1b +A = -7 +M = 26 + +ModInv = f +A = -5 +M = 26 + +ModInv = 19 +A = -3 +M = 26 + +ModInv = 25 +A = -1 +M = 26 + +ModInv = 1 +A = 1 +M = 26 + +ModInv = d +A = 3 +M = 26 + +ModInv = 17 +A = 5 +M = 26 + +ModInv = b +A = 7 +M = 26 + +ModInv = 11 +A = 9 +M = 26 + +ModInv = 7 +A = b +M = 26 + +ModInv = 3 +A = d +M = 26 + +ModInv = 21 +A = f +M = 26 + +ModInv = 9 +A = 11 +M = 26 + +ModInv = 1d +A = 15 +M = 26 + +ModInv = 5 +A = 17 +M = 26 + +ModInv = 23 +A = 19 +M = 26 + +ModInv = 1f +A = 1b +M = 26 + +ModInv = 15 +A = 1d +M = 26 + +ModInv = 1b +A = 1f +M = 26 + +ModInv = f +A = 21 +M = 26 + +ModInv = 19 +A = 23 +M = 26 + +ModInv = 25 +A = 25 +M = 26 + +ModInv = 1 +A = 27 +M = 26 + +ModInv = d +A = 29 +M = 26 + +ModInv = 17 +A = 2b +M = 26 + +ModInv = b +A = 2d +M = 26 + +ModInv = 11 +A = 2f +M = 26 + +ModInv = 7 +A = 31 +M = 26 + +ModInv = 3 +A = 33 +M = 26 + +ModInv = 21 +A = 35 +M = 26 + +ModInv = 9 +A = 37 +M = 26 + +ModInv = 1d +A = 3b +M = 26 + +ModInv = 5 +A = 3d +M = 26 + +ModInv = 23 +A = 3f +M = 26 + +ModInv = 1f +A = 41 +M = 26 + +ModInv = 15 +A = 43 +M = 26 + +ModInv = 1b +A = 45 +M = 26 + +ModInv = f +A = 47 +M = 26 + +ModInv = 19 +A = 49 +M = 26 + +ModInv = 25 +A = 4b +M = 26 + +ModInv = 1 +A = 4d +M = 26 + +ModInv = d +A = 4f +M = 26 + +ModInv = 17 +A = 51 +M = 26 + +ModInv = b +A = 53 +M = 26 + +ModInv = 11 +A = 55 +M = 26 + +ModInv = 7 +A = 57 +M = 26 + +ModInv = 3 +A = 59 +M = 26 + +ModInv = 21 +A = 5b +M = 26 + +ModInv = 9 +A = 5d +M = 26 + +ModInv = 1d +A = 61 +M = 26 + +ModInv = 5 +A = 63 +M = 26 + +ModInv = 17 +A = -64 +M = 27 + +ModInv = 25 +A = -62 +M = 27 + +ModInv = 2 +A = -61 +M = 27 + +ModInv = 10 +A = -5f +M = 27 + +ModInv = 11 +A = -5e +M = 27 + +ModInv = 19 +A = -5c +M = 27 + +ModInv = 7 +A = -59 +M = 27 + +ModInv = 23 +A = -58 +M = 27 + +ModInv = 22 +A = -56 +M = 27 + +ModInv = b +A = -55 +M = 27 + +ModInv = 1f +A = -53 +M = 27 + +ModInv = 1d +A = -52 +M = 27 + +ModInv = 13 +A = -50 +M = 27 + +ModInv = 26 +A = -4f +M = 27 + +ModInv = 1 +A = -4d +M = 27 + +ModInv = 14 +A = -4c +M = 27 + +ModInv = a +A = -4a +M = 27 + +ModInv = 8 +A = -49 +M = 27 + +ModInv = 1c +A = -47 +M = 27 + +ModInv = 5 +A = -46 +M = 27 + +ModInv = 4 +A = -44 +M = 27 + +ModInv = 20 +A = -43 +M = 27 + +ModInv = e +A = -40 +M = 27 + +ModInv = 16 +A = -3e +M = 27 + +ModInv = 17 +A = -3d +M = 27 + +ModInv = 25 +A = -3b +M = 27 + +ModInv = 2 +A = -3a +M = 27 + +ModInv = 10 +A = -38 +M = 27 + +ModInv = 11 +A = -37 +M = 27 + +ModInv = 19 +A = -35 +M = 27 + +ModInv = 7 +A = -32 +M = 27 + +ModInv = 23 +A = -31 +M = 27 + +ModInv = 22 +A = -2f +M = 27 + +ModInv = b +A = -2e +M = 27 + +ModInv = 1f +A = -2c +M = 27 + +ModInv = 1d +A = -2b +M = 27 + +ModInv = 13 +A = -29 +M = 27 + +ModInv = 26 +A = -28 +M = 27 + +ModInv = 1 +A = -26 +M = 27 + +ModInv = 14 +A = -25 +M = 27 + +ModInv = a +A = -23 +M = 27 + +ModInv = 8 +A = -22 +M = 27 + +ModInv = 1c +A = -20 +M = 27 + +ModInv = 5 +A = -1f +M = 27 + +ModInv = 4 +A = -1d +M = 27 + +ModInv = 20 +A = -1c +M = 27 + +ModInv = e +A = -19 +M = 27 + +ModInv = 16 +A = -17 +M = 27 + +ModInv = 17 +A = -16 +M = 27 + +ModInv = 25 +A = -14 +M = 27 + +ModInv = 2 +A = -13 +M = 27 + +ModInv = 10 +A = -11 +M = 27 + +ModInv = 11 +A = -10 +M = 27 + +ModInv = 19 +A = -e +M = 27 + +ModInv = 7 +A = -b +M = 27 + +ModInv = 23 +A = -a +M = 27 + +ModInv = 22 +A = -8 +M = 27 + +ModInv = b +A = -7 +M = 27 + +ModInv = 1f +A = -5 +M = 27 + +ModInv = 1d +A = -4 +M = 27 + +ModInv = 13 +A = -2 +M = 27 + +ModInv = 26 +A = -1 +M = 27 + +ModInv = 1 +A = 1 +M = 27 + +ModInv = 14 +A = 2 +M = 27 + +ModInv = a +A = 4 +M = 27 + +ModInv = 8 +A = 5 +M = 27 + +ModInv = 1c +A = 7 +M = 27 + +ModInv = 5 +A = 8 +M = 27 + +ModInv = 4 +A = a +M = 27 + +ModInv = 20 +A = b +M = 27 + +ModInv = e +A = e +M = 27 + +ModInv = 16 +A = 10 +M = 27 + +ModInv = 17 +A = 11 +M = 27 + +ModInv = 25 +A = 13 +M = 27 + +ModInv = 2 +A = 14 +M = 27 + +ModInv = 10 +A = 16 +M = 27 + +ModInv = 11 +A = 17 +M = 27 + +ModInv = 19 +A = 19 +M = 27 + +ModInv = 7 +A = 1c +M = 27 + +ModInv = 23 +A = 1d +M = 27 + +ModInv = 22 +A = 1f +M = 27 + +ModInv = b +A = 20 +M = 27 + +ModInv = 1f +A = 22 +M = 27 + +ModInv = 1d +A = 23 +M = 27 + +ModInv = 13 +A = 25 +M = 27 + +ModInv = 26 +A = 26 +M = 27 + +ModInv = 1 +A = 28 +M = 27 + +ModInv = 14 +A = 29 +M = 27 + +ModInv = a +A = 2b +M = 27 + +ModInv = 8 +A = 2c +M = 27 + +ModInv = 1c +A = 2e +M = 27 + +ModInv = 5 +A = 2f +M = 27 + +ModInv = 4 +A = 31 +M = 27 + +ModInv = 20 +A = 32 +M = 27 + +ModInv = e +A = 35 +M = 27 + +ModInv = 16 +A = 37 +M = 27 + +ModInv = 17 +A = 38 +M = 27 + +ModInv = 25 +A = 3a +M = 27 + +ModInv = 2 +A = 3b +M = 27 + +ModInv = 10 +A = 3d +M = 27 + +ModInv = 11 +A = 3e +M = 27 + +ModInv = 19 +A = 40 +M = 27 + +ModInv = 7 +A = 43 +M = 27 + +ModInv = 23 +A = 44 +M = 27 + +ModInv = 22 +A = 46 +M = 27 + +ModInv = b +A = 47 +M = 27 + +ModInv = 1f +A = 49 +M = 27 + +ModInv = 1d +A = 4a +M = 27 + +ModInv = 13 +A = 4c +M = 27 + +ModInv = 26 +A = 4d +M = 27 + +ModInv = 1 +A = 4f +M = 27 + +ModInv = 14 +A = 50 +M = 27 + +ModInv = a +A = 52 +M = 27 + +ModInv = 8 +A = 53 +M = 27 + +ModInv = 1c +A = 55 +M = 27 + +ModInv = 5 +A = 56 +M = 27 + +ModInv = 4 +A = 58 +M = 27 + +ModInv = 20 +A = 59 +M = 27 + +ModInv = e +A = 5c +M = 27 + +ModInv = 16 +A = 5e +M = 27 + +ModInv = 17 +A = 5f +M = 27 + +ModInv = 25 +A = 61 +M = 27 + +ModInv = 2 +A = 62 +M = 27 + +ModInv = 15 +A = -63 +M = 28 + +ModInv = 7 +A = -61 +M = 28 + +ModInv = 3 +A = -5d +M = 28 + +ModInv = 1d +A = -5b +M = 28 + +ModInv = 1f +A = -59 +M = 28 + +ModInv = 11 +A = -57 +M = 28 + +ModInv = d +A = -53 +M = 28 + +ModInv = 27 +A = -51 +M = 28 + +ModInv = 1 +A = -4f +M = 28 + +ModInv = 1b +A = -4d +M = 28 + +ModInv = 17 +A = -49 +M = 28 + +ModInv = 9 +A = -47 +M = 28 + +ModInv = b +A = -45 +M = 28 + +ModInv = 25 +A = -43 +M = 28 + +ModInv = 21 +A = -3f +M = 28 + +ModInv = 13 +A = -3d +M = 28 + +ModInv = 15 +A = -3b +M = 28 + +ModInv = 7 +A = -39 +M = 28 + +ModInv = 3 +A = -35 +M = 28 + +ModInv = 1d +A = -33 +M = 28 + +ModInv = 1f +A = -31 +M = 28 + +ModInv = 11 +A = -2f +M = 28 + +ModInv = d +A = -2b +M = 28 + +ModInv = 27 +A = -29 +M = 28 + +ModInv = 1 +A = -27 +M = 28 + +ModInv = 1b +A = -25 +M = 28 + +ModInv = 17 +A = -21 +M = 28 + +ModInv = 9 +A = -1f +M = 28 + +ModInv = b +A = -1d +M = 28 + +ModInv = 25 +A = -1b +M = 28 + +ModInv = 21 +A = -17 +M = 28 + +ModInv = 13 +A = -15 +M = 28 + +ModInv = 15 +A = -13 +M = 28 + +ModInv = 7 +A = -11 +M = 28 + +ModInv = 3 +A = -d +M = 28 + +ModInv = 1d +A = -b +M = 28 + +ModInv = 1f +A = -9 +M = 28 + +ModInv = 11 +A = -7 +M = 28 + +ModInv = d +A = -3 +M = 28 + +ModInv = 27 +A = -1 +M = 28 + +ModInv = 1 +A = 1 +M = 28 + +ModInv = 1b +A = 3 +M = 28 + +ModInv = 17 +A = 7 +M = 28 + +ModInv = 9 +A = 9 +M = 28 + +ModInv = b +A = b +M = 28 + +ModInv = 25 +A = d +M = 28 + +ModInv = 21 +A = 11 +M = 28 + +ModInv = 13 +A = 13 +M = 28 + +ModInv = 15 +A = 15 +M = 28 + +ModInv = 7 +A = 17 +M = 28 + +ModInv = 3 +A = 1b +M = 28 + +ModInv = 1d +A = 1d +M = 28 + +ModInv = 1f +A = 1f +M = 28 + +ModInv = 11 +A = 21 +M = 28 + +ModInv = d +A = 25 +M = 28 + +ModInv = 27 +A = 27 +M = 28 + +ModInv = 1 +A = 29 +M = 28 + +ModInv = 1b +A = 2b +M = 28 + +ModInv = 17 +A = 2f +M = 28 + +ModInv = 9 +A = 31 +M = 28 + +ModInv = b +A = 33 +M = 28 + +ModInv = 25 +A = 35 +M = 28 + +ModInv = 21 +A = 39 +M = 28 + +ModInv = 13 +A = 3b +M = 28 + +ModInv = 15 +A = 3d +M = 28 + +ModInv = 7 +A = 3f +M = 28 + +ModInv = 3 +A = 43 +M = 28 + +ModInv = 1d +A = 45 +M = 28 + +ModInv = 1f +A = 47 +M = 28 + +ModInv = 11 +A = 49 +M = 28 + +ModInv = d +A = 4d +M = 28 + +ModInv = 27 +A = 4f +M = 28 + +ModInv = 1 +A = 51 +M = 28 + +ModInv = 1b +A = 53 +M = 28 + +ModInv = 17 +A = 57 +M = 28 + +ModInv = 9 +A = 59 +M = 28 + +ModInv = b +A = 5b +M = 28 + +ModInv = 25 +A = 5d +M = 28 + +ModInv = 21 +A = 61 +M = 28 + +ModInv = 13 +A = 63 +M = 28 + +ModInv = 19 +A = -64 +M = 29 + +ModInv = c +A = -63 +M = 29 + +ModInv = 17 +A = -62 +M = 29 + +ModInv = 1e +A = -61 +M = 29 + +ModInv = 26 +A = -60 +M = 29 + +ModInv = 16 +A = -5f +M = 29 + +ModInv = 11 +A = -5e +M = 29 + +ModInv = 1a +A = -5d +M = 29 + +ModInv = 4 +A = -5c +M = 29 + +ModInv = 9 +A = -5b +M = 29 + +ModInv = 5 +A = -5a +M = 29 + +ModInv = 23 +A = -59 +M = 29 + +ModInv = 22 +A = -58 +M = 29 + +ModInv = 8 +A = -57 +M = 29 + +ModInv = a +A = -56 +M = 29 + +ModInv = 1b +A = -55 +M = 29 + +ModInv = 14 +A = -54 +M = 29 + +ModInv = 28 +A = -53 +M = 29 + +ModInv = 1 +A = -51 +M = 29 + +ModInv = 15 +A = -50 +M = 29 + +ModInv = e +A = -4f +M = 29 + +ModInv = 1f +A = -4e +M = 29 + +ModInv = 21 +A = -4d +M = 29 + +ModInv = 7 +A = -4c +M = 29 + +ModInv = 6 +A = -4b +M = 29 + +ModInv = 24 +A = -4a +M = 29 + +ModInv = 20 +A = -49 +M = 29 + +ModInv = 25 +A = -48 +M = 29 + +ModInv = f +A = -47 +M = 29 + +ModInv = 18 +A = -46 +M = 29 + +ModInv = 13 +A = -45 +M = 29 + +ModInv = 3 +A = -44 +M = 29 + +ModInv = b +A = -43 +M = 29 + +ModInv = 12 +A = -42 +M = 29 + +ModInv = 1d +A = -41 +M = 29 + +ModInv = 10 +A = -40 +M = 29 + +ModInv = d +A = -3f +M = 29 + +ModInv = 27 +A = -3e +M = 29 + +ModInv = 2 +A = -3d +M = 29 + +ModInv = 1c +A = -3c +M = 29 + +ModInv = 19 +A = -3b +M = 29 + +ModInv = c +A = -3a +M = 29 + +ModInv = 17 +A = -39 +M = 29 + +ModInv = 1e +A = -38 +M = 29 + +ModInv = 26 +A = -37 +M = 29 + +ModInv = 16 +A = -36 +M = 29 + +ModInv = 11 +A = -35 +M = 29 + +ModInv = 1a +A = -34 +M = 29 + +ModInv = 4 +A = -33 +M = 29 + +ModInv = 9 +A = -32 +M = 29 + +ModInv = 5 +A = -31 +M = 29 + +ModInv = 23 +A = -30 +M = 29 + +ModInv = 22 +A = -2f +M = 29 + +ModInv = 8 +A = -2e +M = 29 + +ModInv = a +A = -2d +M = 29 + +ModInv = 1b +A = -2c +M = 29 + +ModInv = 14 +A = -2b +M = 29 + +ModInv = 28 +A = -2a +M = 29 + +ModInv = 1 +A = -28 +M = 29 + +ModInv = 15 +A = -27 +M = 29 + +ModInv = e +A = -26 +M = 29 + +ModInv = 1f +A = -25 +M = 29 + +ModInv = 21 +A = -24 +M = 29 + +ModInv = 7 +A = -23 +M = 29 + +ModInv = 6 +A = -22 +M = 29 + +ModInv = 24 +A = -21 +M = 29 + +ModInv = 20 +A = -20 +M = 29 + +ModInv = 25 +A = -1f +M = 29 + +ModInv = f +A = -1e +M = 29 + +ModInv = 18 +A = -1d +M = 29 + +ModInv = 13 +A = -1c +M = 29 + +ModInv = 3 +A = -1b +M = 29 + +ModInv = b +A = -1a +M = 29 + +ModInv = 12 +A = -19 +M = 29 + +ModInv = 1d +A = -18 +M = 29 + +ModInv = 10 +A = -17 +M = 29 + +ModInv = d +A = -16 +M = 29 + +ModInv = 27 +A = -15 +M = 29 + +ModInv = 2 +A = -14 +M = 29 + +ModInv = 1c +A = -13 +M = 29 + +ModInv = 19 +A = -12 +M = 29 + +ModInv = c +A = -11 +M = 29 + +ModInv = 17 +A = -10 +M = 29 + +ModInv = 1e +A = -f +M = 29 + +ModInv = 26 +A = -e +M = 29 + +ModInv = 16 +A = -d +M = 29 + +ModInv = 11 +A = -c +M = 29 + +ModInv = 1a +A = -b +M = 29 + +ModInv = 4 +A = -a +M = 29 + +ModInv = 9 +A = -9 +M = 29 + +ModInv = 5 +A = -8 +M = 29 + +ModInv = 23 +A = -7 +M = 29 + +ModInv = 22 +A = -6 +M = 29 + +ModInv = 8 +A = -5 +M = 29 + +ModInv = a +A = -4 +M = 29 + +ModInv = 1b +A = -3 +M = 29 + +ModInv = 14 +A = -2 +M = 29 + +ModInv = 28 +A = -1 +M = 29 + +ModInv = 1 +A = 1 +M = 29 + +ModInv = 15 +A = 2 +M = 29 + +ModInv = e +A = 3 +M = 29 + +ModInv = 1f +A = 4 +M = 29 + +ModInv = 21 +A = 5 +M = 29 + +ModInv = 7 +A = 6 +M = 29 + +ModInv = 6 +A = 7 +M = 29 + +ModInv = 24 +A = 8 +M = 29 + +ModInv = 20 +A = 9 +M = 29 + +ModInv = 25 +A = a +M = 29 + +ModInv = f +A = b +M = 29 + +ModInv = 18 +A = c +M = 29 + +ModInv = 13 +A = d +M = 29 + +ModInv = 3 +A = e +M = 29 + +ModInv = b +A = f +M = 29 + +ModInv = 12 +A = 10 +M = 29 + +ModInv = 1d +A = 11 +M = 29 + +ModInv = 10 +A = 12 +M = 29 + +ModInv = d +A = 13 +M = 29 + +ModInv = 27 +A = 14 +M = 29 + +ModInv = 2 +A = 15 +M = 29 + +ModInv = 1c +A = 16 +M = 29 + +ModInv = 19 +A = 17 +M = 29 + +ModInv = c +A = 18 +M = 29 + +ModInv = 17 +A = 19 +M = 29 + +ModInv = 1e +A = 1a +M = 29 + +ModInv = 26 +A = 1b +M = 29 + +ModInv = 16 +A = 1c +M = 29 + +ModInv = 11 +A = 1d +M = 29 + +ModInv = 1a +A = 1e +M = 29 + +ModInv = 4 +A = 1f +M = 29 + +ModInv = 9 +A = 20 +M = 29 + +ModInv = 5 +A = 21 +M = 29 + +ModInv = 23 +A = 22 +M = 29 + +ModInv = 22 +A = 23 +M = 29 + +ModInv = 8 +A = 24 +M = 29 + +ModInv = a +A = 25 +M = 29 + +ModInv = 1b +A = 26 +M = 29 + +ModInv = 14 +A = 27 +M = 29 + +ModInv = 28 +A = 28 +M = 29 + +ModInv = 1 +A = 2a +M = 29 + +ModInv = 15 +A = 2b +M = 29 + +ModInv = e +A = 2c +M = 29 + +ModInv = 1f +A = 2d +M = 29 + +ModInv = 21 +A = 2e +M = 29 + +ModInv = 7 +A = 2f +M = 29 + +ModInv = 6 +A = 30 +M = 29 + +ModInv = 24 +A = 31 +M = 29 + +ModInv = 20 +A = 32 +M = 29 + +ModInv = 25 +A = 33 +M = 29 + +ModInv = f +A = 34 +M = 29 + +ModInv = 18 +A = 35 +M = 29 + +ModInv = 13 +A = 36 +M = 29 + +ModInv = 3 +A = 37 +M = 29 + +ModInv = b +A = 38 +M = 29 + +ModInv = 12 +A = 39 +M = 29 + +ModInv = 1d +A = 3a +M = 29 + +ModInv = 10 +A = 3b +M = 29 + +ModInv = d +A = 3c +M = 29 + +ModInv = 27 +A = 3d +M = 29 + +ModInv = 2 +A = 3e +M = 29 + +ModInv = 1c +A = 3f +M = 29 + +ModInv = 19 +A = 40 +M = 29 + +ModInv = c +A = 41 +M = 29 + +ModInv = 17 +A = 42 +M = 29 + +ModInv = 1e +A = 43 +M = 29 + +ModInv = 26 +A = 44 +M = 29 + +ModInv = 16 +A = 45 +M = 29 + +ModInv = 11 +A = 46 +M = 29 + +ModInv = 1a +A = 47 +M = 29 + +ModInv = 4 +A = 48 +M = 29 + +ModInv = 9 +A = 49 +M = 29 + +ModInv = 5 +A = 4a +M = 29 + +ModInv = 23 +A = 4b +M = 29 + +ModInv = 22 +A = 4c +M = 29 + +ModInv = 8 +A = 4d +M = 29 + +ModInv = a +A = 4e +M = 29 + +ModInv = 1b +A = 4f +M = 29 + +ModInv = 14 +A = 50 +M = 29 + +ModInv = 28 +A = 51 +M = 29 + +ModInv = 1 +A = 53 +M = 29 + +ModInv = 15 +A = 54 +M = 29 + +ModInv = e +A = 55 +M = 29 + +ModInv = 1f +A = 56 +M = 29 + +ModInv = 21 +A = 57 +M = 29 + +ModInv = 7 +A = 58 +M = 29 + +ModInv = 6 +A = 59 +M = 29 + +ModInv = 24 +A = 5a +M = 29 + +ModInv = 20 +A = 5b +M = 29 + +ModInv = 25 +A = 5c +M = 29 + +ModInv = f +A = 5d +M = 29 + +ModInv = 18 +A = 5e +M = 29 + +ModInv = 13 +A = 5f +M = 29 + +ModInv = 3 +A = 60 +M = 29 + +ModInv = b +A = 61 +M = 29 + +ModInv = 12 +A = 62 +M = 29 + +ModInv = 1d +A = 63 +M = 29 + +ModInv = 1d +A = -61 +M = 2a + +ModInv = 13 +A = -5f +M = 2a + +ModInv = 19 +A = -59 +M = 2a + +ModInv = 29 +A = -55 +M = 2a + +ModInv = 1 +A = -53 +M = 2a + +ModInv = 11 +A = -4f +M = 2a + +ModInv = 17 +A = -49 +M = 2a + +ModInv = d +A = -47 +M = 2a + +ModInv = 5 +A = -43 +M = 2a + +ModInv = 1f +A = -41 +M = 2a + +ModInv = b +A = -3d +M = 2a + +ModInv = 25 +A = -3b +M = 2a + +ModInv = 1d +A = -37 +M = 2a + +ModInv = 13 +A = -35 +M = 2a + +ModInv = 19 +A = -2f +M = 2a + +ModInv = 29 +A = -2b +M = 2a + +ModInv = 1 +A = -29 +M = 2a + +ModInv = 11 +A = -25 +M = 2a + +ModInv = 17 +A = -1f +M = 2a + +ModInv = d +A = -1d +M = 2a + +ModInv = 5 +A = -19 +M = 2a + +ModInv = 1f +A = -17 +M = 2a + +ModInv = b +A = -13 +M = 2a + +ModInv = 25 +A = -11 +M = 2a + +ModInv = 1d +A = -d +M = 2a + +ModInv = 13 +A = -b +M = 2a + +ModInv = 19 +A = -5 +M = 2a + +ModInv = 29 +A = -1 +M = 2a + +ModInv = 1 +A = 1 +M = 2a + +ModInv = 11 +A = 5 +M = 2a + +ModInv = 17 +A = b +M = 2a + +ModInv = d +A = d +M = 2a + +ModInv = 5 +A = 11 +M = 2a + +ModInv = 1f +A = 13 +M = 2a + +ModInv = b +A = 17 +M = 2a + +ModInv = 25 +A = 19 +M = 2a + +ModInv = 1d +A = 1d +M = 2a + +ModInv = 13 +A = 1f +M = 2a + +ModInv = 19 +A = 25 +M = 2a + +ModInv = 29 +A = 29 +M = 2a + +ModInv = 1 +A = 2b +M = 2a + +ModInv = 11 +A = 2f +M = 2a + +ModInv = 17 +A = 35 +M = 2a + +ModInv = d +A = 37 +M = 2a + +ModInv = 5 +A = 3b +M = 2a + +ModInv = 1f +A = 3d +M = 2a + +ModInv = b +A = 41 +M = 2a + +ModInv = 25 +A = 43 +M = 2a + +ModInv = 1d +A = 47 +M = 2a + +ModInv = 13 +A = 49 +M = 2a + +ModInv = 19 +A = 4f +M = 2a + +ModInv = 29 +A = 53 +M = 2a + +ModInv = 1 +A = 55 +M = 2a + +ModInv = 11 +A = 59 +M = 2a + +ModInv = 17 +A = 5f +M = 2a + +ModInv = d +A = 61 +M = 2a + +ModInv = 3 +A = -64 +M = 2b + +ModInv = 21 +A = -63 +M = 2b + +ModInv = 19 +A = -62 +M = 2b + +ModInv = 27 +A = -61 +M = 2b + +ModInv = 1e +A = -60 +M = 2b + +ModInv = 13 +A = -5f +M = 2b + +ModInv = 10 +A = -5e +M = 2b + +ModInv = 6 +A = -5d +M = 2b + +ModInv = 7 +A = -5c +M = 2b + +ModInv = 11 +A = -5b +M = 2b + +ModInv = 20 +A = -5a +M = 2b + +ModInv = e +A = -59 +M = 2b + +ModInv = 15 +A = -58 +M = 2b + +ModInv = 2a +A = -57 +M = 2b + +ModInv = 1 +A = -55 +M = 2b + +ModInv = 16 +A = -54 +M = 2b + +ModInv = 1d +A = -53 +M = 2b + +ModInv = b +A = -52 +M = 2b + +ModInv = 1a +A = -51 +M = 2b + +ModInv = 24 +A = -50 +M = 2b + +ModInv = 25 +A = -4f +M = 2b + +ModInv = 1b +A = -4e +M = 2b + +ModInv = 18 +A = -4d +M = 2b + +ModInv = d +A = -4c +M = 2b + +ModInv = 4 +A = -4b +M = 2b + +ModInv = 12 +A = -4a +M = 2b + +ModInv = a +A = -49 +M = 2b + +ModInv = 28 +A = -48 +M = 2b + +ModInv = 17 +A = -47 +M = 2b + +ModInv = 23 +A = -46 +M = 2b + +ModInv = 26 +A = -45 +M = 2b + +ModInv = c +A = -44 +M = 2b + +ModInv = 22 +A = -43 +M = 2b + +ModInv = 1c +A = -42 +M = 2b + +ModInv = 29 +A = -41 +M = 2b + +ModInv = 2 +A = -40 +M = 2b + +ModInv = f +A = -3f +M = 2b + +ModInv = 9 +A = -3e +M = 2b + +ModInv = 1f +A = -3d +M = 2b + +ModInv = 5 +A = -3c +M = 2b + +ModInv = 8 +A = -3b +M = 2b + +ModInv = 14 +A = -3a +M = 2b + +ModInv = 3 +A = -39 +M = 2b + +ModInv = 21 +A = -38 +M = 2b + +ModInv = 19 +A = -37 +M = 2b + +ModInv = 27 +A = -36 +M = 2b + +ModInv = 1e +A = -35 +M = 2b + +ModInv = 13 +A = -34 +M = 2b + +ModInv = 10 +A = -33 +M = 2b + +ModInv = 6 +A = -32 +M = 2b + +ModInv = 7 +A = -31 +M = 2b + +ModInv = 11 +A = -30 +M = 2b + +ModInv = 20 +A = -2f +M = 2b + +ModInv = e +A = -2e +M = 2b + +ModInv = 15 +A = -2d +M = 2b + +ModInv = 2a +A = -2c +M = 2b + +ModInv = 1 +A = -2a +M = 2b + +ModInv = 16 +A = -29 +M = 2b + +ModInv = 1d +A = -28 +M = 2b + +ModInv = b +A = -27 +M = 2b + +ModInv = 1a +A = -26 +M = 2b + +ModInv = 24 +A = -25 +M = 2b + +ModInv = 25 +A = -24 +M = 2b + +ModInv = 1b +A = -23 +M = 2b + +ModInv = 18 +A = -22 +M = 2b + +ModInv = d +A = -21 +M = 2b + +ModInv = 4 +A = -20 +M = 2b + +ModInv = 12 +A = -1f +M = 2b + +ModInv = a +A = -1e +M = 2b + +ModInv = 28 +A = -1d +M = 2b + +ModInv = 17 +A = -1c +M = 2b + +ModInv = 23 +A = -1b +M = 2b + +ModInv = 26 +A = -1a +M = 2b + +ModInv = c +A = -19 +M = 2b + +ModInv = 22 +A = -18 +M = 2b + +ModInv = 1c +A = -17 +M = 2b + +ModInv = 29 +A = -16 +M = 2b + +ModInv = 2 +A = -15 +M = 2b + +ModInv = f +A = -14 +M = 2b + +ModInv = 9 +A = -13 +M = 2b + +ModInv = 1f +A = -12 +M = 2b + +ModInv = 5 +A = -11 +M = 2b + +ModInv = 8 +A = -10 +M = 2b + +ModInv = 14 +A = -f +M = 2b + +ModInv = 3 +A = -e +M = 2b + +ModInv = 21 +A = -d +M = 2b + +ModInv = 19 +A = -c +M = 2b + +ModInv = 27 +A = -b +M = 2b + +ModInv = 1e +A = -a +M = 2b + +ModInv = 13 +A = -9 +M = 2b + +ModInv = 10 +A = -8 +M = 2b + +ModInv = 6 +A = -7 +M = 2b + +ModInv = 7 +A = -6 +M = 2b + +ModInv = 11 +A = -5 +M = 2b + +ModInv = 20 +A = -4 +M = 2b + +ModInv = e +A = -3 +M = 2b + +ModInv = 15 +A = -2 +M = 2b + +ModInv = 2a +A = -1 +M = 2b + +ModInv = 1 +A = 1 +M = 2b + +ModInv = 16 +A = 2 +M = 2b + +ModInv = 1d +A = 3 +M = 2b + +ModInv = b +A = 4 +M = 2b + +ModInv = 1a +A = 5 +M = 2b + +ModInv = 24 +A = 6 +M = 2b + +ModInv = 25 +A = 7 +M = 2b + +ModInv = 1b +A = 8 +M = 2b + +ModInv = 18 +A = 9 +M = 2b + +ModInv = d +A = a +M = 2b + +ModInv = 4 +A = b +M = 2b + +ModInv = 12 +A = c +M = 2b + +ModInv = a +A = d +M = 2b + +ModInv = 28 +A = e +M = 2b + +ModInv = 17 +A = f +M = 2b + +ModInv = 23 +A = 10 +M = 2b + +ModInv = 26 +A = 11 +M = 2b + +ModInv = c +A = 12 +M = 2b + +ModInv = 22 +A = 13 +M = 2b + +ModInv = 1c +A = 14 +M = 2b + +ModInv = 29 +A = 15 +M = 2b + +ModInv = 2 +A = 16 +M = 2b + +ModInv = f +A = 17 +M = 2b + +ModInv = 9 +A = 18 +M = 2b + +ModInv = 1f +A = 19 +M = 2b + +ModInv = 5 +A = 1a +M = 2b + +ModInv = 8 +A = 1b +M = 2b + +ModInv = 14 +A = 1c +M = 2b + +ModInv = 3 +A = 1d +M = 2b + +ModInv = 21 +A = 1e +M = 2b + +ModInv = 19 +A = 1f +M = 2b + +ModInv = 27 +A = 20 +M = 2b + +ModInv = 1e +A = 21 +M = 2b + +ModInv = 13 +A = 22 +M = 2b + +ModInv = 10 +A = 23 +M = 2b + +ModInv = 6 +A = 24 +M = 2b + +ModInv = 7 +A = 25 +M = 2b + +ModInv = 11 +A = 26 +M = 2b + +ModInv = 20 +A = 27 +M = 2b + +ModInv = e +A = 28 +M = 2b + +ModInv = 15 +A = 29 +M = 2b + +ModInv = 2a +A = 2a +M = 2b + +ModInv = 1 +A = 2c +M = 2b + +ModInv = 16 +A = 2d +M = 2b + +ModInv = 1d +A = 2e +M = 2b + +ModInv = b +A = 2f +M = 2b + +ModInv = 1a +A = 30 +M = 2b + +ModInv = 24 +A = 31 +M = 2b + +ModInv = 25 +A = 32 +M = 2b + +ModInv = 1b +A = 33 +M = 2b + +ModInv = 18 +A = 34 +M = 2b + +ModInv = d +A = 35 +M = 2b + +ModInv = 4 +A = 36 +M = 2b + +ModInv = 12 +A = 37 +M = 2b + +ModInv = a +A = 38 +M = 2b + +ModInv = 28 +A = 39 +M = 2b + +ModInv = 17 +A = 3a +M = 2b + +ModInv = 23 +A = 3b +M = 2b + +ModInv = 26 +A = 3c +M = 2b + +ModInv = c +A = 3d +M = 2b + +ModInv = 22 +A = 3e +M = 2b + +ModInv = 1c +A = 3f +M = 2b + +ModInv = 29 +A = 40 +M = 2b + +ModInv = 2 +A = 41 +M = 2b + +ModInv = f +A = 42 +M = 2b + +ModInv = 9 +A = 43 +M = 2b + +ModInv = 1f +A = 44 +M = 2b + +ModInv = 5 +A = 45 +M = 2b + +ModInv = 8 +A = 46 +M = 2b + +ModInv = 14 +A = 47 +M = 2b + +ModInv = 3 +A = 48 +M = 2b + +ModInv = 21 +A = 49 +M = 2b + +ModInv = 19 +A = 4a +M = 2b + +ModInv = 27 +A = 4b +M = 2b + +ModInv = 1e +A = 4c +M = 2b + +ModInv = 13 +A = 4d +M = 2b + +ModInv = 10 +A = 4e +M = 2b + +ModInv = 6 +A = 4f +M = 2b + +ModInv = 7 +A = 50 +M = 2b + +ModInv = 11 +A = 51 +M = 2b + +ModInv = 20 +A = 52 +M = 2b + +ModInv = e +A = 53 +M = 2b + +ModInv = 15 +A = 54 +M = 2b + +ModInv = 2a +A = 55 +M = 2b + +ModInv = 1 +A = 57 +M = 2b + +ModInv = 16 +A = 58 +M = 2b + +ModInv = 1d +A = 59 +M = 2b + +ModInv = b +A = 5a +M = 2b + +ModInv = 1a +A = 5b +M = 2b + +ModInv = 24 +A = 5c +M = 2b + +ModInv = 25 +A = 5d +M = 2b + +ModInv = 1b +A = 5e +M = 2b + +ModInv = 18 +A = 5f +M = 2b + +ModInv = d +A = 60 +M = 2b + +ModInv = 4 +A = 61 +M = 2b + +ModInv = 12 +A = 62 +M = 2b + +ModInv = a +A = 63 +M = 2b + +ModInv = 27 +A = -61 +M = 2c + +ModInv = 19 +A = -5f +M = 2c + +ModInv = 23 +A = -5d +M = 2c + +ModInv = 1d +A = -5b +M = 2c + +ModInv = 2b +A = -59 +M = 2c + +ModInv = 1 +A = -57 +M = 2c + +ModInv = f +A = -55 +M = 2c + +ModInv = 9 +A = -53 +M = 2c + +ModInv = 13 +A = -51 +M = 2c + +ModInv = 5 +A = -4f +M = 2c + +ModInv = 11 +A = -4b +M = 2c + +ModInv = 3 +A = -49 +M = 2c + +ModInv = d +A = -47 +M = 2c + +ModInv = 7 +A = -45 +M = 2c + +ModInv = 15 +A = -43 +M = 2c + +ModInv = 17 +A = -41 +M = 2c + +ModInv = 25 +A = -3f +M = 2c + +ModInv = 1f +A = -3d +M = 2c + +ModInv = 29 +A = -3b +M = 2c + +ModInv = 1b +A = -39 +M = 2c + +ModInv = 27 +A = -35 +M = 2c + +ModInv = 19 +A = -33 +M = 2c + +ModInv = 23 +A = -31 +M = 2c + +ModInv = 1d +A = -2f +M = 2c + +ModInv = 2b +A = -2d +M = 2c + +ModInv = 1 +A = -2b +M = 2c + +ModInv = f +A = -29 +M = 2c + +ModInv = 9 +A = -27 +M = 2c + +ModInv = 13 +A = -25 +M = 2c + +ModInv = 5 +A = -23 +M = 2c + +ModInv = 11 +A = -1f +M = 2c + +ModInv = 3 +A = -1d +M = 2c + +ModInv = d +A = -1b +M = 2c + +ModInv = 7 +A = -19 +M = 2c + +ModInv = 15 +A = -17 +M = 2c + +ModInv = 17 +A = -15 +M = 2c + +ModInv = 25 +A = -13 +M = 2c + +ModInv = 1f +A = -11 +M = 2c + +ModInv = 29 +A = -f +M = 2c + +ModInv = 1b +A = -d +M = 2c + +ModInv = 27 +A = -9 +M = 2c + +ModInv = 19 +A = -7 +M = 2c + +ModInv = 23 +A = -5 +M = 2c + +ModInv = 1d +A = -3 +M = 2c + +ModInv = 2b +A = -1 +M = 2c + +ModInv = 1 +A = 1 +M = 2c + +ModInv = f +A = 3 +M = 2c + +ModInv = 9 +A = 5 +M = 2c + +ModInv = 13 +A = 7 +M = 2c + +ModInv = 5 +A = 9 +M = 2c + +ModInv = 11 +A = d +M = 2c + +ModInv = 3 +A = f +M = 2c + +ModInv = d +A = 11 +M = 2c + +ModInv = 7 +A = 13 +M = 2c + +ModInv = 15 +A = 15 +M = 2c + +ModInv = 17 +A = 17 +M = 2c + +ModInv = 25 +A = 19 +M = 2c + +ModInv = 1f +A = 1b +M = 2c + +ModInv = 29 +A = 1d +M = 2c + +ModInv = 1b +A = 1f +M = 2c + +ModInv = 27 +A = 23 +M = 2c + +ModInv = 19 +A = 25 +M = 2c + +ModInv = 23 +A = 27 +M = 2c + +ModInv = 1d +A = 29 +M = 2c + +ModInv = 2b +A = 2b +M = 2c + +ModInv = 1 +A = 2d +M = 2c + +ModInv = f +A = 2f +M = 2c + +ModInv = 9 +A = 31 +M = 2c + +ModInv = 13 +A = 33 +M = 2c + +ModInv = 5 +A = 35 +M = 2c + +ModInv = 11 +A = 39 +M = 2c + +ModInv = 3 +A = 3b +M = 2c + +ModInv = d +A = 3d +M = 2c + +ModInv = 7 +A = 3f +M = 2c + +ModInv = 15 +A = 41 +M = 2c + +ModInv = 17 +A = 43 +M = 2c + +ModInv = 25 +A = 45 +M = 2c + +ModInv = 1f +A = 47 +M = 2c + +ModInv = 29 +A = 49 +M = 2c + +ModInv = 1b +A = 4b +M = 2c + +ModInv = 27 +A = 4f +M = 2c + +ModInv = 19 +A = 51 +M = 2c + +ModInv = 23 +A = 53 +M = 2c + +ModInv = 1d +A = 55 +M = 2c + +ModInv = 2b +A = 57 +M = 2c + +ModInv = 1 +A = 59 +M = 2c + +ModInv = f +A = 5b +M = 2c + +ModInv = 9 +A = 5d +M = 2c + +ModInv = 13 +A = 5f +M = 2c + +ModInv = 5 +A = 61 +M = 2c + +ModInv = 1c +A = -62 +M = 2d + +ModInv = 20 +A = -61 +M = 2d + +ModInv = b +A = -5e +M = 2d + +ModInv = 16 +A = -5c +M = 2d + +ModInv = 2c +A = -5b +M = 2d + +ModInv = 1 +A = -59 +M = 2d + +ModInv = 17 +A = -58 +M = 2d + +ModInv = 22 +A = -56 +M = 2d + +ModInv = d +A = -53 +M = 2d + +ModInv = 11 +A = -52 +M = 2d + +ModInv = 29 +A = -4f +M = 2d + +ModInv = 7 +A = -4d +M = 2d + +ModInv = 1d +A = -4c +M = 2d + +ModInv = 1f +A = -4a +M = 2d + +ModInv = 8 +A = -49 +M = 2d + +ModInv = 13 +A = -47 +M = 2d + +ModInv = 2b +A = -44 +M = 2d + +ModInv = 2 +A = -43 +M = 2d + +ModInv = 1a +A = -40 +M = 2d + +ModInv = 25 +A = -3e +M = 2d + +ModInv = e +A = -3d +M = 2d + +ModInv = 10 +A = -3b +M = 2d + +ModInv = 26 +A = -3a +M = 2d + +ModInv = 4 +A = -38 +M = 2d + +ModInv = 1c +A = -35 +M = 2d + +ModInv = 20 +A = -34 +M = 2d + +ModInv = b +A = -31 +M = 2d + +ModInv = 16 +A = -2f +M = 2d + +ModInv = 2c +A = -2e +M = 2d + +ModInv = 1 +A = -2c +M = 2d + +ModInv = 17 +A = -2b +M = 2d + +ModInv = 22 +A = -29 +M = 2d + +ModInv = d +A = -26 +M = 2d + +ModInv = 11 +A = -25 +M = 2d + +ModInv = 29 +A = -22 +M = 2d + +ModInv = 7 +A = -20 +M = 2d + +ModInv = 1d +A = -1f +M = 2d + +ModInv = 1f +A = -1d +M = 2d + +ModInv = 8 +A = -1c +M = 2d + +ModInv = 13 +A = -1a +M = 2d + +ModInv = 2b +A = -17 +M = 2d + +ModInv = 2 +A = -16 +M = 2d + +ModInv = 1a +A = -13 +M = 2d + +ModInv = 25 +A = -11 +M = 2d + +ModInv = e +A = -10 +M = 2d + +ModInv = 10 +A = -e +M = 2d + +ModInv = 26 +A = -d +M = 2d + +ModInv = 4 +A = -b +M = 2d + +ModInv = 1c +A = -8 +M = 2d + +ModInv = 20 +A = -7 +M = 2d + +ModInv = b +A = -4 +M = 2d + +ModInv = 16 +A = -2 +M = 2d + +ModInv = 2c +A = -1 +M = 2d + +ModInv = 1 +A = 1 +M = 2d + +ModInv = 17 +A = 2 +M = 2d + +ModInv = 22 +A = 4 +M = 2d + +ModInv = d +A = 7 +M = 2d + +ModInv = 11 +A = 8 +M = 2d + +ModInv = 29 +A = b +M = 2d + +ModInv = 7 +A = d +M = 2d + +ModInv = 1d +A = e +M = 2d + +ModInv = 1f +A = 10 +M = 2d + +ModInv = 8 +A = 11 +M = 2d + +ModInv = 13 +A = 13 +M = 2d + +ModInv = 2b +A = 16 +M = 2d + +ModInv = 2 +A = 17 +M = 2d + +ModInv = 1a +A = 1a +M = 2d + +ModInv = 25 +A = 1c +M = 2d + +ModInv = e +A = 1d +M = 2d + +ModInv = 10 +A = 1f +M = 2d + +ModInv = 26 +A = 20 +M = 2d + +ModInv = 4 +A = 22 +M = 2d + +ModInv = 1c +A = 25 +M = 2d + +ModInv = 20 +A = 26 +M = 2d + +ModInv = b +A = 29 +M = 2d + +ModInv = 16 +A = 2b +M = 2d + +ModInv = 2c +A = 2c +M = 2d + +ModInv = 1 +A = 2e +M = 2d + +ModInv = 17 +A = 2f +M = 2d + +ModInv = 22 +A = 31 +M = 2d + +ModInv = d +A = 34 +M = 2d + +ModInv = 11 +A = 35 +M = 2d + +ModInv = 29 +A = 38 +M = 2d + +ModInv = 7 +A = 3a +M = 2d + +ModInv = 1d +A = 3b +M = 2d + +ModInv = 1f +A = 3d +M = 2d + +ModInv = 8 +A = 3e +M = 2d + +ModInv = 13 +A = 40 +M = 2d + +ModInv = 2b +A = 43 +M = 2d + +ModInv = 2 +A = 44 +M = 2d + +ModInv = 1a +A = 47 +M = 2d + +ModInv = 25 +A = 49 +M = 2d + +ModInv = e +A = 4a +M = 2d + +ModInv = 10 +A = 4c +M = 2d + +ModInv = 26 +A = 4d +M = 2d + +ModInv = 4 +A = 4f +M = 2d + +ModInv = 1c +A = 52 +M = 2d + +ModInv = 20 +A = 53 +M = 2d + +ModInv = b +A = 56 +M = 2d + +ModInv = 16 +A = 58 +M = 2d + +ModInv = 2c +A = 59 +M = 2d + +ModInv = 1 +A = 5b +M = 2d + +ModInv = 17 +A = 5c +M = 2d + +ModInv = 22 +A = 5e +M = 2d + +ModInv = d +A = 61 +M = 2d + +ModInv = 11 +A = 62 +M = 2d + +ModInv = d +A = -63 +M = 2e + +ModInv = 9 +A = -61 +M = 2e + +ModInv = f +A = -5f +M = 2e + +ModInv = 2d +A = -5d +M = 2e + +ModInv = 1 +A = -5b +M = 2e + +ModInv = 1f +A = -59 +M = 2e + +ModInv = 25 +A = -57 +M = 2e + +ModInv = 21 +A = -55 +M = 2e + +ModInv = 29 +A = -53 +M = 2e + +ModInv = 15 +A = -51 +M = 2e + +ModInv = 27 +A = -4f +M = 2e + +ModInv = 2b +A = -4d +M = 2e + +ModInv = 13 +A = -4b +M = 2e + +ModInv = 11 +A = -49 +M = 2e + +ModInv = b +A = -47 +M = 2e + +ModInv = 23 +A = -43 +M = 2e + +ModInv = 1d +A = -41 +M = 2e + +ModInv = 1b +A = -3f +M = 2e + +ModInv = 3 +A = -3d +M = 2e + +ModInv = 7 +A = -3b +M = 2e + +ModInv = 19 +A = -39 +M = 2e + +ModInv = 5 +A = -37 +M = 2e + +ModInv = d +A = -35 +M = 2e + +ModInv = 9 +A = -33 +M = 2e + +ModInv = f +A = -31 +M = 2e + +ModInv = 2d +A = -2f +M = 2e + +ModInv = 1 +A = -2d +M = 2e + +ModInv = 1f +A = -2b +M = 2e + +ModInv = 25 +A = -29 +M = 2e + +ModInv = 21 +A = -27 +M = 2e + +ModInv = 29 +A = -25 +M = 2e + +ModInv = 15 +A = -23 +M = 2e + +ModInv = 27 +A = -21 +M = 2e + +ModInv = 2b +A = -1f +M = 2e + +ModInv = 13 +A = -1d +M = 2e + +ModInv = 11 +A = -1b +M = 2e + +ModInv = b +A = -19 +M = 2e + +ModInv = 23 +A = -15 +M = 2e + +ModInv = 1d +A = -13 +M = 2e + +ModInv = 1b +A = -11 +M = 2e + +ModInv = 3 +A = -f +M = 2e + +ModInv = 7 +A = -d +M = 2e + +ModInv = 19 +A = -b +M = 2e + +ModInv = 5 +A = -9 +M = 2e + +ModInv = d +A = -7 +M = 2e + +ModInv = 9 +A = -5 +M = 2e + +ModInv = f +A = -3 +M = 2e + +ModInv = 2d +A = -1 +M = 2e + +ModInv = 1 +A = 1 +M = 2e + +ModInv = 1f +A = 3 +M = 2e + +ModInv = 25 +A = 5 +M = 2e + +ModInv = 21 +A = 7 +M = 2e + +ModInv = 29 +A = 9 +M = 2e + +ModInv = 15 +A = b +M = 2e + +ModInv = 27 +A = d +M = 2e + +ModInv = 2b +A = f +M = 2e + +ModInv = 13 +A = 11 +M = 2e + +ModInv = 11 +A = 13 +M = 2e + +ModInv = b +A = 15 +M = 2e + +ModInv = 23 +A = 19 +M = 2e + +ModInv = 1d +A = 1b +M = 2e + +ModInv = 1b +A = 1d +M = 2e + +ModInv = 3 +A = 1f +M = 2e + +ModInv = 7 +A = 21 +M = 2e + +ModInv = 19 +A = 23 +M = 2e + +ModInv = 5 +A = 25 +M = 2e + +ModInv = d +A = 27 +M = 2e + +ModInv = 9 +A = 29 +M = 2e + +ModInv = f +A = 2b +M = 2e + +ModInv = 2d +A = 2d +M = 2e + +ModInv = 1 +A = 2f +M = 2e + +ModInv = 1f +A = 31 +M = 2e + +ModInv = 25 +A = 33 +M = 2e + +ModInv = 21 +A = 35 +M = 2e + +ModInv = 29 +A = 37 +M = 2e + +ModInv = 15 +A = 39 +M = 2e + +ModInv = 27 +A = 3b +M = 2e + +ModInv = 2b +A = 3d +M = 2e + +ModInv = 13 +A = 3f +M = 2e + +ModInv = 11 +A = 41 +M = 2e + +ModInv = b +A = 43 +M = 2e + +ModInv = 23 +A = 47 +M = 2e + +ModInv = 1d +A = 49 +M = 2e + +ModInv = 1b +A = 4b +M = 2e + +ModInv = 3 +A = 4d +M = 2e + +ModInv = 7 +A = 4f +M = 2e + +ModInv = 19 +A = 51 +M = 2e + +ModInv = 5 +A = 53 +M = 2e + +ModInv = d +A = 55 +M = 2e + +ModInv = 9 +A = 57 +M = 2e + +ModInv = f +A = 59 +M = 2e + +ModInv = 2d +A = 5b +M = 2e + +ModInv = 1 +A = 5d +M = 2e + +ModInv = 1f +A = 5f +M = 2e + +ModInv = 25 +A = 61 +M = 2e + +ModInv = 21 +A = 63 +M = 2e + +ModInv = 27 +A = -64 +M = 2f + +ModInv = 1c +A = -63 +M = 2f + +ModInv = 23 +A = -62 +M = 2f + +ModInv = 1f +A = -61 +M = 2f + +ModInv = 17 +A = -60 +M = 2f + +ModInv = 2e +A = -5f +M = 2f + +ModInv = 1 +A = -5d +M = 2f + +ModInv = 18 +A = -5c +M = 2f + +ModInv = 10 +A = -5b +M = 2f + +ModInv = c +A = -5a +M = 2f + +ModInv = 13 +A = -59 +M = 2f + +ModInv = 8 +A = -58 +M = 2f + +ModInv = 1b +A = -57 +M = 2f + +ModInv = 6 +A = -56 +M = 2f + +ModInv = 15 +A = -55 +M = 2f + +ModInv = 21 +A = -54 +M = 2f + +ModInv = 1e +A = -53 +M = 2f + +ModInv = 4 +A = -52 +M = 2f + +ModInv = 1d +A = -51 +M = 2f + +ModInv = 25 +A = -50 +M = 2f + +ModInv = 16 +A = -4f +M = 2f + +ModInv = 3 +A = -4e +M = 2f + +ModInv = 24 +A = -4d +M = 2f + +ModInv = 22 +A = -4c +M = 2f + +ModInv = 5 +A = -4b +M = 2f + +ModInv = 28 +A = -4a +M = 2f + +ModInv = 9 +A = -49 +M = 2f + +ModInv = f +A = -48 +M = 2f + +ModInv = 2d +A = -47 +M = 2f + +ModInv = 2 +A = -46 +M = 2f + +ModInv = 20 +A = -45 +M = 2f + +ModInv = 26 +A = -44 +M = 2f + +ModInv = 7 +A = -43 +M = 2f + +ModInv = 2a +A = -42 +M = 2f + +ModInv = d +A = -41 +M = 2f + +ModInv = b +A = -40 +M = 2f + +ModInv = 2c +A = -3f +M = 2f + +ModInv = 19 +A = -3e +M = 2f + +ModInv = a +A = -3d +M = 2f + +ModInv = 12 +A = -3c +M = 2f + +ModInv = 2b +A = -3b +M = 2f + +ModInv = 11 +A = -3a +M = 2f + +ModInv = e +A = -39 +M = 2f + +ModInv = 1a +A = -38 +M = 2f + +ModInv = 29 +A = -37 +M = 2f + +ModInv = 14 +A = -36 +M = 2f + +ModInv = 27 +A = -35 +M = 2f + +ModInv = 1c +A = -34 +M = 2f + +ModInv = 23 +A = -33 +M = 2f + +ModInv = 1f +A = -32 +M = 2f + +ModInv = 17 +A = -31 +M = 2f + +ModInv = 2e +A = -30 +M = 2f + +ModInv = 1 +A = -2e +M = 2f + +ModInv = 18 +A = -2d +M = 2f + +ModInv = 10 +A = -2c +M = 2f + +ModInv = c +A = -2b +M = 2f + +ModInv = 13 +A = -2a +M = 2f + +ModInv = 8 +A = -29 +M = 2f + +ModInv = 1b +A = -28 +M = 2f + +ModInv = 6 +A = -27 +M = 2f + +ModInv = 15 +A = -26 +M = 2f + +ModInv = 21 +A = -25 +M = 2f + +ModInv = 1e +A = -24 +M = 2f + +ModInv = 4 +A = -23 +M = 2f + +ModInv = 1d +A = -22 +M = 2f + +ModInv = 25 +A = -21 +M = 2f + +ModInv = 16 +A = -20 +M = 2f + +ModInv = 3 +A = -1f +M = 2f + +ModInv = 24 +A = -1e +M = 2f + +ModInv = 22 +A = -1d +M = 2f + +ModInv = 5 +A = -1c +M = 2f + +ModInv = 28 +A = -1b +M = 2f + +ModInv = 9 +A = -1a +M = 2f + +ModInv = f +A = -19 +M = 2f + +ModInv = 2d +A = -18 +M = 2f + +ModInv = 2 +A = -17 +M = 2f + +ModInv = 20 +A = -16 +M = 2f + +ModInv = 26 +A = -15 +M = 2f + +ModInv = 7 +A = -14 +M = 2f + +ModInv = 2a +A = -13 +M = 2f + +ModInv = d +A = -12 +M = 2f + +ModInv = b +A = -11 +M = 2f + +ModInv = 2c +A = -10 +M = 2f + +ModInv = 19 +A = -f +M = 2f + +ModInv = a +A = -e +M = 2f + +ModInv = 12 +A = -d +M = 2f + +ModInv = 2b +A = -c +M = 2f + +ModInv = 11 +A = -b +M = 2f + +ModInv = e +A = -a +M = 2f + +ModInv = 1a +A = -9 +M = 2f + +ModInv = 29 +A = -8 +M = 2f + +ModInv = 14 +A = -7 +M = 2f + +ModInv = 27 +A = -6 +M = 2f + +ModInv = 1c +A = -5 +M = 2f + +ModInv = 23 +A = -4 +M = 2f + +ModInv = 1f +A = -3 +M = 2f + +ModInv = 17 +A = -2 +M = 2f + +ModInv = 2e +A = -1 +M = 2f + +ModInv = 1 +A = 1 +M = 2f + +ModInv = 18 +A = 2 +M = 2f + +ModInv = 10 +A = 3 +M = 2f + +ModInv = c +A = 4 +M = 2f + +ModInv = 13 +A = 5 +M = 2f + +ModInv = 8 +A = 6 +M = 2f + +ModInv = 1b +A = 7 +M = 2f + +ModInv = 6 +A = 8 +M = 2f + +ModInv = 15 +A = 9 +M = 2f + +ModInv = 21 +A = a +M = 2f + +ModInv = 1e +A = b +M = 2f + +ModInv = 4 +A = c +M = 2f + +ModInv = 1d +A = d +M = 2f + +ModInv = 25 +A = e +M = 2f + +ModInv = 16 +A = f +M = 2f + +ModInv = 3 +A = 10 +M = 2f + +ModInv = 24 +A = 11 +M = 2f + +ModInv = 22 +A = 12 +M = 2f + +ModInv = 5 +A = 13 +M = 2f + +ModInv = 28 +A = 14 +M = 2f + +ModInv = 9 +A = 15 +M = 2f + +ModInv = f +A = 16 +M = 2f + +ModInv = 2d +A = 17 +M = 2f + +ModInv = 2 +A = 18 +M = 2f + +ModInv = 20 +A = 19 +M = 2f + +ModInv = 26 +A = 1a +M = 2f + +ModInv = 7 +A = 1b +M = 2f + +ModInv = 2a +A = 1c +M = 2f + +ModInv = d +A = 1d +M = 2f + +ModInv = b +A = 1e +M = 2f + +ModInv = 2c +A = 1f +M = 2f + +ModInv = 19 +A = 20 +M = 2f + +ModInv = a +A = 21 +M = 2f + +ModInv = 12 +A = 22 +M = 2f + +ModInv = 2b +A = 23 +M = 2f + +ModInv = 11 +A = 24 +M = 2f + +ModInv = e +A = 25 +M = 2f + +ModInv = 1a +A = 26 +M = 2f + +ModInv = 29 +A = 27 +M = 2f + +ModInv = 14 +A = 28 +M = 2f + +ModInv = 27 +A = 29 +M = 2f + +ModInv = 1c +A = 2a +M = 2f + +ModInv = 23 +A = 2b +M = 2f + +ModInv = 1f +A = 2c +M = 2f + +ModInv = 17 +A = 2d +M = 2f + +ModInv = 2e +A = 2e +M = 2f + +ModInv = 1 +A = 30 +M = 2f + +ModInv = 18 +A = 31 +M = 2f + +ModInv = 10 +A = 32 +M = 2f + +ModInv = c +A = 33 +M = 2f + +ModInv = 13 +A = 34 +M = 2f + +ModInv = 8 +A = 35 +M = 2f + +ModInv = 1b +A = 36 +M = 2f + +ModInv = 6 +A = 37 +M = 2f + +ModInv = 15 +A = 38 +M = 2f + +ModInv = 21 +A = 39 +M = 2f + +ModInv = 1e +A = 3a +M = 2f + +ModInv = 4 +A = 3b +M = 2f + +ModInv = 1d +A = 3c +M = 2f + +ModInv = 25 +A = 3d +M = 2f + +ModInv = 16 +A = 3e +M = 2f + +ModInv = 3 +A = 3f +M = 2f + +ModInv = 24 +A = 40 +M = 2f + +ModInv = 22 +A = 41 +M = 2f + +ModInv = 5 +A = 42 +M = 2f + +ModInv = 28 +A = 43 +M = 2f + +ModInv = 9 +A = 44 +M = 2f + +ModInv = f +A = 45 +M = 2f + +ModInv = 2d +A = 46 +M = 2f + +ModInv = 2 +A = 47 +M = 2f + +ModInv = 20 +A = 48 +M = 2f + +ModInv = 26 +A = 49 +M = 2f + +ModInv = 7 +A = 4a +M = 2f + +ModInv = 2a +A = 4b +M = 2f + +ModInv = d +A = 4c +M = 2f + +ModInv = b +A = 4d +M = 2f + +ModInv = 2c +A = 4e +M = 2f + +ModInv = 19 +A = 4f +M = 2f + +ModInv = a +A = 50 +M = 2f + +ModInv = 12 +A = 51 +M = 2f + +ModInv = 2b +A = 52 +M = 2f + +ModInv = 11 +A = 53 +M = 2f + +ModInv = e +A = 54 +M = 2f + +ModInv = 1a +A = 55 +M = 2f + +ModInv = 29 +A = 56 +M = 2f + +ModInv = 14 +A = 57 +M = 2f + +ModInv = 27 +A = 58 +M = 2f + +ModInv = 1c +A = 59 +M = 2f + +ModInv = 23 +A = 5a +M = 2f + +ModInv = 1f +A = 5b +M = 2f + +ModInv = 17 +A = 5c +M = 2f + +ModInv = 2e +A = 5d +M = 2f + +ModInv = 1 +A = 5f +M = 2f + +ModInv = 18 +A = 60 +M = 2f + +ModInv = 10 +A = 61 +M = 2f + +ModInv = c +A = 62 +M = 2f + +ModInv = 13 +A = 63 +M = 2f + +ModInv = 2f +A = -61 +M = 30 + +ModInv = 1 +A = -5f +M = 30 + +ModInv = 1d +A = -5b +M = 30 + +ModInv = 7 +A = -59 +M = 30 + +ModInv = 23 +A = -55 +M = 30 + +ModInv = 25 +A = -53 +M = 30 + +ModInv = 11 +A = -4f +M = 30 + +ModInv = 2b +A = -4d +M = 30 + +ModInv = 17 +A = -49 +M = 30 + +ModInv = 19 +A = -47 +M = 30 + +ModInv = 5 +A = -43 +M = 30 + +ModInv = 1f +A = -41 +M = 30 + +ModInv = b +A = -3d +M = 30 + +ModInv = d +A = -3b +M = 30 + +ModInv = 29 +A = -37 +M = 30 + +ModInv = 13 +A = -35 +M = 30 + +ModInv = 2f +A = -31 +M = 30 + +ModInv = 1 +A = -2f +M = 30 + +ModInv = 1d +A = -2b +M = 30 + +ModInv = 7 +A = -29 +M = 30 + +ModInv = 23 +A = -25 +M = 30 + +ModInv = 25 +A = -23 +M = 30 + +ModInv = 11 +A = -1f +M = 30 + +ModInv = 2b +A = -1d +M = 30 + +ModInv = 17 +A = -19 +M = 30 + +ModInv = 19 +A = -17 +M = 30 + +ModInv = 5 +A = -13 +M = 30 + +ModInv = 1f +A = -11 +M = 30 + +ModInv = b +A = -d +M = 30 + +ModInv = d +A = -b +M = 30 + +ModInv = 29 +A = -7 +M = 30 + +ModInv = 13 +A = -5 +M = 30 + +ModInv = 2f +A = -1 +M = 30 + +ModInv = 1 +A = 1 +M = 30 + +ModInv = 1d +A = 5 +M = 30 + +ModInv = 7 +A = 7 +M = 30 + +ModInv = 23 +A = b +M = 30 + +ModInv = 25 +A = d +M = 30 + +ModInv = 11 +A = 11 +M = 30 + +ModInv = 2b +A = 13 +M = 30 + +ModInv = 17 +A = 17 +M = 30 + +ModInv = 19 +A = 19 +M = 30 + +ModInv = 5 +A = 1d +M = 30 + +ModInv = 1f +A = 1f +M = 30 + +ModInv = b +A = 23 +M = 30 + +ModInv = d +A = 25 +M = 30 + +ModInv = 29 +A = 29 +M = 30 + +ModInv = 13 +A = 2b +M = 30 + +ModInv = 2f +A = 2f +M = 30 + +ModInv = 1 +A = 31 +M = 30 + +ModInv = 1d +A = 35 +M = 30 + +ModInv = 7 +A = 37 +M = 30 + +ModInv = 23 +A = 3b +M = 30 + +ModInv = 25 +A = 3d +M = 30 + +ModInv = 11 +A = 41 +M = 30 + +ModInv = 2b +A = 43 +M = 30 + +ModInv = 17 +A = 47 +M = 30 + +ModInv = 19 +A = 49 +M = 30 + +ModInv = 5 +A = 4d +M = 30 + +ModInv = 1f +A = 4f +M = 30 + +ModInv = b +A = 53 +M = 30 + +ModInv = d +A = 55 +M = 30 + +ModInv = 29 +A = 59 +M = 30 + +ModInv = 13 +A = 5b +M = 30 + +ModInv = 2f +A = 5f +M = 30 + +ModInv = 1 +A = 61 +M = 30 + +ModInv = 18 +A = -64 +M = 31 + +ModInv = 30 +A = -63 +M = 31 + +ModInv = 1 +A = -61 +M = 31 + +ModInv = 19 +A = -60 +M = 31 + +ModInv = 21 +A = -5f +M = 31 + +ModInv = 25 +A = -5e +M = 31 + +ModInv = a +A = -5d +M = 31 + +ModInv = 29 +A = -5c +M = 31 + +ModInv = 2b +A = -5a +M = 31 + +ModInv = b +A = -59 +M = 31 + +ModInv = 5 +A = -58 +M = 31 + +ModInv = 9 +A = -57 +M = 31 + +ModInv = 2d +A = -56 +M = 31 + +ModInv = 22 +A = -55 +M = 31 + +ModInv = 24 +A = -53 +M = 31 + +ModInv = 2e +A = -52 +M = 31 + +ModInv = 1a +A = -51 +M = 31 + +ModInv = 1e +A = -50 +M = 31 + +ModInv = 1f +A = -4f +M = 31 + +ModInv = 1b +A = -4e +M = 31 + +ModInv = 1d +A = -4c +M = 31 + +ModInv = 20 +A = -4b +M = 31 + +ModInv = 2f +A = -4a +M = 31 + +ModInv = 2 +A = -49 +M = 31 + +ModInv = 11 +A = -48 +M = 31 + +ModInv = 14 +A = -47 +M = 31 + +ModInv = 16 +A = -45 +M = 31 + +ModInv = 12 +A = -44 +M = 31 + +ModInv = 13 +A = -43 +M = 31 + +ModInv = 17 +A = -42 +M = 31 + +ModInv = 3 +A = -41 +M = 31 + +ModInv = d +A = -40 +M = 31 + +ModInv = f +A = -3e +M = 31 + +ModInv = 4 +A = -3d +M = 31 + +ModInv = 28 +A = -3c +M = 31 + +ModInv = 2c +A = -3b +M = 31 + +ModInv = 26 +A = -3a +M = 31 + +ModInv = 6 +A = -39 +M = 31 + +ModInv = 8 +A = -37 +M = 31 + +ModInv = 27 +A = -36 +M = 31 + +ModInv = c +A = -35 +M = 31 + +ModInv = 10 +A = -34 +M = 31 + +ModInv = 18 +A = -33 +M = 31 + +ModInv = 30 +A = -32 +M = 31 + +ModInv = 1 +A = -30 +M = 31 + +ModInv = 19 +A = -2f +M = 31 + +ModInv = 21 +A = -2e +M = 31 + +ModInv = 25 +A = -2d +M = 31 + +ModInv = a +A = -2c +M = 31 + +ModInv = 29 +A = -2b +M = 31 + +ModInv = 2b +A = -29 +M = 31 + +ModInv = b +A = -28 +M = 31 + +ModInv = 5 +A = -27 +M = 31 + +ModInv = 9 +A = -26 +M = 31 + +ModInv = 2d +A = -25 +M = 31 + +ModInv = 22 +A = -24 +M = 31 + +ModInv = 24 +A = -22 +M = 31 + +ModInv = 2e +A = -21 +M = 31 + +ModInv = 1a +A = -20 +M = 31 + +ModInv = 1e +A = -1f +M = 31 + +ModInv = 1f +A = -1e +M = 31 + +ModInv = 1b +A = -1d +M = 31 + +ModInv = 1d +A = -1b +M = 31 + +ModInv = 20 +A = -1a +M = 31 + +ModInv = 2f +A = -19 +M = 31 + +ModInv = 2 +A = -18 +M = 31 + +ModInv = 11 +A = -17 +M = 31 + +ModInv = 14 +A = -16 +M = 31 + +ModInv = 16 +A = -14 +M = 31 + +ModInv = 12 +A = -13 +M = 31 + +ModInv = 13 +A = -12 +M = 31 + +ModInv = 17 +A = -11 +M = 31 + +ModInv = 3 +A = -10 +M = 31 + +ModInv = d +A = -f +M = 31 + +ModInv = f +A = -d +M = 31 + +ModInv = 4 +A = -c +M = 31 + +ModInv = 28 +A = -b +M = 31 + +ModInv = 2c +A = -a +M = 31 + +ModInv = 26 +A = -9 +M = 31 + +ModInv = 6 +A = -8 +M = 31 + +ModInv = 8 +A = -6 +M = 31 + +ModInv = 27 +A = -5 +M = 31 + +ModInv = c +A = -4 +M = 31 + +ModInv = 10 +A = -3 +M = 31 + +ModInv = 18 +A = -2 +M = 31 + +ModInv = 30 +A = -1 +M = 31 + +ModInv = 1 +A = 1 +M = 31 + +ModInv = 19 +A = 2 +M = 31 + +ModInv = 21 +A = 3 +M = 31 + +ModInv = 25 +A = 4 +M = 31 + +ModInv = a +A = 5 +M = 31 + +ModInv = 29 +A = 6 +M = 31 + +ModInv = 2b +A = 8 +M = 31 + +ModInv = b +A = 9 +M = 31 + +ModInv = 5 +A = a +M = 31 + +ModInv = 9 +A = b +M = 31 + +ModInv = 2d +A = c +M = 31 + +ModInv = 22 +A = d +M = 31 + +ModInv = 24 +A = f +M = 31 + +ModInv = 2e +A = 10 +M = 31 + +ModInv = 1a +A = 11 +M = 31 + +ModInv = 1e +A = 12 +M = 31 + +ModInv = 1f +A = 13 +M = 31 + +ModInv = 1b +A = 14 +M = 31 + +ModInv = 1d +A = 16 +M = 31 + +ModInv = 20 +A = 17 +M = 31 + +ModInv = 2f +A = 18 +M = 31 + +ModInv = 2 +A = 19 +M = 31 + +ModInv = 11 +A = 1a +M = 31 + +ModInv = 14 +A = 1b +M = 31 + +ModInv = 16 +A = 1d +M = 31 + +ModInv = 12 +A = 1e +M = 31 + +ModInv = 13 +A = 1f +M = 31 + +ModInv = 17 +A = 20 +M = 31 + +ModInv = 3 +A = 21 +M = 31 + +ModInv = d +A = 22 +M = 31 + +ModInv = f +A = 24 +M = 31 + +ModInv = 4 +A = 25 +M = 31 + +ModInv = 28 +A = 26 +M = 31 + +ModInv = 2c +A = 27 +M = 31 + +ModInv = 26 +A = 28 +M = 31 + +ModInv = 6 +A = 29 +M = 31 + +ModInv = 8 +A = 2b +M = 31 + +ModInv = 27 +A = 2c +M = 31 + +ModInv = c +A = 2d +M = 31 + +ModInv = 10 +A = 2e +M = 31 + +ModInv = 18 +A = 2f +M = 31 + +ModInv = 30 +A = 30 +M = 31 + +ModInv = 1 +A = 32 +M = 31 + +ModInv = 19 +A = 33 +M = 31 + +ModInv = 21 +A = 34 +M = 31 + +ModInv = 25 +A = 35 +M = 31 + +ModInv = a +A = 36 +M = 31 + +ModInv = 29 +A = 37 +M = 31 + +ModInv = 2b +A = 39 +M = 31 + +ModInv = b +A = 3a +M = 31 + +ModInv = 5 +A = 3b +M = 31 + +ModInv = 9 +A = 3c +M = 31 + +ModInv = 2d +A = 3d +M = 31 + +ModInv = 22 +A = 3e +M = 31 + +ModInv = 24 +A = 40 +M = 31 + +ModInv = 2e +A = 41 +M = 31 + +ModInv = 1a +A = 42 +M = 31 + +ModInv = 1e +A = 43 +M = 31 + +ModInv = 1f +A = 44 +M = 31 + +ModInv = 1b +A = 45 +M = 31 + +ModInv = 1d +A = 47 +M = 31 + +ModInv = 20 +A = 48 +M = 31 + +ModInv = 2f +A = 49 +M = 31 + +ModInv = 2 +A = 4a +M = 31 + +ModInv = 11 +A = 4b +M = 31 + +ModInv = 14 +A = 4c +M = 31 + +ModInv = 16 +A = 4e +M = 31 + +ModInv = 12 +A = 4f +M = 31 + +ModInv = 13 +A = 50 +M = 31 + +ModInv = 17 +A = 51 +M = 31 + +ModInv = 3 +A = 52 +M = 31 + +ModInv = d +A = 53 +M = 31 + +ModInv = f +A = 55 +M = 31 + +ModInv = 4 +A = 56 +M = 31 + +ModInv = 28 +A = 57 +M = 31 + +ModInv = 2c +A = 58 +M = 31 + +ModInv = 26 +A = 59 +M = 31 + +ModInv = 6 +A = 5a +M = 31 + +ModInv = 8 +A = 5c +M = 31 + +ModInv = 27 +A = 5d +M = 31 + +ModInv = c +A = 5e +M = 31 + +ModInv = 10 +A = 5f +M = 31 + +ModInv = 18 +A = 60 +M = 31 + +ModInv = 30 +A = 61 +M = 31 + +ModInv = 1 +A = 63 +M = 31 + +ModInv = 1 +A = -63 +M = 32 + +ModInv = 11 +A = -61 +M = 32 + +ModInv = 2b +A = -5d +M = 32 + +ModInv = 27 +A = -5b +M = 32 + +ModInv = 29 +A = -59 +M = 32 + +ModInv = 1b +A = -57 +M = 32 + +ModInv = 3 +A = -53 +M = 32 + +ModInv = 1d +A = -51 +M = 32 + +ModInv = 1f +A = -4f +M = 32 + +ModInv = 25 +A = -4d +M = 32 + +ModInv = d +A = -49 +M = 32 + +ModInv = 13 +A = -47 +M = 32 + +ModInv = 15 +A = -45 +M = 32 + +ModInv = 2f +A = -43 +M = 32 + +ModInv = 17 +A = -3f +M = 32 + +ModInv = 9 +A = -3d +M = 32 + +ModInv = b +A = -3b +M = 32 + +ModInv = 7 +A = -39 +M = 32 + +ModInv = 21 +A = -35 +M = 32 + +ModInv = 31 +A = -33 +M = 32 + +ModInv = 1 +A = -31 +M = 32 + +ModInv = 11 +A = -2f +M = 32 + +ModInv = 2b +A = -2b +M = 32 + +ModInv = 27 +A = -29 +M = 32 + +ModInv = 29 +A = -27 +M = 32 + +ModInv = 1b +A = -25 +M = 32 + +ModInv = 3 +A = -21 +M = 32 + +ModInv = 1d +A = -1f +M = 32 + +ModInv = 1f +A = -1d +M = 32 + +ModInv = 25 +A = -1b +M = 32 + +ModInv = d +A = -17 +M = 32 + +ModInv = 13 +A = -15 +M = 32 + +ModInv = 15 +A = -13 +M = 32 + +ModInv = 2f +A = -11 +M = 32 + +ModInv = 17 +A = -d +M = 32 + +ModInv = 9 +A = -b +M = 32 + +ModInv = b +A = -9 +M = 32 + +ModInv = 7 +A = -7 +M = 32 + +ModInv = 21 +A = -3 +M = 32 + +ModInv = 31 +A = -1 +M = 32 + +ModInv = 1 +A = 1 +M = 32 + +ModInv = 11 +A = 3 +M = 32 + +ModInv = 2b +A = 7 +M = 32 + +ModInv = 27 +A = 9 +M = 32 + +ModInv = 29 +A = b +M = 32 + +ModInv = 1b +A = d +M = 32 + +ModInv = 3 +A = 11 +M = 32 + +ModInv = 1d +A = 13 +M = 32 + +ModInv = 1f +A = 15 +M = 32 + +ModInv = 25 +A = 17 +M = 32 + +ModInv = d +A = 1b +M = 32 + +ModInv = 13 +A = 1d +M = 32 + +ModInv = 15 +A = 1f +M = 32 + +ModInv = 2f +A = 21 +M = 32 + +ModInv = 17 +A = 25 +M = 32 + +ModInv = 9 +A = 27 +M = 32 + +ModInv = b +A = 29 +M = 32 + +ModInv = 7 +A = 2b +M = 32 + +ModInv = 21 +A = 2f +M = 32 + +ModInv = 31 +A = 31 +M = 32 + +ModInv = 1 +A = 33 +M = 32 + +ModInv = 11 +A = 35 +M = 32 + +ModInv = 2b +A = 39 +M = 32 + +ModInv = 27 +A = 3b +M = 32 + +ModInv = 29 +A = 3d +M = 32 + +ModInv = 1b +A = 3f +M = 32 + +ModInv = 3 +A = 43 +M = 32 + +ModInv = 1d +A = 45 +M = 32 + +ModInv = 1f +A = 47 +M = 32 + +ModInv = 25 +A = 49 +M = 32 + +ModInv = d +A = 4d +M = 32 + +ModInv = 13 +A = 4f +M = 32 + +ModInv = 15 +A = 51 +M = 32 + +ModInv = 2f +A = 53 +M = 32 + +ModInv = 17 +A = 57 +M = 32 + +ModInv = 9 +A = 59 +M = 32 + +ModInv = b +A = 5b +M = 32 + +ModInv = 7 +A = 5d +M = 32 + +ModInv = 21 +A = 61 +M = 32 + +ModInv = 31 +A = 63 +M = 32 + +ModInv = 1a +A = -64 +M = 33 + +ModInv = d +A = -62 +M = 33 + +ModInv = 29 +A = -61 +M = 33 + +ModInv = 16 +A = -5f +M = 33 + +ModInv = 20 +A = -5e +M = 33 + +ModInv = 2e +A = -5c +M = 33 + +ModInv = e +A = -5b +M = 33 + +ModInv = 4 +A = -59 +M = 33 + +ModInv = b +A = -58 +M = 33 + +ModInv = 10 +A = -56 +M = 33 + +ModInv = 2b +A = -53 +M = 33 + +ModInv = 17 +A = -52 +M = 33 + +ModInv = 7 +A = -50 +M = 33 + +ModInv = 14 +A = -4f +M = 33 + +ModInv = 31 +A = -4d +M = 33 + +ModInv = 2 +A = -4c +M = 33 + +ModInv = 1f +A = -4a +M = 33 + +ModInv = 2c +A = -49 +M = 33 + +ModInv = 1c +A = -47 +M = 33 + +ModInv = 8 +A = -46 +M = 33 + +ModInv = 23 +A = -43 +M = 33 + +ModInv = 28 +A = -41 +M = 33 + +ModInv = 2f +A = -40 +M = 33 + +ModInv = 25 +A = -3e +M = 33 + +ModInv = 5 +A = -3d +M = 33 + +ModInv = 13 +A = -3b +M = 33 + +ModInv = 1d +A = -3a +M = 33 + +ModInv = a +A = -38 +M = 33 + +ModInv = 26 +A = -37 +M = 33 + +ModInv = 19 +A = -35 +M = 33 + +ModInv = 32 +A = -34 +M = 33 + +ModInv = 1 +A = -32 +M = 33 + +ModInv = 1a +A = -31 +M = 33 + +ModInv = d +A = -2f +M = 33 + +ModInv = 29 +A = -2e +M = 33 + +ModInv = 16 +A = -2c +M = 33 + +ModInv = 20 +A = -2b +M = 33 + +ModInv = 2e +A = -29 +M = 33 + +ModInv = e +A = -28 +M = 33 + +ModInv = 4 +A = -26 +M = 33 + +ModInv = b +A = -25 +M = 33 + +ModInv = 10 +A = -23 +M = 33 + +ModInv = 2b +A = -20 +M = 33 + +ModInv = 17 +A = -1f +M = 33 + +ModInv = 7 +A = -1d +M = 33 + +ModInv = 14 +A = -1c +M = 33 + +ModInv = 31 +A = -1a +M = 33 + +ModInv = 2 +A = -19 +M = 33 + +ModInv = 1f +A = -17 +M = 33 + +ModInv = 2c +A = -16 +M = 33 + +ModInv = 1c +A = -14 +M = 33 + +ModInv = 8 +A = -13 +M = 33 + +ModInv = 23 +A = -10 +M = 33 + +ModInv = 28 +A = -e +M = 33 + +ModInv = 2f +A = -d +M = 33 + +ModInv = 25 +A = -b +M = 33 + +ModInv = 5 +A = -a +M = 33 + +ModInv = 13 +A = -8 +M = 33 + +ModInv = 1d +A = -7 +M = 33 + +ModInv = a +A = -5 +M = 33 + +ModInv = 26 +A = -4 +M = 33 + +ModInv = 19 +A = -2 +M = 33 + +ModInv = 32 +A = -1 +M = 33 + +ModInv = 1 +A = 1 +M = 33 + +ModInv = 1a +A = 2 +M = 33 + +ModInv = d +A = 4 +M = 33 + +ModInv = 29 +A = 5 +M = 33 + +ModInv = 16 +A = 7 +M = 33 + +ModInv = 20 +A = 8 +M = 33 + +ModInv = 2e +A = a +M = 33 + +ModInv = e +A = b +M = 33 + +ModInv = 4 +A = d +M = 33 + +ModInv = b +A = e +M = 33 + +ModInv = 10 +A = 10 +M = 33 + +ModInv = 2b +A = 13 +M = 33 + +ModInv = 17 +A = 14 +M = 33 + +ModInv = 7 +A = 16 +M = 33 + +ModInv = 14 +A = 17 +M = 33 + +ModInv = 31 +A = 19 +M = 33 + +ModInv = 2 +A = 1a +M = 33 + +ModInv = 1f +A = 1c +M = 33 + +ModInv = 2c +A = 1d +M = 33 + +ModInv = 1c +A = 1f +M = 33 + +ModInv = 8 +A = 20 +M = 33 + +ModInv = 23 +A = 23 +M = 33 + +ModInv = 28 +A = 25 +M = 33 + +ModInv = 2f +A = 26 +M = 33 + +ModInv = 25 +A = 28 +M = 33 + +ModInv = 5 +A = 29 +M = 33 + +ModInv = 13 +A = 2b +M = 33 + +ModInv = 1d +A = 2c +M = 33 + +ModInv = a +A = 2e +M = 33 + +ModInv = 26 +A = 2f +M = 33 + +ModInv = 19 +A = 31 +M = 33 + +ModInv = 32 +A = 32 +M = 33 + +ModInv = 1 +A = 34 +M = 33 + +ModInv = 1a +A = 35 +M = 33 + +ModInv = d +A = 37 +M = 33 + +ModInv = 29 +A = 38 +M = 33 + +ModInv = 16 +A = 3a +M = 33 + +ModInv = 20 +A = 3b +M = 33 + +ModInv = 2e +A = 3d +M = 33 + +ModInv = e +A = 3e +M = 33 + +ModInv = 4 +A = 40 +M = 33 + +ModInv = b +A = 41 +M = 33 + +ModInv = 10 +A = 43 +M = 33 + +ModInv = 2b +A = 46 +M = 33 + +ModInv = 17 +A = 47 +M = 33 + +ModInv = 7 +A = 49 +M = 33 + +ModInv = 14 +A = 4a +M = 33 + +ModInv = 31 +A = 4c +M = 33 + +ModInv = 2 +A = 4d +M = 33 + +ModInv = 1f +A = 4f +M = 33 + +ModInv = 2c +A = 50 +M = 33 + +ModInv = 1c +A = 52 +M = 33 + +ModInv = 8 +A = 53 +M = 33 + +ModInv = 23 +A = 56 +M = 33 + +ModInv = 28 +A = 58 +M = 33 + +ModInv = 2f +A = 59 +M = 33 + +ModInv = 25 +A = 5b +M = 33 + +ModInv = 5 +A = 5c +M = 33 + +ModInv = 13 +A = 5e +M = 33 + +ModInv = 1d +A = 5f +M = 33 + +ModInv = a +A = 61 +M = 33 + +ModInv = 26 +A = 62 +M = 33 + +ModInv = 15 +A = -63 +M = 34 + +ModInv = f +A = -61 +M = 34 + +ModInv = 1d +A = -5f +M = 34 + +ModInv = 13 +A = -5d +M = 34 + +ModInv = 7 +A = -59 +M = 34 + +ModInv = 31 +A = -57 +M = 34 + +ModInv = b +A = -55 +M = 34 + +ModInv = 5 +A = -53 +M = 34 + +ModInv = 2b +A = -51 +M = 34 + +ModInv = 19 +A = -4f +M = 34 + +ModInv = 1b +A = -4d +M = 34 + +ModInv = 9 +A = -4b +M = 34 + +ModInv = 2f +A = -49 +M = 34 + +ModInv = 29 +A = -47 +M = 34 + +ModInv = 3 +A = -45 +M = 34 + +ModInv = 2d +A = -43 +M = 34 + +ModInv = 21 +A = -3f +M = 34 + +ModInv = 17 +A = -3d +M = 34 + +ModInv = 25 +A = -3b +M = 34 + +ModInv = 1f +A = -39 +M = 34 + +ModInv = 11 +A = -37 +M = 34 + +ModInv = 33 +A = -35 +M = 34 + +ModInv = 1 +A = -33 +M = 34 + +ModInv = 23 +A = -31 +M = 34 + +ModInv = 15 +A = -2f +M = 34 + +ModInv = f +A = -2d +M = 34 + +ModInv = 1d +A = -2b +M = 34 + +ModInv = 13 +A = -29 +M = 34 + +ModInv = 7 +A = -25 +M = 34 + +ModInv = 31 +A = -23 +M = 34 + +ModInv = b +A = -21 +M = 34 + +ModInv = 5 +A = -1f +M = 34 + +ModInv = 2b +A = -1d +M = 34 + +ModInv = 19 +A = -1b +M = 34 + +ModInv = 1b +A = -19 +M = 34 + +ModInv = 9 +A = -17 +M = 34 + +ModInv = 2f +A = -15 +M = 34 + +ModInv = 29 +A = -13 +M = 34 + +ModInv = 3 +A = -11 +M = 34 + +ModInv = 2d +A = -f +M = 34 + +ModInv = 21 +A = -b +M = 34 + +ModInv = 17 +A = -9 +M = 34 + +ModInv = 25 +A = -7 +M = 34 + +ModInv = 1f +A = -5 +M = 34 + +ModInv = 11 +A = -3 +M = 34 + +ModInv = 33 +A = -1 +M = 34 + +ModInv = 1 +A = 1 +M = 34 + +ModInv = 23 +A = 3 +M = 34 + +ModInv = 15 +A = 5 +M = 34 + +ModInv = f +A = 7 +M = 34 + +ModInv = 1d +A = 9 +M = 34 + +ModInv = 13 +A = b +M = 34 + +ModInv = 7 +A = f +M = 34 + +ModInv = 31 +A = 11 +M = 34 + +ModInv = b +A = 13 +M = 34 + +ModInv = 5 +A = 15 +M = 34 + +ModInv = 2b +A = 17 +M = 34 + +ModInv = 19 +A = 19 +M = 34 + +ModInv = 1b +A = 1b +M = 34 + +ModInv = 9 +A = 1d +M = 34 + +ModInv = 2f +A = 1f +M = 34 + +ModInv = 29 +A = 21 +M = 34 + +ModInv = 3 +A = 23 +M = 34 + +ModInv = 2d +A = 25 +M = 34 + +ModInv = 21 +A = 29 +M = 34 + +ModInv = 17 +A = 2b +M = 34 + +ModInv = 25 +A = 2d +M = 34 + +ModInv = 1f +A = 2f +M = 34 + +ModInv = 11 +A = 31 +M = 34 + +ModInv = 33 +A = 33 +M = 34 + +ModInv = 1 +A = 35 +M = 34 + +ModInv = 23 +A = 37 +M = 34 + +ModInv = 15 +A = 39 +M = 34 + +ModInv = f +A = 3b +M = 34 + +ModInv = 1d +A = 3d +M = 34 + +ModInv = 13 +A = 3f +M = 34 + +ModInv = 7 +A = 43 +M = 34 + +ModInv = 31 +A = 45 +M = 34 + +ModInv = b +A = 47 +M = 34 + +ModInv = 5 +A = 49 +M = 34 + +ModInv = 2b +A = 4b +M = 34 + +ModInv = 19 +A = 4d +M = 34 + +ModInv = 1b +A = 4f +M = 34 + +ModInv = 9 +A = 51 +M = 34 + +ModInv = 2f +A = 53 +M = 34 + +ModInv = 29 +A = 55 +M = 34 + +ModInv = 3 +A = 57 +M = 34 + +ModInv = 2d +A = 59 +M = 34 + +ModInv = 21 +A = 5d +M = 34 + +ModInv = 17 +A = 5f +M = 34 + +ModInv = 25 +A = 61 +M = 34 + +ModInv = 1f +A = 63 +M = 34 + +ModInv = 9 +A = -64 +M = 35 + +ModInv = 26 +A = -63 +M = 35 + +ModInv = 14 +A = -62 +M = 35 + +ModInv = 6 +A = -61 +M = 35 + +ModInv = 10 +A = -60 +M = 35 + +ModInv = 1d +A = -5f +M = 35 + +ModInv = 1f +A = -5e +M = 35 + +ModInv = 31 +A = -5d +M = 35 + +ModInv = 13 +A = -5c +M = 35 + +ModInv = 2e +A = -5b +M = 35 + +ModInv = a +A = -5a +M = 35 + +ModInv = 19 +A = -59 +M = 35 + +ModInv = 3 +A = -58 +M = 35 + +ModInv = e +A = -57 +M = 35 + +ModInv = 8 +A = -56 +M = 35 + +ModInv = 30 +A = -55 +M = 35 + +ModInv = 29 +A = -54 +M = 35 + +ModInv = 1e +A = -53 +M = 35 + +ModInv = 2a +A = -52 +M = 35 + +ModInv = 11 +A = -51 +M = 35 + +ModInv = 33 +A = -50 +M = 35 + +ModInv = 2 +A = -4f +M = 35 + +ModInv = 24 +A = -4e +M = 35 + +ModInv = b +A = -4d +M = 35 + +ModInv = 17 +A = -4c +M = 35 + +ModInv = c +A = -4b +M = 35 + +ModInv = 5 +A = -4a +M = 35 + +ModInv = 2d +A = -49 +M = 35 + +ModInv = 27 +A = -48 +M = 35 + +ModInv = 32 +A = -47 +M = 35 + +ModInv = 1c +A = -46 +M = 35 + +ModInv = 2b +A = -45 +M = 35 + +ModInv = 7 +A = -44 +M = 35 + +ModInv = 22 +A = -43 +M = 35 + +ModInv = 4 +A = -42 +M = 35 + +ModInv = 16 +A = -41 +M = 35 + +ModInv = 18 +A = -40 +M = 35 + +ModInv = 25 +A = -3f +M = 35 + +ModInv = 2f +A = -3e +M = 35 + +ModInv = 21 +A = -3d +M = 35 + +ModInv = f +A = -3c +M = 35 + +ModInv = 2c +A = -3b +M = 35 + +ModInv = 15 +A = -3a +M = 35 + +ModInv = d +A = -39 +M = 35 + +ModInv = 23 +A = -38 +M = 35 + +ModInv = 1a +A = -37 +M = 35 + +ModInv = 34 +A = -36 +M = 35 + +ModInv = 1 +A = -34 +M = 35 + +ModInv = 1b +A = -33 +M = 35 + +ModInv = 12 +A = -32 +M = 35 + +ModInv = 28 +A = -31 +M = 35 + +ModInv = 20 +A = -30 +M = 35 + +ModInv = 9 +A = -2f +M = 35 + +ModInv = 26 +A = -2e +M = 35 + +ModInv = 14 +A = -2d +M = 35 + +ModInv = 6 +A = -2c +M = 35 + +ModInv = 10 +A = -2b +M = 35 + +ModInv = 1d +A = -2a +M = 35 + +ModInv = 1f +A = -29 +M = 35 + +ModInv = 31 +A = -28 +M = 35 + +ModInv = 13 +A = -27 +M = 35 + +ModInv = 2e +A = -26 +M = 35 + +ModInv = a +A = -25 +M = 35 + +ModInv = 19 +A = -24 +M = 35 + +ModInv = 3 +A = -23 +M = 35 + +ModInv = e +A = -22 +M = 35 + +ModInv = 8 +A = -21 +M = 35 + +ModInv = 30 +A = -20 +M = 35 + +ModInv = 29 +A = -1f +M = 35 + +ModInv = 1e +A = -1e +M = 35 + +ModInv = 2a +A = -1d +M = 35 + +ModInv = 11 +A = -1c +M = 35 + +ModInv = 33 +A = -1b +M = 35 + +ModInv = 2 +A = -1a +M = 35 + +ModInv = 24 +A = -19 +M = 35 + +ModInv = b +A = -18 +M = 35 + +ModInv = 17 +A = -17 +M = 35 + +ModInv = c +A = -16 +M = 35 + +ModInv = 5 +A = -15 +M = 35 + +ModInv = 2d +A = -14 +M = 35 + +ModInv = 27 +A = -13 +M = 35 + +ModInv = 32 +A = -12 +M = 35 + +ModInv = 1c +A = -11 +M = 35 + +ModInv = 2b +A = -10 +M = 35 + +ModInv = 7 +A = -f +M = 35 + +ModInv = 22 +A = -e +M = 35 + +ModInv = 4 +A = -d +M = 35 + +ModInv = 16 +A = -c +M = 35 + +ModInv = 18 +A = -b +M = 35 + +ModInv = 25 +A = -a +M = 35 + +ModInv = 2f +A = -9 +M = 35 + +ModInv = 21 +A = -8 +M = 35 + +ModInv = f +A = -7 +M = 35 + +ModInv = 2c +A = -6 +M = 35 + +ModInv = 15 +A = -5 +M = 35 + +ModInv = d +A = -4 +M = 35 + +ModInv = 23 +A = -3 +M = 35 + +ModInv = 1a +A = -2 +M = 35 + +ModInv = 34 +A = -1 +M = 35 + +ModInv = 1 +A = 1 +M = 35 + +ModInv = 1b +A = 2 +M = 35 + +ModInv = 12 +A = 3 +M = 35 + +ModInv = 28 +A = 4 +M = 35 + +ModInv = 20 +A = 5 +M = 35 + +ModInv = 9 +A = 6 +M = 35 + +ModInv = 26 +A = 7 +M = 35 + +ModInv = 14 +A = 8 +M = 35 + +ModInv = 6 +A = 9 +M = 35 + +ModInv = 10 +A = a +M = 35 + +ModInv = 1d +A = b +M = 35 + +ModInv = 1f +A = c +M = 35 + +ModInv = 31 +A = d +M = 35 + +ModInv = 13 +A = e +M = 35 + +ModInv = 2e +A = f +M = 35 + +ModInv = a +A = 10 +M = 35 + +ModInv = 19 +A = 11 +M = 35 + +ModInv = 3 +A = 12 +M = 35 + +ModInv = e +A = 13 +M = 35 + +ModInv = 8 +A = 14 +M = 35 + +ModInv = 30 +A = 15 +M = 35 + +ModInv = 29 +A = 16 +M = 35 + +ModInv = 1e +A = 17 +M = 35 + +ModInv = 2a +A = 18 +M = 35 + +ModInv = 11 +A = 19 +M = 35 + +ModInv = 33 +A = 1a +M = 35 + +ModInv = 2 +A = 1b +M = 35 + +ModInv = 24 +A = 1c +M = 35 + +ModInv = b +A = 1d +M = 35 + +ModInv = 17 +A = 1e +M = 35 + +ModInv = c +A = 1f +M = 35 + +ModInv = 5 +A = 20 +M = 35 + +ModInv = 2d +A = 21 +M = 35 + +ModInv = 27 +A = 22 +M = 35 + +ModInv = 32 +A = 23 +M = 35 + +ModInv = 1c +A = 24 +M = 35 + +ModInv = 2b +A = 25 +M = 35 + +ModInv = 7 +A = 26 +M = 35 + +ModInv = 22 +A = 27 +M = 35 + +ModInv = 4 +A = 28 +M = 35 + +ModInv = 16 +A = 29 +M = 35 + +ModInv = 18 +A = 2a +M = 35 + +ModInv = 25 +A = 2b +M = 35 + +ModInv = 2f +A = 2c +M = 35 + +ModInv = 21 +A = 2d +M = 35 + +ModInv = f +A = 2e +M = 35 + +ModInv = 2c +A = 2f +M = 35 + +ModInv = 15 +A = 30 +M = 35 + +ModInv = d +A = 31 +M = 35 + +ModInv = 23 +A = 32 +M = 35 + +ModInv = 1a +A = 33 +M = 35 + +ModInv = 34 +A = 34 +M = 35 + +ModInv = 1 +A = 36 +M = 35 + +ModInv = 1b +A = 37 +M = 35 + +ModInv = 12 +A = 38 +M = 35 + +ModInv = 28 +A = 39 +M = 35 + +ModInv = 20 +A = 3a +M = 35 + +ModInv = 9 +A = 3b +M = 35 + +ModInv = 26 +A = 3c +M = 35 + +ModInv = 14 +A = 3d +M = 35 + +ModInv = 6 +A = 3e +M = 35 + +ModInv = 10 +A = 3f +M = 35 + +ModInv = 1d +A = 40 +M = 35 + +ModInv = 1f +A = 41 +M = 35 + +ModInv = 31 +A = 42 +M = 35 + +ModInv = 13 +A = 43 +M = 35 + +ModInv = 2e +A = 44 +M = 35 + +ModInv = a +A = 45 +M = 35 + +ModInv = 19 +A = 46 +M = 35 + +ModInv = 3 +A = 47 +M = 35 + +ModInv = e +A = 48 +M = 35 + +ModInv = 8 +A = 49 +M = 35 + +ModInv = 30 +A = 4a +M = 35 + +ModInv = 29 +A = 4b +M = 35 + +ModInv = 1e +A = 4c +M = 35 + +ModInv = 2a +A = 4d +M = 35 + +ModInv = 11 +A = 4e +M = 35 + +ModInv = 33 +A = 4f +M = 35 + +ModInv = 2 +A = 50 +M = 35 + +ModInv = 24 +A = 51 +M = 35 + +ModInv = b +A = 52 +M = 35 + +ModInv = 17 +A = 53 +M = 35 + +ModInv = c +A = 54 +M = 35 + +ModInv = 5 +A = 55 +M = 35 + +ModInv = 2d +A = 56 +M = 35 + +ModInv = 27 +A = 57 +M = 35 + +ModInv = 32 +A = 58 +M = 35 + +ModInv = 1c +A = 59 +M = 35 + +ModInv = 2b +A = 5a +M = 35 + +ModInv = 7 +A = 5b +M = 35 + +ModInv = 22 +A = 5c +M = 35 + +ModInv = 4 +A = 5d +M = 35 + +ModInv = 16 +A = 5e +M = 35 + +ModInv = 18 +A = 5f +M = 35 + +ModInv = 25 +A = 60 +M = 35 + +ModInv = 2f +A = 61 +M = 35 + +ModInv = 21 +A = 62 +M = 35 + +ModInv = f +A = 63 +M = 35 + +ModInv = 5 +A = -61 +M = 36 + +ModInv = 19 +A = -5f +M = 36 + +ModInv = 23 +A = -5b +M = 36 + +ModInv = 25 +A = -59 +M = 36 + +ModInv = 2f +A = -55 +M = 36 + +ModInv = d +A = -53 +M = 36 + +ModInv = 29 +A = -4f +M = 36 + +ModInv = 7 +A = -4d +M = 36 + +ModInv = 11 +A = -49 +M = 36 + +ModInv = 13 +A = -47 +M = 36 + +ModInv = 1d +A = -43 +M = 36 + +ModInv = 31 +A = -41 +M = 36 + +ModInv = 17 +A = -3d +M = 36 + +ModInv = 2b +A = -3b +M = 36 + +ModInv = 35 +A = -37 +M = 36 + +ModInv = 1 +A = -35 +M = 36 + +ModInv = b +A = -31 +M = 36 + +ModInv = 1f +A = -2f +M = 36 + +ModInv = 5 +A = -2b +M = 36 + +ModInv = 19 +A = -29 +M = 36 + +ModInv = 23 +A = -25 +M = 36 + +ModInv = 25 +A = -23 +M = 36 + +ModInv = 2f +A = -1f +M = 36 + +ModInv = d +A = -1d +M = 36 + +ModInv = 29 +A = -19 +M = 36 + +ModInv = 7 +A = -17 +M = 36 + +ModInv = 11 +A = -13 +M = 36 + +ModInv = 13 +A = -11 +M = 36 + +ModInv = 1d +A = -d +M = 36 + +ModInv = 31 +A = -b +M = 36 + +ModInv = 17 +A = -7 +M = 36 + +ModInv = 2b +A = -5 +M = 36 + +ModInv = 35 +A = -1 +M = 36 + +ModInv = 1 +A = 1 +M = 36 + +ModInv = b +A = 5 +M = 36 + +ModInv = 1f +A = 7 +M = 36 + +ModInv = 5 +A = b +M = 36 + +ModInv = 19 +A = d +M = 36 + +ModInv = 23 +A = 11 +M = 36 + +ModInv = 25 +A = 13 +M = 36 + +ModInv = 2f +A = 17 +M = 36 + +ModInv = d +A = 19 +M = 36 + +ModInv = 29 +A = 1d +M = 36 + +ModInv = 7 +A = 1f +M = 36 + +ModInv = 11 +A = 23 +M = 36 + +ModInv = 13 +A = 25 +M = 36 + +ModInv = 1d +A = 29 +M = 36 + +ModInv = 31 +A = 2b +M = 36 + +ModInv = 17 +A = 2f +M = 36 + +ModInv = 2b +A = 31 +M = 36 + +ModInv = 35 +A = 35 +M = 36 + +ModInv = 1 +A = 37 +M = 36 + +ModInv = b +A = 3b +M = 36 + +ModInv = 1f +A = 3d +M = 36 + +ModInv = 5 +A = 41 +M = 36 + +ModInv = 19 +A = 43 +M = 36 + +ModInv = 23 +A = 47 +M = 36 + +ModInv = 25 +A = 49 +M = 36 + +ModInv = 2f +A = 4d +M = 36 + +ModInv = d +A = 4f +M = 36 + +ModInv = 29 +A = 53 +M = 36 + +ModInv = 7 +A = 55 +M = 36 + +ModInv = 11 +A = 59 +M = 36 + +ModInv = 13 +A = 5b +M = 36 + +ModInv = 1d +A = 5f +M = 36 + +ModInv = 31 +A = 61 +M = 36 + +ModInv = 17 +A = -62 +M = 37 + +ModInv = 11 +A = -61 +M = 37 + +ModInv = 4 +A = -60 +M = 37 + +ModInv = 1f +A = -5e +M = 37 + +ModInv = d +A = -5d +M = 37 + +ModInv = 34 +A = -5c +M = 37 + +ModInv = 1d +A = -5b +M = 37 + +ModInv = 15 +A = -59 +M = 37 + +ModInv = c +A = -57 +M = 37 + +ModInv = 27 +A = -56 +M = 37 + +ModInv = 24 +A = -54 +M = 37 + +ModInv = 35 +A = -53 +M = 37 + +ModInv = 2 +A = -52 +M = 37 + +ModInv = 13 +A = -51 +M = 37 + +ModInv = 10 +A = -4f +M = 37 + +ModInv = 2b +A = -4e +M = 37 + +ModInv = 22 +A = -4c +M = 37 + +ModInv = 1a +A = -4a +M = 37 + +ModInv = 3 +A = -49 +M = 37 + +ModInv = 2a +A = -48 +M = 37 + +ModInv = 18 +A = -47 +M = 37 + +ModInv = 33 +A = -45 +M = 37 + +ModInv = 26 +A = -44 +M = 37 + +ModInv = 20 +A = -43 +M = 37 + +ModInv = 6 +A = -40 +M = 37 + +ModInv = 30 +A = -3f +M = 37 + +ModInv = 2f +A = -3e +M = 37 + +ModInv = 9 +A = -3d +M = 37 + +ModInv = 29 +A = -3b +M = 37 + +ModInv = 12 +A = -3a +M = 37 + +ModInv = 1b +A = -39 +M = 37 + +ModInv = 36 +A = -38 +M = 37 + +ModInv = 1 +A = -36 +M = 37 + +ModInv = 1c +A = -35 +M = 37 + +ModInv = 25 +A = -34 +M = 37 + +ModInv = e +A = -33 +M = 37 + +ModInv = 2e +A = -31 +M = 37 + +ModInv = 8 +A = -30 +M = 37 + +ModInv = 7 +A = -2f +M = 37 + +ModInv = 31 +A = -2e +M = 37 + +ModInv = 17 +A = -2b +M = 37 + +ModInv = 11 +A = -2a +M = 37 + +ModInv = 4 +A = -29 +M = 37 + +ModInv = 1f +A = -27 +M = 37 + +ModInv = d +A = -26 +M = 37 + +ModInv = 34 +A = -25 +M = 37 + +ModInv = 1d +A = -24 +M = 37 + +ModInv = 15 +A = -22 +M = 37 + +ModInv = c +A = -20 +M = 37 + +ModInv = 27 +A = -1f +M = 37 + +ModInv = 24 +A = -1d +M = 37 + +ModInv = 35 +A = -1c +M = 37 + +ModInv = 2 +A = -1b +M = 37 + +ModInv = 13 +A = -1a +M = 37 + +ModInv = 10 +A = -18 +M = 37 + +ModInv = 2b +A = -17 +M = 37 + +ModInv = 22 +A = -15 +M = 37 + +ModInv = 1a +A = -13 +M = 37 + +ModInv = 3 +A = -12 +M = 37 + +ModInv = 2a +A = -11 +M = 37 + +ModInv = 18 +A = -10 +M = 37 + +ModInv = 33 +A = -e +M = 37 + +ModInv = 26 +A = -d +M = 37 + +ModInv = 20 +A = -c +M = 37 + +ModInv = 6 +A = -9 +M = 37 + +ModInv = 30 +A = -8 +M = 37 + +ModInv = 2f +A = -7 +M = 37 + +ModInv = 9 +A = -6 +M = 37 + +ModInv = 29 +A = -4 +M = 37 + +ModInv = 12 +A = -3 +M = 37 + +ModInv = 1b +A = -2 +M = 37 + +ModInv = 36 +A = -1 +M = 37 + +ModInv = 1 +A = 1 +M = 37 + +ModInv = 1c +A = 2 +M = 37 + +ModInv = 25 +A = 3 +M = 37 + +ModInv = e +A = 4 +M = 37 + +ModInv = 2e +A = 6 +M = 37 + +ModInv = 8 +A = 7 +M = 37 + +ModInv = 7 +A = 8 +M = 37 + +ModInv = 31 +A = 9 +M = 37 + +ModInv = 17 +A = c +M = 37 + +ModInv = 11 +A = d +M = 37 + +ModInv = 4 +A = e +M = 37 + +ModInv = 1f +A = 10 +M = 37 + +ModInv = d +A = 11 +M = 37 + +ModInv = 34 +A = 12 +M = 37 + +ModInv = 1d +A = 13 +M = 37 + +ModInv = 15 +A = 15 +M = 37 + +ModInv = c +A = 17 +M = 37 + +ModInv = 27 +A = 18 +M = 37 + +ModInv = 24 +A = 1a +M = 37 + +ModInv = 35 +A = 1b +M = 37 + +ModInv = 2 +A = 1c +M = 37 + +ModInv = 13 +A = 1d +M = 37 + +ModInv = 10 +A = 1f +M = 37 + +ModInv = 2b +A = 20 +M = 37 + +ModInv = 22 +A = 22 +M = 37 + +ModInv = 1a +A = 24 +M = 37 + +ModInv = 3 +A = 25 +M = 37 + +ModInv = 2a +A = 26 +M = 37 + +ModInv = 18 +A = 27 +M = 37 + +ModInv = 33 +A = 29 +M = 37 + +ModInv = 26 +A = 2a +M = 37 + +ModInv = 20 +A = 2b +M = 37 + +ModInv = 6 +A = 2e +M = 37 + +ModInv = 30 +A = 2f +M = 37 + +ModInv = 2f +A = 30 +M = 37 + +ModInv = 9 +A = 31 +M = 37 + +ModInv = 29 +A = 33 +M = 37 + +ModInv = 12 +A = 34 +M = 37 + +ModInv = 1b +A = 35 +M = 37 + +ModInv = 36 +A = 36 +M = 37 + +ModInv = 1 +A = 38 +M = 37 + +ModInv = 1c +A = 39 +M = 37 + +ModInv = 25 +A = 3a +M = 37 + +ModInv = e +A = 3b +M = 37 + +ModInv = 2e +A = 3d +M = 37 + +ModInv = 8 +A = 3e +M = 37 + +ModInv = 7 +A = 3f +M = 37 + +ModInv = 31 +A = 40 +M = 37 + +ModInv = 17 +A = 43 +M = 37 + +ModInv = 11 +A = 44 +M = 37 + +ModInv = 4 +A = 45 +M = 37 + +ModInv = 1f +A = 47 +M = 37 + +ModInv = d +A = 48 +M = 37 + +ModInv = 34 +A = 49 +M = 37 + +ModInv = 1d +A = 4a +M = 37 + +ModInv = 15 +A = 4c +M = 37 + +ModInv = c +A = 4e +M = 37 + +ModInv = 27 +A = 4f +M = 37 + +ModInv = 24 +A = 51 +M = 37 + +ModInv = 35 +A = 52 +M = 37 + +ModInv = 2 +A = 53 +M = 37 + +ModInv = 13 +A = 54 +M = 37 + +ModInv = 10 +A = 56 +M = 37 + +ModInv = 2b +A = 57 +M = 37 + +ModInv = 22 +A = 59 +M = 37 + +ModInv = 1a +A = 5b +M = 37 + +ModInv = 3 +A = 5c +M = 37 + +ModInv = 2a +A = 5d +M = 37 + +ModInv = 18 +A = 5e +M = 37 + +ModInv = 33 +A = 60 +M = 37 + +ModInv = 26 +A = 61 +M = 37 + +ModInv = 20 +A = 62 +M = 37 + +ModInv = d +A = -63 +M = 38 + +ModInv = f +A = -61 +M = 38 + +ModInv = 21 +A = -5f +M = 38 + +ModInv = 3 +A = -5d +M = 38 + +ModInv = 27 +A = -59 +M = 38 + +ModInv = 9 +A = -57 +M = 38 + +ModInv = 1b +A = -55 +M = 38 + +ModInv = 1d +A = -53 +M = 38 + +ModInv = 2f +A = -51 +M = 38 + +ModInv = 11 +A = -4f +M = 38 + +ModInv = 35 +A = -4b +M = 38 + +ModInv = 17 +A = -49 +M = 38 + +ModInv = 29 +A = -47 +M = 38 + +ModInv = 2b +A = -45 +M = 38 + +ModInv = 5 +A = -43 +M = 38 + +ModInv = 1f +A = -41 +M = 38 + +ModInv = b +A = -3d +M = 38 + +ModInv = 25 +A = -3b +M = 38 + +ModInv = 37 +A = -39 +M = 38 + +ModInv = 1 +A = -37 +M = 38 + +ModInv = 13 +A = -35 +M = 38 + +ModInv = 2d +A = -33 +M = 38 + +ModInv = 19 +A = -2f +M = 38 + +ModInv = 33 +A = -2d +M = 38 + +ModInv = d +A = -2b +M = 38 + +ModInv = f +A = -29 +M = 38 + +ModInv = 21 +A = -27 +M = 38 + +ModInv = 3 +A = -25 +M = 38 + +ModInv = 27 +A = -21 +M = 38 + +ModInv = 9 +A = -1f +M = 38 + +ModInv = 1b +A = -1d +M = 38 + +ModInv = 1d +A = -1b +M = 38 + +ModInv = 2f +A = -19 +M = 38 + +ModInv = 11 +A = -17 +M = 38 + +ModInv = 35 +A = -13 +M = 38 + +ModInv = 17 +A = -11 +M = 38 + +ModInv = 29 +A = -f +M = 38 + +ModInv = 2b +A = -d +M = 38 + +ModInv = 5 +A = -b +M = 38 + +ModInv = 1f +A = -9 +M = 38 + +ModInv = b +A = -5 +M = 38 + +ModInv = 25 +A = -3 +M = 38 + +ModInv = 37 +A = -1 +M = 38 + +ModInv = 1 +A = 1 +M = 38 + +ModInv = 13 +A = 3 +M = 38 + +ModInv = 2d +A = 5 +M = 38 + +ModInv = 19 +A = 9 +M = 38 + +ModInv = 33 +A = b +M = 38 + +ModInv = d +A = d +M = 38 + +ModInv = f +A = f +M = 38 + +ModInv = 21 +A = 11 +M = 38 + +ModInv = 3 +A = 13 +M = 38 + +ModInv = 27 +A = 17 +M = 38 + +ModInv = 9 +A = 19 +M = 38 + +ModInv = 1b +A = 1b +M = 38 + +ModInv = 1d +A = 1d +M = 38 + +ModInv = 2f +A = 1f +M = 38 + +ModInv = 11 +A = 21 +M = 38 + +ModInv = 35 +A = 25 +M = 38 + +ModInv = 17 +A = 27 +M = 38 + +ModInv = 29 +A = 29 +M = 38 + +ModInv = 2b +A = 2b +M = 38 + +ModInv = 5 +A = 2d +M = 38 + +ModInv = 1f +A = 2f +M = 38 + +ModInv = b +A = 33 +M = 38 + +ModInv = 25 +A = 35 +M = 38 + +ModInv = 37 +A = 37 +M = 38 + +ModInv = 1 +A = 39 +M = 38 + +ModInv = 13 +A = 3b +M = 38 + +ModInv = 2d +A = 3d +M = 38 + +ModInv = 19 +A = 41 +M = 38 + +ModInv = 33 +A = 43 +M = 38 + +ModInv = d +A = 45 +M = 38 + +ModInv = f +A = 47 +M = 38 + +ModInv = 21 +A = 49 +M = 38 + +ModInv = 3 +A = 4b +M = 38 + +ModInv = 27 +A = 4f +M = 38 + +ModInv = 9 +A = 51 +M = 38 + +ModInv = 1b +A = 53 +M = 38 + +ModInv = 1d +A = 55 +M = 38 + +ModInv = 2f +A = 57 +M = 38 + +ModInv = 11 +A = 59 +M = 38 + +ModInv = 35 +A = 5d +M = 38 + +ModInv = 17 +A = 5f +M = 38 + +ModInv = 29 +A = 61 +M = 38 + +ModInv = 2b +A = 63 +M = 38 + +ModInv = 35 +A = -64 +M = 39 + +ModInv = 19 +A = -62 +M = 39 + +ModInv = 2f +A = -61 +M = 39 + +ModInv = 14 +A = -5e +M = 39 + +ModInv = d +A = -5c +M = 39 + +ModInv = 5 +A = -5b +M = 39 + +ModInv = 10 +A = -59 +M = 39 + +ModInv = b +A = -58 +M = 39 + +ModInv = 37 +A = -56 +M = 39 + +ModInv = 2 +A = -55 +M = 39 + +ModInv = 2e +A = -53 +M = 39 + +ModInv = 29 +A = -52 +M = 39 + +ModInv = 34 +A = -50 +M = 39 + +ModInv = 2c +A = -4f +M = 39 + +ModInv = 25 +A = -4d +M = 39 + +ModInv = a +A = -4a +M = 39 + +ModInv = 20 +A = -49 +M = 39 + +ModInv = 4 +A = -47 +M = 39 + +ModInv = 23 +A = -46 +M = 39 + +ModInv = 1f +A = -44 +M = 39 + +ModInv = 11 +A = -43 +M = 39 + +ModInv = 7 +A = -41 +M = 39 + +ModInv = 8 +A = -40 +M = 39 + +ModInv = 22 +A = -3e +M = 39 + +ModInv = e +A = -3d +M = 39 + +ModInv = 1c +A = -3b +M = 39 + +ModInv = 38 +A = -3a +M = 39 + +ModInv = 1 +A = -38 +M = 39 + +ModInv = 1d +A = -37 +M = 39 + +ModInv = 2b +A = -35 +M = 39 + +ModInv = 17 +A = -34 +M = 39 + +ModInv = 31 +A = -32 +M = 39 + +ModInv = 32 +A = -31 +M = 39 + +ModInv = 28 +A = -2f +M = 39 + +ModInv = 1a +A = -2e +M = 39 + +ModInv = 16 +A = -2c +M = 39 + +ModInv = 35 +A = -2b +M = 39 + +ModInv = 19 +A = -29 +M = 39 + +ModInv = 2f +A = -28 +M = 39 + +ModInv = 14 +A = -25 +M = 39 + +ModInv = d +A = -23 +M = 39 + +ModInv = 5 +A = -22 +M = 39 + +ModInv = 10 +A = -20 +M = 39 + +ModInv = b +A = -1f +M = 39 + +ModInv = 37 +A = -1d +M = 39 + +ModInv = 2 +A = -1c +M = 39 + +ModInv = 2e +A = -1a +M = 39 + +ModInv = 29 +A = -19 +M = 39 + +ModInv = 34 +A = -17 +M = 39 + +ModInv = 2c +A = -16 +M = 39 + +ModInv = 25 +A = -14 +M = 39 + +ModInv = a +A = -11 +M = 39 + +ModInv = 20 +A = -10 +M = 39 + +ModInv = 4 +A = -e +M = 39 + +ModInv = 23 +A = -d +M = 39 + +ModInv = 1f +A = -b +M = 39 + +ModInv = 11 +A = -a +M = 39 + +ModInv = 7 +A = -8 +M = 39 + +ModInv = 8 +A = -7 +M = 39 + +ModInv = 22 +A = -5 +M = 39 + +ModInv = e +A = -4 +M = 39 + +ModInv = 1c +A = -2 +M = 39 + +ModInv = 38 +A = -1 +M = 39 + +ModInv = 1 +A = 1 +M = 39 + +ModInv = 1d +A = 2 +M = 39 + +ModInv = 2b +A = 4 +M = 39 + +ModInv = 17 +A = 5 +M = 39 + +ModInv = 31 +A = 7 +M = 39 + +ModInv = 32 +A = 8 +M = 39 + +ModInv = 28 +A = a +M = 39 + +ModInv = 1a +A = b +M = 39 + +ModInv = 16 +A = d +M = 39 + +ModInv = 35 +A = e +M = 39 + +ModInv = 19 +A = 10 +M = 39 + +ModInv = 2f +A = 11 +M = 39 + +ModInv = 14 +A = 14 +M = 39 + +ModInv = d +A = 16 +M = 39 + +ModInv = 5 +A = 17 +M = 39 + +ModInv = 10 +A = 19 +M = 39 + +ModInv = b +A = 1a +M = 39 + +ModInv = 37 +A = 1c +M = 39 + +ModInv = 2 +A = 1d +M = 39 + +ModInv = 2e +A = 1f +M = 39 + +ModInv = 29 +A = 20 +M = 39 + +ModInv = 34 +A = 22 +M = 39 + +ModInv = 2c +A = 23 +M = 39 + +ModInv = 25 +A = 25 +M = 39 + +ModInv = a +A = 28 +M = 39 + +ModInv = 20 +A = 29 +M = 39 + +ModInv = 4 +A = 2b +M = 39 + +ModInv = 23 +A = 2c +M = 39 + +ModInv = 1f +A = 2e +M = 39 + +ModInv = 11 +A = 2f +M = 39 + +ModInv = 7 +A = 31 +M = 39 + +ModInv = 8 +A = 32 +M = 39 + +ModInv = 22 +A = 34 +M = 39 + +ModInv = e +A = 35 +M = 39 + +ModInv = 1c +A = 37 +M = 39 + +ModInv = 38 +A = 38 +M = 39 + +ModInv = 1 +A = 3a +M = 39 + +ModInv = 1d +A = 3b +M = 39 + +ModInv = 2b +A = 3d +M = 39 + +ModInv = 17 +A = 3e +M = 39 + +ModInv = 31 +A = 40 +M = 39 + +ModInv = 32 +A = 41 +M = 39 + +ModInv = 28 +A = 43 +M = 39 + +ModInv = 1a +A = 44 +M = 39 + +ModInv = 16 +A = 46 +M = 39 + +ModInv = 35 +A = 47 +M = 39 + +ModInv = 19 +A = 49 +M = 39 + +ModInv = 2f +A = 4a +M = 39 + +ModInv = 14 +A = 4d +M = 39 + +ModInv = d +A = 4f +M = 39 + +ModInv = 5 +A = 50 +M = 39 + +ModInv = 10 +A = 52 +M = 39 + +ModInv = b +A = 53 +M = 39 + +ModInv = 37 +A = 55 +M = 39 + +ModInv = 2 +A = 56 +M = 39 + +ModInv = 2e +A = 58 +M = 39 + +ModInv = 29 +A = 59 +M = 39 + +ModInv = 34 +A = 5b +M = 39 + +ModInv = 2c +A = 5c +M = 39 + +ModInv = 25 +A = 5e +M = 39 + +ModInv = a +A = 61 +M = 39 + +ModInv = 20 +A = 62 +M = 39 + +ModInv = 29 +A = -63 +M = 3a + +ModInv = 37 +A = -61 +M = 3a + +ModInv = 2f +A = -5f +M = 3a + +ModInv = 35 +A = -5d +M = 3a + +ModInv = 7 +A = -5b +M = 3a + +ModInv = 2b +A = -59 +M = 3a + +ModInv = f +A = -55 +M = 3a + +ModInv = 33 +A = -53 +M = 3a + +ModInv = 5 +A = -51 +M = 3a + +ModInv = b +A = -4f +M = 3a + +ModInv = 3 +A = -4d +M = 3a + +ModInv = 11 +A = -4b +M = 3a + +ModInv = 1b +A = -49 +M = 3a + +ModInv = 31 +A = -47 +M = 3a + +ModInv = 15 +A = -45 +M = 3a + +ModInv = 2d +A = -43 +M = 3a + +ModInv = 21 +A = -41 +M = 3a + +ModInv = 17 +A = -3f +M = 3a + +ModInv = 13 +A = -3d +M = 3a + +ModInv = 39 +A = -3b +M = 3a + +ModInv = 1 +A = -39 +M = 3a + +ModInv = 27 +A = -37 +M = 3a + +ModInv = 23 +A = -35 +M = 3a + +ModInv = 19 +A = -33 +M = 3a + +ModInv = d +A = -31 +M = 3a + +ModInv = 25 +A = -2f +M = 3a + +ModInv = 9 +A = -2d +M = 3a + +ModInv = 1f +A = -2b +M = 3a + +ModInv = 29 +A = -29 +M = 3a + +ModInv = 37 +A = -27 +M = 3a + +ModInv = 2f +A = -25 +M = 3a + +ModInv = 35 +A = -23 +M = 3a + +ModInv = 7 +A = -21 +M = 3a + +ModInv = 2b +A = -1f +M = 3a + +ModInv = f +A = -1b +M = 3a + +ModInv = 33 +A = -19 +M = 3a + +ModInv = 5 +A = -17 +M = 3a + +ModInv = b +A = -15 +M = 3a + +ModInv = 3 +A = -13 +M = 3a + +ModInv = 11 +A = -11 +M = 3a + +ModInv = 1b +A = -f +M = 3a + +ModInv = 31 +A = -d +M = 3a + +ModInv = 15 +A = -b +M = 3a + +ModInv = 2d +A = -9 +M = 3a + +ModInv = 21 +A = -7 +M = 3a + +ModInv = 17 +A = -5 +M = 3a + +ModInv = 13 +A = -3 +M = 3a + +ModInv = 39 +A = -1 +M = 3a + +ModInv = 1 +A = 1 +M = 3a + +ModInv = 27 +A = 3 +M = 3a + +ModInv = 23 +A = 5 +M = 3a + +ModInv = 19 +A = 7 +M = 3a + +ModInv = d +A = 9 +M = 3a + +ModInv = 25 +A = b +M = 3a + +ModInv = 9 +A = d +M = 3a + +ModInv = 1f +A = f +M = 3a + +ModInv = 29 +A = 11 +M = 3a + +ModInv = 37 +A = 13 +M = 3a + +ModInv = 2f +A = 15 +M = 3a + +ModInv = 35 +A = 17 +M = 3a + +ModInv = 7 +A = 19 +M = 3a + +ModInv = 2b +A = 1b +M = 3a + +ModInv = f +A = 1f +M = 3a + +ModInv = 33 +A = 21 +M = 3a + +ModInv = 5 +A = 23 +M = 3a + +ModInv = b +A = 25 +M = 3a + +ModInv = 3 +A = 27 +M = 3a + +ModInv = 11 +A = 29 +M = 3a + +ModInv = 1b +A = 2b +M = 3a + +ModInv = 31 +A = 2d +M = 3a + +ModInv = 15 +A = 2f +M = 3a + +ModInv = 2d +A = 31 +M = 3a + +ModInv = 21 +A = 33 +M = 3a + +ModInv = 17 +A = 35 +M = 3a + +ModInv = 13 +A = 37 +M = 3a + +ModInv = 39 +A = 39 +M = 3a + +ModInv = 1 +A = 3b +M = 3a + +ModInv = 27 +A = 3d +M = 3a + +ModInv = 23 +A = 3f +M = 3a + +ModInv = 19 +A = 41 +M = 3a + +ModInv = d +A = 43 +M = 3a + +ModInv = 25 +A = 45 +M = 3a + +ModInv = 9 +A = 47 +M = 3a + +ModInv = 1f +A = 49 +M = 3a + +ModInv = 29 +A = 4b +M = 3a + +ModInv = 37 +A = 4d +M = 3a + +ModInv = 2f +A = 4f +M = 3a + +ModInv = 35 +A = 51 +M = 3a + +ModInv = 7 +A = 53 +M = 3a + +ModInv = 2b +A = 55 +M = 3a + +ModInv = f +A = 59 +M = 3a + +ModInv = 33 +A = 5b +M = 3a + +ModInv = 5 +A = 5d +M = 3a + +ModInv = b +A = 5f +M = 3a + +ModInv = 3 +A = 61 +M = 3a + +ModInv = 11 +A = 63 +M = 3a + +ModInv = 17 +A = -64 +M = 3b + +ModInv = 1c +A = -63 +M = 3b + +ModInv = 3 +A = -62 +M = 3b + +ModInv = 2d +A = -61 +M = 3b + +ModInv = 33 +A = -60 +M = 3b + +ModInv = 12 +A = -5f +M = 3b + +ModInv = 20 +A = -5e +M = 3b + +ModInv = 1a +A = -5d +M = 3b + +ModInv = 19 +A = -5c +M = 3b + +ModInv = 23 +A = -5b +M = 3b + +ModInv = 13 +A = -5a +M = 3b + +ModInv = 39 +A = -59 +M = 3b + +ModInv = 2 +A = -58 +M = 3b + +ModInv = 28 +A = -57 +M = 3b + +ModInv = 18 +A = -56 +M = 3b + +ModInv = 22 +A = -55 +M = 3b + +ModInv = 21 +A = -54 +M = 3b + +ModInv = 1b +A = -53 +M = 3b + +ModInv = 29 +A = -52 +M = 3b + +ModInv = 8 +A = -51 +M = 3b + +ModInv = e +A = -50 +M = 3b + +ModInv = 38 +A = -4f +M = 3b + +ModInv = 1f +A = -4e +M = 3b + +ModInv = 24 +A = -4d +M = 3b + +ModInv = 34 +A = -4c +M = 3b + +ModInv = b +A = -4b +M = 3b + +ModInv = 37 +A = -4a +M = 3b + +ModInv = 15 +A = -49 +M = 3b + +ModInv = 9 +A = -48 +M = 3b + +ModInv = 36 +A = -47 +M = 3b + +ModInv = 10 +A = -46 +M = 3b + +ModInv = 35 +A = -45 +M = 3b + +ModInv = d +A = -44 +M = 3b + +ModInv = 16 +A = -43 +M = 3b + +ModInv = 2a +A = -42 +M = 3b + +ModInv = 31 +A = -41 +M = 3b + +ModInv = 2f +A = -40 +M = 3b + +ModInv = 2c +A = -3f +M = 3b + +ModInv = 27 +A = -3e +M = 3b + +ModInv = 1d +A = -3d +M = 3b + +ModInv = 3a +A = -3c +M = 3b + +ModInv = 1 +A = -3a +M = 3b + +ModInv = 1e +A = -39 +M = 3b + +ModInv = 14 +A = -38 +M = 3b + +ModInv = f +A = -37 +M = 3b + +ModInv = c +A = -36 +M = 3b + +ModInv = a +A = -35 +M = 3b + +ModInv = 11 +A = -34 +M = 3b + +ModInv = 25 +A = -33 +M = 3b + +ModInv = 2e +A = -32 +M = 3b + +ModInv = 6 +A = -31 +M = 3b + +ModInv = 2b +A = -30 +M = 3b + +ModInv = 5 +A = -2f +M = 3b + +ModInv = 32 +A = -2e +M = 3b + +ModInv = 26 +A = -2d +M = 3b + +ModInv = 4 +A = -2c +M = 3b + +ModInv = 30 +A = -2b +M = 3b + +ModInv = 7 +A = -2a +M = 3b + +ModInv = 17 +A = -29 +M = 3b + +ModInv = 1c +A = -28 +M = 3b + +ModInv = 3 +A = -27 +M = 3b + +ModInv = 2d +A = -26 +M = 3b + +ModInv = 33 +A = -25 +M = 3b + +ModInv = 12 +A = -24 +M = 3b + +ModInv = 20 +A = -23 +M = 3b + +ModInv = 1a +A = -22 +M = 3b + +ModInv = 19 +A = -21 +M = 3b + +ModInv = 23 +A = -20 +M = 3b + +ModInv = 13 +A = -1f +M = 3b + +ModInv = 39 +A = -1e +M = 3b + +ModInv = 2 +A = -1d +M = 3b + +ModInv = 28 +A = -1c +M = 3b + +ModInv = 18 +A = -1b +M = 3b + +ModInv = 22 +A = -1a +M = 3b + +ModInv = 21 +A = -19 +M = 3b + +ModInv = 1b +A = -18 +M = 3b + +ModInv = 29 +A = -17 +M = 3b + +ModInv = 8 +A = -16 +M = 3b + +ModInv = e +A = -15 +M = 3b + +ModInv = 38 +A = -14 +M = 3b + +ModInv = 1f +A = -13 +M = 3b + +ModInv = 24 +A = -12 +M = 3b + +ModInv = 34 +A = -11 +M = 3b + +ModInv = b +A = -10 +M = 3b + +ModInv = 37 +A = -f +M = 3b + +ModInv = 15 +A = -e +M = 3b + +ModInv = 9 +A = -d +M = 3b + +ModInv = 36 +A = -c +M = 3b + +ModInv = 10 +A = -b +M = 3b + +ModInv = 35 +A = -a +M = 3b + +ModInv = d +A = -9 +M = 3b + +ModInv = 16 +A = -8 +M = 3b + +ModInv = 2a +A = -7 +M = 3b + +ModInv = 31 +A = -6 +M = 3b + +ModInv = 2f +A = -5 +M = 3b + +ModInv = 2c +A = -4 +M = 3b + +ModInv = 27 +A = -3 +M = 3b + +ModInv = 1d +A = -2 +M = 3b + +ModInv = 3a +A = -1 +M = 3b + +ModInv = 1 +A = 1 +M = 3b + +ModInv = 1e +A = 2 +M = 3b + +ModInv = 14 +A = 3 +M = 3b + +ModInv = f +A = 4 +M = 3b + +ModInv = c +A = 5 +M = 3b + +ModInv = a +A = 6 +M = 3b + +ModInv = 11 +A = 7 +M = 3b + +ModInv = 25 +A = 8 +M = 3b + +ModInv = 2e +A = 9 +M = 3b + +ModInv = 6 +A = a +M = 3b + +ModInv = 2b +A = b +M = 3b + +ModInv = 5 +A = c +M = 3b + +ModInv = 32 +A = d +M = 3b + +ModInv = 26 +A = e +M = 3b + +ModInv = 4 +A = f +M = 3b + +ModInv = 30 +A = 10 +M = 3b + +ModInv = 7 +A = 11 +M = 3b + +ModInv = 17 +A = 12 +M = 3b + +ModInv = 1c +A = 13 +M = 3b + +ModInv = 3 +A = 14 +M = 3b + +ModInv = 2d +A = 15 +M = 3b + +ModInv = 33 +A = 16 +M = 3b + +ModInv = 12 +A = 17 +M = 3b + +ModInv = 20 +A = 18 +M = 3b + +ModInv = 1a +A = 19 +M = 3b + +ModInv = 19 +A = 1a +M = 3b + +ModInv = 23 +A = 1b +M = 3b + +ModInv = 13 +A = 1c +M = 3b + +ModInv = 39 +A = 1d +M = 3b + +ModInv = 2 +A = 1e +M = 3b + +ModInv = 28 +A = 1f +M = 3b + +ModInv = 18 +A = 20 +M = 3b + +ModInv = 22 +A = 21 +M = 3b + +ModInv = 21 +A = 22 +M = 3b + +ModInv = 1b +A = 23 +M = 3b + +ModInv = 29 +A = 24 +M = 3b + +ModInv = 8 +A = 25 +M = 3b + +ModInv = e +A = 26 +M = 3b + +ModInv = 38 +A = 27 +M = 3b + +ModInv = 1f +A = 28 +M = 3b + +ModInv = 24 +A = 29 +M = 3b + +ModInv = 34 +A = 2a +M = 3b + +ModInv = b +A = 2b +M = 3b + +ModInv = 37 +A = 2c +M = 3b + +ModInv = 15 +A = 2d +M = 3b + +ModInv = 9 +A = 2e +M = 3b + +ModInv = 36 +A = 2f +M = 3b + +ModInv = 10 +A = 30 +M = 3b + +ModInv = 35 +A = 31 +M = 3b + +ModInv = d +A = 32 +M = 3b + +ModInv = 16 +A = 33 +M = 3b + +ModInv = 2a +A = 34 +M = 3b + +ModInv = 31 +A = 35 +M = 3b + +ModInv = 2f +A = 36 +M = 3b + +ModInv = 2c +A = 37 +M = 3b + +ModInv = 27 +A = 38 +M = 3b + +ModInv = 1d +A = 39 +M = 3b + +ModInv = 3a +A = 3a +M = 3b + +ModInv = 1 +A = 3c +M = 3b + +ModInv = 1e +A = 3d +M = 3b + +ModInv = 14 +A = 3e +M = 3b + +ModInv = f +A = 3f +M = 3b + +ModInv = c +A = 40 +M = 3b + +ModInv = a +A = 41 +M = 3b + +ModInv = 11 +A = 42 +M = 3b + +ModInv = 25 +A = 43 +M = 3b + +ModInv = 2e +A = 44 +M = 3b + +ModInv = 6 +A = 45 +M = 3b + +ModInv = 2b +A = 46 +M = 3b + +ModInv = 5 +A = 47 +M = 3b + +ModInv = 32 +A = 48 +M = 3b + +ModInv = 26 +A = 49 +M = 3b + +ModInv = 4 +A = 4a +M = 3b + +ModInv = 30 +A = 4b +M = 3b + +ModInv = 7 +A = 4c +M = 3b + +ModInv = 17 +A = 4d +M = 3b + +ModInv = 1c +A = 4e +M = 3b + +ModInv = 3 +A = 4f +M = 3b + +ModInv = 2d +A = 50 +M = 3b + +ModInv = 33 +A = 51 +M = 3b + +ModInv = 12 +A = 52 +M = 3b + +ModInv = 20 +A = 53 +M = 3b + +ModInv = 1a +A = 54 +M = 3b + +ModInv = 19 +A = 55 +M = 3b + +ModInv = 23 +A = 56 +M = 3b + +ModInv = 13 +A = 57 +M = 3b + +ModInv = 39 +A = 58 +M = 3b + +ModInv = 2 +A = 59 +M = 3b + +ModInv = 28 +A = 5a +M = 3b + +ModInv = 18 +A = 5b +M = 3b + +ModInv = 22 +A = 5c +M = 3b + +ModInv = 21 +A = 5d +M = 3b + +ModInv = 1b +A = 5e +M = 3b + +ModInv = 29 +A = 5f +M = 3b + +ModInv = 8 +A = 60 +M = 3b + +ModInv = e +A = 61 +M = 3b + +ModInv = 38 +A = 62 +M = 3b + +ModInv = 1f +A = 63 +M = 3b + +ModInv = 2f +A = -61 +M = 3c + +ModInv = 1d +A = -5b +M = 3c + +ModInv = 1f +A = -59 +M = 3c + +ModInv = d +A = -53 +M = 3c + +ModInv = 29 +A = -4f +M = 3c + +ModInv = 7 +A = -4d +M = 3c + +ModInv = 17 +A = -49 +M = 3c + +ModInv = 31 +A = -47 +M = 3c + +ModInv = 11 +A = -43 +M = 3c + +ModInv = 3b +A = -3d +M = 3c + +ModInv = 1 +A = -3b +M = 3c + +ModInv = 2b +A = -35 +M = 3c + +ModInv = b +A = -31 +M = 3c + +ModInv = 25 +A = -2f +M = 3c + +ModInv = 35 +A = -2b +M = 3c + +ModInv = 13 +A = -29 +M = 3c + +ModInv = 2f +A = -25 +M = 3c + +ModInv = 1d +A = -1f +M = 3c + +ModInv = 1f +A = -1d +M = 3c + +ModInv = d +A = -17 +M = 3c + +ModInv = 29 +A = -13 +M = 3c + +ModInv = 7 +A = -11 +M = 3c + +ModInv = 17 +A = -d +M = 3c + +ModInv = 31 +A = -b +M = 3c + +ModInv = 11 +A = -7 +M = 3c + +ModInv = 3b +A = -1 +M = 3c + +ModInv = 1 +A = 1 +M = 3c + +ModInv = 2b +A = 7 +M = 3c + +ModInv = b +A = b +M = 3c + +ModInv = 25 +A = d +M = 3c + +ModInv = 35 +A = 11 +M = 3c + +ModInv = 13 +A = 13 +M = 3c + +ModInv = 2f +A = 17 +M = 3c + +ModInv = 1d +A = 1d +M = 3c + +ModInv = 1f +A = 1f +M = 3c + +ModInv = d +A = 25 +M = 3c + +ModInv = 29 +A = 29 +M = 3c + +ModInv = 7 +A = 2b +M = 3c + +ModInv = 17 +A = 2f +M = 3c + +ModInv = 31 +A = 31 +M = 3c + +ModInv = 11 +A = 35 +M = 3c + +ModInv = 3b +A = 3b +M = 3c + +ModInv = 1 +A = 3d +M = 3c + +ModInv = 2b +A = 43 +M = 3c + +ModInv = b +A = 47 +M = 3c + +ModInv = 25 +A = 49 +M = 3c + +ModInv = 35 +A = 4d +M = 3c + +ModInv = 13 +A = 4f +M = 3c + +ModInv = 2f +A = 53 +M = 3c + +ModInv = 1d +A = 59 +M = 3c + +ModInv = 1f +A = 5b +M = 3c + +ModInv = d +A = 61 +M = 3c + +ModInv = 19 +A = -64 +M = 3d + +ModInv = 8 +A = -63 +M = 3d + +ModInv = 1c +A = -62 +M = 3d + +ModInv = 16 +A = -61 +M = 3d + +ModInv = 36 +A = -60 +M = 3d + +ModInv = 34 +A = -5f +M = 3d + +ModInv = 18 +A = -5e +M = 3d + +ModInv = 28 +A = -5d +M = 3d + +ModInv = 3b +A = -5c +M = 3d + +ModInv = 2 +A = -5b +M = 3d + +ModInv = 15 +A = -5a +M = 3d + +ModInv = 25 +A = -59 +M = 3d + +ModInv = 9 +A = -58 +M = 3d + +ModInv = 7 +A = -57 +M = 3d + +ModInv = 27 +A = -56 +M = 3d + +ModInv = 21 +A = -55 +M = 3d + +ModInv = 35 +A = -54 +M = 3d + +ModInv = 24 +A = -53 +M = 3d + +ModInv = 1d +A = -52 +M = 3d + +ModInv = 3 +A = -51 +M = 3d + +ModInv = 10 +A = -50 +M = 3d + +ModInv = 2c +A = -4f +M = 3d + +ModInv = 2b +A = -4e +M = 3d + +ModInv = 13 +A = -4d +M = 3d + +ModInv = 4 +A = -4c +M = 3d + +ModInv = d +A = -4b +M = 3d + +ModInv = e +A = -4a +M = 3d + +ModInv = 5 +A = -49 +M = 3d + +ModInv = b +A = -48 +M = 3d + +ModInv = 6 +A = -47 +M = 3d + +ModInv = 1b +A = -46 +M = 3d + +ModInv = 26 +A = -45 +M = 3d + +ModInv = 1a +A = -44 +M = 3d + +ModInv = a +A = -43 +M = 3d + +ModInv = c +A = -42 +M = 3d + +ModInv = f +A = -41 +M = 3d + +ModInv = 14 +A = -40 +M = 3d + +ModInv = 1e +A = -3f +M = 3d + +ModInv = 3c +A = -3e +M = 3d + +ModInv = 1 +A = -3c +M = 3d + +ModInv = 1f +A = -3b +M = 3d + +ModInv = 29 +A = -3a +M = 3d + +ModInv = 2e +A = -39 +M = 3d + +ModInv = 31 +A = -38 +M = 3d + +ModInv = 33 +A = -37 +M = 3d + +ModInv = 23 +A = -36 +M = 3d + +ModInv = 17 +A = -35 +M = 3d + +ModInv = 22 +A = -34 +M = 3d + +ModInv = 37 +A = -33 +M = 3d + +ModInv = 32 +A = -32 +M = 3d + +ModInv = 38 +A = -31 +M = 3d + +ModInv = 2f +A = -30 +M = 3d + +ModInv = 30 +A = -2f +M = 3d + +ModInv = 39 +A = -2e +M = 3d + +ModInv = 2a +A = -2d +M = 3d + +ModInv = 12 +A = -2c +M = 3d + +ModInv = 11 +A = -2b +M = 3d + +ModInv = 2d +A = -2a +M = 3d + +ModInv = 3a +A = -29 +M = 3d + +ModInv = 20 +A = -28 +M = 3d + +ModInv = 19 +A = -27 +M = 3d + +ModInv = 8 +A = -26 +M = 3d + +ModInv = 1c +A = -25 +M = 3d + +ModInv = 16 +A = -24 +M = 3d + +ModInv = 36 +A = -23 +M = 3d + +ModInv = 34 +A = -22 +M = 3d + +ModInv = 18 +A = -21 +M = 3d + +ModInv = 28 +A = -20 +M = 3d + +ModInv = 3b +A = -1f +M = 3d + +ModInv = 2 +A = -1e +M = 3d + +ModInv = 15 +A = -1d +M = 3d + +ModInv = 25 +A = -1c +M = 3d + +ModInv = 9 +A = -1b +M = 3d + +ModInv = 7 +A = -1a +M = 3d + +ModInv = 27 +A = -19 +M = 3d + +ModInv = 21 +A = -18 +M = 3d + +ModInv = 35 +A = -17 +M = 3d + +ModInv = 24 +A = -16 +M = 3d + +ModInv = 1d +A = -15 +M = 3d + +ModInv = 3 +A = -14 +M = 3d + +ModInv = 10 +A = -13 +M = 3d + +ModInv = 2c +A = -12 +M = 3d + +ModInv = 2b +A = -11 +M = 3d + +ModInv = 13 +A = -10 +M = 3d + +ModInv = 4 +A = -f +M = 3d + +ModInv = d +A = -e +M = 3d + +ModInv = e +A = -d +M = 3d + +ModInv = 5 +A = -c +M = 3d + +ModInv = b +A = -b +M = 3d + +ModInv = 6 +A = -a +M = 3d + +ModInv = 1b +A = -9 +M = 3d + +ModInv = 26 +A = -8 +M = 3d + +ModInv = 1a +A = -7 +M = 3d + +ModInv = a +A = -6 +M = 3d + +ModInv = c +A = -5 +M = 3d + +ModInv = f +A = -4 +M = 3d + +ModInv = 14 +A = -3 +M = 3d + +ModInv = 1e +A = -2 +M = 3d + +ModInv = 3c +A = -1 +M = 3d + +ModInv = 1 +A = 1 +M = 3d + +ModInv = 1f +A = 2 +M = 3d + +ModInv = 29 +A = 3 +M = 3d + +ModInv = 2e +A = 4 +M = 3d + +ModInv = 31 +A = 5 +M = 3d + +ModInv = 33 +A = 6 +M = 3d + +ModInv = 23 +A = 7 +M = 3d + +ModInv = 17 +A = 8 +M = 3d + +ModInv = 22 +A = 9 +M = 3d + +ModInv = 37 +A = a +M = 3d + +ModInv = 32 +A = b +M = 3d + +ModInv = 38 +A = c +M = 3d + +ModInv = 2f +A = d +M = 3d + +ModInv = 30 +A = e +M = 3d + +ModInv = 39 +A = f +M = 3d + +ModInv = 2a +A = 10 +M = 3d + +ModInv = 12 +A = 11 +M = 3d + +ModInv = 11 +A = 12 +M = 3d + +ModInv = 2d +A = 13 +M = 3d + +ModInv = 3a +A = 14 +M = 3d + +ModInv = 20 +A = 15 +M = 3d + +ModInv = 19 +A = 16 +M = 3d + +ModInv = 8 +A = 17 +M = 3d + +ModInv = 1c +A = 18 +M = 3d + +ModInv = 16 +A = 19 +M = 3d + +ModInv = 36 +A = 1a +M = 3d + +ModInv = 34 +A = 1b +M = 3d + +ModInv = 18 +A = 1c +M = 3d + +ModInv = 28 +A = 1d +M = 3d + +ModInv = 3b +A = 1e +M = 3d + +ModInv = 2 +A = 1f +M = 3d + +ModInv = 15 +A = 20 +M = 3d + +ModInv = 25 +A = 21 +M = 3d + +ModInv = 9 +A = 22 +M = 3d + +ModInv = 7 +A = 23 +M = 3d + +ModInv = 27 +A = 24 +M = 3d + +ModInv = 21 +A = 25 +M = 3d + +ModInv = 35 +A = 26 +M = 3d + +ModInv = 24 +A = 27 +M = 3d + +ModInv = 1d +A = 28 +M = 3d + +ModInv = 3 +A = 29 +M = 3d + +ModInv = 10 +A = 2a +M = 3d + +ModInv = 2c +A = 2b +M = 3d + +ModInv = 2b +A = 2c +M = 3d + +ModInv = 13 +A = 2d +M = 3d + +ModInv = 4 +A = 2e +M = 3d + +ModInv = d +A = 2f +M = 3d + +ModInv = e +A = 30 +M = 3d + +ModInv = 5 +A = 31 +M = 3d + +ModInv = b +A = 32 +M = 3d + +ModInv = 6 +A = 33 +M = 3d + +ModInv = 1b +A = 34 +M = 3d + +ModInv = 26 +A = 35 +M = 3d + +ModInv = 1a +A = 36 +M = 3d + +ModInv = a +A = 37 +M = 3d + +ModInv = c +A = 38 +M = 3d + +ModInv = f +A = 39 +M = 3d + +ModInv = 14 +A = 3a +M = 3d + +ModInv = 1e +A = 3b +M = 3d + +ModInv = 3c +A = 3c +M = 3d + +ModInv = 1 +A = 3e +M = 3d + +ModInv = 1f +A = 3f +M = 3d + +ModInv = 29 +A = 40 +M = 3d + +ModInv = 2e +A = 41 +M = 3d + +ModInv = 31 +A = 42 +M = 3d + +ModInv = 33 +A = 43 +M = 3d + +ModInv = 23 +A = 44 +M = 3d + +ModInv = 17 +A = 45 +M = 3d + +ModInv = 22 +A = 46 +M = 3d + +ModInv = 37 +A = 47 +M = 3d + +ModInv = 32 +A = 48 +M = 3d + +ModInv = 38 +A = 49 +M = 3d + +ModInv = 2f +A = 4a +M = 3d + +ModInv = 30 +A = 4b +M = 3d + +ModInv = 39 +A = 4c +M = 3d + +ModInv = 2a +A = 4d +M = 3d + +ModInv = 12 +A = 4e +M = 3d + +ModInv = 11 +A = 4f +M = 3d + +ModInv = 2d +A = 50 +M = 3d + +ModInv = 3a +A = 51 +M = 3d + +ModInv = 20 +A = 52 +M = 3d + +ModInv = 19 +A = 53 +M = 3d + +ModInv = 8 +A = 54 +M = 3d + +ModInv = 1c +A = 55 +M = 3d + +ModInv = 16 +A = 56 +M = 3d + +ModInv = 36 +A = 57 +M = 3d + +ModInv = 34 +A = 58 +M = 3d + +ModInv = 18 +A = 59 +M = 3d + +ModInv = 28 +A = 5a +M = 3d + +ModInv = 3b +A = 5b +M = 3d + +ModInv = 2 +A = 5c +M = 3d + +ModInv = 15 +A = 5d +M = 3d + +ModInv = 25 +A = 5e +M = 3d + +ModInv = 9 +A = 5f +M = 3d + +ModInv = 7 +A = 60 +M = 3d + +ModInv = 27 +A = 61 +M = 3d + +ModInv = 21 +A = 62 +M = 3d + +ModInv = 35 +A = 63 +M = 3d + +ModInv = 5 +A = -63 +M = 3e + +ModInv = 17 +A = -61 +M = 3e + +ModInv = f +A = -5f +M = 3e + +ModInv = 2f +A = -5b +M = 3e + +ModInv = 27 +A = -59 +M = 3e + +ModInv = 39 +A = -57 +M = 3e + +ModInv = 23 +A = -55 +M = 3e + +ModInv = 3b +A = -53 +M = 3e + +ModInv = d +A = -51 +M = 3e + +ModInv = 33 +A = -4f +M = 3e + +ModInv = 21 +A = -4d +M = 3e + +ModInv = 13 +A = -4b +M = 3e + +ModInv = 2d +A = -49 +M = 3e + +ModInv = 37 +A = -47 +M = 3e + +ModInv = 35 +A = -45 +M = 3e + +ModInv = 25 +A = -43 +M = 3e + +ModInv = 29 +A = -41 +M = 3e + +ModInv = 3d +A = -3f +M = 3e + +ModInv = 1 +A = -3d +M = 3e + +ModInv = 15 +A = -3b +M = 3e + +ModInv = 19 +A = -39 +M = 3e + +ModInv = 9 +A = -37 +M = 3e + +ModInv = 7 +A = -35 +M = 3e + +ModInv = 11 +A = -33 +M = 3e + +ModInv = 2b +A = -31 +M = 3e + +ModInv = 1d +A = -2f +M = 3e + +ModInv = b +A = -2d +M = 3e + +ModInv = 31 +A = -2b +M = 3e + +ModInv = 3 +A = -29 +M = 3e + +ModInv = 1b +A = -27 +M = 3e + +ModInv = 5 +A = -25 +M = 3e + +ModInv = 17 +A = -23 +M = 3e + +ModInv = f +A = -21 +M = 3e + +ModInv = 2f +A = -1d +M = 3e + +ModInv = 27 +A = -1b +M = 3e + +ModInv = 39 +A = -19 +M = 3e + +ModInv = 23 +A = -17 +M = 3e + +ModInv = 3b +A = -15 +M = 3e + +ModInv = d +A = -13 +M = 3e + +ModInv = 33 +A = -11 +M = 3e + +ModInv = 21 +A = -f +M = 3e + +ModInv = 13 +A = -d +M = 3e + +ModInv = 2d +A = -b +M = 3e + +ModInv = 37 +A = -9 +M = 3e + +ModInv = 35 +A = -7 +M = 3e + +ModInv = 25 +A = -5 +M = 3e + +ModInv = 29 +A = -3 +M = 3e + +ModInv = 3d +A = -1 +M = 3e + +ModInv = 1 +A = 1 +M = 3e + +ModInv = 15 +A = 3 +M = 3e + +ModInv = 19 +A = 5 +M = 3e + +ModInv = 9 +A = 7 +M = 3e + +ModInv = 7 +A = 9 +M = 3e + +ModInv = 11 +A = b +M = 3e + +ModInv = 2b +A = d +M = 3e + +ModInv = 1d +A = f +M = 3e + +ModInv = b +A = 11 +M = 3e + +ModInv = 31 +A = 13 +M = 3e + +ModInv = 3 +A = 15 +M = 3e + +ModInv = 1b +A = 17 +M = 3e + +ModInv = 5 +A = 19 +M = 3e + +ModInv = 17 +A = 1b +M = 3e + +ModInv = f +A = 1d +M = 3e + +ModInv = 2f +A = 21 +M = 3e + +ModInv = 27 +A = 23 +M = 3e + +ModInv = 39 +A = 25 +M = 3e + +ModInv = 23 +A = 27 +M = 3e + +ModInv = 3b +A = 29 +M = 3e + +ModInv = d +A = 2b +M = 3e + +ModInv = 33 +A = 2d +M = 3e + +ModInv = 21 +A = 2f +M = 3e + +ModInv = 13 +A = 31 +M = 3e + +ModInv = 2d +A = 33 +M = 3e + +ModInv = 37 +A = 35 +M = 3e + +ModInv = 35 +A = 37 +M = 3e + +ModInv = 25 +A = 39 +M = 3e + +ModInv = 29 +A = 3b +M = 3e + +ModInv = 3d +A = 3d +M = 3e + +ModInv = 1 +A = 3f +M = 3e + +ModInv = 15 +A = 41 +M = 3e + +ModInv = 19 +A = 43 +M = 3e + +ModInv = 9 +A = 45 +M = 3e + +ModInv = 7 +A = 47 +M = 3e + +ModInv = 11 +A = 49 +M = 3e + +ModInv = 2b +A = 4b +M = 3e + +ModInv = 1d +A = 4d +M = 3e + +ModInv = b +A = 4f +M = 3e + +ModInv = 31 +A = 51 +M = 3e + +ModInv = 3 +A = 53 +M = 3e + +ModInv = 1b +A = 55 +M = 3e + +ModInv = 5 +A = 57 +M = 3e + +ModInv = 17 +A = 59 +M = 3e + +ModInv = f +A = 5b +M = 3e + +ModInv = 2f +A = 5f +M = 3e + +ModInv = 27 +A = 61 +M = 3e + +ModInv = 39 +A = 63 +M = 3e + +ModInv = 11 +A = -64 +M = 3f + +ModInv = 32 +A = -61 +M = 3f + +ModInv = 3d +A = -5f +M = 3f + +ModInv = 2 +A = -5e +M = 3f + +ModInv = d +A = -5c +M = 3f + +ModInv = 2e +A = -59 +M = 3f + +ModInv = 5 +A = -58 +M = 3f + +ModInv = 34 +A = -56 +M = 3f + +ModInv = 14 +A = -55 +M = 3f + +ModInv = 16 +A = -53 +M = 3f + +ModInv = 35 +A = -52 +M = 3f + +ModInv = 25 +A = -50 +M = 3f + +ModInv = 3b +A = -4f +M = 3f + +ModInv = 1d +A = -4c +M = 3f + +ModInv = 28 +A = -4a +M = 3f + +ModInv = 2c +A = -49 +M = 3f + +ModInv = 37 +A = -47 +M = 3f + +ModInv = 19 +A = -44 +M = 3f + +ModInv = 2f +A = -43 +M = 3f + +ModInv = 1f +A = -41 +M = 3f + +ModInv = 3e +A = -40 +M = 3f + +ModInv = 1 +A = -3e +M = 3f + +ModInv = 20 +A = -3d +M = 3f + +ModInv = 10 +A = -3b +M = 3f + +ModInv = 26 +A = -3a +M = 3f + +ModInv = 8 +A = -37 +M = 3f + +ModInv = 13 +A = -35 +M = 3f + +ModInv = 17 +A = -34 +M = 3f + +ModInv = 22 +A = -32 +M = 3f + +ModInv = 4 +A = -2f +M = 3f + +ModInv = 1a +A = -2e +M = 3f + +ModInv = a +A = -2c +M = 3f + +ModInv = 29 +A = -2b +M = 3f + +ModInv = 2b +A = -29 +M = 3f + +ModInv = b +A = -28 +M = 3f + +ModInv = 3a +A = -26 +M = 3f + +ModInv = 11 +A = -25 +M = 3f + +ModInv = 32 +A = -22 +M = 3f + +ModInv = 3d +A = -20 +M = 3f + +ModInv = 2 +A = -1f +M = 3f + +ModInv = d +A = -1d +M = 3f + +ModInv = 2e +A = -1a +M = 3f + +ModInv = 5 +A = -19 +M = 3f + +ModInv = 34 +A = -17 +M = 3f + +ModInv = 14 +A = -16 +M = 3f + +ModInv = 16 +A = -14 +M = 3f + +ModInv = 35 +A = -13 +M = 3f + +ModInv = 25 +A = -11 +M = 3f + +ModInv = 3b +A = -10 +M = 3f + +ModInv = 1d +A = -d +M = 3f + +ModInv = 28 +A = -b +M = 3f + +ModInv = 2c +A = -a +M = 3f + +ModInv = 37 +A = -8 +M = 3f + +ModInv = 19 +A = -5 +M = 3f + +ModInv = 2f +A = -4 +M = 3f + +ModInv = 1f +A = -2 +M = 3f + +ModInv = 3e +A = -1 +M = 3f + +ModInv = 1 +A = 1 +M = 3f + +ModInv = 20 +A = 2 +M = 3f + +ModInv = 10 +A = 4 +M = 3f + +ModInv = 26 +A = 5 +M = 3f + +ModInv = 8 +A = 8 +M = 3f + +ModInv = 13 +A = a +M = 3f + +ModInv = 17 +A = b +M = 3f + +ModInv = 22 +A = d +M = 3f + +ModInv = 4 +A = 10 +M = 3f + +ModInv = 1a +A = 11 +M = 3f + +ModInv = a +A = 13 +M = 3f + +ModInv = 29 +A = 14 +M = 3f + +ModInv = 2b +A = 16 +M = 3f + +ModInv = b +A = 17 +M = 3f + +ModInv = 3a +A = 19 +M = 3f + +ModInv = 11 +A = 1a +M = 3f + +ModInv = 32 +A = 1d +M = 3f + +ModInv = 3d +A = 1f +M = 3f + +ModInv = 2 +A = 20 +M = 3f + +ModInv = d +A = 22 +M = 3f + +ModInv = 2e +A = 25 +M = 3f + +ModInv = 5 +A = 26 +M = 3f + +ModInv = 34 +A = 28 +M = 3f + +ModInv = 14 +A = 29 +M = 3f + +ModInv = 16 +A = 2b +M = 3f + +ModInv = 35 +A = 2c +M = 3f + +ModInv = 25 +A = 2e +M = 3f + +ModInv = 3b +A = 2f +M = 3f + +ModInv = 1d +A = 32 +M = 3f + +ModInv = 28 +A = 34 +M = 3f + +ModInv = 2c +A = 35 +M = 3f + +ModInv = 37 +A = 37 +M = 3f + +ModInv = 19 +A = 3a +M = 3f + +ModInv = 2f +A = 3b +M = 3f + +ModInv = 1f +A = 3d +M = 3f + +ModInv = 3e +A = 3e +M = 3f + +ModInv = 1 +A = 40 +M = 3f + +ModInv = 20 +A = 41 +M = 3f + +ModInv = 10 +A = 43 +M = 3f + +ModInv = 26 +A = 44 +M = 3f + +ModInv = 8 +A = 47 +M = 3f + +ModInv = 13 +A = 49 +M = 3f + +ModInv = 17 +A = 4a +M = 3f + +ModInv = 22 +A = 4c +M = 3f + +ModInv = 4 +A = 4f +M = 3f + +ModInv = 1a +A = 50 +M = 3f + +ModInv = a +A = 52 +M = 3f + +ModInv = 29 +A = 53 +M = 3f + +ModInv = 2b +A = 55 +M = 3f + +ModInv = b +A = 56 +M = 3f + +ModInv = 3a +A = 58 +M = 3f + +ModInv = 11 +A = 59 +M = 3f + +ModInv = 32 +A = 5c +M = 3f + +ModInv = 3d +A = 5e +M = 3f + +ModInv = 2 +A = 5f +M = 3f + +ModInv = d +A = 61 +M = 3f + +ModInv = 35 +A = -63 +M = 40 + +ModInv = 1f +A = -61 +M = 40 + +ModInv = 21 +A = -5f +M = 40 + +ModInv = b +A = -5d +M = 40 + +ModInv = 2d +A = -5b +M = 40 + +ModInv = 17 +A = -59 +M = 40 + +ModInv = 19 +A = -57 +M = 40 + +ModInv = 3 +A = -55 +M = 40 + +ModInv = 25 +A = -53 +M = 40 + +ModInv = f +A = -51 +M = 40 + +ModInv = 11 +A = -4f +M = 40 + +ModInv = 3b +A = -4d +M = 40 + +ModInv = 1d +A = -4b +M = 40 + +ModInv = 7 +A = -49 +M = 40 + +ModInv = 9 +A = -47 +M = 40 + +ModInv = 33 +A = -45 +M = 40 + +ModInv = 15 +A = -43 +M = 40 + +ModInv = 3f +A = -41 +M = 40 + +ModInv = 1 +A = -3f +M = 40 + +ModInv = 2b +A = -3d +M = 40 + +ModInv = d +A = -3b +M = 40 + +ModInv = 37 +A = -39 +M = 40 + +ModInv = 39 +A = -37 +M = 40 + +ModInv = 23 +A = -35 +M = 40 + +ModInv = 5 +A = -33 +M = 40 + +ModInv = 2f +A = -31 +M = 40 + +ModInv = 31 +A = -2f +M = 40 + +ModInv = 1b +A = -2d +M = 40 + +ModInv = 3d +A = -2b +M = 40 + +ModInv = 27 +A = -29 +M = 40 + +ModInv = 29 +A = -27 +M = 40 + +ModInv = 13 +A = -25 +M = 40 + +ModInv = 35 +A = -23 +M = 40 + +ModInv = 1f +A = -21 +M = 40 + +ModInv = 21 +A = -1f +M = 40 + +ModInv = b +A = -1d +M = 40 + +ModInv = 2d +A = -1b +M = 40 + +ModInv = 17 +A = -19 +M = 40 + +ModInv = 19 +A = -17 +M = 40 + +ModInv = 3 +A = -15 +M = 40 + +ModInv = 25 +A = -13 +M = 40 + +ModInv = f +A = -11 +M = 40 + +ModInv = 11 +A = -f +M = 40 + +ModInv = 3b +A = -d +M = 40 + +ModInv = 1d +A = -b +M = 40 + +ModInv = 7 +A = -9 +M = 40 + +ModInv = 9 +A = -7 +M = 40 + +ModInv = 33 +A = -5 +M = 40 + +ModInv = 15 +A = -3 +M = 40 + +ModInv = 3f +A = -1 +M = 40 + +ModInv = 1 +A = 1 +M = 40 + +ModInv = 2b +A = 3 +M = 40 + +ModInv = d +A = 5 +M = 40 + +ModInv = 37 +A = 7 +M = 40 + +ModInv = 39 +A = 9 +M = 40 + +ModInv = 23 +A = b +M = 40 + +ModInv = 5 +A = d +M = 40 + +ModInv = 2f +A = f +M = 40 + +ModInv = 31 +A = 11 +M = 40 + +ModInv = 1b +A = 13 +M = 40 + +ModInv = 3d +A = 15 +M = 40 + +ModInv = 27 +A = 17 +M = 40 + +ModInv = 29 +A = 19 +M = 40 + +ModInv = 13 +A = 1b +M = 40 + +ModInv = 35 +A = 1d +M = 40 + +ModInv = 1f +A = 1f +M = 40 + +ModInv = 21 +A = 21 +M = 40 + +ModInv = b +A = 23 +M = 40 + +ModInv = 2d +A = 25 +M = 40 + +ModInv = 17 +A = 27 +M = 40 + +ModInv = 19 +A = 29 +M = 40 + +ModInv = 3 +A = 2b +M = 40 + +ModInv = 25 +A = 2d +M = 40 + +ModInv = f +A = 2f +M = 40 + +ModInv = 11 +A = 31 +M = 40 + +ModInv = 3b +A = 33 +M = 40 + +ModInv = 1d +A = 35 +M = 40 + +ModInv = 7 +A = 37 +M = 40 + +ModInv = 9 +A = 39 +M = 40 + +ModInv = 33 +A = 3b +M = 40 + +ModInv = 15 +A = 3d +M = 40 + +ModInv = 3f +A = 3f +M = 40 + +ModInv = 1 +A = 41 +M = 40 + +ModInv = 2b +A = 43 +M = 40 + +ModInv = d +A = 45 +M = 40 + +ModInv = 37 +A = 47 +M = 40 + +ModInv = 39 +A = 49 +M = 40 + +ModInv = 23 +A = 4b +M = 40 + +ModInv = 5 +A = 4d +M = 40 + +ModInv = 2f +A = 4f +M = 40 + +ModInv = 31 +A = 51 +M = 40 + +ModInv = 1b +A = 53 +M = 40 + +ModInv = 3d +A = 55 +M = 40 + +ModInv = 27 +A = 57 +M = 40 + +ModInv = 29 +A = 59 +M = 40 + +ModInv = 13 +A = 5b +M = 40 + +ModInv = 35 +A = 5d +M = 40 + +ModInv = 1f +A = 5f +M = 40 + +ModInv = 21 +A = 61 +M = 40 + +ModInv = b +A = 63 +M = 40 + +ModInv = 15 +A = -63 +M = 41 + +ModInv = 3f +A = -62 +M = 41 + +ModInv = 2 +A = -61 +M = 41 + +ModInv = 2c +A = -60 +M = 41 + +ModInv = 38 +A = -5e +M = 41 + +ModInv = 3a +A = -5d +M = 41 + +ModInv = c +A = -5c +M = 41 + +ModInv = 2e +A = -59 +M = 41 + +ModInv = 30 +A = -58 +M = 41 + +ModInv = 3e +A = -57 +M = 41 + +ModInv = 22 +A = -56 +M = 41 + +ModInv = 29 +A = -54 +M = 41 + +ModInv = 12 +A = -53 +M = 41 + +ModInv = 2a +A = -52 +M = 41 + +ModInv = 4 +A = -51 +M = 41 + +ModInv = 33 +A = -4f +M = 41 + +ModInv = 1b +A = -4d +M = 41 + +ModInv = 3b +A = -4c +M = 41 + +ModInv = 24 +A = -4a +M = 41 + +ModInv = 8 +A = -49 +M = 41 + +ModInv = 25 +A = -48 +M = 41 + +ModInv = 36 +A = -47 +M = 41 + +ModInv = 10 +A = -45 +M = 41 + +ModInv = 2b +A = -44 +M = 41 + +ModInv = 20 +A = -43 +M = 41 + +ModInv = 40 +A = -42 +M = 41 + +ModInv = 1 +A = -40 +M = 41 + +ModInv = 21 +A = -3f +M = 41 + +ModInv = 16 +A = -3e +M = 41 + +ModInv = 31 +A = -3d +M = 41 + +ModInv = b +A = -3b +M = 41 + +ModInv = 1c +A = -3a +M = 41 + +ModInv = 39 +A = -39 +M = 41 + +ModInv = 1d +A = -38 +M = 41 + +ModInv = 6 +A = -36 +M = 41 + +ModInv = 26 +A = -35 +M = 41 + +ModInv = e +A = -33 +M = 41 + +ModInv = 3d +A = -31 +M = 41 + +ModInv = 17 +A = -30 +M = 41 + +ModInv = 2f +A = -2f +M = 41 + +ModInv = 18 +A = -2e +M = 41 + +ModInv = 1f +A = -2c +M = 41 + +ModInv = 3 +A = -2b +M = 41 + +ModInv = 11 +A = -2a +M = 41 + +ModInv = 13 +A = -29 +M = 41 + +ModInv = 35 +A = -26 +M = 41 + +ModInv = 7 +A = -25 +M = 41 + +ModInv = 9 +A = -24 +M = 41 + +ModInv = 15 +A = -22 +M = 41 + +ModInv = 3f +A = -21 +M = 41 + +ModInv = 2 +A = -20 +M = 41 + +ModInv = 2c +A = -1f +M = 41 + +ModInv = 38 +A = -1d +M = 41 + +ModInv = 3a +A = -1c +M = 41 + +ModInv = c +A = -1b +M = 41 + +ModInv = 2e +A = -18 +M = 41 + +ModInv = 30 +A = -17 +M = 41 + +ModInv = 3e +A = -16 +M = 41 + +ModInv = 22 +A = -15 +M = 41 + +ModInv = 29 +A = -13 +M = 41 + +ModInv = 12 +A = -12 +M = 41 + +ModInv = 2a +A = -11 +M = 41 + +ModInv = 4 +A = -10 +M = 41 + +ModInv = 33 +A = -e +M = 41 + +ModInv = 1b +A = -c +M = 41 + +ModInv = 3b +A = -b +M = 41 + +ModInv = 24 +A = -9 +M = 41 + +ModInv = 8 +A = -8 +M = 41 + +ModInv = 25 +A = -7 +M = 41 + +ModInv = 36 +A = -6 +M = 41 + +ModInv = 10 +A = -4 +M = 41 + +ModInv = 2b +A = -3 +M = 41 + +ModInv = 20 +A = -2 +M = 41 + +ModInv = 40 +A = -1 +M = 41 + +ModInv = 1 +A = 1 +M = 41 + +ModInv = 21 +A = 2 +M = 41 + +ModInv = 16 +A = 3 +M = 41 + +ModInv = 31 +A = 4 +M = 41 + +ModInv = b +A = 6 +M = 41 + +ModInv = 1c +A = 7 +M = 41 + +ModInv = 39 +A = 8 +M = 41 + +ModInv = 1d +A = 9 +M = 41 + +ModInv = 6 +A = b +M = 41 + +ModInv = 26 +A = c +M = 41 + +ModInv = e +A = e +M = 41 + +ModInv = 3d +A = 10 +M = 41 + +ModInv = 17 +A = 11 +M = 41 + +ModInv = 2f +A = 12 +M = 41 + +ModInv = 18 +A = 13 +M = 41 + +ModInv = 1f +A = 15 +M = 41 + +ModInv = 3 +A = 16 +M = 41 + +ModInv = 11 +A = 17 +M = 41 + +ModInv = 13 +A = 18 +M = 41 + +ModInv = 35 +A = 1b +M = 41 + +ModInv = 7 +A = 1c +M = 41 + +ModInv = 9 +A = 1d +M = 41 + +ModInv = 15 +A = 1f +M = 41 + +ModInv = 3f +A = 20 +M = 41 + +ModInv = 2 +A = 21 +M = 41 + +ModInv = 2c +A = 22 +M = 41 + +ModInv = 38 +A = 24 +M = 41 + +ModInv = 3a +A = 25 +M = 41 + +ModInv = c +A = 26 +M = 41 + +ModInv = 2e +A = 29 +M = 41 + +ModInv = 30 +A = 2a +M = 41 + +ModInv = 3e +A = 2b +M = 41 + +ModInv = 22 +A = 2c +M = 41 + +ModInv = 29 +A = 2e +M = 41 + +ModInv = 12 +A = 2f +M = 41 + +ModInv = 2a +A = 30 +M = 41 + +ModInv = 4 +A = 31 +M = 41 + +ModInv = 33 +A = 33 +M = 41 + +ModInv = 1b +A = 35 +M = 41 + +ModInv = 3b +A = 36 +M = 41 + +ModInv = 24 +A = 38 +M = 41 + +ModInv = 8 +A = 39 +M = 41 + +ModInv = 25 +A = 3a +M = 41 + +ModInv = 36 +A = 3b +M = 41 + +ModInv = 10 +A = 3d +M = 41 + +ModInv = 2b +A = 3e +M = 41 + +ModInv = 20 +A = 3f +M = 41 + +ModInv = 40 +A = 40 +M = 41 + +ModInv = 1 +A = 42 +M = 41 + +ModInv = 21 +A = 43 +M = 41 + +ModInv = 16 +A = 44 +M = 41 + +ModInv = 31 +A = 45 +M = 41 + +ModInv = b +A = 47 +M = 41 + +ModInv = 1c +A = 48 +M = 41 + +ModInv = 39 +A = 49 +M = 41 + +ModInv = 1d +A = 4a +M = 41 + +ModInv = 6 +A = 4c +M = 41 + +ModInv = 26 +A = 4d +M = 41 + +ModInv = e +A = 4f +M = 41 + +ModInv = 3d +A = 51 +M = 41 + +ModInv = 17 +A = 52 +M = 41 + +ModInv = 2f +A = 53 +M = 41 + +ModInv = 18 +A = 54 +M = 41 + +ModInv = 1f +A = 56 +M = 41 + +ModInv = 3 +A = 57 +M = 41 + +ModInv = 11 +A = 58 +M = 41 + +ModInv = 13 +A = 59 +M = 41 + +ModInv = 35 +A = 5c +M = 41 + +ModInv = 7 +A = 5d +M = 41 + +ModInv = 9 +A = 5e +M = 41 + +ModInv = 15 +A = 60 +M = 41 + +ModInv = 3f +A = 61 +M = 41 + +ModInv = 2 +A = 62 +M = 41 + +ModInv = 2c +A = 63 +M = 41 + +ModInv = 11 +A = -61 +M = 42 + +ModInv = 19 +A = -5f +M = 42 + +ModInv = 1d +A = -5b +M = 42 + +ModInv = 2b +A = -59 +M = 42 + +ModInv = 3b +A = -55 +M = 42 + +ModInv = 1f +A = -53 +M = 42 + +ModInv = 5 +A = -4f +M = 42 + +ModInv = 2f +A = -49 +M = 42 + +ModInv = d +A = -47 +M = 42 + +ModInv = 41 +A = -43 +M = 42 + +ModInv = 1 +A = -41 +M = 42 + +ModInv = 35 +A = -3d +M = 42 + +ModInv = 13 +A = -3b +M = 42 + +ModInv = 3d +A = -35 +M = 42 + +ModInv = 23 +A = -31 +M = 42 + +ModInv = 7 +A = -2f +M = 42 + +ModInv = 17 +A = -2b +M = 42 + +ModInv = 25 +A = -29 +M = 42 + +ModInv = 29 +A = -25 +M = 42 + +ModInv = 31 +A = -23 +M = 42 + +ModInv = 11 +A = -1f +M = 42 + +ModInv = 19 +A = -1d +M = 42 + +ModInv = 1d +A = -19 +M = 42 + +ModInv = 2b +A = -17 +M = 42 + +ModInv = 3b +A = -13 +M = 42 + +ModInv = 1f +A = -11 +M = 42 + +ModInv = 5 +A = -d +M = 42 + +ModInv = 2f +A = -7 +M = 42 + +ModInv = d +A = -5 +M = 42 + +ModInv = 41 +A = -1 +M = 42 + +ModInv = 1 +A = 1 +M = 42 + +ModInv = 35 +A = 5 +M = 42 + +ModInv = 13 +A = 7 +M = 42 + +ModInv = 3d +A = d +M = 42 + +ModInv = 23 +A = 11 +M = 42 + +ModInv = 7 +A = 13 +M = 42 + +ModInv = 17 +A = 17 +M = 42 + +ModInv = 25 +A = 19 +M = 42 + +ModInv = 29 +A = 1d +M = 42 + +ModInv = 31 +A = 1f +M = 42 + +ModInv = 11 +A = 23 +M = 42 + +ModInv = 19 +A = 25 +M = 42 + +ModInv = 1d +A = 29 +M = 42 + +ModInv = 2b +A = 2b +M = 42 + +ModInv = 3b +A = 2f +M = 42 + +ModInv = 1f +A = 31 +M = 42 + +ModInv = 5 +A = 35 +M = 42 + +ModInv = 2f +A = 3b +M = 42 + +ModInv = d +A = 3d +M = 42 + +ModInv = 41 +A = 41 +M = 42 + +ModInv = 1 +A = 43 +M = 42 + +ModInv = 35 +A = 47 +M = 42 + +ModInv = 13 +A = 49 +M = 42 + +ModInv = 3d +A = 4f +M = 42 + +ModInv = 23 +A = 53 +M = 42 + +ModInv = 7 +A = 55 +M = 42 + +ModInv = 17 +A = 59 +M = 42 + +ModInv = 25 +A = 5b +M = 42 + +ModInv = 29 +A = 5f +M = 42 + +ModInv = 31 +A = 61 +M = 42 + +ModInv = 2 +A = -64 +M = 43 + +ModInv = 17 +A = -63 +M = 43 + +ModInv = 36 +A = -62 +M = 43 + +ModInv = 1d +A = -61 +M = 43 + +ModInv = 1e +A = -60 +M = 43 + +ModInv = 37 +A = -5f +M = 43 + +ModInv = 3e +A = -5e +M = 43 + +ModInv = 12 +A = -5d +M = 43 + +ModInv = 8 +A = -5c +M = 43 + +ModInv = 35 +A = -5b +M = 43 + +ModInv = 20 +A = -5a +M = 43 + +ModInv = 3 +A = -59 +M = 43 + +ModInv = 33 +A = -58 +M = 43 + +ModInv = a +A = -57 +M = 43 + +ModInv = 7 +A = -56 +M = 43 + +ModInv = 1a +A = -55 +M = 43 + +ModInv = 3f +A = -54 +M = 43 + +ModInv = 2e +A = -53 +M = 43 + +ModInv = 3a +A = -52 +M = 43 + +ModInv = 2b +A = -51 +M = 43 + +ModInv = 24 +A = -50 +M = 43 + +ModInv = 27 +A = -4f +M = 43 + +ModInv = 6 +A = -4e +M = 43 + +ModInv = 14 +A = -4d +M = 43 + +ModInv = 34 +A = -4c +M = 43 + +ModInv = 19 +A = -4b +M = 43 + +ModInv = 13 +A = -4a +M = 43 + +ModInv = b +A = -49 +M = 43 + +ModInv = 28 +A = -48 +M = 43 + +ModInv = 32 +A = -47 +M = 43 + +ModInv = 16 +A = -46 +M = 43 + +ModInv = 21 +A = -45 +M = 43 + +ModInv = 42 +A = -44 +M = 43 + +ModInv = 1 +A = -42 +M = 43 + +ModInv = 22 +A = -41 +M = 43 + +ModInv = 2d +A = -40 +M = 43 + +ModInv = 11 +A = -3f +M = 43 + +ModInv = 1b +A = -3e +M = 43 + +ModInv = 38 +A = -3d +M = 43 + +ModInv = 30 +A = -3c +M = 43 + +ModInv = 2a +A = -3b +M = 43 + +ModInv = f +A = -3a +M = 43 + +ModInv = 2f +A = -39 +M = 43 + +ModInv = 3d +A = -38 +M = 43 + +ModInv = 1c +A = -37 +M = 43 + +ModInv = 1f +A = -36 +M = 43 + +ModInv = 18 +A = -35 +M = 43 + +ModInv = 9 +A = -34 +M = 43 + +ModInv = 15 +A = -33 +M = 43 + +ModInv = 4 +A = -32 +M = 43 + +ModInv = 29 +A = -31 +M = 43 + +ModInv = 3c +A = -30 +M = 43 + +ModInv = 39 +A = -2f +M = 43 + +ModInv = 10 +A = -2e +M = 43 + +ModInv = 40 +A = -2d +M = 43 + +ModInv = 23 +A = -2c +M = 43 + +ModInv = e +A = -2b +M = 43 + +ModInv = 3b +A = -2a +M = 43 + +ModInv = 31 +A = -29 +M = 43 + +ModInv = 5 +A = -28 +M = 43 + +ModInv = c +A = -27 +M = 43 + +ModInv = 25 +A = -26 +M = 43 + +ModInv = 26 +A = -25 +M = 43 + +ModInv = d +A = -24 +M = 43 + +ModInv = 2c +A = -23 +M = 43 + +ModInv = 41 +A = -22 +M = 43 + +ModInv = 2 +A = -21 +M = 43 + +ModInv = 17 +A = -20 +M = 43 + +ModInv = 36 +A = -1f +M = 43 + +ModInv = 1d +A = -1e +M = 43 + +ModInv = 1e +A = -1d +M = 43 + +ModInv = 37 +A = -1c +M = 43 + +ModInv = 3e +A = -1b +M = 43 + +ModInv = 12 +A = -1a +M = 43 + +ModInv = 8 +A = -19 +M = 43 + +ModInv = 35 +A = -18 +M = 43 + +ModInv = 20 +A = -17 +M = 43 + +ModInv = 3 +A = -16 +M = 43 + +ModInv = 33 +A = -15 +M = 43 + +ModInv = a +A = -14 +M = 43 + +ModInv = 7 +A = -13 +M = 43 + +ModInv = 1a +A = -12 +M = 43 + +ModInv = 3f +A = -11 +M = 43 + +ModInv = 2e +A = -10 +M = 43 + +ModInv = 3a +A = -f +M = 43 + +ModInv = 2b +A = -e +M = 43 + +ModInv = 24 +A = -d +M = 43 + +ModInv = 27 +A = -c +M = 43 + +ModInv = 6 +A = -b +M = 43 + +ModInv = 14 +A = -a +M = 43 + +ModInv = 34 +A = -9 +M = 43 + +ModInv = 19 +A = -8 +M = 43 + +ModInv = 13 +A = -7 +M = 43 + +ModInv = b +A = -6 +M = 43 + +ModInv = 28 +A = -5 +M = 43 + +ModInv = 32 +A = -4 +M = 43 + +ModInv = 16 +A = -3 +M = 43 + +ModInv = 21 +A = -2 +M = 43 + +ModInv = 42 +A = -1 +M = 43 + +ModInv = 1 +A = 1 +M = 43 + +ModInv = 22 +A = 2 +M = 43 + +ModInv = 2d +A = 3 +M = 43 + +ModInv = 11 +A = 4 +M = 43 + +ModInv = 1b +A = 5 +M = 43 + +ModInv = 38 +A = 6 +M = 43 + +ModInv = 30 +A = 7 +M = 43 + +ModInv = 2a +A = 8 +M = 43 + +ModInv = f +A = 9 +M = 43 + +ModInv = 2f +A = a +M = 43 + +ModInv = 3d +A = b +M = 43 + +ModInv = 1c +A = c +M = 43 + +ModInv = 1f +A = d +M = 43 + +ModInv = 18 +A = e +M = 43 + +ModInv = 9 +A = f +M = 43 + +ModInv = 15 +A = 10 +M = 43 + +ModInv = 4 +A = 11 +M = 43 + +ModInv = 29 +A = 12 +M = 43 + +ModInv = 3c +A = 13 +M = 43 + +ModInv = 39 +A = 14 +M = 43 + +ModInv = 10 +A = 15 +M = 43 + +ModInv = 40 +A = 16 +M = 43 + +ModInv = 23 +A = 17 +M = 43 + +ModInv = e +A = 18 +M = 43 + +ModInv = 3b +A = 19 +M = 43 + +ModInv = 31 +A = 1a +M = 43 + +ModInv = 5 +A = 1b +M = 43 + +ModInv = c +A = 1c +M = 43 + +ModInv = 25 +A = 1d +M = 43 + +ModInv = 26 +A = 1e +M = 43 + +ModInv = d +A = 1f +M = 43 + +ModInv = 2c +A = 20 +M = 43 + +ModInv = 41 +A = 21 +M = 43 + +ModInv = 2 +A = 22 +M = 43 + +ModInv = 17 +A = 23 +M = 43 + +ModInv = 36 +A = 24 +M = 43 + +ModInv = 1d +A = 25 +M = 43 + +ModInv = 1e +A = 26 +M = 43 + +ModInv = 37 +A = 27 +M = 43 + +ModInv = 3e +A = 28 +M = 43 + +ModInv = 12 +A = 29 +M = 43 + +ModInv = 8 +A = 2a +M = 43 + +ModInv = 35 +A = 2b +M = 43 + +ModInv = 20 +A = 2c +M = 43 + +ModInv = 3 +A = 2d +M = 43 + +ModInv = 33 +A = 2e +M = 43 + +ModInv = a +A = 2f +M = 43 + +ModInv = 7 +A = 30 +M = 43 + +ModInv = 1a +A = 31 +M = 43 + +ModInv = 3f +A = 32 +M = 43 + +ModInv = 2e +A = 33 +M = 43 + +ModInv = 3a +A = 34 +M = 43 + +ModInv = 2b +A = 35 +M = 43 + +ModInv = 24 +A = 36 +M = 43 + +ModInv = 27 +A = 37 +M = 43 + +ModInv = 6 +A = 38 +M = 43 + +ModInv = 14 +A = 39 +M = 43 + +ModInv = 34 +A = 3a +M = 43 + +ModInv = 19 +A = 3b +M = 43 + +ModInv = 13 +A = 3c +M = 43 + +ModInv = b +A = 3d +M = 43 + +ModInv = 28 +A = 3e +M = 43 + +ModInv = 32 +A = 3f +M = 43 + +ModInv = 16 +A = 40 +M = 43 + +ModInv = 21 +A = 41 +M = 43 + +ModInv = 42 +A = 42 +M = 43 + +ModInv = 1 +A = 44 +M = 43 + +ModInv = 22 +A = 45 +M = 43 + +ModInv = 2d +A = 46 +M = 43 + +ModInv = 11 +A = 47 +M = 43 + +ModInv = 1b +A = 48 +M = 43 + +ModInv = 38 +A = 49 +M = 43 + +ModInv = 30 +A = 4a +M = 43 + +ModInv = 2a +A = 4b +M = 43 + +ModInv = f +A = 4c +M = 43 + +ModInv = 2f +A = 4d +M = 43 + +ModInv = 3d +A = 4e +M = 43 + +ModInv = 1c +A = 4f +M = 43 + +ModInv = 1f +A = 50 +M = 43 + +ModInv = 18 +A = 51 +M = 43 + +ModInv = 9 +A = 52 +M = 43 + +ModInv = 15 +A = 53 +M = 43 + +ModInv = 4 +A = 54 +M = 43 + +ModInv = 29 +A = 55 +M = 43 + +ModInv = 3c +A = 56 +M = 43 + +ModInv = 39 +A = 57 +M = 43 + +ModInv = 10 +A = 58 +M = 43 + +ModInv = 40 +A = 59 +M = 43 + +ModInv = 23 +A = 5a +M = 43 + +ModInv = e +A = 5b +M = 43 + +ModInv = 3b +A = 5c +M = 43 + +ModInv = 31 +A = 5d +M = 43 + +ModInv = 5 +A = 5e +M = 43 + +ModInv = c +A = 5f +M = 43 + +ModInv = 25 +A = 60 +M = 43 + +ModInv = 26 +A = 61 +M = 43 + +ModInv = d +A = 62 +M = 43 + +ModInv = 2c +A = 63 +M = 43 + +ModInv = 39 +A = -63 +M = 44 + +ModInv = 7 +A = -61 +M = 44 + +ModInv = 5 +A = -5f +M = 44 + +ModInv = 13 +A = -5d +M = 44 + +ModInv = 41 +A = -5b +M = 44 + +ModInv = 37 +A = -59 +M = 44 + +ModInv = 19 +A = -57 +M = 44 + +ModInv = 9 +A = -53 +M = 44 + +ModInv = 2f +A = -51 +M = 44 + +ModInv = 25 +A = -4f +M = 44 + +ModInv = f +A = -4d +M = 44 + +ModInv = 1d +A = -4b +M = 44 + +ModInv = 1b +A = -49 +M = 44 + +ModInv = 2d +A = -47 +M = 44 + +ModInv = 43 +A = -45 +M = 44 + +ModInv = 1 +A = -43 +M = 44 + +ModInv = 17 +A = -41 +M = 44 + +ModInv = 29 +A = -3f +M = 44 + +ModInv = 27 +A = -3d +M = 44 + +ModInv = 35 +A = -3b +M = 44 + +ModInv = 1f +A = -39 +M = 44 + +ModInv = 15 +A = -37 +M = 44 + +ModInv = 3b +A = -35 +M = 44 + +ModInv = 2b +A = -31 +M = 44 + +ModInv = d +A = -2f +M = 44 + +ModInv = 3 +A = -2d +M = 44 + +ModInv = 31 +A = -2b +M = 44 + +ModInv = 3f +A = -29 +M = 44 + +ModInv = 3d +A = -27 +M = 44 + +ModInv = b +A = -25 +M = 44 + +ModInv = 21 +A = -23 +M = 44 + +ModInv = 23 +A = -21 +M = 44 + +ModInv = 39 +A = -1f +M = 44 + +ModInv = 7 +A = -1d +M = 44 + +ModInv = 5 +A = -1b +M = 44 + +ModInv = 13 +A = -19 +M = 44 + +ModInv = 41 +A = -17 +M = 44 + +ModInv = 37 +A = -15 +M = 44 + +ModInv = 19 +A = -13 +M = 44 + +ModInv = 9 +A = -f +M = 44 + +ModInv = 2f +A = -d +M = 44 + +ModInv = 25 +A = -b +M = 44 + +ModInv = f +A = -9 +M = 44 + +ModInv = 1d +A = -7 +M = 44 + +ModInv = 1b +A = -5 +M = 44 + +ModInv = 2d +A = -3 +M = 44 + +ModInv = 43 +A = -1 +M = 44 + +ModInv = 1 +A = 1 +M = 44 + +ModInv = 17 +A = 3 +M = 44 + +ModInv = 29 +A = 5 +M = 44 + +ModInv = 27 +A = 7 +M = 44 + +ModInv = 35 +A = 9 +M = 44 + +ModInv = 1f +A = b +M = 44 + +ModInv = 15 +A = d +M = 44 + +ModInv = 3b +A = f +M = 44 + +ModInv = 2b +A = 13 +M = 44 + +ModInv = d +A = 15 +M = 44 + +ModInv = 3 +A = 17 +M = 44 + +ModInv = 31 +A = 19 +M = 44 + +ModInv = 3f +A = 1b +M = 44 + +ModInv = 3d +A = 1d +M = 44 + +ModInv = b +A = 1f +M = 44 + +ModInv = 21 +A = 21 +M = 44 + +ModInv = 23 +A = 23 +M = 44 + +ModInv = 39 +A = 25 +M = 44 + +ModInv = 7 +A = 27 +M = 44 + +ModInv = 5 +A = 29 +M = 44 + +ModInv = 13 +A = 2b +M = 44 + +ModInv = 41 +A = 2d +M = 44 + +ModInv = 37 +A = 2f +M = 44 + +ModInv = 19 +A = 31 +M = 44 + +ModInv = 9 +A = 35 +M = 44 + +ModInv = 2f +A = 37 +M = 44 + +ModInv = 25 +A = 39 +M = 44 + +ModInv = f +A = 3b +M = 44 + +ModInv = 1d +A = 3d +M = 44 + +ModInv = 1b +A = 3f +M = 44 + +ModInv = 2d +A = 41 +M = 44 + +ModInv = 43 +A = 43 +M = 44 + +ModInv = 1 +A = 45 +M = 44 + +ModInv = 17 +A = 47 +M = 44 + +ModInv = 29 +A = 49 +M = 44 + +ModInv = 27 +A = 4b +M = 44 + +ModInv = 35 +A = 4d +M = 44 + +ModInv = 1f +A = 4f +M = 44 + +ModInv = 15 +A = 51 +M = 44 + +ModInv = 3b +A = 53 +M = 44 + +ModInv = 2b +A = 57 +M = 44 + +ModInv = d +A = 59 +M = 44 + +ModInv = 3 +A = 5b +M = 44 + +ModInv = 31 +A = 5d +M = 44 + +ModInv = 3f +A = 5f +M = 44 + +ModInv = 3d +A = 61 +M = 44 + +ModInv = b +A = 63 +M = 44 + +ModInv = 14 +A = -64 +M = 45 + +ModInv = 13 +A = -62 +M = 45 + +ModInv = 20 +A = -61 +M = 45 + +ModInv = 3d +A = -5f +M = 45 + +ModInv = b +A = -5e +M = 45 + +ModInv = 2f +A = -5b +M = 45 + +ModInv = 1f +A = -59 +M = 45 + +ModInv = 1d +A = -58 +M = 45 + +ModInv = 4 +A = -56 +M = 45 + +ModInv = 38 +A = -55 +M = 45 + +ModInv = 40 +A = -53 +M = 45 + +ModInv = 35 +A = -52 +M = 45 + +ModInv = 19 +A = -50 +M = 45 + +ModInv = 3e +A = -4f +M = 45 + +ModInv = 2b +A = -4d +M = 45 + +ModInv = 3b +A = -4c +M = 45 + +ModInv = 37 +A = -4a +M = 45 + +ModInv = 11 +A = -49 +M = 45 + +ModInv = 22 +A = -47 +M = 45 + +ModInv = 44 +A = -46 +M = 45 + +ModInv = 1 +A = -44 +M = 45 + +ModInv = 23 +A = -43 +M = 45 + +ModInv = 34 +A = -41 +M = 45 + +ModInv = e +A = -40 +M = 45 + +ModInv = a +A = -3e +M = 45 + +ModInv = 1a +A = -3d +M = 45 + +ModInv = 7 +A = -3b +M = 45 + +ModInv = 2c +A = -3a +M = 45 + +ModInv = 10 +A = -38 +M = 45 + +ModInv = 5 +A = -37 +M = 45 + +ModInv = d +A = -35 +M = 45 + +ModInv = 41 +A = -34 +M = 45 + +ModInv = 28 +A = -32 +M = 45 + +ModInv = 26 +A = -31 +M = 45 + +ModInv = 16 +A = -2f +M = 45 + +ModInv = 3a +A = -2c +M = 45 + +ModInv = 8 +A = -2b +M = 45 + +ModInv = 25 +A = -29 +M = 45 + +ModInv = 32 +A = -28 +M = 45 + +ModInv = 31 +A = -26 +M = 45 + +ModInv = 29 +A = -25 +M = 45 + +ModInv = 43 +A = -23 +M = 45 + +ModInv = 2 +A = -22 +M = 45 + +ModInv = 1c +A = -20 +M = 45 + +ModInv = 14 +A = -1f +M = 45 + +ModInv = 13 +A = -1d +M = 45 + +ModInv = 20 +A = -1c +M = 45 + +ModInv = 3d +A = -1a +M = 45 + +ModInv = b +A = -19 +M = 45 + +ModInv = 2f +A = -16 +M = 45 + +ModInv = 1f +A = -14 +M = 45 + +ModInv = 1d +A = -13 +M = 45 + +ModInv = 4 +A = -11 +M = 45 + +ModInv = 38 +A = -10 +M = 45 + +ModInv = 40 +A = -e +M = 45 + +ModInv = 35 +A = -d +M = 45 + +ModInv = 19 +A = -b +M = 45 + +ModInv = 3e +A = -a +M = 45 + +ModInv = 2b +A = -8 +M = 45 + +ModInv = 3b +A = -7 +M = 45 + +ModInv = 37 +A = -5 +M = 45 + +ModInv = 11 +A = -4 +M = 45 + +ModInv = 22 +A = -2 +M = 45 + +ModInv = 44 +A = -1 +M = 45 + +ModInv = 1 +A = 1 +M = 45 + +ModInv = 23 +A = 2 +M = 45 + +ModInv = 34 +A = 4 +M = 45 + +ModInv = e +A = 5 +M = 45 + +ModInv = a +A = 7 +M = 45 + +ModInv = 1a +A = 8 +M = 45 + +ModInv = 7 +A = a +M = 45 + +ModInv = 2c +A = b +M = 45 + +ModInv = 10 +A = d +M = 45 + +ModInv = 5 +A = e +M = 45 + +ModInv = d +A = 10 +M = 45 + +ModInv = 41 +A = 11 +M = 45 + +ModInv = 28 +A = 13 +M = 45 + +ModInv = 26 +A = 14 +M = 45 + +ModInv = 16 +A = 16 +M = 45 + +ModInv = 3a +A = 19 +M = 45 + +ModInv = 8 +A = 1a +M = 45 + +ModInv = 25 +A = 1c +M = 45 + +ModInv = 32 +A = 1d +M = 45 + +ModInv = 31 +A = 1f +M = 45 + +ModInv = 29 +A = 20 +M = 45 + +ModInv = 43 +A = 22 +M = 45 + +ModInv = 2 +A = 23 +M = 45 + +ModInv = 1c +A = 25 +M = 45 + +ModInv = 14 +A = 26 +M = 45 + +ModInv = 13 +A = 28 +M = 45 + +ModInv = 20 +A = 29 +M = 45 + +ModInv = 3d +A = 2b +M = 45 + +ModInv = b +A = 2c +M = 45 + +ModInv = 2f +A = 2f +M = 45 + +ModInv = 1f +A = 31 +M = 45 + +ModInv = 1d +A = 32 +M = 45 + +ModInv = 4 +A = 34 +M = 45 + +ModInv = 38 +A = 35 +M = 45 + +ModInv = 40 +A = 37 +M = 45 + +ModInv = 35 +A = 38 +M = 45 + +ModInv = 19 +A = 3a +M = 45 + +ModInv = 3e +A = 3b +M = 45 + +ModInv = 2b +A = 3d +M = 45 + +ModInv = 3b +A = 3e +M = 45 + +ModInv = 37 +A = 40 +M = 45 + +ModInv = 11 +A = 41 +M = 45 + +ModInv = 22 +A = 43 +M = 45 + +ModInv = 44 +A = 44 +M = 45 + +ModInv = 1 +A = 46 +M = 45 + +ModInv = 23 +A = 47 +M = 45 + +ModInv = 34 +A = 49 +M = 45 + +ModInv = e +A = 4a +M = 45 + +ModInv = a +A = 4c +M = 45 + +ModInv = 1a +A = 4d +M = 45 + +ModInv = 7 +A = 4f +M = 45 + +ModInv = 2c +A = 50 +M = 45 + +ModInv = 10 +A = 52 +M = 45 + +ModInv = 5 +A = 53 +M = 45 + +ModInv = d +A = 55 +M = 45 + +ModInv = 41 +A = 56 +M = 45 + +ModInv = 28 +A = 58 +M = 45 + +ModInv = 26 +A = 59 +M = 45 + +ModInv = 16 +A = 5b +M = 45 + +ModInv = 3a +A = 5e +M = 45 + +ModInv = 8 +A = 5f +M = 45 + +ModInv = 25 +A = 61 +M = 45 + +ModInv = 32 +A = 62 +M = 45 + +ModInv = 29 +A = -63 +M = 46 + +ModInv = 39 +A = -61 +M = 46 + +ModInv = 3 +A = -5d +M = 46 + +ModInv = b +A = -59 +M = 46 + +ModInv = 25 +A = -57 +M = 46 + +ModInv = 2b +A = -53 +M = 46 + +ModInv = 13 +A = -51 +M = 46 + +ModInv = 1f +A = -4f +M = 46 + +ModInv = 17 +A = -49 +M = 46 + +ModInv = 45 +A = -47 +M = 46 + +ModInv = 1 +A = -45 +M = 46 + +ModInv = 2f +A = -43 +M = 46 + +ModInv = 27 +A = -3d +M = 46 + +ModInv = 33 +A = -3b +M = 46 + +ModInv = 1b +A = -39 +M = 46 + +ModInv = 21 +A = -35 +M = 46 + +ModInv = 3b +A = -33 +M = 46 + +ModInv = 43 +A = -2f +M = 46 + +ModInv = d +A = -2b +M = 46 + +ModInv = 1d +A = -29 +M = 46 + +ModInv = 3d +A = -27 +M = 46 + +ModInv = 11 +A = -25 +M = 46 + +ModInv = 35 +A = -21 +M = 46 + +ModInv = 9 +A = -1f +M = 46 + +ModInv = 29 +A = -1d +M = 46 + +ModInv = 39 +A = -1b +M = 46 + +ModInv = 3 +A = -17 +M = 46 + +ModInv = b +A = -13 +M = 46 + +ModInv = 25 +A = -11 +M = 46 + +ModInv = 2b +A = -d +M = 46 + +ModInv = 13 +A = -b +M = 46 + +ModInv = 1f +A = -9 +M = 46 + +ModInv = 17 +A = -3 +M = 46 + +ModInv = 45 +A = -1 +M = 46 + +ModInv = 1 +A = 1 +M = 46 + +ModInv = 2f +A = 3 +M = 46 + +ModInv = 27 +A = 9 +M = 46 + +ModInv = 33 +A = b +M = 46 + +ModInv = 1b +A = d +M = 46 + +ModInv = 21 +A = 11 +M = 46 + +ModInv = 3b +A = 13 +M = 46 + +ModInv = 43 +A = 17 +M = 46 + +ModInv = d +A = 1b +M = 46 + +ModInv = 1d +A = 1d +M = 46 + +ModInv = 3d +A = 1f +M = 46 + +ModInv = 11 +A = 21 +M = 46 + +ModInv = 35 +A = 25 +M = 46 + +ModInv = 9 +A = 27 +M = 46 + +ModInv = 29 +A = 29 +M = 46 + +ModInv = 39 +A = 2b +M = 46 + +ModInv = 3 +A = 2f +M = 46 + +ModInv = b +A = 33 +M = 46 + +ModInv = 25 +A = 35 +M = 46 + +ModInv = 2b +A = 39 +M = 46 + +ModInv = 13 +A = 3b +M = 46 + +ModInv = 1f +A = 3d +M = 46 + +ModInv = 17 +A = 43 +M = 46 + +ModInv = 45 +A = 45 +M = 46 + +ModInv = 1 +A = 47 +M = 46 + +ModInv = 2f +A = 49 +M = 46 + +ModInv = 27 +A = 4f +M = 46 + +ModInv = 33 +A = 51 +M = 46 + +ModInv = 1b +A = 53 +M = 46 + +ModInv = 21 +A = 57 +M = 46 + +ModInv = 3b +A = 59 +M = 46 + +ModInv = 43 +A = 5d +M = 46 + +ModInv = d +A = 61 +M = 46 + +ModInv = 1d +A = 63 +M = 46 + +ModInv = 16 +A = -64 +M = 47 + +ModInv = 26 +A = -63 +M = 47 + +ModInv = 15 +A = -62 +M = 47 + +ModInv = 1e +A = -61 +M = 47 + +ModInv = 11 +A = -60 +M = 47 + +ModInv = 44 +A = -5f +M = 47 + +ModInv = 25 +A = -5e +M = 47 + +ModInv = 1d +A = -5d +M = 47 + +ModInv = 1b +A = -5c +M = 47 + +ModInv = 27 +A = -5b +M = 47 + +ModInv = 38 +A = -5a +M = 47 + +ModInv = 43 +A = -59 +M = 47 + +ModInv = 19 +A = -58 +M = 47 + +ModInv = 1f +A = -57 +M = 47 + +ModInv = 34 +A = -56 +M = 47 + +ModInv = 5 +A = -55 +M = 47 + +ModInv = 3c +A = -54 +M = 47 + +ModInv = 41 +A = -53 +M = 47 + +ModInv = 3a +A = -52 +M = 47 + +ModInv = 7 +A = -51 +M = 47 + +ModInv = 3f +A = -50 +M = 47 + +ModInv = 3e +A = -4f +M = 47 + +ModInv = a +A = -4e +M = 47 + +ModInv = 3b +A = -4d +M = 47 + +ModInv = e +A = -4c +M = 47 + +ModInv = 35 +A = -4b +M = 47 + +ModInv = 2f +A = -4a +M = 47 + +ModInv = 23 +A = -49 +M = 47 + +ModInv = 46 +A = -48 +M = 47 + +ModInv = 1 +A = -46 +M = 47 + +ModInv = 24 +A = -45 +M = 47 + +ModInv = 18 +A = -44 +M = 47 + +ModInv = 12 +A = -43 +M = 47 + +ModInv = 39 +A = -42 +M = 47 + +ModInv = c +A = -41 +M = 47 + +ModInv = 3d +A = -40 +M = 47 + +ModInv = 9 +A = -3f +M = 47 + +ModInv = 8 +A = -3e +M = 47 + +ModInv = 40 +A = -3d +M = 47 + +ModInv = d +A = -3c +M = 47 + +ModInv = 6 +A = -3b +M = 47 + +ModInv = b +A = -3a +M = 47 + +ModInv = 42 +A = -39 +M = 47 + +ModInv = 13 +A = -38 +M = 47 + +ModInv = 28 +A = -37 +M = 47 + +ModInv = 2e +A = -36 +M = 47 + +ModInv = 4 +A = -35 +M = 47 + +ModInv = f +A = -34 +M = 47 + +ModInv = 20 +A = -33 +M = 47 + +ModInv = 2c +A = -32 +M = 47 + +ModInv = 2a +A = -31 +M = 47 + +ModInv = 22 +A = -30 +M = 47 + +ModInv = 3 +A = -2f +M = 47 + +ModInv = 36 +A = -2e +M = 47 + +ModInv = 29 +A = -2d +M = 47 + +ModInv = 32 +A = -2c +M = 47 + +ModInv = 21 +A = -2b +M = 47 + +ModInv = 31 +A = -2a +M = 47 + +ModInv = 2d +A = -29 +M = 47 + +ModInv = 37 +A = -28 +M = 47 + +ModInv = 14 +A = -27 +M = 47 + +ModInv = 1c +A = -26 +M = 47 + +ModInv = 17 +A = -25 +M = 47 + +ModInv = 45 +A = -24 +M = 47 + +ModInv = 2 +A = -23 +M = 47 + +ModInv = 30 +A = -22 +M = 47 + +ModInv = 2b +A = -21 +M = 47 + +ModInv = 33 +A = -20 +M = 47 + +ModInv = 10 +A = -1f +M = 47 + +ModInv = 1a +A = -1e +M = 47 + +ModInv = 16 +A = -1d +M = 47 + +ModInv = 26 +A = -1c +M = 47 + +ModInv = 15 +A = -1b +M = 47 + +ModInv = 1e +A = -1a +M = 47 + +ModInv = 11 +A = -19 +M = 47 + +ModInv = 44 +A = -18 +M = 47 + +ModInv = 25 +A = -17 +M = 47 + +ModInv = 1d +A = -16 +M = 47 + +ModInv = 1b +A = -15 +M = 47 + +ModInv = 27 +A = -14 +M = 47 + +ModInv = 38 +A = -13 +M = 47 + +ModInv = 43 +A = -12 +M = 47 + +ModInv = 19 +A = -11 +M = 47 + +ModInv = 1f +A = -10 +M = 47 + +ModInv = 34 +A = -f +M = 47 + +ModInv = 5 +A = -e +M = 47 + +ModInv = 3c +A = -d +M = 47 + +ModInv = 41 +A = -c +M = 47 + +ModInv = 3a +A = -b +M = 47 + +ModInv = 7 +A = -a +M = 47 + +ModInv = 3f +A = -9 +M = 47 + +ModInv = 3e +A = -8 +M = 47 + +ModInv = a +A = -7 +M = 47 + +ModInv = 3b +A = -6 +M = 47 + +ModInv = e +A = -5 +M = 47 + +ModInv = 35 +A = -4 +M = 47 + +ModInv = 2f +A = -3 +M = 47 + +ModInv = 23 +A = -2 +M = 47 + +ModInv = 46 +A = -1 +M = 47 + +ModInv = 1 +A = 1 +M = 47 + +ModInv = 24 +A = 2 +M = 47 + +ModInv = 18 +A = 3 +M = 47 + +ModInv = 12 +A = 4 +M = 47 + +ModInv = 39 +A = 5 +M = 47 + +ModInv = c +A = 6 +M = 47 + +ModInv = 3d +A = 7 +M = 47 + +ModInv = 9 +A = 8 +M = 47 + +ModInv = 8 +A = 9 +M = 47 + +ModInv = 40 +A = a +M = 47 + +ModInv = d +A = b +M = 47 + +ModInv = 6 +A = c +M = 47 + +ModInv = b +A = d +M = 47 + +ModInv = 42 +A = e +M = 47 + +ModInv = 13 +A = f +M = 47 + +ModInv = 28 +A = 10 +M = 47 + +ModInv = 2e +A = 11 +M = 47 + +ModInv = 4 +A = 12 +M = 47 + +ModInv = f +A = 13 +M = 47 + +ModInv = 20 +A = 14 +M = 47 + +ModInv = 2c +A = 15 +M = 47 + +ModInv = 2a +A = 16 +M = 47 + +ModInv = 22 +A = 17 +M = 47 + +ModInv = 3 +A = 18 +M = 47 + +ModInv = 36 +A = 19 +M = 47 + +ModInv = 29 +A = 1a +M = 47 + +ModInv = 32 +A = 1b +M = 47 + +ModInv = 21 +A = 1c +M = 47 + +ModInv = 31 +A = 1d +M = 47 + +ModInv = 2d +A = 1e +M = 47 + +ModInv = 37 +A = 1f +M = 47 + +ModInv = 14 +A = 20 +M = 47 + +ModInv = 1c +A = 21 +M = 47 + +ModInv = 17 +A = 22 +M = 47 + +ModInv = 45 +A = 23 +M = 47 + +ModInv = 2 +A = 24 +M = 47 + +ModInv = 30 +A = 25 +M = 47 + +ModInv = 2b +A = 26 +M = 47 + +ModInv = 33 +A = 27 +M = 47 + +ModInv = 10 +A = 28 +M = 47 + +ModInv = 1a +A = 29 +M = 47 + +ModInv = 16 +A = 2a +M = 47 + +ModInv = 26 +A = 2b +M = 47 + +ModInv = 15 +A = 2c +M = 47 + +ModInv = 1e +A = 2d +M = 47 + +ModInv = 11 +A = 2e +M = 47 + +ModInv = 44 +A = 2f +M = 47 + +ModInv = 25 +A = 30 +M = 47 + +ModInv = 1d +A = 31 +M = 47 + +ModInv = 1b +A = 32 +M = 47 + +ModInv = 27 +A = 33 +M = 47 + +ModInv = 38 +A = 34 +M = 47 + +ModInv = 43 +A = 35 +M = 47 + +ModInv = 19 +A = 36 +M = 47 + +ModInv = 1f +A = 37 +M = 47 + +ModInv = 34 +A = 38 +M = 47 + +ModInv = 5 +A = 39 +M = 47 + +ModInv = 3c +A = 3a +M = 47 + +ModInv = 41 +A = 3b +M = 47 + +ModInv = 3a +A = 3c +M = 47 + +ModInv = 7 +A = 3d +M = 47 + +ModInv = 3f +A = 3e +M = 47 + +ModInv = 3e +A = 3f +M = 47 + +ModInv = a +A = 40 +M = 47 + +ModInv = 3b +A = 41 +M = 47 + +ModInv = e +A = 42 +M = 47 + +ModInv = 35 +A = 43 +M = 47 + +ModInv = 2f +A = 44 +M = 47 + +ModInv = 23 +A = 45 +M = 47 + +ModInv = 46 +A = 46 +M = 47 + +ModInv = 1 +A = 48 +M = 47 + +ModInv = 24 +A = 49 +M = 47 + +ModInv = 18 +A = 4a +M = 47 + +ModInv = 12 +A = 4b +M = 47 + +ModInv = 39 +A = 4c +M = 47 + +ModInv = c +A = 4d +M = 47 + +ModInv = 3d +A = 4e +M = 47 + +ModInv = 9 +A = 4f +M = 47 + +ModInv = 8 +A = 50 +M = 47 + +ModInv = 40 +A = 51 +M = 47 + +ModInv = d +A = 52 +M = 47 + +ModInv = 6 +A = 53 +M = 47 + +ModInv = b +A = 54 +M = 47 + +ModInv = 42 +A = 55 +M = 47 + +ModInv = 13 +A = 56 +M = 47 + +ModInv = 28 +A = 57 +M = 47 + +ModInv = 2e +A = 58 +M = 47 + +ModInv = 4 +A = 59 +M = 47 + +ModInv = f +A = 5a +M = 47 + +ModInv = 20 +A = 5b +M = 47 + +ModInv = 2c +A = 5c +M = 47 + +ModInv = 2a +A = 5d +M = 47 + +ModInv = 22 +A = 5e +M = 47 + +ModInv = 3 +A = 5f +M = 47 + +ModInv = 36 +A = 60 +M = 47 + +ModInv = 29 +A = 61 +M = 47 + +ModInv = 32 +A = 62 +M = 47 + +ModInv = 21 +A = 63 +M = 47 + +ModInv = 17 +A = -61 +M = 48 + +ModInv = 19 +A = -5f +M = 48 + +ModInv = 35 +A = -5b +M = 48 + +ModInv = 37 +A = -59 +M = 48 + +ModInv = b +A = -55 +M = 48 + +ModInv = d +A = -53 +M = 48 + +ModInv = 29 +A = -4f +M = 48 + +ModInv = 2b +A = -4d +M = 48 + +ModInv = 47 +A = -49 +M = 48 + +ModInv = 1 +A = -47 +M = 48 + +ModInv = 1d +A = -43 +M = 48 + +ModInv = 1f +A = -41 +M = 48 + +ModInv = 3b +A = -3d +M = 48 + +ModInv = 3d +A = -3b +M = 48 + +ModInv = 11 +A = -37 +M = 48 + +ModInv = 13 +A = -35 +M = 48 + +ModInv = 2f +A = -31 +M = 48 + +ModInv = 31 +A = -2f +M = 48 + +ModInv = 5 +A = -2b +M = 48 + +ModInv = 7 +A = -29 +M = 48 + +ModInv = 23 +A = -25 +M = 48 + +ModInv = 25 +A = -23 +M = 48 + +ModInv = 41 +A = -1f +M = 48 + +ModInv = 43 +A = -1d +M = 48 + +ModInv = 17 +A = -19 +M = 48 + +ModInv = 19 +A = -17 +M = 48 + +ModInv = 35 +A = -13 +M = 48 + +ModInv = 37 +A = -11 +M = 48 + +ModInv = b +A = -d +M = 48 + +ModInv = d +A = -b +M = 48 + +ModInv = 29 +A = -7 +M = 48 + +ModInv = 2b +A = -5 +M = 48 + +ModInv = 47 +A = -1 +M = 48 + +ModInv = 1 +A = 1 +M = 48 + +ModInv = 1d +A = 5 +M = 48 + +ModInv = 1f +A = 7 +M = 48 + +ModInv = 3b +A = b +M = 48 + +ModInv = 3d +A = d +M = 48 + +ModInv = 11 +A = 11 +M = 48 + +ModInv = 13 +A = 13 +M = 48 + +ModInv = 2f +A = 17 +M = 48 + +ModInv = 31 +A = 19 +M = 48 + +ModInv = 5 +A = 1d +M = 48 + +ModInv = 7 +A = 1f +M = 48 + +ModInv = 23 +A = 23 +M = 48 + +ModInv = 25 +A = 25 +M = 48 + +ModInv = 41 +A = 29 +M = 48 + +ModInv = 43 +A = 2b +M = 48 + +ModInv = 17 +A = 2f +M = 48 + +ModInv = 19 +A = 31 +M = 48 + +ModInv = 35 +A = 35 +M = 48 + +ModInv = 37 +A = 37 +M = 48 + +ModInv = b +A = 3b +M = 48 + +ModInv = d +A = 3d +M = 48 + +ModInv = 29 +A = 41 +M = 48 + +ModInv = 2b +A = 43 +M = 48 + +ModInv = 47 +A = 47 +M = 48 + +ModInv = 1 +A = 49 +M = 48 + +ModInv = 1d +A = 4d +M = 48 + +ModInv = 1f +A = 4f +M = 48 + +ModInv = 3b +A = 53 +M = 48 + +ModInv = 3d +A = 55 +M = 48 + +ModInv = 11 +A = 59 +M = 48 + +ModInv = 13 +A = 5b +M = 48 + +ModInv = 2f +A = 5f +M = 48 + +ModInv = 31 +A = 61 +M = 48 + +ModInv = 1b +A = -64 +M = 49 + +ModInv = e +A = -63 +M = 49 + +ModInv = 23 +A = -62 +M = 49 + +ModInv = 3 +A = -61 +M = 49 + +ModInv = 13 +A = -60 +M = 49 + +ModInv = 3f +A = -5f +M = 49 + +ModInv = 42 +A = -5e +M = 49 + +ModInv = 3e +A = -5d +M = 49 + +ModInv = 17 +A = -5c +M = 49 + +ModInv = 4 +A = -5b +M = 49 + +ModInv = 1e +A = -5a +M = 49 + +ModInv = 29 +A = -59 +M = 49 + +ModInv = 22 +A = -58 +M = 49 + +ModInv = 1a +A = -57 +M = 49 + +ModInv = 1c +A = -56 +M = 49 + +ModInv = 6 +A = -55 +M = 49 + +ModInv = 35 +A = -54 +M = 49 + +ModInv = 33 +A = -53 +M = 49 + +ModInv = 8 +A = -52 +M = 49 + +ModInv = 9 +A = -51 +M = 49 + +ModInv = 34 +A = -50 +M = 49 + +ModInv = c +A = -4f +M = 49 + +ModInv = 1d +A = -4e +M = 49 + +ModInv = 12 +A = -4d +M = 49 + +ModInv = 18 +A = -4c +M = 49 + +ModInv = 24 +A = -4b +M = 49 + +ModInv = 48 +A = -4a +M = 49 + +ModInv = 1 +A = -48 +M = 49 + +ModInv = 25 +A = -47 +M = 49 + +ModInv = 31 +A = -46 +M = 49 + +ModInv = 37 +A = -45 +M = 49 + +ModInv = 2c +A = -44 +M = 49 + +ModInv = 3d +A = -43 +M = 49 + +ModInv = 15 +A = -42 +M = 49 + +ModInv = 40 +A = -41 +M = 49 + +ModInv = 41 +A = -40 +M = 49 + +ModInv = 16 +A = -3f +M = 49 + +ModInv = 14 +A = -3e +M = 49 + +ModInv = 43 +A = -3d +M = 49 + +ModInv = 2d +A = -3c +M = 49 + +ModInv = 2f +A = -3b +M = 49 + +ModInv = 27 +A = -3a +M = 49 + +ModInv = 20 +A = -39 +M = 49 + +ModInv = 2b +A = -38 +M = 49 + +ModInv = 45 +A = -37 +M = 49 + +ModInv = 32 +A = -36 +M = 49 + +ModInv = b +A = -35 +M = 49 + +ModInv = 7 +A = -34 +M = 49 + +ModInv = a +A = -33 +M = 49 + +ModInv = 36 +A = -32 +M = 49 + +ModInv = 46 +A = -31 +M = 49 + +ModInv = 26 +A = -30 +M = 49 + +ModInv = 3b +A = -2f +M = 49 + +ModInv = 2e +A = -2e +M = 49 + +ModInv = 3c +A = -2d +M = 49 + +ModInv = 44 +A = -2c +M = 49 + +ModInv = 38 +A = -2b +M = 49 + +ModInv = 21 +A = -2a +M = 49 + +ModInv = 10 +A = -29 +M = 49 + +ModInv = 1f +A = -28 +M = 49 + +ModInv = 3a +A = -27 +M = 49 + +ModInv = 30 +A = -26 +M = 49 + +ModInv = 47 +A = -25 +M = 49 + +ModInv = 2 +A = -24 +M = 49 + +ModInv = 19 +A = -23 +M = 49 + +ModInv = f +A = -22 +M = 49 + +ModInv = 2a +A = -21 +M = 49 + +ModInv = 39 +A = -20 +M = 49 + +ModInv = 28 +A = -1f +M = 49 + +ModInv = 11 +A = -1e +M = 49 + +ModInv = 5 +A = -1d +M = 49 + +ModInv = d +A = -1c +M = 49 + +ModInv = 1b +A = -1b +M = 49 + +ModInv = e +A = -1a +M = 49 + +ModInv = 23 +A = -19 +M = 49 + +ModInv = 3 +A = -18 +M = 49 + +ModInv = 13 +A = -17 +M = 49 + +ModInv = 3f +A = -16 +M = 49 + +ModInv = 42 +A = -15 +M = 49 + +ModInv = 3e +A = -14 +M = 49 + +ModInv = 17 +A = -13 +M = 49 + +ModInv = 4 +A = -12 +M = 49 + +ModInv = 1e +A = -11 +M = 49 + +ModInv = 29 +A = -10 +M = 49 + +ModInv = 22 +A = -f +M = 49 + +ModInv = 1a +A = -e +M = 49 + +ModInv = 1c +A = -d +M = 49 + +ModInv = 6 +A = -c +M = 49 + +ModInv = 35 +A = -b +M = 49 + +ModInv = 33 +A = -a +M = 49 + +ModInv = 8 +A = -9 +M = 49 + +ModInv = 9 +A = -8 +M = 49 + +ModInv = 34 +A = -7 +M = 49 + +ModInv = c +A = -6 +M = 49 + +ModInv = 1d +A = -5 +M = 49 + +ModInv = 12 +A = -4 +M = 49 + +ModInv = 18 +A = -3 +M = 49 + +ModInv = 24 +A = -2 +M = 49 + +ModInv = 48 +A = -1 +M = 49 + +ModInv = 1 +A = 1 +M = 49 + +ModInv = 25 +A = 2 +M = 49 + +ModInv = 31 +A = 3 +M = 49 + +ModInv = 37 +A = 4 +M = 49 + +ModInv = 2c +A = 5 +M = 49 + +ModInv = 3d +A = 6 +M = 49 + +ModInv = 15 +A = 7 +M = 49 + +ModInv = 40 +A = 8 +M = 49 + +ModInv = 41 +A = 9 +M = 49 + +ModInv = 16 +A = a +M = 49 + +ModInv = 14 +A = b +M = 49 + +ModInv = 43 +A = c +M = 49 + +ModInv = 2d +A = d +M = 49 + +ModInv = 2f +A = e +M = 49 + +ModInv = 27 +A = f +M = 49 + +ModInv = 20 +A = 10 +M = 49 + +ModInv = 2b +A = 11 +M = 49 + +ModInv = 45 +A = 12 +M = 49 + +ModInv = 32 +A = 13 +M = 49 + +ModInv = b +A = 14 +M = 49 + +ModInv = 7 +A = 15 +M = 49 + +ModInv = a +A = 16 +M = 49 + +ModInv = 36 +A = 17 +M = 49 + +ModInv = 46 +A = 18 +M = 49 + +ModInv = 26 +A = 19 +M = 49 + +ModInv = 3b +A = 1a +M = 49 + +ModInv = 2e +A = 1b +M = 49 + +ModInv = 3c +A = 1c +M = 49 + +ModInv = 44 +A = 1d +M = 49 + +ModInv = 38 +A = 1e +M = 49 + +ModInv = 21 +A = 1f +M = 49 + +ModInv = 10 +A = 20 +M = 49 + +ModInv = 1f +A = 21 +M = 49 + +ModInv = 3a +A = 22 +M = 49 + +ModInv = 30 +A = 23 +M = 49 + +ModInv = 47 +A = 24 +M = 49 + +ModInv = 2 +A = 25 +M = 49 + +ModInv = 19 +A = 26 +M = 49 + +ModInv = f +A = 27 +M = 49 + +ModInv = 2a +A = 28 +M = 49 + +ModInv = 39 +A = 29 +M = 49 + +ModInv = 28 +A = 2a +M = 49 + +ModInv = 11 +A = 2b +M = 49 + +ModInv = 5 +A = 2c +M = 49 + +ModInv = d +A = 2d +M = 49 + +ModInv = 1b +A = 2e +M = 49 + +ModInv = e +A = 2f +M = 49 + +ModInv = 23 +A = 30 +M = 49 + +ModInv = 3 +A = 31 +M = 49 + +ModInv = 13 +A = 32 +M = 49 + +ModInv = 3f +A = 33 +M = 49 + +ModInv = 42 +A = 34 +M = 49 + +ModInv = 3e +A = 35 +M = 49 + +ModInv = 17 +A = 36 +M = 49 + +ModInv = 4 +A = 37 +M = 49 + +ModInv = 1e +A = 38 +M = 49 + +ModInv = 29 +A = 39 +M = 49 + +ModInv = 22 +A = 3a +M = 49 + +ModInv = 1a +A = 3b +M = 49 + +ModInv = 1c +A = 3c +M = 49 + +ModInv = 6 +A = 3d +M = 49 + +ModInv = 35 +A = 3e +M = 49 + +ModInv = 33 +A = 3f +M = 49 + +ModInv = 8 +A = 40 +M = 49 + +ModInv = 9 +A = 41 +M = 49 + +ModInv = 34 +A = 42 +M = 49 + +ModInv = c +A = 43 +M = 49 + +ModInv = 1d +A = 44 +M = 49 + +ModInv = 12 +A = 45 +M = 49 + +ModInv = 18 +A = 46 +M = 49 + +ModInv = 24 +A = 47 +M = 49 + +ModInv = 48 +A = 48 +M = 49 + +ModInv = 1 +A = 4a +M = 49 + +ModInv = 25 +A = 4b +M = 49 + +ModInv = 31 +A = 4c +M = 49 + +ModInv = 37 +A = 4d +M = 49 + +ModInv = 2c +A = 4e +M = 49 + +ModInv = 3d +A = 4f +M = 49 + +ModInv = 15 +A = 50 +M = 49 + +ModInv = 40 +A = 51 +M = 49 + +ModInv = 41 +A = 52 +M = 49 + +ModInv = 16 +A = 53 +M = 49 + +ModInv = 14 +A = 54 +M = 49 + +ModInv = 43 +A = 55 +M = 49 + +ModInv = 2d +A = 56 +M = 49 + +ModInv = 2f +A = 57 +M = 49 + +ModInv = 27 +A = 58 +M = 49 + +ModInv = 20 +A = 59 +M = 49 + +ModInv = 2b +A = 5a +M = 49 + +ModInv = 45 +A = 5b +M = 49 + +ModInv = 32 +A = 5c +M = 49 + +ModInv = b +A = 5d +M = 49 + +ModInv = 7 +A = 5e +M = 49 + +ModInv = a +A = 5f +M = 49 + +ModInv = 36 +A = 60 +M = 49 + +ModInv = 46 +A = 61 +M = 49 + +ModInv = 26 +A = 62 +M = 49 + +ModInv = 3b +A = 63 +M = 49 + +ModInv = 47 +A = -63 +M = 4a + +ModInv = 2d +A = -61 +M = 4a + +ModInv = 7 +A = -5f +M = 4a + +ModInv = 23 +A = -5d +M = 4a + +ModInv = d +A = -5b +M = 4a + +ModInv = 45 +A = -59 +M = 4a + +ModInv = 11 +A = -57 +M = 4a + +ModInv = 2f +A = -55 +M = 4a + +ModInv = 29 +A = -53 +M = 4a + +ModInv = 15 +A = -51 +M = 4a + +ModInv = 3b +A = -4f +M = 4a + +ModInv = 31 +A = -4d +M = 4a + +ModInv = 49 +A = -4b +M = 4a + +ModInv = 1 +A = -49 +M = 4a + +ModInv = 19 +A = -47 +M = 4a + +ModInv = f +A = -45 +M = 4a + +ModInv = 35 +A = -43 +M = 4a + +ModInv = 21 +A = -41 +M = 4a + +ModInv = 1b +A = -3f +M = 4a + +ModInv = 39 +A = -3d +M = 4a + +ModInv = 5 +A = -3b +M = 4a + +ModInv = 3d +A = -39 +M = 4a + +ModInv = 27 +A = -37 +M = 4a + +ModInv = 43 +A = -35 +M = 4a + +ModInv = 1d +A = -33 +M = 4a + +ModInv = 3 +A = -31 +M = 4a + +ModInv = b +A = -2f +M = 4a + +ModInv = 17 +A = -2d +M = 4a + +ModInv = 2b +A = -2b +M = 4a + +ModInv = 9 +A = -29 +M = 4a + +ModInv = 37 +A = -27 +M = 4a + +ModInv = 13 +A = -23 +M = 4a + +ModInv = 41 +A = -21 +M = 4a + +ModInv = 1f +A = -1f +M = 4a + +ModInv = 33 +A = -1d +M = 4a + +ModInv = 3f +A = -1b +M = 4a + +ModInv = 47 +A = -19 +M = 4a + +ModInv = 2d +A = -17 +M = 4a + +ModInv = 7 +A = -15 +M = 4a + +ModInv = 23 +A = -13 +M = 4a + +ModInv = d +A = -11 +M = 4a + +ModInv = 45 +A = -f +M = 4a + +ModInv = 11 +A = -d +M = 4a + +ModInv = 2f +A = -b +M = 4a + +ModInv = 29 +A = -9 +M = 4a + +ModInv = 15 +A = -7 +M = 4a + +ModInv = 3b +A = -5 +M = 4a + +ModInv = 31 +A = -3 +M = 4a + +ModInv = 49 +A = -1 +M = 4a + +ModInv = 1 +A = 1 +M = 4a + +ModInv = 19 +A = 3 +M = 4a + +ModInv = f +A = 5 +M = 4a + +ModInv = 35 +A = 7 +M = 4a + +ModInv = 21 +A = 9 +M = 4a + +ModInv = 1b +A = b +M = 4a + +ModInv = 39 +A = d +M = 4a + +ModInv = 5 +A = f +M = 4a + +ModInv = 3d +A = 11 +M = 4a + +ModInv = 27 +A = 13 +M = 4a + +ModInv = 43 +A = 15 +M = 4a + +ModInv = 1d +A = 17 +M = 4a + +ModInv = 3 +A = 19 +M = 4a + +ModInv = b +A = 1b +M = 4a + +ModInv = 17 +A = 1d +M = 4a + +ModInv = 2b +A = 1f +M = 4a + +ModInv = 9 +A = 21 +M = 4a + +ModInv = 37 +A = 23 +M = 4a + +ModInv = 13 +A = 27 +M = 4a + +ModInv = 41 +A = 29 +M = 4a + +ModInv = 1f +A = 2b +M = 4a + +ModInv = 33 +A = 2d +M = 4a + +ModInv = 3f +A = 2f +M = 4a + +ModInv = 47 +A = 31 +M = 4a + +ModInv = 2d +A = 33 +M = 4a + +ModInv = 7 +A = 35 +M = 4a + +ModInv = 23 +A = 37 +M = 4a + +ModInv = d +A = 39 +M = 4a + +ModInv = 45 +A = 3b +M = 4a + +ModInv = 11 +A = 3d +M = 4a + +ModInv = 2f +A = 3f +M = 4a + +ModInv = 29 +A = 41 +M = 4a + +ModInv = 15 +A = 43 +M = 4a + +ModInv = 3b +A = 45 +M = 4a + +ModInv = 31 +A = 47 +M = 4a + +ModInv = 49 +A = 49 +M = 4a + +ModInv = 1 +A = 4b +M = 4a + +ModInv = 19 +A = 4d +M = 4a + +ModInv = f +A = 4f +M = 4a + +ModInv = 35 +A = 51 +M = 4a + +ModInv = 21 +A = 53 +M = 4a + +ModInv = 1b +A = 55 +M = 4a + +ModInv = 39 +A = 57 +M = 4a + +ModInv = 5 +A = 59 +M = 4a + +ModInv = 3d +A = 5b +M = 4a + +ModInv = 27 +A = 5d +M = 4a + +ModInv = 43 +A = 5f +M = 4a + +ModInv = 1d +A = 61 +M = 4a + +ModInv = 3 +A = 63 +M = 4a + +ModInv = d +A = -62 +M = 4b + +ModInv = 11 +A = -61 +M = 4b + +ModInv = 47 +A = -5e +M = 4b + +ModInv = 16 +A = -5c +M = 4b + +ModInv = e +A = -5b +M = 4b + +ModInv = 10 +A = -59 +M = 4b + +ModInv = 17 +A = -58 +M = 4b + +ModInv = 22 +A = -56 +M = 4b + +ModInv = 1c +A = -53 +M = 4b + +ModInv = 20 +A = -52 +M = 4b + +ModInv = 38 +A = -4f +M = 4b + +ModInv = 25 +A = -4d +M = 4b + +ModInv = 4a +A = -4c +M = 4b + +ModInv = 1 +A = -4a +M = 4b + +ModInv = 26 +A = -49 +M = 4b + +ModInv = 13 +A = -47 +M = 4b + +ModInv = 2b +A = -44 +M = 4b + +ModInv = 2f +A = -43 +M = 4b + +ModInv = 29 +A = -40 +M = 4b + +ModInv = 34 +A = -3e +M = 4b + +ModInv = 3b +A = -3d +M = 4b + +ModInv = 3d +A = -3b +M = 4b + +ModInv = 35 +A = -3a +M = 4b + +ModInv = 4 +A = -38 +M = 4b + +ModInv = 3a +A = -35 +M = 4b + +ModInv = 3e +A = -34 +M = 4b + +ModInv = 1a +A = -31 +M = 4b + +ModInv = 43 +A = -2f +M = 4b + +ModInv = 2c +A = -2e +M = 4b + +ModInv = 2e +A = -2c +M = 4b + +ModInv = 44 +A = -2b +M = 4b + +ModInv = 40 +A = -29 +M = 4b + +ModInv = 49 +A = -26 +M = 4b + +ModInv = 2 +A = -25 +M = 4b + +ModInv = b +A = -22 +M = 4b + +ModInv = 7 +A = -20 +M = 4b + +ModInv = 1d +A = -1f +M = 4b + +ModInv = 1f +A = -1d +M = 4b + +ModInv = 8 +A = -1c +M = 4b + +ModInv = 31 +A = -1a +M = 4b + +ModInv = d +A = -17 +M = 4b + +ModInv = 11 +A = -16 +M = 4b + +ModInv = 47 +A = -13 +M = 4b + +ModInv = 16 +A = -11 +M = 4b + +ModInv = e +A = -10 +M = 4b + +ModInv = 10 +A = -e +M = 4b + +ModInv = 17 +A = -d +M = 4b + +ModInv = 22 +A = -b +M = 4b + +ModInv = 1c +A = -8 +M = 4b + +ModInv = 20 +A = -7 +M = 4b + +ModInv = 38 +A = -4 +M = 4b + +ModInv = 25 +A = -2 +M = 4b + +ModInv = 4a +A = -1 +M = 4b + +ModInv = 1 +A = 1 +M = 4b + +ModInv = 26 +A = 2 +M = 4b + +ModInv = 13 +A = 4 +M = 4b + +ModInv = 2b +A = 7 +M = 4b + +ModInv = 2f +A = 8 +M = 4b + +ModInv = 29 +A = b +M = 4b + +ModInv = 34 +A = d +M = 4b + +ModInv = 3b +A = e +M = 4b + +ModInv = 3d +A = 10 +M = 4b + +ModInv = 35 +A = 11 +M = 4b + +ModInv = 4 +A = 13 +M = 4b + +ModInv = 3a +A = 16 +M = 4b + +ModInv = 3e +A = 17 +M = 4b + +ModInv = 1a +A = 1a +M = 4b + +ModInv = 43 +A = 1c +M = 4b + +ModInv = 2c +A = 1d +M = 4b + +ModInv = 2e +A = 1f +M = 4b + +ModInv = 44 +A = 20 +M = 4b + +ModInv = 40 +A = 22 +M = 4b + +ModInv = 49 +A = 25 +M = 4b + +ModInv = 2 +A = 26 +M = 4b + +ModInv = b +A = 29 +M = 4b + +ModInv = 7 +A = 2b +M = 4b + +ModInv = 1d +A = 2c +M = 4b + +ModInv = 1f +A = 2e +M = 4b + +ModInv = 8 +A = 2f +M = 4b + +ModInv = 31 +A = 31 +M = 4b + +ModInv = d +A = 34 +M = 4b + +ModInv = 11 +A = 35 +M = 4b + +ModInv = 47 +A = 38 +M = 4b + +ModInv = 16 +A = 3a +M = 4b + +ModInv = e +A = 3b +M = 4b + +ModInv = 10 +A = 3d +M = 4b + +ModInv = 17 +A = 3e +M = 4b + +ModInv = 22 +A = 40 +M = 4b + +ModInv = 1c +A = 43 +M = 4b + +ModInv = 20 +A = 44 +M = 4b + +ModInv = 38 +A = 47 +M = 4b + +ModInv = 25 +A = 49 +M = 4b + +ModInv = 4a +A = 4a +M = 4b + +ModInv = 1 +A = 4c +M = 4b + +ModInv = 26 +A = 4d +M = 4b + +ModInv = 13 +A = 4f +M = 4b + +ModInv = 2b +A = 52 +M = 4b + +ModInv = 2f +A = 53 +M = 4b + +ModInv = 29 +A = 56 +M = 4b + +ModInv = 34 +A = 58 +M = 4b + +ModInv = 3b +A = 59 +M = 4b + +ModInv = 3d +A = 5b +M = 4b + +ModInv = 35 +A = 5c +M = 4b + +ModInv = 4 +A = 5e +M = 4b + +ModInv = 3a +A = 61 +M = 4b + +ModInv = 3e +A = 62 +M = 4b + +ModInv = 21 +A = -63 +M = 4c + +ModInv = 2f +A = -61 +M = 4c + +ModInv = 43 +A = -5d +M = 4c + +ModInv = 5 +A = -5b +M = 4c + +ModInv = 23 +A = -59 +M = 4c + +ModInv = 45 +A = -57 +M = 4c + +ModInv = 3b +A = -55 +M = 4c + +ModInv = 41 +A = -53 +M = 4c + +ModInv = f +A = -51 +M = 4c + +ModInv = 19 +A = -4f +M = 4c + +ModInv = 4b +A = -4d +M = 4c + +ModInv = 1 +A = -4b +M = 4c + +ModInv = 33 +A = -49 +M = 4c + +ModInv = 3d +A = -47 +M = 4c + +ModInv = b +A = -45 +M = 4c + +ModInv = 11 +A = -43 +M = 4c + +ModInv = 7 +A = -41 +M = 4c + +ModInv = 29 +A = -3f +M = 4c + +ModInv = 47 +A = -3d +M = 4c + +ModInv = 9 +A = -3b +M = 4c + +ModInv = 1d +A = -37 +M = 4c + +ModInv = 2b +A = -35 +M = 4c + +ModInv = 49 +A = -33 +M = 4c + +ModInv = 1f +A = -31 +M = 4c + +ModInv = 15 +A = -2f +M = 4c + +ModInv = 1b +A = -2d +M = 4c + +ModInv = 35 +A = -2b +M = 4c + +ModInv = 3f +A = -29 +M = 4c + +ModInv = 25 +A = -27 +M = 4c + +ModInv = 27 +A = -25 +M = 4c + +ModInv = d +A = -23 +M = 4c + +ModInv = 17 +A = -21 +M = 4c + +ModInv = 31 +A = -1f +M = 4c + +ModInv = 37 +A = -1d +M = 4c + +ModInv = 2d +A = -1b +M = 4c + +ModInv = 3 +A = -19 +M = 4c + +ModInv = 21 +A = -17 +M = 4c + +ModInv = 2f +A = -15 +M = 4c + +ModInv = 43 +A = -11 +M = 4c + +ModInv = 5 +A = -f +M = 4c + +ModInv = 23 +A = -d +M = 4c + +ModInv = 45 +A = -b +M = 4c + +ModInv = 3b +A = -9 +M = 4c + +ModInv = 41 +A = -7 +M = 4c + +ModInv = f +A = -5 +M = 4c + +ModInv = 19 +A = -3 +M = 4c + +ModInv = 4b +A = -1 +M = 4c + +ModInv = 1 +A = 1 +M = 4c + +ModInv = 33 +A = 3 +M = 4c + +ModInv = 3d +A = 5 +M = 4c + +ModInv = b +A = 7 +M = 4c + +ModInv = 11 +A = 9 +M = 4c + +ModInv = 7 +A = b +M = 4c + +ModInv = 29 +A = d +M = 4c + +ModInv = 47 +A = f +M = 4c + +ModInv = 9 +A = 11 +M = 4c + +ModInv = 1d +A = 15 +M = 4c + +ModInv = 2b +A = 17 +M = 4c + +ModInv = 49 +A = 19 +M = 4c + +ModInv = 1f +A = 1b +M = 4c + +ModInv = 15 +A = 1d +M = 4c + +ModInv = 1b +A = 1f +M = 4c + +ModInv = 35 +A = 21 +M = 4c + +ModInv = 3f +A = 23 +M = 4c + +ModInv = 25 +A = 25 +M = 4c + +ModInv = 27 +A = 27 +M = 4c + +ModInv = d +A = 29 +M = 4c + +ModInv = 17 +A = 2b +M = 4c + +ModInv = 31 +A = 2d +M = 4c + +ModInv = 37 +A = 2f +M = 4c + +ModInv = 2d +A = 31 +M = 4c + +ModInv = 3 +A = 33 +M = 4c + +ModInv = 21 +A = 35 +M = 4c + +ModInv = 2f +A = 37 +M = 4c + +ModInv = 43 +A = 3b +M = 4c + +ModInv = 5 +A = 3d +M = 4c + +ModInv = 23 +A = 3f +M = 4c + +ModInv = 45 +A = 41 +M = 4c + +ModInv = 3b +A = 43 +M = 4c + +ModInv = 41 +A = 45 +M = 4c + +ModInv = f +A = 47 +M = 4c + +ModInv = 19 +A = 49 +M = 4c + +ModInv = 4b +A = 4b +M = 4c + +ModInv = 1 +A = 4d +M = 4c + +ModInv = 33 +A = 4f +M = 4c + +ModInv = 3d +A = 51 +M = 4c + +ModInv = b +A = 53 +M = 4c + +ModInv = 11 +A = 55 +M = 4c + +ModInv = 7 +A = 57 +M = 4c + +ModInv = 29 +A = 59 +M = 4c + +ModInv = 47 +A = 5b +M = 4c + +ModInv = 9 +A = 5d +M = 4c + +ModInv = 1d +A = 61 +M = 4c + +ModInv = 2b +A = 63 +M = 4c + +ModInv = a +A = -64 +M = 4d + +ModInv = 32 +A = -61 +M = 4d + +ModInv = 4 +A = -60 +M = 4d + +ModInv = 2f +A = -5f +M = 4d + +ModInv = 9 +A = -5e +M = 4d + +ModInv = 18 +A = -5d +M = 4d + +ModInv = 29 +A = -5c +M = 4d + +ModInv = 47 +A = -5a +M = 4d + +ModInv = 20 +A = -59 +M = 4d + +ModInv = 17 +A = -57 +M = 4d + +ModInv = 11 +A = -56 +M = 4d + +ModInv = 30 +A = -55 +M = 4d + +ModInv = 40 +A = -53 +M = 4d + +ModInv = 2e +A = -52 +M = 4d + +ModInv = 13 +A = -51 +M = 4d + +ModInv = 33 +A = -50 +M = 4d + +ModInv = 26 +A = -4f +M = 4d + +ModInv = 4c +A = -4e +M = 4d + +ModInv = 1 +A = -4c +M = 4d + +ModInv = 27 +A = -4b +M = 4d + +ModInv = 1a +A = -4a +M = 4d + +ModInv = 3a +A = -49 +M = 4d + +ModInv = 1f +A = -48 +M = 4d + +ModInv = d +A = -47 +M = 4d + +ModInv = 1d +A = -45 +M = 4d + +ModInv = 3c +A = -44 +M = 4d + +ModInv = 36 +A = -43 +M = 4d + +ModInv = 2d +A = -41 +M = 4d + +ModInv = 6 +A = -40 +M = 4d + +ModInv = 24 +A = -3e +M = 4d + +ModInv = 35 +A = -3d +M = 4d + +ModInv = 44 +A = -3c +M = 4d + +ModInv = 1e +A = -3b +M = 4d + +ModInv = 49 +A = -3a +M = 4d + +ModInv = 1b +A = -39 +M = 4d + +ModInv = 43 +A = -36 +M = 4d + +ModInv = 3d +A = -35 +M = 4d + +ModInv = 25 +A = -34 +M = 4d + +ModInv = 3 +A = -33 +M = 4d + +ModInv = 14 +A = -32 +M = 4d + +ModInv = 8 +A = -30 +M = 4d + +ModInv = 12 +A = -2f +M = 4d + +ModInv = 5 +A = -2e +M = 4d + +ModInv = 41 +A = -2d +M = 4d + +ModInv = 22 +A = -2b +M = 4d + +ModInv = f +A = -29 +M = 4d + +ModInv = 19 +A = -28 +M = 4d + +ModInv = 4b +A = -27 +M = 4d + +ModInv = 2 +A = -26 +M = 4d + +ModInv = 34 +A = -25 +M = 4d + +ModInv = 3e +A = -24 +M = 4d + +ModInv = 2b +A = -22 +M = 4d + +ModInv = c +A = -20 +M = 4d + +ModInv = 48 +A = -1f +M = 4d + +ModInv = 3b +A = -1e +M = 4d + +ModInv = 45 +A = -1d +M = 4d + +ModInv = 39 +A = -1b +M = 4d + +ModInv = 4a +A = -1a +M = 4d + +ModInv = 28 +A = -19 +M = 4d + +ModInv = 10 +A = -18 +M = 4d + +ModInv = a +A = -17 +M = 4d + +ModInv = 32 +A = -14 +M = 4d + +ModInv = 4 +A = -13 +M = 4d + +ModInv = 2f +A = -12 +M = 4d + +ModInv = 9 +A = -11 +M = 4d + +ModInv = 18 +A = -10 +M = 4d + +ModInv = 29 +A = -f +M = 4d + +ModInv = 47 +A = -d +M = 4d + +ModInv = 20 +A = -c +M = 4d + +ModInv = 17 +A = -a +M = 4d + +ModInv = 11 +A = -9 +M = 4d + +ModInv = 30 +A = -8 +M = 4d + +ModInv = 40 +A = -6 +M = 4d + +ModInv = 2e +A = -5 +M = 4d + +ModInv = 13 +A = -4 +M = 4d + +ModInv = 33 +A = -3 +M = 4d + +ModInv = 26 +A = -2 +M = 4d + +ModInv = 4c +A = -1 +M = 4d + +ModInv = 1 +A = 1 +M = 4d + +ModInv = 27 +A = 2 +M = 4d + +ModInv = 1a +A = 3 +M = 4d + +ModInv = 3a +A = 4 +M = 4d + +ModInv = 1f +A = 5 +M = 4d + +ModInv = d +A = 6 +M = 4d + +ModInv = 1d +A = 8 +M = 4d + +ModInv = 3c +A = 9 +M = 4d + +ModInv = 36 +A = a +M = 4d + +ModInv = 2d +A = c +M = 4d + +ModInv = 6 +A = d +M = 4d + +ModInv = 24 +A = f +M = 4d + +ModInv = 35 +A = 10 +M = 4d + +ModInv = 44 +A = 11 +M = 4d + +ModInv = 1e +A = 12 +M = 4d + +ModInv = 49 +A = 13 +M = 4d + +ModInv = 1b +A = 14 +M = 4d + +ModInv = 43 +A = 17 +M = 4d + +ModInv = 3d +A = 18 +M = 4d + +ModInv = 25 +A = 19 +M = 4d + +ModInv = 3 +A = 1a +M = 4d + +ModInv = 14 +A = 1b +M = 4d + +ModInv = 8 +A = 1d +M = 4d + +ModInv = 12 +A = 1e +M = 4d + +ModInv = 5 +A = 1f +M = 4d + +ModInv = 41 +A = 20 +M = 4d + +ModInv = 22 +A = 22 +M = 4d + +ModInv = f +A = 24 +M = 4d + +ModInv = 19 +A = 25 +M = 4d + +ModInv = 4b +A = 26 +M = 4d + +ModInv = 2 +A = 27 +M = 4d + +ModInv = 34 +A = 28 +M = 4d + +ModInv = 3e +A = 29 +M = 4d + +ModInv = 2b +A = 2b +M = 4d + +ModInv = c +A = 2d +M = 4d + +ModInv = 48 +A = 2e +M = 4d + +ModInv = 3b +A = 2f +M = 4d + +ModInv = 45 +A = 30 +M = 4d + +ModInv = 39 +A = 32 +M = 4d + +ModInv = 4a +A = 33 +M = 4d + +ModInv = 28 +A = 34 +M = 4d + +ModInv = 10 +A = 35 +M = 4d + +ModInv = a +A = 36 +M = 4d + +ModInv = 32 +A = 39 +M = 4d + +ModInv = 4 +A = 3a +M = 4d + +ModInv = 2f +A = 3b +M = 4d + +ModInv = 9 +A = 3c +M = 4d + +ModInv = 18 +A = 3d +M = 4d + +ModInv = 29 +A = 3e +M = 4d + +ModInv = 47 +A = 40 +M = 4d + +ModInv = 20 +A = 41 +M = 4d + +ModInv = 17 +A = 43 +M = 4d + +ModInv = 11 +A = 44 +M = 4d + +ModInv = 30 +A = 45 +M = 4d + +ModInv = 40 +A = 47 +M = 4d + +ModInv = 2e +A = 48 +M = 4d + +ModInv = 13 +A = 49 +M = 4d + +ModInv = 33 +A = 4a +M = 4d + +ModInv = 26 +A = 4b +M = 4d + +ModInv = 4c +A = 4c +M = 4d + +ModInv = 1 +A = 4e +M = 4d + +ModInv = 27 +A = 4f +M = 4d + +ModInv = 1a +A = 50 +M = 4d + +ModInv = 3a +A = 51 +M = 4d + +ModInv = 1f +A = 52 +M = 4d + +ModInv = d +A = 53 +M = 4d + +ModInv = 1d +A = 55 +M = 4d + +ModInv = 3c +A = 56 +M = 4d + +ModInv = 36 +A = 57 +M = 4d + +ModInv = 2d +A = 59 +M = 4d + +ModInv = 6 +A = 5a +M = 4d + +ModInv = 24 +A = 5c +M = 4d + +ModInv = 35 +A = 5d +M = 4d + +ModInv = 44 +A = 5e +M = 4d + +ModInv = 1e +A = 5f +M = 4d + +ModInv = 49 +A = 60 +M = 4d + +ModInv = 1b +A = 61 +M = 4d + +ModInv = 29 +A = -61 +M = 4e + +ModInv = 37 +A = -5f +M = 4e + +ModInv = 7 +A = -59 +M = 4e + +ModInv = b +A = -55 +M = 4e + +ModInv = 1f +A = -53 +M = 4e + +ModInv = 4d +A = -4f +M = 4e + +ModInv = 1 +A = -4d +M = 4e + +ModInv = 2f +A = -49 +M = 4e + +ModInv = 43 +A = -47 +M = 4e + +ModInv = 47 +A = -43 +M = 4e + +ModInv = 17 +A = -3d +M = 4e + +ModInv = 25 +A = -3b +M = 4e + +ModInv = 11 +A = -37 +M = 4e + +ModInv = 19 +A = -35 +M = 4e + +ModInv = 23 +A = -31 +M = 4e + +ModInv = 49 +A = -2f +M = 4e + +ModInv = 1d +A = -2b +M = 4e + +ModInv = 13 +A = -29 +M = 4e + +ModInv = 3b +A = -25 +M = 4e + +ModInv = 31 +A = -23 +M = 4e + +ModInv = 5 +A = -1f +M = 4e + +ModInv = 2b +A = -1d +M = 4e + +ModInv = 35 +A = -19 +M = 4e + +ModInv = 3d +A = -17 +M = 4e + +ModInv = 29 +A = -13 +M = 4e + +ModInv = 37 +A = -11 +M = 4e + +ModInv = 7 +A = -b +M = 4e + +ModInv = b +A = -7 +M = 4e + +ModInv = 1f +A = -5 +M = 4e + +ModInv = 4d +A = -1 +M = 4e + +ModInv = 1 +A = 1 +M = 4e + +ModInv = 2f +A = 5 +M = 4e + +ModInv = 43 +A = 7 +M = 4e + +ModInv = 47 +A = b +M = 4e + +ModInv = 17 +A = 11 +M = 4e + +ModInv = 25 +A = 13 +M = 4e + +ModInv = 11 +A = 17 +M = 4e + +ModInv = 19 +A = 19 +M = 4e + +ModInv = 23 +A = 1d +M = 4e + +ModInv = 49 +A = 1f +M = 4e + +ModInv = 1d +A = 23 +M = 4e + +ModInv = 13 +A = 25 +M = 4e + +ModInv = 3b +A = 29 +M = 4e + +ModInv = 31 +A = 2b +M = 4e + +ModInv = 5 +A = 2f +M = 4e + +ModInv = 2b +A = 31 +M = 4e + +ModInv = 35 +A = 35 +M = 4e + +ModInv = 3d +A = 37 +M = 4e + +ModInv = 29 +A = 3b +M = 4e + +ModInv = 37 +A = 3d +M = 4e + +ModInv = 7 +A = 43 +M = 4e + +ModInv = b +A = 47 +M = 4e + +ModInv = 1f +A = 49 +M = 4e + +ModInv = 4d +A = 4d +M = 4e + +ModInv = 1 +A = 4f +M = 4e + +ModInv = 2f +A = 53 +M = 4e + +ModInv = 43 +A = 55 +M = 4e + +ModInv = 47 +A = 59 +M = 4e + +ModInv = 17 +A = 5f +M = 4e + +ModInv = 25 +A = 61 +M = 4e + +ModInv = f +A = -64 +M = 4f + +ModInv = 4b +A = -63 +M = 4f + +ModInv = 36 +A = -62 +M = 4f + +ModInv = 39 +A = -61 +M = 4f + +ModInv = 41 +A = -60 +M = 4f + +ModInv = 4a +A = -5f +M = 4f + +ModInv = 15 +A = -5e +M = 4f + +ModInv = 3e +A = -5d +M = 4f + +ModInv = 6 +A = -5c +M = 4f + +ModInv = 2e +A = -5b +M = 4f + +ModInv = 2b +A = -5a +M = 4f + +ModInv = 47 +A = -59 +M = 4f + +ModInv = 23 +A = -58 +M = 4f + +ModInv = 45 +A = -57 +M = 4f + +ModInv = 2d +A = -56 +M = 4f + +ModInv = d +A = -55 +M = 4f + +ModInv = 3f +A = -54 +M = 4f + +ModInv = 3b +A = -53 +M = 4f + +ModInv = 1a +A = -52 +M = 4f + +ModInv = 27 +A = -51 +M = 4f + +ModInv = 4e +A = -50 +M = 4f + +ModInv = 1 +A = -4e +M = 4f + +ModInv = 28 +A = -4d +M = 4f + +ModInv = 35 +A = -4c +M = 4f + +ModInv = 14 +A = -4b +M = 4f + +ModInv = 10 +A = -4a +M = 4f + +ModInv = 42 +A = -49 +M = 4f + +ModInv = 22 +A = -48 +M = 4f + +ModInv = a +A = -47 +M = 4f + +ModInv = 2c +A = -46 +M = 4f + +ModInv = 8 +A = -45 +M = 4f + +ModInv = 24 +A = -44 +M = 4f + +ModInv = 21 +A = -43 +M = 4f + +ModInv = 49 +A = -42 +M = 4f + +ModInv = 11 +A = -41 +M = 4f + +ModInv = 3a +A = -40 +M = 4f + +ModInv = 5 +A = -3f +M = 4f + +ModInv = e +A = -3e +M = 4f + +ModInv = 16 +A = -3d +M = 4f + +ModInv = 19 +A = -3c +M = 4f + +ModInv = 4 +A = -3b +M = 4f + +ModInv = 40 +A = -3a +M = 4f + +ModInv = 12 +A = -39 +M = 4f + +ModInv = 37 +A = -38 +M = 4f + +ModInv = 38 +A = -37 +M = 4f + +ModInv = 13 +A = -36 +M = 4f + +ModInv = 4c +A = -35 +M = 4f + +ModInv = 29 +A = -34 +M = 4f + +ModInv = 30 +A = -33 +M = 4f + +ModInv = 1e +A = -32 +M = 4f + +ModInv = 1d +A = -31 +M = 4f + +ModInv = 33 +A = -30 +M = 4f + +ModInv = 2a +A = -2f +M = 4f + +ModInv = c +A = -2e +M = 4f + +ModInv = 7 +A = -2d +M = 4f + +ModInv = 46 +A = -2c +M = 4f + +ModInv = b +A = -2b +M = 4f + +ModInv = 2f +A = -2a +M = 4f + +ModInv = 34 +A = -29 +M = 4f + +ModInv = 4d +A = -28 +M = 4f + +ModInv = 2 +A = -27 +M = 4f + +ModInv = 1b +A = -26 +M = 4f + +ModInv = 20 +A = -25 +M = 4f + +ModInv = 44 +A = -24 +M = 4f + +ModInv = 9 +A = -23 +M = 4f + +ModInv = 48 +A = -22 +M = 4f + +ModInv = 43 +A = -21 +M = 4f + +ModInv = 25 +A = -20 +M = 4f + +ModInv = 1c +A = -1f +M = 4f + +ModInv = 32 +A = -1e +M = 4f + +ModInv = 31 +A = -1d +M = 4f + +ModInv = 1f +A = -1c +M = 4f + +ModInv = 26 +A = -1b +M = 4f + +ModInv = 3 +A = -1a +M = 4f + +ModInv = 3c +A = -19 +M = 4f + +ModInv = 17 +A = -18 +M = 4f + +ModInv = 18 +A = -17 +M = 4f + +ModInv = 3d +A = -16 +M = 4f + +ModInv = f +A = -15 +M = 4f + +ModInv = 4b +A = -14 +M = 4f + +ModInv = 36 +A = -13 +M = 4f + +ModInv = 39 +A = -12 +M = 4f + +ModInv = 41 +A = -11 +M = 4f + +ModInv = 4a +A = -10 +M = 4f + +ModInv = 15 +A = -f +M = 4f + +ModInv = 3e +A = -e +M = 4f + +ModInv = 6 +A = -d +M = 4f + +ModInv = 2e +A = -c +M = 4f + +ModInv = 2b +A = -b +M = 4f + +ModInv = 47 +A = -a +M = 4f + +ModInv = 23 +A = -9 +M = 4f + +ModInv = 45 +A = -8 +M = 4f + +ModInv = 2d +A = -7 +M = 4f + +ModInv = d +A = -6 +M = 4f + +ModInv = 3f +A = -5 +M = 4f + +ModInv = 3b +A = -4 +M = 4f + +ModInv = 1a +A = -3 +M = 4f + +ModInv = 27 +A = -2 +M = 4f + +ModInv = 4e +A = -1 +M = 4f + +ModInv = 1 +A = 1 +M = 4f + +ModInv = 28 +A = 2 +M = 4f + +ModInv = 35 +A = 3 +M = 4f + +ModInv = 14 +A = 4 +M = 4f + +ModInv = 10 +A = 5 +M = 4f + +ModInv = 42 +A = 6 +M = 4f + +ModInv = 22 +A = 7 +M = 4f + +ModInv = a +A = 8 +M = 4f + +ModInv = 2c +A = 9 +M = 4f + +ModInv = 8 +A = a +M = 4f + +ModInv = 24 +A = b +M = 4f + +ModInv = 21 +A = c +M = 4f + +ModInv = 49 +A = d +M = 4f + +ModInv = 11 +A = e +M = 4f + +ModInv = 3a +A = f +M = 4f + +ModInv = 5 +A = 10 +M = 4f + +ModInv = e +A = 11 +M = 4f + +ModInv = 16 +A = 12 +M = 4f + +ModInv = 19 +A = 13 +M = 4f + +ModInv = 4 +A = 14 +M = 4f + +ModInv = 40 +A = 15 +M = 4f + +ModInv = 12 +A = 16 +M = 4f + +ModInv = 37 +A = 17 +M = 4f + +ModInv = 38 +A = 18 +M = 4f + +ModInv = 13 +A = 19 +M = 4f + +ModInv = 4c +A = 1a +M = 4f + +ModInv = 29 +A = 1b +M = 4f + +ModInv = 30 +A = 1c +M = 4f + +ModInv = 1e +A = 1d +M = 4f + +ModInv = 1d +A = 1e +M = 4f + +ModInv = 33 +A = 1f +M = 4f + +ModInv = 2a +A = 20 +M = 4f + +ModInv = c +A = 21 +M = 4f + +ModInv = 7 +A = 22 +M = 4f + +ModInv = 46 +A = 23 +M = 4f + +ModInv = b +A = 24 +M = 4f + +ModInv = 2f +A = 25 +M = 4f + +ModInv = 34 +A = 26 +M = 4f + +ModInv = 4d +A = 27 +M = 4f + +ModInv = 2 +A = 28 +M = 4f + +ModInv = 1b +A = 29 +M = 4f + +ModInv = 20 +A = 2a +M = 4f + +ModInv = 44 +A = 2b +M = 4f + +ModInv = 9 +A = 2c +M = 4f + +ModInv = 48 +A = 2d +M = 4f + +ModInv = 43 +A = 2e +M = 4f + +ModInv = 25 +A = 2f +M = 4f + +ModInv = 1c +A = 30 +M = 4f + +ModInv = 32 +A = 31 +M = 4f + +ModInv = 31 +A = 32 +M = 4f + +ModInv = 1f +A = 33 +M = 4f + +ModInv = 26 +A = 34 +M = 4f + +ModInv = 3 +A = 35 +M = 4f + +ModInv = 3c +A = 36 +M = 4f + +ModInv = 17 +A = 37 +M = 4f + +ModInv = 18 +A = 38 +M = 4f + +ModInv = 3d +A = 39 +M = 4f + +ModInv = f +A = 3a +M = 4f + +ModInv = 4b +A = 3b +M = 4f + +ModInv = 36 +A = 3c +M = 4f + +ModInv = 39 +A = 3d +M = 4f + +ModInv = 41 +A = 3e +M = 4f + +ModInv = 4a +A = 3f +M = 4f + +ModInv = 15 +A = 40 +M = 4f + +ModInv = 3e +A = 41 +M = 4f + +ModInv = 6 +A = 42 +M = 4f + +ModInv = 2e +A = 43 +M = 4f + +ModInv = 2b +A = 44 +M = 4f + +ModInv = 47 +A = 45 +M = 4f + +ModInv = 23 +A = 46 +M = 4f + +ModInv = 45 +A = 47 +M = 4f + +ModInv = 2d +A = 48 +M = 4f + +ModInv = d +A = 49 +M = 4f + +ModInv = 3f +A = 4a +M = 4f + +ModInv = 3b +A = 4b +M = 4f + +ModInv = 1a +A = 4c +M = 4f + +ModInv = 27 +A = 4d +M = 4f + +ModInv = 4e +A = 4e +M = 4f + +ModInv = 1 +A = 50 +M = 4f + +ModInv = 28 +A = 51 +M = 4f + +ModInv = 35 +A = 52 +M = 4f + +ModInv = 14 +A = 53 +M = 4f + +ModInv = 10 +A = 54 +M = 4f + +ModInv = 42 +A = 55 +M = 4f + +ModInv = 22 +A = 56 +M = 4f + +ModInv = a +A = 57 +M = 4f + +ModInv = 2c +A = 58 +M = 4f + +ModInv = 8 +A = 59 +M = 4f + +ModInv = 24 +A = 5a +M = 4f + +ModInv = 21 +A = 5b +M = 4f + +ModInv = 49 +A = 5c +M = 4f + +ModInv = 11 +A = 5d +M = 4f + +ModInv = 3a +A = 5e +M = 4f + +ModInv = 5 +A = 5f +M = 4f + +ModInv = e +A = 60 +M = 4f + +ModInv = 16 +A = 61 +M = 4f + +ModInv = 19 +A = 62 +M = 4f + +ModInv = 4 +A = 63 +M = 4f + +ModInv = 15 +A = -63 +M = 50 + +ModInv = 2f +A = -61 +M = 50 + +ModInv = 2b +A = -5d +M = 50 + +ModInv = 1d +A = -5b +M = 50 + +ModInv = 47 +A = -59 +M = 50 + +ModInv = 39 +A = -57 +M = 50 + +ModInv = 35 +A = -53 +M = 50 + +ModInv = 4f +A = -51 +M = 50 + +ModInv = 1 +A = -4f +M = 50 + +ModInv = 1b +A = -4d +M = 50 + +ModInv = 17 +A = -49 +M = 50 + +ModInv = 9 +A = -47 +M = 50 + +ModInv = 33 +A = -45 +M = 50 + +ModInv = 25 +A = -43 +M = 50 + +ModInv = 21 +A = -3f +M = 50 + +ModInv = 3b +A = -3d +M = 50 + +ModInv = 3d +A = -3b +M = 50 + +ModInv = 7 +A = -39 +M = 50 + +ModInv = 3 +A = -35 +M = 50 + +ModInv = 45 +A = -33 +M = 50 + +ModInv = 1f +A = -31 +M = 50 + +ModInv = 11 +A = -2f +M = 50 + +ModInv = d +A = -2b +M = 50 + +ModInv = 27 +A = -29 +M = 50 + +ModInv = 29 +A = -27 +M = 50 + +ModInv = 43 +A = -25 +M = 50 + +ModInv = 3f +A = -21 +M = 50 + +ModInv = 31 +A = -1f +M = 50 + +ModInv = b +A = -1d +M = 50 + +ModInv = 4d +A = -1b +M = 50 + +ModInv = 49 +A = -17 +M = 50 + +ModInv = 13 +A = -15 +M = 50 + +ModInv = 15 +A = -13 +M = 50 + +ModInv = 2f +A = -11 +M = 50 + +ModInv = 2b +A = -d +M = 50 + +ModInv = 1d +A = -b +M = 50 + +ModInv = 47 +A = -9 +M = 50 + +ModInv = 39 +A = -7 +M = 50 + +ModInv = 35 +A = -3 +M = 50 + +ModInv = 4f +A = -1 +M = 50 + +ModInv = 1 +A = 1 +M = 50 + +ModInv = 1b +A = 3 +M = 50 + +ModInv = 17 +A = 7 +M = 50 + +ModInv = 9 +A = 9 +M = 50 + +ModInv = 33 +A = b +M = 50 + +ModInv = 25 +A = d +M = 50 + +ModInv = 21 +A = 11 +M = 50 + +ModInv = 3b +A = 13 +M = 50 + +ModInv = 3d +A = 15 +M = 50 + +ModInv = 7 +A = 17 +M = 50 + +ModInv = 3 +A = 1b +M = 50 + +ModInv = 45 +A = 1d +M = 50 + +ModInv = 1f +A = 1f +M = 50 + +ModInv = 11 +A = 21 +M = 50 + +ModInv = d +A = 25 +M = 50 + +ModInv = 27 +A = 27 +M = 50 + +ModInv = 29 +A = 29 +M = 50 + +ModInv = 43 +A = 2b +M = 50 + +ModInv = 3f +A = 2f +M = 50 + +ModInv = 31 +A = 31 +M = 50 + +ModInv = b +A = 33 +M = 50 + +ModInv = 4d +A = 35 +M = 50 + +ModInv = 49 +A = 39 +M = 50 + +ModInv = 13 +A = 3b +M = 50 + +ModInv = 15 +A = 3d +M = 50 + +ModInv = 2f +A = 3f +M = 50 + +ModInv = 2b +A = 43 +M = 50 + +ModInv = 1d +A = 45 +M = 50 + +ModInv = 47 +A = 47 +M = 50 + +ModInv = 39 +A = 49 +M = 50 + +ModInv = 35 +A = 4d +M = 50 + +ModInv = 4f +A = 4f +M = 50 + +ModInv = 1 +A = 51 +M = 50 + +ModInv = 1b +A = 53 +M = 50 + +ModInv = 17 +A = 57 +M = 50 + +ModInv = 9 +A = 59 +M = 50 + +ModInv = 33 +A = 5b +M = 50 + +ModInv = 25 +A = 5d +M = 50 + +ModInv = 21 +A = 61 +M = 50 + +ModInv = 3b +A = 63 +M = 50 + +ModInv = 11 +A = -64 +M = 51 + +ModInv = 13 +A = -62 +M = 51 + +ModInv = 5 +A = -61 +M = 51 + +ModInv = 34 +A = -5f +M = 51 + +ModInv = 38 +A = -5e +M = 51 + +ModInv = 16 +A = -5c +M = 51 + +ModInv = 8 +A = -5b +M = 51 + +ModInv = a +A = -59 +M = 51 + +ModInv = 17 +A = -58 +M = 51 + +ModInv = 10 +A = -56 +M = 51 + +ModInv = 14 +A = -55 +M = 51 + +ModInv = 28 +A = -53 +M = 51 + +ModInv = 50 +A = -52 +M = 51 + +ModInv = 1 +A = -50 +M = 51 + +ModInv = 29 +A = -4f +M = 51 + +ModInv = 3d +A = -4d +M = 51 + +ModInv = 41 +A = -4c +M = 51 + +ModInv = 3a +A = -4a +M = 51 + +ModInv = 47 +A = -49 +M = 51 + +ModInv = 49 +A = -47 +M = 51 + +ModInv = 3b +A = -46 +M = 51 + +ModInv = 19 +A = -44 +M = 51 + +ModInv = 1d +A = -43 +M = 51 + +ModInv = 4c +A = -41 +M = 51 + +ModInv = 3e +A = -40 +M = 51 + +ModInv = 40 +A = -3e +M = 51 + +ModInv = 4d +A = -3d +M = 51 + +ModInv = 46 +A = -3b +M = 51 + +ModInv = 4a +A = -3a +M = 51 + +ModInv = d +A = -38 +M = 51 + +ModInv = 35 +A = -37 +M = 51 + +ModInv = 37 +A = -35 +M = 51 + +ModInv = e +A = -34 +M = 51 + +ModInv = 22 +A = -32 +M = 51 + +ModInv = 26 +A = -31 +M = 51 + +ModInv = 1f +A = -2f +M = 51 + +ModInv = 2c +A = -2e +M = 51 + +ModInv = 2e +A = -2c +M = 51 + +ModInv = 20 +A = -2b +M = 51 + +ModInv = 4f +A = -29 +M = 51 + +ModInv = 2 +A = -28 +M = 51 + +ModInv = 31 +A = -26 +M = 51 + +ModInv = 23 +A = -25 +M = 51 + +ModInv = 25 +A = -23 +M = 51 + +ModInv = 32 +A = -22 +M = 51 + +ModInv = 2b +A = -20 +M = 51 + +ModInv = 2f +A = -1f +M = 51 + +ModInv = 43 +A = -1d +M = 51 + +ModInv = 1a +A = -1c +M = 51 + +ModInv = 1c +A = -1a +M = 51 + +ModInv = 44 +A = -19 +M = 51 + +ModInv = 7 +A = -17 +M = 51 + +ModInv = b +A = -16 +M = 51 + +ModInv = 4 +A = -14 +M = 51 + +ModInv = 11 +A = -13 +M = 51 + +ModInv = 13 +A = -11 +M = 51 + +ModInv = 5 +A = -10 +M = 51 + +ModInv = 34 +A = -e +M = 51 + +ModInv = 38 +A = -d +M = 51 + +ModInv = 16 +A = -b +M = 51 + +ModInv = 8 +A = -a +M = 51 + +ModInv = a +A = -8 +M = 51 + +ModInv = 17 +A = -7 +M = 51 + +ModInv = 10 +A = -5 +M = 51 + +ModInv = 14 +A = -4 +M = 51 + +ModInv = 28 +A = -2 +M = 51 + +ModInv = 50 +A = -1 +M = 51 + +ModInv = 1 +A = 1 +M = 51 + +ModInv = 29 +A = 2 +M = 51 + +ModInv = 3d +A = 4 +M = 51 + +ModInv = 41 +A = 5 +M = 51 + +ModInv = 3a +A = 7 +M = 51 + +ModInv = 47 +A = 8 +M = 51 + +ModInv = 49 +A = a +M = 51 + +ModInv = 3b +A = b +M = 51 + +ModInv = 19 +A = d +M = 51 + +ModInv = 1d +A = e +M = 51 + +ModInv = 4c +A = 10 +M = 51 + +ModInv = 3e +A = 11 +M = 51 + +ModInv = 40 +A = 13 +M = 51 + +ModInv = 4d +A = 14 +M = 51 + +ModInv = 46 +A = 16 +M = 51 + +ModInv = 4a +A = 17 +M = 51 + +ModInv = d +A = 19 +M = 51 + +ModInv = 35 +A = 1a +M = 51 + +ModInv = 37 +A = 1c +M = 51 + +ModInv = e +A = 1d +M = 51 + +ModInv = 22 +A = 1f +M = 51 + +ModInv = 26 +A = 20 +M = 51 + +ModInv = 1f +A = 22 +M = 51 + +ModInv = 2c +A = 23 +M = 51 + +ModInv = 2e +A = 25 +M = 51 + +ModInv = 20 +A = 26 +M = 51 + +ModInv = 4f +A = 28 +M = 51 + +ModInv = 2 +A = 29 +M = 51 + +ModInv = 31 +A = 2b +M = 51 + +ModInv = 23 +A = 2c +M = 51 + +ModInv = 25 +A = 2e +M = 51 + +ModInv = 32 +A = 2f +M = 51 + +ModInv = 2b +A = 31 +M = 51 + +ModInv = 2f +A = 32 +M = 51 + +ModInv = 43 +A = 34 +M = 51 + +ModInv = 1a +A = 35 +M = 51 + +ModInv = 1c +A = 37 +M = 51 + +ModInv = 44 +A = 38 +M = 51 + +ModInv = 7 +A = 3a +M = 51 + +ModInv = b +A = 3b +M = 51 + +ModInv = 4 +A = 3d +M = 51 + +ModInv = 11 +A = 3e +M = 51 + +ModInv = 13 +A = 40 +M = 51 + +ModInv = 5 +A = 41 +M = 51 + +ModInv = 34 +A = 43 +M = 51 + +ModInv = 38 +A = 44 +M = 51 + +ModInv = 16 +A = 46 +M = 51 + +ModInv = 8 +A = 47 +M = 51 + +ModInv = a +A = 49 +M = 51 + +ModInv = 17 +A = 4a +M = 51 + +ModInv = 10 +A = 4c +M = 51 + +ModInv = 14 +A = 4d +M = 51 + +ModInv = 28 +A = 4f +M = 51 + +ModInv = 50 +A = 50 +M = 51 + +ModInv = 1 +A = 52 +M = 51 + +ModInv = 29 +A = 53 +M = 51 + +ModInv = 3d +A = 55 +M = 51 + +ModInv = 41 +A = 56 +M = 51 + +ModInv = 3a +A = 58 +M = 51 + +ModInv = 47 +A = 59 +M = 51 + +ModInv = 49 +A = 5b +M = 51 + +ModInv = 3b +A = 5c +M = 51 + +ModInv = 19 +A = 5e +M = 51 + +ModInv = 1d +A = 5f +M = 51 + +ModInv = 4c +A = 61 +M = 51 + +ModInv = 3e +A = 62 +M = 51 + +ModInv = 35 +A = -63 +M = 52 + +ModInv = 47 +A = -61 +M = 52 + +ModInv = 3f +A = -5f +M = 52 + +ModInv = 43 +A = -5d +M = 52 + +ModInv = 9 +A = -5b +M = 52 + +ModInv = 23 +A = -59 +M = 52 + +ModInv = 31 +A = -57 +M = 52 + +ModInv = 1b +A = -55 +M = 52 + +ModInv = 51 +A = -53 +M = 52 + +ModInv = 1 +A = -51 +M = 52 + +ModInv = 37 +A = -4f +M = 52 + +ModInv = 21 +A = -4d +M = 52 + +ModInv = 2f +A = -4b +M = 52 + +ModInv = 49 +A = -49 +M = 52 + +ModInv = f +A = -47 +M = 52 + +ModInv = 13 +A = -45 +M = 52 + +ModInv = b +A = -43 +M = 52 + +ModInv = 1d +A = -41 +M = 52 + +ModInv = d +A = -3f +M = 52 + +ModInv = 2b +A = -3d +M = 52 + +ModInv = 19 +A = -3b +M = 52 + +ModInv = 17 +A = -39 +M = 52 + +ModInv = 4f +A = -37 +M = 52 + +ModInv = 11 +A = -35 +M = 52 + +ModInv = 2d +A = -33 +M = 52 + +ModInv = 5 +A = -31 +M = 52 + +ModInv = 4b +A = -2f +M = 52 + +ModInv = 33 +A = -2d +M = 52 + +ModInv = 3d +A = -2b +M = 52 + +ModInv = 15 +A = -27 +M = 52 + +ModInv = 1f +A = -25 +M = 52 + +ModInv = 7 +A = -23 +M = 52 + +ModInv = 4d +A = -21 +M = 52 + +ModInv = 25 +A = -1f +M = 52 + +ModInv = 41 +A = -1d +M = 52 + +ModInv = 3 +A = -1b +M = 52 + +ModInv = 3b +A = -19 +M = 52 + +ModInv = 39 +A = -17 +M = 52 + +ModInv = 27 +A = -15 +M = 52 + +ModInv = 45 +A = -13 +M = 52 + +ModInv = 35 +A = -11 +M = 52 + +ModInv = 47 +A = -f +M = 52 + +ModInv = 3f +A = -d +M = 52 + +ModInv = 43 +A = -b +M = 52 + +ModInv = 9 +A = -9 +M = 52 + +ModInv = 23 +A = -7 +M = 52 + +ModInv = 31 +A = -5 +M = 52 + +ModInv = 1b +A = -3 +M = 52 + +ModInv = 51 +A = -1 +M = 52 + +ModInv = 1 +A = 1 +M = 52 + +ModInv = 37 +A = 3 +M = 52 + +ModInv = 21 +A = 5 +M = 52 + +ModInv = 2f +A = 7 +M = 52 + +ModInv = 49 +A = 9 +M = 52 + +ModInv = f +A = b +M = 52 + +ModInv = 13 +A = d +M = 52 + +ModInv = b +A = f +M = 52 + +ModInv = 1d +A = 11 +M = 52 + +ModInv = d +A = 13 +M = 52 + +ModInv = 2b +A = 15 +M = 52 + +ModInv = 19 +A = 17 +M = 52 + +ModInv = 17 +A = 19 +M = 52 + +ModInv = 4f +A = 1b +M = 52 + +ModInv = 11 +A = 1d +M = 52 + +ModInv = 2d +A = 1f +M = 52 + +ModInv = 5 +A = 21 +M = 52 + +ModInv = 4b +A = 23 +M = 52 + +ModInv = 33 +A = 25 +M = 52 + +ModInv = 3d +A = 27 +M = 52 + +ModInv = 15 +A = 2b +M = 52 + +ModInv = 1f +A = 2d +M = 52 + +ModInv = 7 +A = 2f +M = 52 + +ModInv = 4d +A = 31 +M = 52 + +ModInv = 25 +A = 33 +M = 52 + +ModInv = 41 +A = 35 +M = 52 + +ModInv = 3 +A = 37 +M = 52 + +ModInv = 3b +A = 39 +M = 52 + +ModInv = 39 +A = 3b +M = 52 + +ModInv = 27 +A = 3d +M = 52 + +ModInv = 45 +A = 3f +M = 52 + +ModInv = 35 +A = 41 +M = 52 + +ModInv = 47 +A = 43 +M = 52 + +ModInv = 3f +A = 45 +M = 52 + +ModInv = 43 +A = 47 +M = 52 + +ModInv = 9 +A = 49 +M = 52 + +ModInv = 23 +A = 4b +M = 52 + +ModInv = 31 +A = 4d +M = 52 + +ModInv = 1b +A = 4f +M = 52 + +ModInv = 51 +A = 51 +M = 52 + +ModInv = 1 +A = 53 +M = 52 + +ModInv = 37 +A = 55 +M = 52 + +ModInv = 21 +A = 57 +M = 52 + +ModInv = 2f +A = 59 +M = 52 + +ModInv = 49 +A = 5b +M = 52 + +ModInv = f +A = 5d +M = 52 + +ModInv = 13 +A = 5f +M = 52 + +ModInv = b +A = 61 +M = 52 + +ModInv = 1d +A = 63 +M = 52 + +ModInv = 27 +A = -64 +M = 53 + +ModInv = 39 +A = -63 +M = 53 + +ModInv = b +A = -62 +M = 53 + +ModInv = 4d +A = -61 +M = 53 + +ModInv = 33 +A = -60 +M = 53 + +ModInv = 4c +A = -5f +M = 53 + +ModInv = f +A = -5e +M = 53 + +ModInv = 3a +A = -5d +M = 53 + +ModInv = 2e +A = -5c +M = 53 + +ModInv = 1f +A = -5b +M = 53 + +ModInv = 47 +A = -5a +M = 53 + +ModInv = 45 +A = -59 +M = 53 + +ModInv = 21 +A = -58 +M = 53 + +ModInv = 3e +A = -57 +M = 53 + +ModInv = 37 +A = -56 +M = 53 + +ModInv = 29 +A = -55 +M = 53 + +ModInv = 52 +A = -54 +M = 53 + +ModInv = 1 +A = -52 +M = 53 + +ModInv = 2a +A = -51 +M = 53 + +ModInv = 1c +A = -50 +M = 53 + +ModInv = 15 +A = -4f +M = 53 + +ModInv = 32 +A = -4e +M = 53 + +ModInv = e +A = -4d +M = 53 + +ModInv = c +A = -4c +M = 53 + +ModInv = 34 +A = -4b +M = 53 + +ModInv = 25 +A = -4a +M = 53 + +ModInv = 19 +A = -49 +M = 53 + +ModInv = 44 +A = -48 +M = 53 + +ModInv = 7 +A = -47 +M = 53 + +ModInv = 20 +A = -46 +M = 53 + +ModInv = 6 +A = -45 +M = 53 + +ModInv = 48 +A = -44 +M = 53 + +ModInv = 1a +A = -43 +M = 53 + +ModInv = 2c +A = -42 +M = 53 + +ModInv = 3c +A = -41 +M = 53 + +ModInv = 23 +A = -40 +M = 53 + +ModInv = 36 +A = -3f +M = 53 + +ModInv = 4 +A = -3e +M = 53 + +ModInv = 22 +A = -3d +M = 53 + +ModInv = 41 +A = -3c +M = 53 + +ModInv = 2d +A = -3b +M = 53 + +ModInv = a +A = -3a +M = 53 + +ModInv = 10 +A = -39 +M = 53 + +ModInv = 28 +A = -38 +M = 53 + +ModInv = 3 +A = -37 +M = 53 + +ModInv = 3f +A = -36 +M = 53 + +ModInv = 24 +A = -35 +M = 53 + +ModInv = 4b +A = -34 +M = 53 + +ModInv = d +A = -33 +M = 53 + +ModInv = 4e +A = -32 +M = 53 + +ModInv = 16 +A = -31 +M = 53 + +ModInv = 13 +A = -30 +M = 53 + +ModInv = 1e +A = -2f +M = 53 + +ModInv = 9 +A = -2e +M = 53 + +ModInv = 3b +A = -2d +M = 53 + +ModInv = 42 +A = -2c +M = 53 + +ModInv = 1b +A = -2b +M = 53 + +ModInv = 51 +A = -2a +M = 53 + +ModInv = 2 +A = -29 +M = 53 + +ModInv = 38 +A = -28 +M = 53 + +ModInv = 11 +A = -27 +M = 53 + +ModInv = 18 +A = -26 +M = 53 + +ModInv = 4a +A = -25 +M = 53 + +ModInv = 35 +A = -24 +M = 53 + +ModInv = 40 +A = -23 +M = 53 + +ModInv = 3d +A = -22 +M = 53 + +ModInv = 5 +A = -21 +M = 53 + +ModInv = 46 +A = -20 +M = 53 + +ModInv = 8 +A = -1f +M = 53 + +ModInv = 2f +A = -1e +M = 53 + +ModInv = 14 +A = -1d +M = 53 + +ModInv = 50 +A = -1c +M = 53 + +ModInv = 2b +A = -1b +M = 53 + +ModInv = 43 +A = -1a +M = 53 + +ModInv = 49 +A = -19 +M = 53 + +ModInv = 26 +A = -18 +M = 53 + +ModInv = 12 +A = -17 +M = 53 + +ModInv = 31 +A = -16 +M = 53 + +ModInv = 4f +A = -15 +M = 53 + +ModInv = 1d +A = -14 +M = 53 + +ModInv = 30 +A = -13 +M = 53 + +ModInv = 17 +A = -12 +M = 53 + +ModInv = 27 +A = -11 +M = 53 + +ModInv = 39 +A = -10 +M = 53 + +ModInv = b +A = -f +M = 53 + +ModInv = 4d +A = -e +M = 53 + +ModInv = 33 +A = -d +M = 53 + +ModInv = 4c +A = -c +M = 53 + +ModInv = f +A = -b +M = 53 + +ModInv = 3a +A = -a +M = 53 + +ModInv = 2e +A = -9 +M = 53 + +ModInv = 1f +A = -8 +M = 53 + +ModInv = 47 +A = -7 +M = 53 + +ModInv = 45 +A = -6 +M = 53 + +ModInv = 21 +A = -5 +M = 53 + +ModInv = 3e +A = -4 +M = 53 + +ModInv = 37 +A = -3 +M = 53 + +ModInv = 29 +A = -2 +M = 53 + +ModInv = 52 +A = -1 +M = 53 + +ModInv = 1 +A = 1 +M = 53 + +ModInv = 2a +A = 2 +M = 53 + +ModInv = 1c +A = 3 +M = 53 + +ModInv = 15 +A = 4 +M = 53 + +ModInv = 32 +A = 5 +M = 53 + +ModInv = e +A = 6 +M = 53 + +ModInv = c +A = 7 +M = 53 + +ModInv = 34 +A = 8 +M = 53 + +ModInv = 25 +A = 9 +M = 53 + +ModInv = 19 +A = a +M = 53 + +ModInv = 44 +A = b +M = 53 + +ModInv = 7 +A = c +M = 53 + +ModInv = 20 +A = d +M = 53 + +ModInv = 6 +A = e +M = 53 + +ModInv = 48 +A = f +M = 53 + +ModInv = 1a +A = 10 +M = 53 + +ModInv = 2c +A = 11 +M = 53 + +ModInv = 3c +A = 12 +M = 53 + +ModInv = 23 +A = 13 +M = 53 + +ModInv = 36 +A = 14 +M = 53 + +ModInv = 4 +A = 15 +M = 53 + +ModInv = 22 +A = 16 +M = 53 + +ModInv = 41 +A = 17 +M = 53 + +ModInv = 2d +A = 18 +M = 53 + +ModInv = a +A = 19 +M = 53 + +ModInv = 10 +A = 1a +M = 53 + +ModInv = 28 +A = 1b +M = 53 + +ModInv = 3 +A = 1c +M = 53 + +ModInv = 3f +A = 1d +M = 53 + +ModInv = 24 +A = 1e +M = 53 + +ModInv = 4b +A = 1f +M = 53 + +ModInv = d +A = 20 +M = 53 + +ModInv = 4e +A = 21 +M = 53 + +ModInv = 16 +A = 22 +M = 53 + +ModInv = 13 +A = 23 +M = 53 + +ModInv = 1e +A = 24 +M = 53 + +ModInv = 9 +A = 25 +M = 53 + +ModInv = 3b +A = 26 +M = 53 + +ModInv = 42 +A = 27 +M = 53 + +ModInv = 1b +A = 28 +M = 53 + +ModInv = 51 +A = 29 +M = 53 + +ModInv = 2 +A = 2a +M = 53 + +ModInv = 38 +A = 2b +M = 53 + +ModInv = 11 +A = 2c +M = 53 + +ModInv = 18 +A = 2d +M = 53 + +ModInv = 4a +A = 2e +M = 53 + +ModInv = 35 +A = 2f +M = 53 + +ModInv = 40 +A = 30 +M = 53 + +ModInv = 3d +A = 31 +M = 53 + +ModInv = 5 +A = 32 +M = 53 + +ModInv = 46 +A = 33 +M = 53 + +ModInv = 8 +A = 34 +M = 53 + +ModInv = 2f +A = 35 +M = 53 + +ModInv = 14 +A = 36 +M = 53 + +ModInv = 50 +A = 37 +M = 53 + +ModInv = 2b +A = 38 +M = 53 + +ModInv = 43 +A = 39 +M = 53 + +ModInv = 49 +A = 3a +M = 53 + +ModInv = 26 +A = 3b +M = 53 + +ModInv = 12 +A = 3c +M = 53 + +ModInv = 31 +A = 3d +M = 53 + +ModInv = 4f +A = 3e +M = 53 + +ModInv = 1d +A = 3f +M = 53 + +ModInv = 30 +A = 40 +M = 53 + +ModInv = 17 +A = 41 +M = 53 + +ModInv = 27 +A = 42 +M = 53 + +ModInv = 39 +A = 43 +M = 53 + +ModInv = b +A = 44 +M = 53 + +ModInv = 4d +A = 45 +M = 53 + +ModInv = 33 +A = 46 +M = 53 + +ModInv = 4c +A = 47 +M = 53 + +ModInv = f +A = 48 +M = 53 + +ModInv = 3a +A = 49 +M = 53 + +ModInv = 2e +A = 4a +M = 53 + +ModInv = 1f +A = 4b +M = 53 + +ModInv = 47 +A = 4c +M = 53 + +ModInv = 45 +A = 4d +M = 53 + +ModInv = 21 +A = 4e +M = 53 + +ModInv = 3e +A = 4f +M = 53 + +ModInv = 37 +A = 50 +M = 53 + +ModInv = 29 +A = 51 +M = 53 + +ModInv = 52 +A = 52 +M = 53 + +ModInv = 1 +A = 54 +M = 53 + +ModInv = 2a +A = 55 +M = 53 + +ModInv = 1c +A = 56 +M = 53 + +ModInv = 15 +A = 57 +M = 53 + +ModInv = 32 +A = 58 +M = 53 + +ModInv = e +A = 59 +M = 53 + +ModInv = c +A = 5a +M = 53 + +ModInv = 34 +A = 5b +M = 53 + +ModInv = 25 +A = 5c +M = 53 + +ModInv = 19 +A = 5d +M = 53 + +ModInv = 44 +A = 5e +M = 53 + +ModInv = 7 +A = 5f +M = 53 + +ModInv = 20 +A = 60 +M = 53 + +ModInv = 6 +A = 61 +M = 53 + +ModInv = 48 +A = 62 +M = 53 + +ModInv = 1a +A = 63 +M = 53 + +ModInv = 47 +A = -61 +M = 54 + +ModInv = 3d +A = -5f +M = 54 + +ModInv = 43 +A = -59 +M = 54 + +ModInv = 53 +A = -55 +M = 54 + +ModInv = 1 +A = -53 +M = 54 + +ModInv = 11 +A = -4f +M = 54 + +ModInv = 17 +A = -49 +M = 54 + +ModInv = d +A = -47 +M = 54 + +ModInv = 5 +A = -43 +M = 54 + +ModInv = 1f +A = -41 +M = 54 + +ModInv = b +A = -3d +M = 54 + +ModInv = 25 +A = -3b +M = 54 + +ModInv = 1d +A = -37 +M = 54 + +ModInv = 13 +A = -35 +M = 54 + +ModInv = 19 +A = -2f +M = 54 + +ModInv = 29 +A = -2b +M = 54 + +ModInv = 2b +A = -29 +M = 54 + +ModInv = 3b +A = -25 +M = 54 + +ModInv = 41 +A = -1f +M = 54 + +ModInv = 37 +A = -1d +M = 54 + +ModInv = 2f +A = -19 +M = 54 + +ModInv = 49 +A = -17 +M = 54 + +ModInv = 35 +A = -13 +M = 54 + +ModInv = 4f +A = -11 +M = 54 + +ModInv = 47 +A = -d +M = 54 + +ModInv = 3d +A = -b +M = 54 + +ModInv = 43 +A = -5 +M = 54 + +ModInv = 53 +A = -1 +M = 54 + +ModInv = 1 +A = 1 +M = 54 + +ModInv = 11 +A = 5 +M = 54 + +ModInv = 17 +A = b +M = 54 + +ModInv = d +A = d +M = 54 + +ModInv = 5 +A = 11 +M = 54 + +ModInv = 1f +A = 13 +M = 54 + +ModInv = b +A = 17 +M = 54 + +ModInv = 25 +A = 19 +M = 54 + +ModInv = 1d +A = 1d +M = 54 + +ModInv = 13 +A = 1f +M = 54 + +ModInv = 19 +A = 25 +M = 54 + +ModInv = 29 +A = 29 +M = 54 + +ModInv = 2b +A = 2b +M = 54 + +ModInv = 3b +A = 2f +M = 54 + +ModInv = 41 +A = 35 +M = 54 + +ModInv = 37 +A = 37 +M = 54 + +ModInv = 2f +A = 3b +M = 54 + +ModInv = 49 +A = 3d +M = 54 + +ModInv = 35 +A = 41 +M = 54 + +ModInv = 4f +A = 43 +M = 54 + +ModInv = 47 +A = 47 +M = 54 + +ModInv = 3d +A = 49 +M = 54 + +ModInv = 43 +A = 4f +M = 54 + +ModInv = 53 +A = 53 +M = 54 + +ModInv = 1 +A = 55 +M = 54 + +ModInv = 11 +A = 59 +M = 54 + +ModInv = 17 +A = 5f +M = 54 + +ModInv = d +A = 61 +M = 54 + +ModInv = 6 +A = -63 +M = 55 + +ModInv = d +A = -62 +M = 55 + +ModInv = 7 +A = -61 +M = 55 + +ModInv = 36 +A = -60 +M = 55 + +ModInv = 42 +A = -5e +M = 55 + +ModInv = 35 +A = -5d +M = 55 + +ModInv = c +A = -5c +M = 55 + +ModInv = e +A = -5b +M = 55 + +ModInv = 15 +A = -59 +M = 55 + +ModInv = 1c +A = -58 +M = 55 + +ModInv = 2a +A = -57 +M = 55 + +ModInv = 54 +A = -56 +M = 55 + +ModInv = 1 +A = -54 +M = 55 + +ModInv = 2b +A = -53 +M = 55 + +ModInv = 39 +A = -52 +M = 55 + +ModInv = 40 +A = -51 +M = 55 + +ModInv = 47 +A = -4f +M = 55 + +ModInv = 49 +A = -4e +M = 55 + +ModInv = 20 +A = -4d +M = 55 + +ModInv = 13 +A = -4c +M = 55 + +ModInv = 1f +A = -4a +M = 55 + +ModInv = 4e +A = -49 +M = 55 + +ModInv = 48 +A = -48 +M = 55 + +ModInv = 4f +A = -47 +M = 55 + +ModInv = 10 +A = -45 +M = 55 + +ModInv = 34 +A = -43 +M = 55 + +ModInv = 9 +A = -42 +M = 55 + +ModInv = 51 +A = -40 +M = 55 + +ModInv = 3a +A = -3f +M = 55 + +ModInv = 25 +A = -3e +M = 55 + +ModInv = 27 +A = -3d +M = 55 + +ModInv = 24 +A = -3b +M = 55 + +ModInv = 3f +A = -3a +M = 55 + +ModInv = 52 +A = -39 +M = 55 + +ModInv = 2c +A = -38 +M = 55 + +ModInv = b +A = -36 +M = 55 + +ModInv = 8 +A = -35 +M = 55 + +ModInv = 43 +A = -34 +M = 55 + +ModInv = 1a +A = -31 +M = 55 + +ModInv = 17 +A = -30 +M = 55 + +ModInv = 2f +A = -2f +M = 55 + +ModInv = 18 +A = -2e +M = 55 + +ModInv = 38 +A = -2c +M = 55 + +ModInv = 53 +A = -2b +M = 55 + +ModInv = 2 +A = -2a +M = 55 + +ModInv = 1d +A = -29 +M = 55 + +ModInv = 3d +A = -27 +M = 55 + +ModInv = 26 +A = -26 +M = 55 + +ModInv = 3e +A = -25 +M = 55 + +ModInv = 3b +A = -24 +M = 55 + +ModInv = 12 +A = -21 +M = 55 + +ModInv = 4d +A = -20 +M = 55 + +ModInv = 4a +A = -1f +M = 55 + +ModInv = 29 +A = -1d +M = 55 + +ModInv = 3 +A = -1c +M = 55 + +ModInv = 16 +A = -1b +M = 55 + +ModInv = 31 +A = -1a +M = 55 + +ModInv = 2e +A = -18 +M = 55 + +ModInv = 30 +A = -17 +M = 55 + +ModInv = 1b +A = -16 +M = 55 + +ModInv = 4 +A = -15 +M = 55 + +ModInv = 4c +A = -13 +M = 55 + +ModInv = 21 +A = -12 +M = 55 + +ModInv = 45 +A = -10 +M = 55 + +ModInv = 6 +A = -e +M = 55 + +ModInv = d +A = -d +M = 55 + +ModInv = 7 +A = -c +M = 55 + +ModInv = 36 +A = -b +M = 55 + +ModInv = 42 +A = -9 +M = 55 + +ModInv = 35 +A = -8 +M = 55 + +ModInv = c +A = -7 +M = 55 + +ModInv = e +A = -6 +M = 55 + +ModInv = 15 +A = -4 +M = 55 + +ModInv = 1c +A = -3 +M = 55 + +ModInv = 2a +A = -2 +M = 55 + +ModInv = 54 +A = -1 +M = 55 + +ModInv = 1 +A = 1 +M = 55 + +ModInv = 2b +A = 2 +M = 55 + +ModInv = 39 +A = 3 +M = 55 + +ModInv = 40 +A = 4 +M = 55 + +ModInv = 47 +A = 6 +M = 55 + +ModInv = 49 +A = 7 +M = 55 + +ModInv = 20 +A = 8 +M = 55 + +ModInv = 13 +A = 9 +M = 55 + +ModInv = 1f +A = b +M = 55 + +ModInv = 4e +A = c +M = 55 + +ModInv = 48 +A = d +M = 55 + +ModInv = 4f +A = e +M = 55 + +ModInv = 10 +A = 10 +M = 55 + +ModInv = 34 +A = 12 +M = 55 + +ModInv = 9 +A = 13 +M = 55 + +ModInv = 51 +A = 15 +M = 55 + +ModInv = 3a +A = 16 +M = 55 + +ModInv = 25 +A = 17 +M = 55 + +ModInv = 27 +A = 18 +M = 55 + +ModInv = 24 +A = 1a +M = 55 + +ModInv = 3f +A = 1b +M = 55 + +ModInv = 52 +A = 1c +M = 55 + +ModInv = 2c +A = 1d +M = 55 + +ModInv = b +A = 1f +M = 55 + +ModInv = 8 +A = 20 +M = 55 + +ModInv = 43 +A = 21 +M = 55 + +ModInv = 1a +A = 24 +M = 55 + +ModInv = 17 +A = 25 +M = 55 + +ModInv = 2f +A = 26 +M = 55 + +ModInv = 18 +A = 27 +M = 55 + +ModInv = 38 +A = 29 +M = 55 + +ModInv = 53 +A = 2a +M = 55 + +ModInv = 2 +A = 2b +M = 55 + +ModInv = 1d +A = 2c +M = 55 + +ModInv = 3d +A = 2e +M = 55 + +ModInv = 26 +A = 2f +M = 55 + +ModInv = 3e +A = 30 +M = 55 + +ModInv = 3b +A = 31 +M = 55 + +ModInv = 12 +A = 34 +M = 55 + +ModInv = 4d +A = 35 +M = 55 + +ModInv = 4a +A = 36 +M = 55 + +ModInv = 29 +A = 38 +M = 55 + +ModInv = 3 +A = 39 +M = 55 + +ModInv = 16 +A = 3a +M = 55 + +ModInv = 31 +A = 3b +M = 55 + +ModInv = 2e +A = 3d +M = 55 + +ModInv = 30 +A = 3e +M = 55 + +ModInv = 1b +A = 3f +M = 55 + +ModInv = 4 +A = 40 +M = 55 + +ModInv = 4c +A = 42 +M = 55 + +ModInv = 21 +A = 43 +M = 55 + +ModInv = 45 +A = 45 +M = 55 + +ModInv = 6 +A = 47 +M = 55 + +ModInv = d +A = 48 +M = 55 + +ModInv = 7 +A = 49 +M = 55 + +ModInv = 36 +A = 4a +M = 55 + +ModInv = 42 +A = 4c +M = 55 + +ModInv = 35 +A = 4d +M = 55 + +ModInv = c +A = 4e +M = 55 + +ModInv = e +A = 4f +M = 55 + +ModInv = 15 +A = 51 +M = 55 + +ModInv = 1c +A = 52 +M = 55 + +ModInv = 2a +A = 53 +M = 55 + +ModInv = 54 +A = 54 +M = 55 + +ModInv = 1 +A = 56 +M = 55 + +ModInv = 2b +A = 57 +M = 55 + +ModInv = 39 +A = 58 +M = 55 + +ModInv = 40 +A = 59 +M = 55 + +ModInv = 47 +A = 5b +M = 55 + +ModInv = 49 +A = 5c +M = 55 + +ModInv = 20 +A = 5d +M = 55 + +ModInv = 13 +A = 5e +M = 55 + +ModInv = 1f +A = 60 +M = 55 + +ModInv = 4e +A = 61 +M = 55 + +ModInv = 48 +A = 62 +M = 55 + +ModInv = 4f +A = 63 +M = 55 + +ModInv = 21 +A = -63 +M = 56 + +ModInv = 27 +A = -61 +M = 56 + +ModInv = 13 +A = -5f +M = 56 + +ModInv = 31 +A = -5d +M = 56 + +ModInv = 11 +A = -5b +M = 56 + +ModInv = 39 +A = -59 +M = 56 + +ModInv = 55 +A = -57 +M = 56 + +ModInv = 1 +A = -55 +M = 56 + +ModInv = 1d +A = -53 +M = 56 + +ModInv = 45 +A = -51 +M = 56 + +ModInv = 25 +A = -4f +M = 56 + +ModInv = 43 +A = -4d +M = 56 + +ModInv = 2f +A = -4b +M = 56 + +ModInv = 35 +A = -49 +M = 56 + +ModInv = 17 +A = -47 +M = 56 + +ModInv = 51 +A = -45 +M = 56 + +ModInv = 4d +A = -43 +M = 56 + +ModInv = 29 +A = -41 +M = 56 + +ModInv = f +A = -3f +M = 56 + +ModInv = 1f +A = -3d +M = 56 + +ModInv = 33 +A = -3b +M = 56 + +ModInv = 3 +A = -39 +M = 56 + +ModInv = 19 +A = -37 +M = 56 + +ModInv = 49 +A = -35 +M = 56 + +ModInv = 3b +A = -33 +M = 56 + +ModInv = 7 +A = -31 +M = 56 + +ModInv = 4b +A = -2f +M = 56 + +ModInv = 15 +A = -2d +M = 56 + +ModInv = 41 +A = -29 +M = 56 + +ModInv = b +A = -27 +M = 56 + +ModInv = 4f +A = -25 +M = 56 + +ModInv = 1b +A = -23 +M = 56 + +ModInv = d +A = -21 +M = 56 + +ModInv = 3d +A = -1f +M = 56 + +ModInv = 53 +A = -1d +M = 56 + +ModInv = 23 +A = -1b +M = 56 + +ModInv = 37 +A = -19 +M = 56 + +ModInv = 47 +A = -17 +M = 56 + +ModInv = 2d +A = -15 +M = 56 + +ModInv = 9 +A = -13 +M = 56 + +ModInv = 5 +A = -11 +M = 56 + +ModInv = 3f +A = -f +M = 56 + +ModInv = 21 +A = -d +M = 56 + +ModInv = 27 +A = -b +M = 56 + +ModInv = 13 +A = -9 +M = 56 + +ModInv = 31 +A = -7 +M = 56 + +ModInv = 11 +A = -5 +M = 56 + +ModInv = 39 +A = -3 +M = 56 + +ModInv = 55 +A = -1 +M = 56 + +ModInv = 1 +A = 1 +M = 56 + +ModInv = 1d +A = 3 +M = 56 + +ModInv = 45 +A = 5 +M = 56 + +ModInv = 25 +A = 7 +M = 56 + +ModInv = 43 +A = 9 +M = 56 + +ModInv = 2f +A = b +M = 56 + +ModInv = 35 +A = d +M = 56 + +ModInv = 17 +A = f +M = 56 + +ModInv = 51 +A = 11 +M = 56 + +ModInv = 4d +A = 13 +M = 56 + +ModInv = 29 +A = 15 +M = 56 + +ModInv = f +A = 17 +M = 56 + +ModInv = 1f +A = 19 +M = 56 + +ModInv = 33 +A = 1b +M = 56 + +ModInv = 3 +A = 1d +M = 56 + +ModInv = 19 +A = 1f +M = 56 + +ModInv = 49 +A = 21 +M = 56 + +ModInv = 3b +A = 23 +M = 56 + +ModInv = 7 +A = 25 +M = 56 + +ModInv = 4b +A = 27 +M = 56 + +ModInv = 15 +A = 29 +M = 56 + +ModInv = 41 +A = 2d +M = 56 + +ModInv = b +A = 2f +M = 56 + +ModInv = 4f +A = 31 +M = 56 + +ModInv = 1b +A = 33 +M = 56 + +ModInv = d +A = 35 +M = 56 + +ModInv = 3d +A = 37 +M = 56 + +ModInv = 53 +A = 39 +M = 56 + +ModInv = 23 +A = 3b +M = 56 + +ModInv = 37 +A = 3d +M = 56 + +ModInv = 47 +A = 3f +M = 56 + +ModInv = 2d +A = 41 +M = 56 + +ModInv = 9 +A = 43 +M = 56 + +ModInv = 5 +A = 45 +M = 56 + +ModInv = 3f +A = 47 +M = 56 + +ModInv = 21 +A = 49 +M = 56 + +ModInv = 27 +A = 4b +M = 56 + +ModInv = 13 +A = 4d +M = 56 + +ModInv = 31 +A = 4f +M = 56 + +ModInv = 11 +A = 51 +M = 56 + +ModInv = 39 +A = 53 +M = 56 + +ModInv = 55 +A = 55 +M = 56 + +ModInv = 1 +A = 57 +M = 56 + +ModInv = 1d +A = 59 +M = 56 + +ModInv = 45 +A = 5b +M = 56 + +ModInv = 25 +A = 5d +M = 56 + +ModInv = 43 +A = 5f +M = 56 + +ModInv = 2f +A = 61 +M = 56 + +ModInv = 35 +A = 63 +M = 56 + +ModInv = 14 +A = -64 +M = 57 + +ModInv = 4f +A = -62 +M = 57 + +ModInv = 1a +A = -61 +M = 57 + +ModInv = 4c +A = -5f +M = 57 + +ModInv = 3e +A = -5e +M = 57 + +ModInv = 34 +A = -5c +M = 57 + +ModInv = 41 +A = -5b +M = 57 + +ModInv = 2b +A = -59 +M = 57 + +ModInv = 56 +A = -58 +M = 57 + +ModInv = 1 +A = -56 +M = 57 + +ModInv = 2c +A = -55 +M = 57 + +ModInv = 16 +A = -53 +M = 57 + +ModInv = 23 +A = -52 +M = 57 + +ModInv = 19 +A = -50 +M = 57 + +ModInv = b +A = -4f +M = 57 + +ModInv = 3d +A = -4d +M = 57 + +ModInv = 8 +A = -4c +M = 57 + +ModInv = 43 +A = -4a +M = 57 + +ModInv = 38 +A = -49 +M = 57 + +ModInv = 31 +A = -47 +M = 57 + +ModInv = 29 +A = -46 +M = 57 + +ModInv = 37 +A = -44 +M = 57 + +ModInv = 4a +A = -43 +M = 57 + +ModInv = 4 +A = -41 +M = 57 + +ModInv = 35 +A = -40 +M = 57 + +ModInv = 7 +A = -3e +M = 57 + +ModInv = 4d +A = -3d +M = 57 + +ModInv = 1c +A = -3b +M = 57 + +ModInv = 49 +A = -38 +M = 57 + +ModInv = 44 +A = -37 +M = 57 + +ModInv = 40 +A = -35 +M = 57 + +ModInv = 5 +A = -34 +M = 57 + +ModInv = 28 +A = -32 +M = 57 + +ModInv = 47 +A = -31 +M = 57 + +ModInv = 25 +A = -2f +M = 57 + +ModInv = 11 +A = -2e +M = 57 + +ModInv = 55 +A = -2c +M = 57 + +ModInv = 2 +A = -2b +M = 57 + +ModInv = 46 +A = -29 +M = 57 + +ModInv = 32 +A = -28 +M = 57 + +ModInv = 10 +A = -26 +M = 57 + +ModInv = 2f +A = -25 +M = 57 + +ModInv = 52 +A = -23 +M = 57 + +ModInv = 17 +A = -22 +M = 57 + +ModInv = 13 +A = -20 +M = 57 + +ModInv = e +A = -1f +M = 57 + +ModInv = 3b +A = -1c +M = 57 + +ModInv = a +A = -1a +M = 57 + +ModInv = 50 +A = -19 +M = 57 + +ModInv = 22 +A = -17 +M = 57 + +ModInv = 53 +A = -16 +M = 57 + +ModInv = d +A = -14 +M = 57 + +ModInv = 20 +A = -13 +M = 57 + +ModInv = 2e +A = -11 +M = 57 + +ModInv = 26 +A = -10 +M = 57 + +ModInv = 1f +A = -e +M = 57 + +ModInv = 14 +A = -d +M = 57 + +ModInv = 4f +A = -b +M = 57 + +ModInv = 1a +A = -a +M = 57 + +ModInv = 4c +A = -8 +M = 57 + +ModInv = 3e +A = -7 +M = 57 + +ModInv = 34 +A = -5 +M = 57 + +ModInv = 41 +A = -4 +M = 57 + +ModInv = 2b +A = -2 +M = 57 + +ModInv = 56 +A = -1 +M = 57 + +ModInv = 1 +A = 1 +M = 57 + +ModInv = 2c +A = 2 +M = 57 + +ModInv = 16 +A = 4 +M = 57 + +ModInv = 23 +A = 5 +M = 57 + +ModInv = 19 +A = 7 +M = 57 + +ModInv = b +A = 8 +M = 57 + +ModInv = 3d +A = a +M = 57 + +ModInv = 8 +A = b +M = 57 + +ModInv = 43 +A = d +M = 57 + +ModInv = 38 +A = e +M = 57 + +ModInv = 31 +A = 10 +M = 57 + +ModInv = 29 +A = 11 +M = 57 + +ModInv = 37 +A = 13 +M = 57 + +ModInv = 4a +A = 14 +M = 57 + +ModInv = 4 +A = 16 +M = 57 + +ModInv = 35 +A = 17 +M = 57 + +ModInv = 7 +A = 19 +M = 57 + +ModInv = 4d +A = 1a +M = 57 + +ModInv = 1c +A = 1c +M = 57 + +ModInv = 49 +A = 1f +M = 57 + +ModInv = 44 +A = 20 +M = 57 + +ModInv = 40 +A = 22 +M = 57 + +ModInv = 5 +A = 23 +M = 57 + +ModInv = 28 +A = 25 +M = 57 + +ModInv = 47 +A = 26 +M = 57 + +ModInv = 25 +A = 28 +M = 57 + +ModInv = 11 +A = 29 +M = 57 + +ModInv = 55 +A = 2b +M = 57 + +ModInv = 2 +A = 2c +M = 57 + +ModInv = 46 +A = 2e +M = 57 + +ModInv = 32 +A = 2f +M = 57 + +ModInv = 10 +A = 31 +M = 57 + +ModInv = 2f +A = 32 +M = 57 + +ModInv = 52 +A = 34 +M = 57 + +ModInv = 17 +A = 35 +M = 57 + +ModInv = 13 +A = 37 +M = 57 + +ModInv = e +A = 38 +M = 57 + +ModInv = 3b +A = 3b +M = 57 + +ModInv = a +A = 3d +M = 57 + +ModInv = 50 +A = 3e +M = 57 + +ModInv = 22 +A = 40 +M = 57 + +ModInv = 53 +A = 41 +M = 57 + +ModInv = d +A = 43 +M = 57 + +ModInv = 20 +A = 44 +M = 57 + +ModInv = 2e +A = 46 +M = 57 + +ModInv = 26 +A = 47 +M = 57 + +ModInv = 1f +A = 49 +M = 57 + +ModInv = 14 +A = 4a +M = 57 + +ModInv = 4f +A = 4c +M = 57 + +ModInv = 1a +A = 4d +M = 57 + +ModInv = 4c +A = 4f +M = 57 + +ModInv = 3e +A = 50 +M = 57 + +ModInv = 34 +A = 52 +M = 57 + +ModInv = 41 +A = 53 +M = 57 + +ModInv = 2b +A = 55 +M = 57 + +ModInv = 56 +A = 56 +M = 57 + +ModInv = 1 +A = 58 +M = 57 + +ModInv = 2c +A = 59 +M = 57 + +ModInv = 16 +A = 5b +M = 57 + +ModInv = 23 +A = 5c +M = 57 + +ModInv = 19 +A = 5e +M = 57 + +ModInv = b +A = 5f +M = 57 + +ModInv = 3d +A = 61 +M = 57 + +ModInv = 8 +A = 62 +M = 57 + +ModInv = 27 +A = -61 +M = 58 + +ModInv = 19 +A = -5f +M = 58 + +ModInv = 23 +A = -5d +M = 58 + +ModInv = 1d +A = -5b +M = 58 + +ModInv = 57 +A = -59 +M = 58 + +ModInv = 1 +A = -57 +M = 58 + +ModInv = 3b +A = -55 +M = 58 + +ModInv = 35 +A = -53 +M = 58 + +ModInv = 3f +A = -51 +M = 58 + +ModInv = 31 +A = -4f +M = 58 + +ModInv = 3d +A = -4b +M = 58 + +ModInv = 2f +A = -49 +M = 58 + +ModInv = 39 +A = -47 +M = 58 + +ModInv = 33 +A = -45 +M = 58 + +ModInv = 15 +A = -43 +M = 58 + +ModInv = 17 +A = -41 +M = 58 + +ModInv = 51 +A = -3f +M = 58 + +ModInv = 4b +A = -3d +M = 58 + +ModInv = 55 +A = -3b +M = 58 + +ModInv = 47 +A = -39 +M = 58 + +ModInv = 53 +A = -35 +M = 58 + +ModInv = 45 +A = -33 +M = 58 + +ModInv = 4f +A = -31 +M = 58 + +ModInv = 49 +A = -2f +M = 58 + +ModInv = 2b +A = -2d +M = 58 + +ModInv = 2d +A = -2b +M = 58 + +ModInv = f +A = -29 +M = 58 + +ModInv = 9 +A = -27 +M = 58 + +ModInv = 13 +A = -25 +M = 58 + +ModInv = 5 +A = -23 +M = 58 + +ModInv = 11 +A = -1f +M = 58 + +ModInv = 3 +A = -1d +M = 58 + +ModInv = d +A = -1b +M = 58 + +ModInv = 7 +A = -19 +M = 58 + +ModInv = 41 +A = -17 +M = 58 + +ModInv = 43 +A = -15 +M = 58 + +ModInv = 25 +A = -13 +M = 58 + +ModInv = 1f +A = -11 +M = 58 + +ModInv = 29 +A = -f +M = 58 + +ModInv = 1b +A = -d +M = 58 + +ModInv = 27 +A = -9 +M = 58 + +ModInv = 19 +A = -7 +M = 58 + +ModInv = 23 +A = -5 +M = 58 + +ModInv = 1d +A = -3 +M = 58 + +ModInv = 57 +A = -1 +M = 58 + +ModInv = 1 +A = 1 +M = 58 + +ModInv = 3b +A = 3 +M = 58 + +ModInv = 35 +A = 5 +M = 58 + +ModInv = 3f +A = 7 +M = 58 + +ModInv = 31 +A = 9 +M = 58 + +ModInv = 3d +A = d +M = 58 + +ModInv = 2f +A = f +M = 58 + +ModInv = 39 +A = 11 +M = 58 + +ModInv = 33 +A = 13 +M = 58 + +ModInv = 15 +A = 15 +M = 58 + +ModInv = 17 +A = 17 +M = 58 + +ModInv = 51 +A = 19 +M = 58 + +ModInv = 4b +A = 1b +M = 58 + +ModInv = 55 +A = 1d +M = 58 + +ModInv = 47 +A = 1f +M = 58 + +ModInv = 53 +A = 23 +M = 58 + +ModInv = 45 +A = 25 +M = 58 + +ModInv = 4f +A = 27 +M = 58 + +ModInv = 49 +A = 29 +M = 58 + +ModInv = 2b +A = 2b +M = 58 + +ModInv = 2d +A = 2d +M = 58 + +ModInv = f +A = 2f +M = 58 + +ModInv = 9 +A = 31 +M = 58 + +ModInv = 13 +A = 33 +M = 58 + +ModInv = 5 +A = 35 +M = 58 + +ModInv = 11 +A = 39 +M = 58 + +ModInv = 3 +A = 3b +M = 58 + +ModInv = d +A = 3d +M = 58 + +ModInv = 7 +A = 3f +M = 58 + +ModInv = 41 +A = 41 +M = 58 + +ModInv = 43 +A = 43 +M = 58 + +ModInv = 25 +A = 45 +M = 58 + +ModInv = 1f +A = 47 +M = 58 + +ModInv = 29 +A = 49 +M = 58 + +ModInv = 1b +A = 4b +M = 58 + +ModInv = 27 +A = 4f +M = 58 + +ModInv = 19 +A = 51 +M = 58 + +ModInv = 23 +A = 53 +M = 58 + +ModInv = 1d +A = 55 +M = 58 + +ModInv = 57 +A = 57 +M = 58 + +ModInv = 1 +A = 59 +M = 58 + +ModInv = 3b +A = 5b +M = 58 + +ModInv = 35 +A = 5d +M = 58 + +ModInv = 3f +A = 5f +M = 58 + +ModInv = 31 +A = 61 +M = 58 + +ModInv = 8 +A = -64 +M = 59 + +ModInv = 50 +A = -63 +M = 59 + +ModInv = 4f +A = -62 +M = 59 + +ModInv = b +A = -61 +M = 59 + +ModInv = 26 +A = -60 +M = 59 + +ModInv = 4a +A = -5f +M = 59 + +ModInv = 47 +A = -5e +M = 59 + +ModInv = 16 +A = -5d +M = 59 + +ModInv = 3b +A = -5c +M = 59 + +ModInv = 2c +A = -5b +M = 59 + +ModInv = 58 +A = -5a +M = 59 + +ModInv = 1 +A = -58 +M = 59 + +ModInv = 2d +A = -57 +M = 59 + +ModInv = 1e +A = -56 +M = 59 + +ModInv = 43 +A = -55 +M = 59 + +ModInv = 12 +A = -54 +M = 59 + +ModInv = f +A = -53 +M = 59 + +ModInv = 33 +A = -52 +M = 59 + +ModInv = 4e +A = -51 +M = 59 + +ModInv = a +A = -50 +M = 59 + +ModInv = 9 +A = -4f +M = 59 + +ModInv = 51 +A = -4e +M = 59 + +ModInv = 34 +A = -4d +M = 59 + +ModInv = 30 +A = -4c +M = 59 + +ModInv = 46 +A = -4b +M = 59 + +ModInv = 6 +A = -4a +M = 59 + +ModInv = 27 +A = -49 +M = 59 + +ModInv = 15 +A = -48 +M = 59 + +ModInv = 5 +A = -47 +M = 59 + +ModInv = 4b +A = -46 +M = 59 + +ModInv = 31 +A = -45 +M = 59 + +ModInv = 11 +A = -44 +M = 59 + +ModInv = 55 +A = -43 +M = 59 + +ModInv = 1f +A = -42 +M = 59 + +ModInv = 1a +A = -41 +M = 59 + +ModInv = 39 +A = -40 +M = 59 + +ModInv = 18 +A = -3f +M = 59 + +ModInv = 21 +A = -3e +M = 59 + +ModInv = 23 +A = -3d +M = 59 + +ModInv = 2b +A = -3c +M = 59 + +ModInv = 3 +A = -3b +M = 59 + +ModInv = 17 +A = -3a +M = 59 + +ModInv = 40 +A = -39 +M = 59 + +ModInv = 1b +A = -38 +M = 59 + +ModInv = 37 +A = -37 +M = 59 + +ModInv = 1c +A = -36 +M = 59 + +ModInv = 2f +A = -35 +M = 59 + +ModInv = 4d +A = -34 +M = 59 + +ModInv = 52 +A = -33 +M = 59 + +ModInv = 10 +A = -32 +M = 59 + +ModInv = 45 +A = -31 +M = 59 + +ModInv = 4c +A = -30 +M = 59 + +ModInv = 35 +A = -2f +M = 59 + +ModInv = 1d +A = -2e +M = 59 + +ModInv = 57 +A = -2d +M = 59 + +ModInv = 2 +A = -2c +M = 59 + +ModInv = 3c +A = -2b +M = 59 + +ModInv = 24 +A = -2a +M = 59 + +ModInv = d +A = -29 +M = 59 + +ModInv = 14 +A = -28 +M = 59 + +ModInv = 49 +A = -27 +M = 59 + +ModInv = 7 +A = -26 +M = 59 + +ModInv = c +A = -25 +M = 59 + +ModInv = 2a +A = -24 +M = 59 + +ModInv = 3d +A = -23 +M = 59 + +ModInv = 22 +A = -22 +M = 59 + +ModInv = 3e +A = -21 +M = 59 + +ModInv = 19 +A = -20 +M = 59 + +ModInv = 42 +A = -1f +M = 59 + +ModInv = 56 +A = -1e +M = 59 + +ModInv = 2e +A = -1d +M = 59 + +ModInv = 36 +A = -1c +M = 59 + +ModInv = 38 +A = -1b +M = 59 + +ModInv = 41 +A = -1a +M = 59 + +ModInv = 20 +A = -19 +M = 59 + +ModInv = 3f +A = -18 +M = 59 + +ModInv = 3a +A = -17 +M = 59 + +ModInv = 4 +A = -16 +M = 59 + +ModInv = 48 +A = -15 +M = 59 + +ModInv = 28 +A = -14 +M = 59 + +ModInv = e +A = -13 +M = 59 + +ModInv = 54 +A = -12 +M = 59 + +ModInv = 44 +A = -11 +M = 59 + +ModInv = 32 +A = -10 +M = 59 + +ModInv = 53 +A = -f +M = 59 + +ModInv = 13 +A = -e +M = 59 + +ModInv = 29 +A = -d +M = 59 + +ModInv = 25 +A = -c +M = 59 + +ModInv = 8 +A = -b +M = 59 + +ModInv = 50 +A = -a +M = 59 + +ModInv = 4f +A = -9 +M = 59 + +ModInv = b +A = -8 +M = 59 + +ModInv = 26 +A = -7 +M = 59 + +ModInv = 4a +A = -6 +M = 59 + +ModInv = 47 +A = -5 +M = 59 + +ModInv = 16 +A = -4 +M = 59 + +ModInv = 3b +A = -3 +M = 59 + +ModInv = 2c +A = -2 +M = 59 + +ModInv = 58 +A = -1 +M = 59 + +ModInv = 1 +A = 1 +M = 59 + +ModInv = 2d +A = 2 +M = 59 + +ModInv = 1e +A = 3 +M = 59 + +ModInv = 43 +A = 4 +M = 59 + +ModInv = 12 +A = 5 +M = 59 + +ModInv = f +A = 6 +M = 59 + +ModInv = 33 +A = 7 +M = 59 + +ModInv = 4e +A = 8 +M = 59 + +ModInv = a +A = 9 +M = 59 + +ModInv = 9 +A = a +M = 59 + +ModInv = 51 +A = b +M = 59 + +ModInv = 34 +A = c +M = 59 + +ModInv = 30 +A = d +M = 59 + +ModInv = 46 +A = e +M = 59 + +ModInv = 6 +A = f +M = 59 + +ModInv = 27 +A = 10 +M = 59 + +ModInv = 15 +A = 11 +M = 59 + +ModInv = 5 +A = 12 +M = 59 + +ModInv = 4b +A = 13 +M = 59 + +ModInv = 31 +A = 14 +M = 59 + +ModInv = 11 +A = 15 +M = 59 + +ModInv = 55 +A = 16 +M = 59 + +ModInv = 1f +A = 17 +M = 59 + +ModInv = 1a +A = 18 +M = 59 + +ModInv = 39 +A = 19 +M = 59 + +ModInv = 18 +A = 1a +M = 59 + +ModInv = 21 +A = 1b +M = 59 + +ModInv = 23 +A = 1c +M = 59 + +ModInv = 2b +A = 1d +M = 59 + +ModInv = 3 +A = 1e +M = 59 + +ModInv = 17 +A = 1f +M = 59 + +ModInv = 40 +A = 20 +M = 59 + +ModInv = 1b +A = 21 +M = 59 + +ModInv = 37 +A = 22 +M = 59 + +ModInv = 1c +A = 23 +M = 59 + +ModInv = 2f +A = 24 +M = 59 + +ModInv = 4d +A = 25 +M = 59 + +ModInv = 52 +A = 26 +M = 59 + +ModInv = 10 +A = 27 +M = 59 + +ModInv = 45 +A = 28 +M = 59 + +ModInv = 4c +A = 29 +M = 59 + +ModInv = 35 +A = 2a +M = 59 + +ModInv = 1d +A = 2b +M = 59 + +ModInv = 57 +A = 2c +M = 59 + +ModInv = 2 +A = 2d +M = 59 + +ModInv = 3c +A = 2e +M = 59 + +ModInv = 24 +A = 2f +M = 59 + +ModInv = d +A = 30 +M = 59 + +ModInv = 14 +A = 31 +M = 59 + +ModInv = 49 +A = 32 +M = 59 + +ModInv = 7 +A = 33 +M = 59 + +ModInv = c +A = 34 +M = 59 + +ModInv = 2a +A = 35 +M = 59 + +ModInv = 3d +A = 36 +M = 59 + +ModInv = 22 +A = 37 +M = 59 + +ModInv = 3e +A = 38 +M = 59 + +ModInv = 19 +A = 39 +M = 59 + +ModInv = 42 +A = 3a +M = 59 + +ModInv = 56 +A = 3b +M = 59 + +ModInv = 2e +A = 3c +M = 59 + +ModInv = 36 +A = 3d +M = 59 + +ModInv = 38 +A = 3e +M = 59 + +ModInv = 41 +A = 3f +M = 59 + +ModInv = 20 +A = 40 +M = 59 + +ModInv = 3f +A = 41 +M = 59 + +ModInv = 3a +A = 42 +M = 59 + +ModInv = 4 +A = 43 +M = 59 + +ModInv = 48 +A = 44 +M = 59 + +ModInv = 28 +A = 45 +M = 59 + +ModInv = e +A = 46 +M = 59 + +ModInv = 54 +A = 47 +M = 59 + +ModInv = 44 +A = 48 +M = 59 + +ModInv = 32 +A = 49 +M = 59 + +ModInv = 53 +A = 4a +M = 59 + +ModInv = 13 +A = 4b +M = 59 + +ModInv = 29 +A = 4c +M = 59 + +ModInv = 25 +A = 4d +M = 59 + +ModInv = 8 +A = 4e +M = 59 + +ModInv = 50 +A = 4f +M = 59 + +ModInv = 4f +A = 50 +M = 59 + +ModInv = b +A = 51 +M = 59 + +ModInv = 26 +A = 52 +M = 59 + +ModInv = 4a +A = 53 +M = 59 + +ModInv = 47 +A = 54 +M = 59 + +ModInv = 16 +A = 55 +M = 59 + +ModInv = 3b +A = 56 +M = 59 + +ModInv = 2c +A = 57 +M = 59 + +ModInv = 58 +A = 58 +M = 59 + +ModInv = 1 +A = 5a +M = 59 + +ModInv = 2d +A = 5b +M = 59 + +ModInv = 1e +A = 5c +M = 59 + +ModInv = 43 +A = 5d +M = 59 + +ModInv = 12 +A = 5e +M = 59 + +ModInv = f +A = 5f +M = 59 + +ModInv = 33 +A = 60 +M = 59 + +ModInv = 4e +A = 61 +M = 59 + +ModInv = a +A = 62 +M = 59 + +ModInv = 9 +A = 63 +M = 59 + +ModInv = 4d +A = -61 +M = 5a + +ModInv = 59 +A = -5b +M = 5a + +ModInv = 1 +A = -59 +M = 5a + +ModInv = d +A = -53 +M = 5a + +ModInv = 29 +A = -4f +M = 5a + +ModInv = 7 +A = -4d +M = 5a + +ModInv = 35 +A = -49 +M = 5a + +ModInv = 13 +A = -47 +M = 5a + +ModInv = 2f +A = -43 +M = 5a + +ModInv = 3b +A = -3d +M = 5a + +ModInv = 3d +A = -3b +M = 5a + +ModInv = 49 +A = -35 +M = 5a + +ModInv = b +A = -31 +M = 5a + +ModInv = 43 +A = -2f +M = 5a + +ModInv = 17 +A = -2b +M = 5a + +ModInv = 4f +A = -29 +M = 5a + +ModInv = 11 +A = -25 +M = 5a + +ModInv = 1d +A = -1f +M = 5a + +ModInv = 1f +A = -1d +M = 5a + +ModInv = 2b +A = -17 +M = 5a + +ModInv = 47 +A = -13 +M = 5a + +ModInv = 25 +A = -11 +M = 5a + +ModInv = 53 +A = -d +M = 5a + +ModInv = 31 +A = -b +M = 5a + +ModInv = 4d +A = -7 +M = 5a + +ModInv = 59 +A = -1 +M = 5a + +ModInv = 1 +A = 1 +M = 5a + +ModInv = d +A = 7 +M = 5a + +ModInv = 29 +A = b +M = 5a + +ModInv = 7 +A = d +M = 5a + +ModInv = 35 +A = 11 +M = 5a + +ModInv = 13 +A = 13 +M = 5a + +ModInv = 2f +A = 17 +M = 5a + +ModInv = 3b +A = 1d +M = 5a + +ModInv = 3d +A = 1f +M = 5a + +ModInv = 49 +A = 25 +M = 5a + +ModInv = b +A = 29 +M = 5a + +ModInv = 43 +A = 2b +M = 5a + +ModInv = 17 +A = 2f +M = 5a + +ModInv = 4f +A = 31 +M = 5a + +ModInv = 11 +A = 35 +M = 5a + +ModInv = 1d +A = 3b +M = 5a + +ModInv = 1f +A = 3d +M = 5a + +ModInv = 2b +A = 43 +M = 5a + +ModInv = 47 +A = 47 +M = 5a + +ModInv = 25 +A = 49 +M = 5a + +ModInv = 53 +A = 4d +M = 5a + +ModInv = 31 +A = 4f +M = 5a + +ModInv = 4d +A = 53 +M = 5a + +ModInv = 59 +A = 59 +M = 5a + +ModInv = 1 +A = 5b +M = 5a + +ModInv = d +A = 61 +M = 5a + +ModInv = a +A = -64 +M = 5b + +ModInv = 22 +A = -63 +M = 5b + +ModInv = f +A = -61 +M = 5b + +ModInv = 12 +A = -60 +M = 5b + +ModInv = 44 +A = -5f +M = 5b + +ModInv = 1e +A = -5e +M = 5b + +ModInv = 2d +A = -5d +M = 5b + +ModInv = 5a +A = -5c +M = 5b + +ModInv = 1 +A = -5a +M = 5b + +ModInv = 2e +A = -59 +M = 5b + +ModInv = 3d +A = -58 +M = 5b + +ModInv = 17 +A = -57 +M = 5b + +ModInv = 49 +A = -56 +M = 5b + +ModInv = 4c +A = -55 +M = 5b + +ModInv = 39 +A = -53 +M = 5b + +ModInv = 51 +A = -52 +M = 5b + +ModInv = 52 +A = -51 +M = 5b + +ModInv = 3a +A = -50 +M = 5b + +ModInv = 26 +A = -4f +M = 5b + +ModInv = 55 +A = -4c +M = 5b + +ModInv = 4a +A = -4b +M = 5b + +ModInv = 4b +A = -4a +M = 5b + +ModInv = 56 +A = -49 +M = 5b + +ModInv = 18 +A = -48 +M = 5b + +ModInv = 29 +A = -47 +M = 5b + +ModInv = 1d +A = -45 +M = 5b + +ModInv = 4 +A = -44 +M = 5b + +ModInv = 13 +A = -43 +M = 5b + +ModInv = 33 +A = -42 +M = 5b + +ModInv = 1b +A = -40 +M = 5b + +ModInv = 16 +A = -3e +M = 5b + +ModInv = 58 +A = -3d +M = 5b + +ModInv = 2f +A = -3c +M = 5b + +ModInv = 25 +A = -3b +M = 5b + +ModInv = 50 +A = -3a +M = 5b + +ModInv = 53 +A = -39 +M = 5b + +ModInv = 2b +A = -37 +M = 5b + +ModInv = 20 +A = -36 +M = 5b + +ModInv = c +A = -35 +M = 5b + +ModInv = 42 +A = -33 +M = 5b + +ModInv = 14 +A = -32 +M = 5b + +ModInv = 24 +A = -30 +M = 5b + +ModInv = 3c +A = -2f +M = 5b + +ModInv = 59 +A = -2e +M = 5b + +ModInv = 2 +A = -2d +M = 5b + +ModInv = 1f +A = -2c +M = 5b + +ModInv = 37 +A = -2b +M = 5b + +ModInv = 47 +A = -29 +M = 5b + +ModInv = 19 +A = -28 +M = 5b + +ModInv = 4f +A = -26 +M = 5b + +ModInv = 3b +A = -25 +M = 5b + +ModInv = 30 +A = -24 +M = 5b + +ModInv = 8 +A = -22 +M = 5b + +ModInv = b +A = -21 +M = 5b + +ModInv = 36 +A = -20 +M = 5b + +ModInv = 2c +A = -1f +M = 5b + +ModInv = 3 +A = -1e +M = 5b + +ModInv = 45 +A = -1d +M = 5b + +ModInv = 40 +A = -1b +M = 5b + +ModInv = 28 +A = -19 +M = 5b + +ModInv = 48 +A = -18 +M = 5b + +ModInv = 57 +A = -17 +M = 5b + +ModInv = 3e +A = -16 +M = 5b + +ModInv = 32 +A = -14 +M = 5b + +ModInv = 43 +A = -13 +M = 5b + +ModInv = 5 +A = -12 +M = 5b + +ModInv = 10 +A = -11 +M = 5b + +ModInv = 11 +A = -10 +M = 5b + +ModInv = 6 +A = -f +M = 5b + +ModInv = 35 +A = -c +M = 5b + +ModInv = 21 +A = -b +M = 5b + +ModInv = 9 +A = -a +M = 5b + +ModInv = a +A = -9 +M = 5b + +ModInv = 22 +A = -8 +M = 5b + +ModInv = f +A = -6 +M = 5b + +ModInv = 12 +A = -5 +M = 5b + +ModInv = 44 +A = -4 +M = 5b + +ModInv = 1e +A = -3 +M = 5b + +ModInv = 2d +A = -2 +M = 5b + +ModInv = 5a +A = -1 +M = 5b + +ModInv = 1 +A = 1 +M = 5b + +ModInv = 2e +A = 2 +M = 5b + +ModInv = 3d +A = 3 +M = 5b + +ModInv = 17 +A = 4 +M = 5b + +ModInv = 49 +A = 5 +M = 5b + +ModInv = 4c +A = 6 +M = 5b + +ModInv = 39 +A = 8 +M = 5b + +ModInv = 51 +A = 9 +M = 5b + +ModInv = 52 +A = a +M = 5b + +ModInv = 3a +A = b +M = 5b + +ModInv = 26 +A = c +M = 5b + +ModInv = 55 +A = f +M = 5b + +ModInv = 4a +A = 10 +M = 5b + +ModInv = 4b +A = 11 +M = 5b + +ModInv = 56 +A = 12 +M = 5b + +ModInv = 18 +A = 13 +M = 5b + +ModInv = 29 +A = 14 +M = 5b + +ModInv = 1d +A = 16 +M = 5b + +ModInv = 4 +A = 17 +M = 5b + +ModInv = 13 +A = 18 +M = 5b + +ModInv = 33 +A = 19 +M = 5b + +ModInv = 1b +A = 1b +M = 5b + +ModInv = 16 +A = 1d +M = 5b + +ModInv = 58 +A = 1e +M = 5b + +ModInv = 2f +A = 1f +M = 5b + +ModInv = 25 +A = 20 +M = 5b + +ModInv = 50 +A = 21 +M = 5b + +ModInv = 53 +A = 22 +M = 5b + +ModInv = 2b +A = 24 +M = 5b + +ModInv = 20 +A = 25 +M = 5b + +ModInv = c +A = 26 +M = 5b + +ModInv = 42 +A = 28 +M = 5b + +ModInv = 14 +A = 29 +M = 5b + +ModInv = 24 +A = 2b +M = 5b + +ModInv = 3c +A = 2c +M = 5b + +ModInv = 59 +A = 2d +M = 5b + +ModInv = 2 +A = 2e +M = 5b + +ModInv = 1f +A = 2f +M = 5b + +ModInv = 37 +A = 30 +M = 5b + +ModInv = 47 +A = 32 +M = 5b + +ModInv = 19 +A = 33 +M = 5b + +ModInv = 4f +A = 35 +M = 5b + +ModInv = 3b +A = 36 +M = 5b + +ModInv = 30 +A = 37 +M = 5b + +ModInv = 8 +A = 39 +M = 5b + +ModInv = b +A = 3a +M = 5b + +ModInv = 36 +A = 3b +M = 5b + +ModInv = 2c +A = 3c +M = 5b + +ModInv = 3 +A = 3d +M = 5b + +ModInv = 45 +A = 3e +M = 5b + +ModInv = 40 +A = 40 +M = 5b + +ModInv = 28 +A = 42 +M = 5b + +ModInv = 48 +A = 43 +M = 5b + +ModInv = 57 +A = 44 +M = 5b + +ModInv = 3e +A = 45 +M = 5b + +ModInv = 32 +A = 47 +M = 5b + +ModInv = 43 +A = 48 +M = 5b + +ModInv = 5 +A = 49 +M = 5b + +ModInv = 10 +A = 4a +M = 5b + +ModInv = 11 +A = 4b +M = 5b + +ModInv = 6 +A = 4c +M = 5b + +ModInv = 35 +A = 4f +M = 5b + +ModInv = 21 +A = 50 +M = 5b + +ModInv = 9 +A = 51 +M = 5b + +ModInv = a +A = 52 +M = 5b + +ModInv = 22 +A = 53 +M = 5b + +ModInv = f +A = 55 +M = 5b + +ModInv = 12 +A = 56 +M = 5b + +ModInv = 44 +A = 57 +M = 5b + +ModInv = 1e +A = 58 +M = 5b + +ModInv = 2d +A = 59 +M = 5b + +ModInv = 5a +A = 5a +M = 5b + +ModInv = 1 +A = 5c +M = 5b + +ModInv = 2e +A = 5d +M = 5b + +ModInv = 3d +A = 5e +M = 5b + +ModInv = 17 +A = 5f +M = 5b + +ModInv = 49 +A = 60 +M = 5b + +ModInv = 4c +A = 61 +M = 5b + +ModInv = 39 +A = 63 +M = 5b + +ModInv = d +A = -63 +M = 5c + +ModInv = 37 +A = -61 +M = 5c + +ModInv = 3d +A = -5f +M = 5c + +ModInv = 5b +A = -5d +M = 5c + +ModInv = 1 +A = -5b +M = 5c + +ModInv = 1f +A = -59 +M = 5c + +ModInv = 25 +A = -57 +M = 5c + +ModInv = 4f +A = -55 +M = 5c + +ModInv = 29 +A = -53 +M = 5c + +ModInv = 43 +A = -51 +M = 5c + +ModInv = 55 +A = -4f +M = 5c + +ModInv = 2b +A = -4d +M = 5c + +ModInv = 41 +A = -4b +M = 5c + +ModInv = 3f +A = -49 +M = 5c + +ModInv = 39 +A = -47 +M = 5c + +ModInv = 51 +A = -43 +M = 5c + +ModInv = 4b +A = -41 +M = 5c + +ModInv = 49 +A = -3f +M = 5c + +ModInv = 3 +A = -3d +M = 5c + +ModInv = 35 +A = -3b +M = 5c + +ModInv = 47 +A = -39 +M = 5c + +ModInv = 5 +A = -37 +M = 5c + +ModInv = 3b +A = -35 +M = 5c + +ModInv = 9 +A = -33 +M = 5c + +ModInv = f +A = -31 +M = 5c + +ModInv = 2d +A = -2f +M = 5c + +ModInv = 2f +A = -2d +M = 5c + +ModInv = 4d +A = -2b +M = 5c + +ModInv = 53 +A = -29 +M = 5c + +ModInv = 21 +A = -27 +M = 5c + +ModInv = 57 +A = -25 +M = 5c + +ModInv = 15 +A = -23 +M = 5c + +ModInv = 27 +A = -21 +M = 5c + +ModInv = 59 +A = -1f +M = 5c + +ModInv = 13 +A = -1d +M = 5c + +ModInv = 11 +A = -1b +M = 5c + +ModInv = b +A = -19 +M = 5c + +ModInv = 23 +A = -15 +M = 5c + +ModInv = 1d +A = -13 +M = 5c + +ModInv = 1b +A = -11 +M = 5c + +ModInv = 31 +A = -f +M = 5c + +ModInv = 7 +A = -d +M = 5c + +ModInv = 19 +A = -b +M = 5c + +ModInv = 33 +A = -9 +M = 5c + +ModInv = d +A = -7 +M = 5c + +ModInv = 37 +A = -5 +M = 5c + +ModInv = 3d +A = -3 +M = 5c + +ModInv = 5b +A = -1 +M = 5c + +ModInv = 1 +A = 1 +M = 5c + +ModInv = 1f +A = 3 +M = 5c + +ModInv = 25 +A = 5 +M = 5c + +ModInv = 4f +A = 7 +M = 5c + +ModInv = 29 +A = 9 +M = 5c + +ModInv = 43 +A = b +M = 5c + +ModInv = 55 +A = d +M = 5c + +ModInv = 2b +A = f +M = 5c + +ModInv = 41 +A = 11 +M = 5c + +ModInv = 3f +A = 13 +M = 5c + +ModInv = 39 +A = 15 +M = 5c + +ModInv = 51 +A = 19 +M = 5c + +ModInv = 4b +A = 1b +M = 5c + +ModInv = 49 +A = 1d +M = 5c + +ModInv = 3 +A = 1f +M = 5c + +ModInv = 35 +A = 21 +M = 5c + +ModInv = 47 +A = 23 +M = 5c + +ModInv = 5 +A = 25 +M = 5c + +ModInv = 3b +A = 27 +M = 5c + +ModInv = 9 +A = 29 +M = 5c + +ModInv = f +A = 2b +M = 5c + +ModInv = 2d +A = 2d +M = 5c + +ModInv = 2f +A = 2f +M = 5c + +ModInv = 4d +A = 31 +M = 5c + +ModInv = 53 +A = 33 +M = 5c + +ModInv = 21 +A = 35 +M = 5c + +ModInv = 57 +A = 37 +M = 5c + +ModInv = 15 +A = 39 +M = 5c + +ModInv = 27 +A = 3b +M = 5c + +ModInv = 59 +A = 3d +M = 5c + +ModInv = 13 +A = 3f +M = 5c + +ModInv = 11 +A = 41 +M = 5c + +ModInv = b +A = 43 +M = 5c + +ModInv = 23 +A = 47 +M = 5c + +ModInv = 1d +A = 49 +M = 5c + +ModInv = 1b +A = 4b +M = 5c + +ModInv = 31 +A = 4d +M = 5c + +ModInv = 7 +A = 4f +M = 5c + +ModInv = 19 +A = 51 +M = 5c + +ModInv = 33 +A = 53 +M = 5c + +ModInv = d +A = 55 +M = 5c + +ModInv = 37 +A = 57 +M = 5c + +ModInv = 3d +A = 59 +M = 5c + +ModInv = 5b +A = 5b +M = 5c + +ModInv = 1 +A = 5d +M = 5c + +ModInv = 1f +A = 5f +M = 5c + +ModInv = 25 +A = 61 +M = 5c + +ModInv = 4f +A = 63 +M = 5c + +ModInv = 35 +A = -64 +M = 5d + +ModInv = 25 +A = -62 +M = 5d + +ModInv = 17 +A = -61 +M = 5d + +ModInv = 2e +A = -5f +M = 5d + +ModInv = 5c +A = -5e +M = 5d + +ModInv = 1 +A = -5c +M = 5d + +ModInv = 2f +A = -5b +M = 5d + +ModInv = 46 +A = -59 +M = 5d + +ModInv = 38 +A = -58 +M = 5d + +ModInv = 28 +A = -56 +M = 5d + +ModInv = 23 +A = -55 +M = 5d + +ModInv = 1c +A = -53 +M = 5d + +ModInv = 11 +A = -52 +M = 5d + +ModInv = 2b +A = -50 +M = 5d + +ModInv = 14 +A = -4f +M = 5d + +ModInv = 40 +A = -4d +M = 5d + +ModInv = b +A = -4c +M = 5d + +ModInv = 31 +A = -4a +M = 5d + +ModInv = e +A = -49 +M = 5d + +ModInv = 37 +A = -47 +M = 5d + +ModInv = 59 +A = -46 +M = 5d + +ModInv = 43 +A = -44 +M = 5d + +ModInv = 44 +A = -43 +M = 5d + +ModInv = a +A = -41 +M = 5d + +ModInv = 4d +A = -40 +M = 5d + +ModInv = 20 +A = -3d +M = 5d + +ModInv = 34 +A = -3b +M = 5d + +ModInv = 8 +A = -3a +M = 5d + +ModInv = 58 +A = -38 +M = 5d + +ModInv = 47 +A = -37 +M = 5d + +ModInv = 7 +A = -35 +M = 5d + +ModInv = 3b +A = -34 +M = 5d + +ModInv = d +A = -32 +M = 5d + +ModInv = 4a +A = -31 +M = 5d + +ModInv = 5b +A = -2f +M = 5d + +ModInv = 2 +A = -2e +M = 5d + +ModInv = 13 +A = -2c +M = 5d + +ModInv = 50 +A = -2b +M = 5d + +ModInv = 22 +A = -29 +M = 5d + +ModInv = 56 +A = -28 +M = 5d + +ModInv = 16 +A = -26 +M = 5d + +ModInv = 5 +A = -25 +M = 5d + +ModInv = 55 +A = -23 +M = 5d + +ModInv = 29 +A = -22 +M = 5d + +ModInv = 3d +A = -20 +M = 5d + +ModInv = 10 +A = -1d +M = 5d + +ModInv = 53 +A = -1c +M = 5d + +ModInv = 19 +A = -1a +M = 5d + +ModInv = 1a +A = -19 +M = 5d + +ModInv = 4 +A = -17 +M = 5d + +ModInv = 26 +A = -16 +M = 5d + +ModInv = 4f +A = -14 +M = 5d + +ModInv = 2c +A = -13 +M = 5d + +ModInv = 52 +A = -11 +M = 5d + +ModInv = 1d +A = -10 +M = 5d + +ModInv = 49 +A = -e +M = 5d + +ModInv = 32 +A = -d +M = 5d + +ModInv = 4c +A = -b +M = 5d + +ModInv = 41 +A = -a +M = 5d + +ModInv = 3a +A = -8 +M = 5d + +ModInv = 35 +A = -7 +M = 5d + +ModInv = 25 +A = -5 +M = 5d + +ModInv = 17 +A = -4 +M = 5d + +ModInv = 2e +A = -2 +M = 5d + +ModInv = 5c +A = -1 +M = 5d + +ModInv = 1 +A = 1 +M = 5d + +ModInv = 2f +A = 2 +M = 5d + +ModInv = 46 +A = 4 +M = 5d + +ModInv = 38 +A = 5 +M = 5d + +ModInv = 28 +A = 7 +M = 5d + +ModInv = 23 +A = 8 +M = 5d + +ModInv = 1c +A = a +M = 5d + +ModInv = 11 +A = b +M = 5d + +ModInv = 2b +A = d +M = 5d + +ModInv = 14 +A = e +M = 5d + +ModInv = 40 +A = 10 +M = 5d + +ModInv = b +A = 11 +M = 5d + +ModInv = 31 +A = 13 +M = 5d + +ModInv = e +A = 14 +M = 5d + +ModInv = 37 +A = 16 +M = 5d + +ModInv = 59 +A = 17 +M = 5d + +ModInv = 43 +A = 19 +M = 5d + +ModInv = 44 +A = 1a +M = 5d + +ModInv = a +A = 1c +M = 5d + +ModInv = 4d +A = 1d +M = 5d + +ModInv = 20 +A = 20 +M = 5d + +ModInv = 34 +A = 22 +M = 5d + +ModInv = 8 +A = 23 +M = 5d + +ModInv = 58 +A = 25 +M = 5d + +ModInv = 47 +A = 26 +M = 5d + +ModInv = 7 +A = 28 +M = 5d + +ModInv = 3b +A = 29 +M = 5d + +ModInv = d +A = 2b +M = 5d + +ModInv = 4a +A = 2c +M = 5d + +ModInv = 5b +A = 2e +M = 5d + +ModInv = 2 +A = 2f +M = 5d + +ModInv = 13 +A = 31 +M = 5d + +ModInv = 50 +A = 32 +M = 5d + +ModInv = 22 +A = 34 +M = 5d + +ModInv = 56 +A = 35 +M = 5d + +ModInv = 16 +A = 37 +M = 5d + +ModInv = 5 +A = 38 +M = 5d + +ModInv = 55 +A = 3a +M = 5d + +ModInv = 29 +A = 3b +M = 5d + +ModInv = 3d +A = 3d +M = 5d + +ModInv = 10 +A = 40 +M = 5d + +ModInv = 53 +A = 41 +M = 5d + +ModInv = 19 +A = 43 +M = 5d + +ModInv = 1a +A = 44 +M = 5d + +ModInv = 4 +A = 46 +M = 5d + +ModInv = 26 +A = 47 +M = 5d + +ModInv = 4f +A = 49 +M = 5d + +ModInv = 2c +A = 4a +M = 5d + +ModInv = 52 +A = 4c +M = 5d + +ModInv = 1d +A = 4d +M = 5d + +ModInv = 49 +A = 4f +M = 5d + +ModInv = 32 +A = 50 +M = 5d + +ModInv = 4c +A = 52 +M = 5d + +ModInv = 41 +A = 53 +M = 5d + +ModInv = 3a +A = 55 +M = 5d + +ModInv = 35 +A = 56 +M = 5d + +ModInv = 25 +A = 58 +M = 5d + +ModInv = 17 +A = 59 +M = 5d + +ModInv = 2e +A = 5b +M = 5d + +ModInv = 5c +A = 5c +M = 5d + +ModInv = 1 +A = 5e +M = 5d + +ModInv = 2f +A = 5f +M = 5d + +ModInv = 46 +A = 61 +M = 5d + +ModInv = 38 +A = 62 +M = 5d + +ModInv = 4b +A = -63 +M = 5e + +ModInv = 1f +A = -61 +M = 5e + +ModInv = 5d +A = -5f +M = 5e + +ModInv = 1 +A = -5d +M = 5e + +ModInv = 3f +A = -5b +M = 5e + +ModInv = 13 +A = -59 +M = 5e + +ModInv = 1b +A = -57 +M = 5e + +ModInv = 15 +A = -55 +M = 5e + +ModInv = 4d +A = -53 +M = 5e + +ModInv = 1d +A = -51 +M = 5e + +ModInv = 45 +A = -4f +M = 5e + +ModInv = 53 +A = -4d +M = 5e + +ModInv = 5 +A = -4b +M = 5e + +ModInv = 9 +A = -49 +M = 5e + +ModInv = 2d +A = -47 +M = 5e + +ModInv = 4f +A = -45 +M = 5e + +ModInv = 7 +A = -43 +M = 5e + +ModInv = d +A = -41 +M = 5e + +ModInv = 5b +A = -3f +M = 5e + +ModInv = 39 +A = -3d +M = 5e + +ModInv = 2b +A = -3b +M = 5e + +ModInv = 3d +A = -39 +M = 5e + +ModInv = 29 +A = -37 +M = 5e + +ModInv = 27 +A = -35 +M = 5e + +ModInv = 23 +A = -33 +M = 5e + +ModInv = 17 +A = -31 +M = 5e + +ModInv = 47 +A = -2d +M = 5e + +ModInv = 3b +A = -2b +M = 5e + +ModInv = 37 +A = -29 +M = 5e + +ModInv = 35 +A = -27 +M = 5e + +ModInv = 21 +A = -25 +M = 5e + +ModInv = 33 +A = -23 +M = 5e + +ModInv = 25 +A = -21 +M = 5e + +ModInv = 3 +A = -1f +M = 5e + +ModInv = 51 +A = -1d +M = 5e + +ModInv = 57 +A = -1b +M = 5e + +ModInv = f +A = -19 +M = 5e + +ModInv = 31 +A = -17 +M = 5e + +ModInv = 55 +A = -15 +M = 5e + +ModInv = 59 +A = -13 +M = 5e + +ModInv = b +A = -11 +M = 5e + +ModInv = 19 +A = -f +M = 5e + +ModInv = 41 +A = -d +M = 5e + +ModInv = 11 +A = -b +M = 5e + +ModInv = 49 +A = -9 +M = 5e + +ModInv = 43 +A = -7 +M = 5e + +ModInv = 4b +A = -5 +M = 5e + +ModInv = 1f +A = -3 +M = 5e + +ModInv = 5d +A = -1 +M = 5e + +ModInv = 1 +A = 1 +M = 5e + +ModInv = 3f +A = 3 +M = 5e + +ModInv = 13 +A = 5 +M = 5e + +ModInv = 1b +A = 7 +M = 5e + +ModInv = 15 +A = 9 +M = 5e + +ModInv = 4d +A = b +M = 5e + +ModInv = 1d +A = d +M = 5e + +ModInv = 45 +A = f +M = 5e + +ModInv = 53 +A = 11 +M = 5e + +ModInv = 5 +A = 13 +M = 5e + +ModInv = 9 +A = 15 +M = 5e + +ModInv = 2d +A = 17 +M = 5e + +ModInv = 4f +A = 19 +M = 5e + +ModInv = 7 +A = 1b +M = 5e + +ModInv = d +A = 1d +M = 5e + +ModInv = 5b +A = 1f +M = 5e + +ModInv = 39 +A = 21 +M = 5e + +ModInv = 2b +A = 23 +M = 5e + +ModInv = 3d +A = 25 +M = 5e + +ModInv = 29 +A = 27 +M = 5e + +ModInv = 27 +A = 29 +M = 5e + +ModInv = 23 +A = 2b +M = 5e + +ModInv = 17 +A = 2d +M = 5e + +ModInv = 47 +A = 31 +M = 5e + +ModInv = 3b +A = 33 +M = 5e + +ModInv = 37 +A = 35 +M = 5e + +ModInv = 35 +A = 37 +M = 5e + +ModInv = 21 +A = 39 +M = 5e + +ModInv = 33 +A = 3b +M = 5e + +ModInv = 25 +A = 3d +M = 5e + +ModInv = 3 +A = 3f +M = 5e + +ModInv = 51 +A = 41 +M = 5e + +ModInv = 57 +A = 43 +M = 5e + +ModInv = f +A = 45 +M = 5e + +ModInv = 31 +A = 47 +M = 5e + +ModInv = 55 +A = 49 +M = 5e + +ModInv = 59 +A = 4b +M = 5e + +ModInv = b +A = 4d +M = 5e + +ModInv = 19 +A = 4f +M = 5e + +ModInv = 41 +A = 51 +M = 5e + +ModInv = 11 +A = 53 +M = 5e + +ModInv = 49 +A = 55 +M = 5e + +ModInv = 43 +A = 57 +M = 5e + +ModInv = 4b +A = 59 +M = 5e + +ModInv = 1f +A = 5b +M = 5e + +ModInv = 5d +A = 5d +M = 5e + +ModInv = 1 +A = 5f +M = 5e + +ModInv = 3f +A = 61 +M = 5e + +ModInv = 13 +A = 63 +M = 5e + +ModInv = 47 +A = -63 +M = 5f + +ModInv = 3f +A = -62 +M = 5f + +ModInv = 2f +A = -61 +M = 5f + +ModInv = 5e +A = -60 +M = 5f + +ModInv = 1 +A = -5e +M = 5f + +ModInv = 30 +A = -5d +M = 5f + +ModInv = 20 +A = -5c +M = 5f + +ModInv = 18 +A = -5b +M = 5f + +ModInv = 10 +A = -59 +M = 5f + +ModInv = 44 +A = -58 +M = 5f + +ModInv = c +A = -57 +M = 5f + +ModInv = 4a +A = -56 +M = 5f + +ModInv = 1a +A = -54 +M = 5f + +ModInv = 8 +A = -53 +M = 5f + +ModInv = 16 +A = -52 +M = 5f + +ModInv = 22 +A = -51 +M = 5f + +ModInv = 6 +A = -4f +M = 5f + +ModInv = 1c +A = -4e +M = 5f + +ModInv = 25 +A = -4d +M = 5f + +ModInv = 56 +A = -4a +M = 5f + +ModInv = d +A = -49 +M = 5f + +ModInv = 3e +A = -48 +M = 5f + +ModInv = 4 +A = -47 +M = 5f + +ModInv = b +A = -45 +M = 5f + +ModInv = 58 +A = -44 +M = 5f + +ModInv = 11 +A = -43 +M = 5f + +ModInv = 3b +A = -42 +M = 5f + +ModInv = 2e +A = -40 +M = 5f + +ModInv = 3 +A = -3f +M = 5f + +ModInv = 48 +A = -3e +M = 5f + +ModInv = e +A = -3d +M = 5f + +ModInv = 42 +A = -3b +M = 5f + +ModInv = 12 +A = -3a +M = 5f + +ModInv = 27 +A = -38 +M = 5f + +ModInv = 33 +A = -36 +M = 5f + +ModInv = 2b +A = -35 +M = 5f + +ModInv = 2a +A = -34 +M = 5f + +ModInv = 36 +A = -33 +M = 5f + +ModInv = 1f +A = -31 +M = 5f + +ModInv = 5d +A = -30 +M = 5f + +ModInv = 2 +A = -2f +M = 5f + +ModInv = 40 +A = -2e +M = 5f + +ModInv = 29 +A = -2c +M = 5f + +ModInv = 35 +A = -2b +M = 5f + +ModInv = 34 +A = -2a +M = 5f + +ModInv = 2c +A = -29 +M = 5f + +ModInv = 38 +A = -27 +M = 5f + +ModInv = 4d +A = -25 +M = 5f + +ModInv = 1d +A = -24 +M = 5f + +ModInv = 51 +A = -22 +M = 5f + +ModInv = 17 +A = -21 +M = 5f + +ModInv = 5c +A = -20 +M = 5f + +ModInv = 31 +A = -1f +M = 5f + +ModInv = 24 +A = -1d +M = 5f + +ModInv = 4e +A = -1c +M = 5f + +ModInv = 7 +A = -1b +M = 5f + +ModInv = 54 +A = -1a +M = 5f + +ModInv = 5b +A = -18 +M = 5f + +ModInv = 21 +A = -17 +M = 5f + +ModInv = 52 +A = -16 +M = 5f + +ModInv = 9 +A = -15 +M = 5f + +ModInv = 3a +A = -12 +M = 5f + +ModInv = 43 +A = -11 +M = 5f + +ModInv = 59 +A = -10 +M = 5f + +ModInv = 3d +A = -e +M = 5f + +ModInv = 49 +A = -d +M = 5f + +ModInv = 57 +A = -c +M = 5f + +ModInv = 45 +A = -b +M = 5f + +ModInv = 15 +A = -9 +M = 5f + +ModInv = 53 +A = -8 +M = 5f + +ModInv = 1b +A = -7 +M = 5f + +ModInv = 4f +A = -6 +M = 5f + +ModInv = 47 +A = -4 +M = 5f + +ModInv = 3f +A = -3 +M = 5f + +ModInv = 2f +A = -2 +M = 5f + +ModInv = 5e +A = -1 +M = 5f + +ModInv = 1 +A = 1 +M = 5f + +ModInv = 30 +A = 2 +M = 5f + +ModInv = 20 +A = 3 +M = 5f + +ModInv = 18 +A = 4 +M = 5f + +ModInv = 10 +A = 6 +M = 5f + +ModInv = 44 +A = 7 +M = 5f + +ModInv = c +A = 8 +M = 5f + +ModInv = 4a +A = 9 +M = 5f + +ModInv = 1a +A = b +M = 5f + +ModInv = 8 +A = c +M = 5f + +ModInv = 16 +A = d +M = 5f + +ModInv = 22 +A = e +M = 5f + +ModInv = 6 +A = 10 +M = 5f + +ModInv = 1c +A = 11 +M = 5f + +ModInv = 25 +A = 12 +M = 5f + +ModInv = 56 +A = 15 +M = 5f + +ModInv = d +A = 16 +M = 5f + +ModInv = 3e +A = 17 +M = 5f + +ModInv = 4 +A = 18 +M = 5f + +ModInv = b +A = 1a +M = 5f + +ModInv = 58 +A = 1b +M = 5f + +ModInv = 11 +A = 1c +M = 5f + +ModInv = 3b +A = 1d +M = 5f + +ModInv = 2e +A = 1f +M = 5f + +ModInv = 3 +A = 20 +M = 5f + +ModInv = 48 +A = 21 +M = 5f + +ModInv = e +A = 22 +M = 5f + +ModInv = 42 +A = 24 +M = 5f + +ModInv = 12 +A = 25 +M = 5f + +ModInv = 27 +A = 27 +M = 5f + +ModInv = 33 +A = 29 +M = 5f + +ModInv = 2b +A = 2a +M = 5f + +ModInv = 2a +A = 2b +M = 5f + +ModInv = 36 +A = 2c +M = 5f + +ModInv = 1f +A = 2e +M = 5f + +ModInv = 5d +A = 2f +M = 5f + +ModInv = 2 +A = 30 +M = 5f + +ModInv = 40 +A = 31 +M = 5f + +ModInv = 29 +A = 33 +M = 5f + +ModInv = 35 +A = 34 +M = 5f + +ModInv = 34 +A = 35 +M = 5f + +ModInv = 2c +A = 36 +M = 5f + +ModInv = 38 +A = 38 +M = 5f + +ModInv = 4d +A = 3a +M = 5f + +ModInv = 1d +A = 3b +M = 5f + +ModInv = 51 +A = 3d +M = 5f + +ModInv = 17 +A = 3e +M = 5f + +ModInv = 5c +A = 3f +M = 5f + +ModInv = 31 +A = 40 +M = 5f + +ModInv = 24 +A = 42 +M = 5f + +ModInv = 4e +A = 43 +M = 5f + +ModInv = 7 +A = 44 +M = 5f + +ModInv = 54 +A = 45 +M = 5f + +ModInv = 5b +A = 47 +M = 5f + +ModInv = 21 +A = 48 +M = 5f + +ModInv = 52 +A = 49 +M = 5f + +ModInv = 9 +A = 4a +M = 5f + +ModInv = 3a +A = 4d +M = 5f + +ModInv = 43 +A = 4e +M = 5f + +ModInv = 59 +A = 4f +M = 5f + +ModInv = 3d +A = 51 +M = 5f + +ModInv = 49 +A = 52 +M = 5f + +ModInv = 57 +A = 53 +M = 5f + +ModInv = 45 +A = 54 +M = 5f + +ModInv = 15 +A = 56 +M = 5f + +ModInv = 53 +A = 57 +M = 5f + +ModInv = 1b +A = 58 +M = 5f + +ModInv = 4f +A = 59 +M = 5f + +ModInv = 47 +A = 5b +M = 5f + +ModInv = 3f +A = 5c +M = 5f + +ModInv = 2f +A = 5d +M = 5f + +ModInv = 5e +A = 5e +M = 5f + +ModInv = 1 +A = 60 +M = 5f + +ModInv = 30 +A = 61 +M = 5f + +ModInv = 20 +A = 62 +M = 5f + +ModInv = 18 +A = 63 +M = 5f + +ModInv = 5f +A = -61 +M = 60 + +ModInv = 1 +A = -5f +M = 60 + +ModInv = 4d +A = -5b +M = 60 + +ModInv = 37 +A = -59 +M = 60 + +ModInv = 23 +A = -55 +M = 60 + +ModInv = 25 +A = -53 +M = 60 + +ModInv = 11 +A = -4f +M = 60 + +ModInv = 5b +A = -4d +M = 60 + +ModInv = 47 +A = -49 +M = 60 + +ModInv = 49 +A = -47 +M = 60 + +ModInv = 35 +A = -43 +M = 60 + +ModInv = 1f +A = -41 +M = 60 + +ModInv = b +A = -3d +M = 60 + +ModInv = d +A = -3b +M = 60 + +ModInv = 59 +A = -37 +M = 60 + +ModInv = 43 +A = -35 +M = 60 + +ModInv = 2f +A = -31 +M = 60 + +ModInv = 31 +A = -2f +M = 60 + +ModInv = 1d +A = -2b +M = 60 + +ModInv = 7 +A = -29 +M = 60 + +ModInv = 53 +A = -25 +M = 60 + +ModInv = 55 +A = -23 +M = 60 + +ModInv = 41 +A = -1f +M = 60 + +ModInv = 2b +A = -1d +M = 60 + +ModInv = 17 +A = -19 +M = 60 + +ModInv = 19 +A = -17 +M = 60 + +ModInv = 5 +A = -13 +M = 60 + +ModInv = 4f +A = -11 +M = 60 + +ModInv = 3b +A = -d +M = 60 + +ModInv = 3d +A = -b +M = 60 + +ModInv = 29 +A = -7 +M = 60 + +ModInv = 13 +A = -5 +M = 60 + +ModInv = 5f +A = -1 +M = 60 + +ModInv = 1 +A = 1 +M = 60 + +ModInv = 4d +A = 5 +M = 60 + +ModInv = 37 +A = 7 +M = 60 + +ModInv = 23 +A = b +M = 60 + +ModInv = 25 +A = d +M = 60 + +ModInv = 11 +A = 11 +M = 60 + +ModInv = 5b +A = 13 +M = 60 + +ModInv = 47 +A = 17 +M = 60 + +ModInv = 49 +A = 19 +M = 60 + +ModInv = 35 +A = 1d +M = 60 + +ModInv = 1f +A = 1f +M = 60 + +ModInv = b +A = 23 +M = 60 + +ModInv = d +A = 25 +M = 60 + +ModInv = 59 +A = 29 +M = 60 + +ModInv = 43 +A = 2b +M = 60 + +ModInv = 2f +A = 2f +M = 60 + +ModInv = 31 +A = 31 +M = 60 + +ModInv = 1d +A = 35 +M = 60 + +ModInv = 7 +A = 37 +M = 60 + +ModInv = 53 +A = 3b +M = 60 + +ModInv = 55 +A = 3d +M = 60 + +ModInv = 41 +A = 41 +M = 60 + +ModInv = 2b +A = 43 +M = 60 + +ModInv = 17 +A = 47 +M = 60 + +ModInv = 19 +A = 49 +M = 60 + +ModInv = 5 +A = 4d +M = 60 + +ModInv = 4f +A = 4f +M = 60 + +ModInv = 3b +A = 53 +M = 60 + +ModInv = 3d +A = 55 +M = 60 + +ModInv = 29 +A = 59 +M = 60 + +ModInv = 13 +A = 5b +M = 60 + +ModInv = 5f +A = 5f +M = 60 + +ModInv = 1 +A = 61 +M = 60 + +ModInv = 20 +A = -64 +M = 61 + +ModInv = 30 +A = -63 +M = 61 + +ModInv = 60 +A = -62 +M = 61 + +ModInv = 1 +A = -60 +M = 61 + +ModInv = 31 +A = -5f +M = 61 + +ModInv = 41 +A = -5e +M = 61 + +ModInv = 49 +A = -5d +M = 61 + +ModInv = 27 +A = -5c +M = 61 + +ModInv = 51 +A = -5b +M = 61 + +ModInv = e +A = -5a +M = 61 + +ModInv = 55 +A = -59 +M = 61 + +ModInv = 36 +A = -58 +M = 61 + +ModInv = 44 +A = -57 +M = 61 + +ModInv = 35 +A = -56 +M = 61 + +ModInv = 59 +A = -55 +M = 61 + +ModInv = f +A = -54 +M = 61 + +ModInv = 7 +A = -53 +M = 61 + +ModInv = d +A = -52 +M = 61 + +ModInv = 5b +A = -51 +M = 61 + +ModInv = 28 +A = -50 +M = 61 + +ModInv = 1b +A = -4f +M = 61 + +ModInv = 2e +A = -4e +M = 61 + +ModInv = 22 +A = -4d +M = 61 + +ModInv = 25 +A = -4c +M = 61 + +ModInv = 4b +A = -4b +M = 61 + +ModInv = 26 +A = -4a +M = 61 + +ModInv = 5d +A = -49 +M = 61 + +ModInv = 42 +A = -48 +M = 61 + +ModInv = 38 +A = -47 +M = 61 + +ModInv = 12 +A = -46 +M = 61 + +ModInv = 34 +A = -45 +M = 61 + +ModInv = 57 +A = -44 +M = 61 + +ModInv = 37 +A = -43 +M = 61 + +ModInv = 48 +A = -42 +M = 61 + +ModInv = 5e +A = -41 +M = 61 + +ModInv = 32 +A = -40 +M = 61 + +ModInv = 14 +A = -3f +M = 61 + +ModInv = 3d +A = -3e +M = 61 + +ModInv = 3e +A = -3d +M = 61 + +ModInv = 15 +A = -3c +M = 61 + +ModInv = 17 +A = -3b +M = 61 + +ModInv = 5 +A = -3a +M = 61 + +ModInv = 11 +A = -39 +M = 61 + +ModInv = 47 +A = -38 +M = 61 + +ModInv = 43 +A = -37 +M = 61 + +ModInv = 58 +A = -36 +M = 61 + +ModInv = 56 +A = -35 +M = 61 + +ModInv = 45 +A = -34 +M = 61 + +ModInv = 13 +A = -33 +M = 61 + +ModInv = 40 +A = -32 +M = 61 + +ModInv = 5f +A = -31 +M = 61 + +ModInv = 2 +A = -30 +M = 61 + +ModInv = 21 +A = -2f +M = 61 + +ModInv = 4e +A = -2e +M = 61 + +ModInv = 1c +A = -2d +M = 61 + +ModInv = b +A = -2c +M = 61 + +ModInv = 9 +A = -2b +M = 61 + +ModInv = 1e +A = -2a +M = 61 + +ModInv = 1a +A = -29 +M = 61 + +ModInv = 50 +A = -28 +M = 61 + +ModInv = 5c +A = -27 +M = 61 + +ModInv = 4a +A = -26 +M = 61 + +ModInv = 4c +A = -25 +M = 61 + +ModInv = 23 +A = -24 +M = 61 + +ModInv = 24 +A = -23 +M = 61 + +ModInv = 4d +A = -22 +M = 61 + +ModInv = 2f +A = -21 +M = 61 + +ModInv = 3 +A = -20 +M = 61 + +ModInv = 19 +A = -1f +M = 61 + +ModInv = 2a +A = -1e +M = 61 + +ModInv = a +A = -1d +M = 61 + +ModInv = 2d +A = -1c +M = 61 + +ModInv = 4f +A = -1b +M = 61 + +ModInv = 29 +A = -1a +M = 61 + +ModInv = 1f +A = -19 +M = 61 + +ModInv = 4 +A = -18 +M = 61 + +ModInv = 3b +A = -17 +M = 61 + +ModInv = 16 +A = -16 +M = 61 + +ModInv = 3c +A = -15 +M = 61 + +ModInv = 3f +A = -14 +M = 61 + +ModInv = 33 +A = -13 +M = 61 + +ModInv = 46 +A = -12 +M = 61 + +ModInv = 39 +A = -11 +M = 61 + +ModInv = 6 +A = -10 +M = 61 + +ModInv = 54 +A = -f +M = 61 + +ModInv = 5a +A = -e +M = 61 + +ModInv = 52 +A = -d +M = 61 + +ModInv = 8 +A = -c +M = 61 + +ModInv = 2c +A = -b +M = 61 + +ModInv = 1d +A = -a +M = 61 + +ModInv = 2b +A = -9 +M = 61 + +ModInv = c +A = -8 +M = 61 + +ModInv = 53 +A = -7 +M = 61 + +ModInv = 10 +A = -6 +M = 61 + +ModInv = 3a +A = -5 +M = 61 + +ModInv = 18 +A = -4 +M = 61 + +ModInv = 20 +A = -3 +M = 61 + +ModInv = 30 +A = -2 +M = 61 + +ModInv = 60 +A = -1 +M = 61 + +ModInv = 1 +A = 1 +M = 61 + +ModInv = 31 +A = 2 +M = 61 + +ModInv = 41 +A = 3 +M = 61 + +ModInv = 49 +A = 4 +M = 61 + +ModInv = 27 +A = 5 +M = 61 + +ModInv = 51 +A = 6 +M = 61 + +ModInv = e +A = 7 +M = 61 + +ModInv = 55 +A = 8 +M = 61 + +ModInv = 36 +A = 9 +M = 61 + +ModInv = 44 +A = a +M = 61 + +ModInv = 35 +A = b +M = 61 + +ModInv = 59 +A = c +M = 61 + +ModInv = f +A = d +M = 61 + +ModInv = 7 +A = e +M = 61 + +ModInv = d +A = f +M = 61 + +ModInv = 5b +A = 10 +M = 61 + +ModInv = 28 +A = 11 +M = 61 + +ModInv = 1b +A = 12 +M = 61 + +ModInv = 2e +A = 13 +M = 61 + +ModInv = 22 +A = 14 +M = 61 + +ModInv = 25 +A = 15 +M = 61 + +ModInv = 4b +A = 16 +M = 61 + +ModInv = 26 +A = 17 +M = 61 + +ModInv = 5d +A = 18 +M = 61 + +ModInv = 42 +A = 19 +M = 61 + +ModInv = 38 +A = 1a +M = 61 + +ModInv = 12 +A = 1b +M = 61 + +ModInv = 34 +A = 1c +M = 61 + +ModInv = 57 +A = 1d +M = 61 + +ModInv = 37 +A = 1e +M = 61 + +ModInv = 48 +A = 1f +M = 61 + +ModInv = 5e +A = 20 +M = 61 + +ModInv = 32 +A = 21 +M = 61 + +ModInv = 14 +A = 22 +M = 61 + +ModInv = 3d +A = 23 +M = 61 + +ModInv = 3e +A = 24 +M = 61 + +ModInv = 15 +A = 25 +M = 61 + +ModInv = 17 +A = 26 +M = 61 + +ModInv = 5 +A = 27 +M = 61 + +ModInv = 11 +A = 28 +M = 61 + +ModInv = 47 +A = 29 +M = 61 + +ModInv = 43 +A = 2a +M = 61 + +ModInv = 58 +A = 2b +M = 61 + +ModInv = 56 +A = 2c +M = 61 + +ModInv = 45 +A = 2d +M = 61 + +ModInv = 13 +A = 2e +M = 61 + +ModInv = 40 +A = 2f +M = 61 + +ModInv = 5f +A = 30 +M = 61 + +ModInv = 2 +A = 31 +M = 61 + +ModInv = 21 +A = 32 +M = 61 + +ModInv = 4e +A = 33 +M = 61 + +ModInv = 1c +A = 34 +M = 61 + +ModInv = b +A = 35 +M = 61 + +ModInv = 9 +A = 36 +M = 61 + +ModInv = 1e +A = 37 +M = 61 + +ModInv = 1a +A = 38 +M = 61 + +ModInv = 50 +A = 39 +M = 61 + +ModInv = 5c +A = 3a +M = 61 + +ModInv = 4a +A = 3b +M = 61 + +ModInv = 4c +A = 3c +M = 61 + +ModInv = 23 +A = 3d +M = 61 + +ModInv = 24 +A = 3e +M = 61 + +ModInv = 4d +A = 3f +M = 61 + +ModInv = 2f +A = 40 +M = 61 + +ModInv = 3 +A = 41 +M = 61 + +ModInv = 19 +A = 42 +M = 61 + +ModInv = 2a +A = 43 +M = 61 + +ModInv = a +A = 44 +M = 61 + +ModInv = 2d +A = 45 +M = 61 + +ModInv = 4f +A = 46 +M = 61 + +ModInv = 29 +A = 47 +M = 61 + +ModInv = 1f +A = 48 +M = 61 + +ModInv = 4 +A = 49 +M = 61 + +ModInv = 3b +A = 4a +M = 61 + +ModInv = 16 +A = 4b +M = 61 + +ModInv = 3c +A = 4c +M = 61 + +ModInv = 3f +A = 4d +M = 61 + +ModInv = 33 +A = 4e +M = 61 + +ModInv = 46 +A = 4f +M = 61 + +ModInv = 39 +A = 50 +M = 61 + +ModInv = 6 +A = 51 +M = 61 + +ModInv = 54 +A = 52 +M = 61 + +ModInv = 5a +A = 53 +M = 61 + +ModInv = 52 +A = 54 +M = 61 + +ModInv = 8 +A = 55 +M = 61 + +ModInv = 2c +A = 56 +M = 61 + +ModInv = 1d +A = 57 +M = 61 + +ModInv = 2b +A = 58 +M = 61 + +ModInv = c +A = 59 +M = 61 + +ModInv = 53 +A = 5a +M = 61 + +ModInv = 10 +A = 5b +M = 61 + +ModInv = 3a +A = 5c +M = 61 + +ModInv = 18 +A = 5d +M = 61 + +ModInv = 20 +A = 5e +M = 61 + +ModInv = 30 +A = 5f +M = 61 + +ModInv = 60 +A = 60 +M = 61 + +ModInv = 1 +A = 62 +M = 61 + +ModInv = 31 +A = 63 +M = 61 + +ModInv = 61 +A = -63 +M = 62 + +ModInv = 1 +A = -61 +M = 62 + +ModInv = 21 +A = -5f +M = 62 + +ModInv = 3b +A = -5d +M = 62 + +ModInv = b +A = -59 +M = 62 + +ModInv = 9 +A = -57 +M = 62 + +ModInv = 53 +A = -55 +M = 62 + +ModInv = 55 +A = -53 +M = 62 + +ModInv = 4b +A = -51 +M = 62 + +ModInv = 1f +A = -4f +M = 62 + +ModInv = 51 +A = -4b +M = 62 + +ModInv = 33 +A = -49 +M = 62 + +ModInv = 45 +A = -47 +M = 62 + +ModInv = 47 +A = -45 +M = 62 + +ModInv = 13 +A = -43 +M = 62 + +ModInv = 3 +A = -41 +M = 62 + +ModInv = 35 +A = -3d +M = 62 + +ModInv = 5d +A = -3b +M = 62 + +ModInv = 37 +A = -39 +M = 62 + +ModInv = 39 +A = -37 +M = 62 + +ModInv = 3d +A = -35 +M = 62 + +ModInv = 49 +A = -33 +M = 62 + +ModInv = 19 +A = -2f +M = 62 + +ModInv = 25 +A = -2d +M = 62 + +ModInv = 29 +A = -2b +M = 62 + +ModInv = 2b +A = -29 +M = 62 + +ModInv = 5 +A = -27 +M = 62 + +ModInv = 2d +A = -25 +M = 62 + +ModInv = 5f +A = -21 +M = 62 + +ModInv = 4f +A = -1f +M = 62 + +ModInv = 1b +A = -1d +M = 62 + +ModInv = 1d +A = -1b +M = 62 + +ModInv = 2f +A = -19 +M = 62 + +ModInv = 11 +A = -17 +M = 62 + +ModInv = 43 +A = -13 +M = 62 + +ModInv = 17 +A = -11 +M = 62 + +ModInv = d +A = -f +M = 62 + +ModInv = f +A = -d +M = 62 + +ModInv = 59 +A = -b +M = 62 + +ModInv = 57 +A = -9 +M = 62 + +ModInv = 27 +A = -5 +M = 62 + +ModInv = 41 +A = -3 +M = 62 + +ModInv = 61 +A = -1 +M = 62 + +ModInv = 1 +A = 1 +M = 62 + +ModInv = 21 +A = 3 +M = 62 + +ModInv = 3b +A = 5 +M = 62 + +ModInv = b +A = 9 +M = 62 + +ModInv = 9 +A = b +M = 62 + +ModInv = 53 +A = d +M = 62 + +ModInv = 55 +A = f +M = 62 + +ModInv = 4b +A = 11 +M = 62 + +ModInv = 1f +A = 13 +M = 62 + +ModInv = 51 +A = 17 +M = 62 + +ModInv = 33 +A = 19 +M = 62 + +ModInv = 45 +A = 1b +M = 62 + +ModInv = 47 +A = 1d +M = 62 + +ModInv = 13 +A = 1f +M = 62 + +ModInv = 3 +A = 21 +M = 62 + +ModInv = 35 +A = 25 +M = 62 + +ModInv = 5d +A = 27 +M = 62 + +ModInv = 37 +A = 29 +M = 62 + +ModInv = 39 +A = 2b +M = 62 + +ModInv = 3d +A = 2d +M = 62 + +ModInv = 49 +A = 2f +M = 62 + +ModInv = 19 +A = 33 +M = 62 + +ModInv = 25 +A = 35 +M = 62 + +ModInv = 29 +A = 37 +M = 62 + +ModInv = 2b +A = 39 +M = 62 + +ModInv = 5 +A = 3b +M = 62 + +ModInv = 2d +A = 3d +M = 62 + +ModInv = 5f +A = 41 +M = 62 + +ModInv = 4f +A = 43 +M = 62 + +ModInv = 1b +A = 45 +M = 62 + +ModInv = 1d +A = 47 +M = 62 + +ModInv = 2f +A = 49 +M = 62 + +ModInv = 11 +A = 4b +M = 62 + +ModInv = 43 +A = 4f +M = 62 + +ModInv = 17 +A = 51 +M = 62 + +ModInv = d +A = 53 +M = 62 + +ModInv = f +A = 55 +M = 62 + +ModInv = 59 +A = 57 +M = 62 + +ModInv = 57 +A = 59 +M = 62 + +ModInv = 27 +A = 5d +M = 62 + +ModInv = 41 +A = 5f +M = 62 + +ModInv = 61 +A = 61 +M = 62 + +ModInv = 1 +A = 63 +M = 62 + +ModInv = 62 +A = -64 +M = 63 + +ModInv = 1 +A = -62 +M = 63 + +ModInv = 32 +A = -61 +M = 63 + +ModInv = 19 +A = -5f +M = 63 + +ModInv = 14 +A = -5e +M = 63 + +ModInv = 55 +A = -5c +M = 63 + +ModInv = 3e +A = -5b +M = 63 + +ModInv = a +A = -59 +M = 63 + +ModInv = 3d +A = -56 +M = 63 + +ModInv = 5c +A = -55 +M = 63 + +ModInv = 1f +A = -53 +M = 63 + +ModInv = 23 +A = -52 +M = 63 + +ModInv = 49 +A = -50 +M = 63 + +ModInv = 5 +A = -4f +M = 63 + +ModInv = 38 +A = -4c +M = 63 + +ModInv = 4 +A = -4a +M = 63 + +ModInv = 50 +A = -49 +M = 63 + +ModInv = 2e +A = -47 +M = 63 + +ModInv = 29 +A = -46 +M = 63 + +ModInv = 10 +A = -44 +M = 63 + +ModInv = 41 +A = -43 +M = 63 + +ModInv = 43 +A = -41 +M = 63 + +ModInv = 11 +A = -40 +M = 63 + +ModInv = 5b +A = -3e +M = 63 + +ModInv = 56 +A = -3d +M = 63 + +ModInv = 34 +A = -3b +M = 63 + +ModInv = 1d +A = -3a +M = 63 + +ModInv = 4c +A = -38 +M = 63 + +ModInv = 1c +A = -35 +M = 63 + +ModInv = 3b +A = -34 +M = 63 + +ModInv = 61 +A = -32 +M = 63 + +ModInv = 2 +A = -31 +M = 63 + +ModInv = 28 +A = -2f +M = 63 + +ModInv = 47 +A = -2e +M = 63 + +ModInv = 17 +A = -2b +M = 63 + +ModInv = 46 +A = -29 +M = 63 + +ModInv = 2f +A = -28 +M = 63 + +ModInv = d +A = -26 +M = 63 + +ModInv = 8 +A = -25 +M = 63 + +ModInv = 52 +A = -23 +M = 63 + +ModInv = 20 +A = -22 +M = 63 + +ModInv = 22 +A = -20 +M = 63 + +ModInv = 53 +A = -1f +M = 63 + +ModInv = 3a +A = -1d +M = 63 + +ModInv = 35 +A = -1c +M = 63 + +ModInv = 13 +A = -1a +M = 63 + +ModInv = 5f +A = -19 +M = 63 + +ModInv = 2b +A = -17 +M = 63 + +ModInv = 5e +A = -14 +M = 63 + +ModInv = 1a +A = -13 +M = 63 + +ModInv = 40 +A = -11 +M = 63 + +ModInv = 44 +A = -10 +M = 63 + +ModInv = 7 +A = -e +M = 63 + +ModInv = 26 +A = -d +M = 63 + +ModInv = 59 +A = -a +M = 63 + +ModInv = 25 +A = -8 +M = 63 + +ModInv = e +A = -7 +M = 63 + +ModInv = 4f +A = -5 +M = 63 + +ModInv = 4a +A = -4 +M = 63 + +ModInv = 31 +A = -2 +M = 63 + +ModInv = 62 +A = -1 +M = 63 + +ModInv = 1 +A = 1 +M = 63 + +ModInv = 32 +A = 2 +M = 63 + +ModInv = 19 +A = 4 +M = 63 + +ModInv = 14 +A = 5 +M = 63 + +ModInv = 55 +A = 7 +M = 63 + +ModInv = 3e +A = 8 +M = 63 + +ModInv = a +A = a +M = 63 + +ModInv = 3d +A = d +M = 63 + +ModInv = 5c +A = e +M = 63 + +ModInv = 1f +A = 10 +M = 63 + +ModInv = 23 +A = 11 +M = 63 + +ModInv = 49 +A = 13 +M = 63 + +ModInv = 5 +A = 14 +M = 63 + +ModInv = 38 +A = 17 +M = 63 + +ModInv = 4 +A = 19 +M = 63 + +ModInv = 50 +A = 1a +M = 63 + +ModInv = 2e +A = 1c +M = 63 + +ModInv = 29 +A = 1d +M = 63 + +ModInv = 10 +A = 1f +M = 63 + +ModInv = 41 +A = 20 +M = 63 + +ModInv = 43 +A = 22 +M = 63 + +ModInv = 11 +A = 23 +M = 63 + +ModInv = 5b +A = 25 +M = 63 + +ModInv = 56 +A = 26 +M = 63 + +ModInv = 34 +A = 28 +M = 63 + +ModInv = 1d +A = 29 +M = 63 + +ModInv = 4c +A = 2b +M = 63 + +ModInv = 1c +A = 2e +M = 63 + +ModInv = 3b +A = 2f +M = 63 + +ModInv = 61 +A = 31 +M = 63 + +ModInv = 2 +A = 32 +M = 63 + +ModInv = 28 +A = 34 +M = 63 + +ModInv = 47 +A = 35 +M = 63 + +ModInv = 17 +A = 38 +M = 63 + +ModInv = 46 +A = 3a +M = 63 + +ModInv = 2f +A = 3b +M = 63 + +ModInv = d +A = 3d +M = 63 + +ModInv = 8 +A = 3e +M = 63 + +ModInv = 52 +A = 40 +M = 63 + +ModInv = 20 +A = 41 +M = 63 + +ModInv = 22 +A = 43 +M = 63 + +ModInv = 53 +A = 44 +M = 63 + +ModInv = 3a +A = 46 +M = 63 + +ModInv = 35 +A = 47 +M = 63 + +ModInv = 13 +A = 49 +M = 63 + +ModInv = 5f +A = 4a +M = 63 + +ModInv = 2b +A = 4c +M = 63 + +ModInv = 5e +A = 4f +M = 63 + +ModInv = 1a +A = 50 +M = 63 + +ModInv = 40 +A = 52 +M = 63 + +ModInv = 44 +A = 53 +M = 63 + +ModInv = 7 +A = 55 +M = 63 + +ModInv = 26 +A = 56 +M = 63 + +ModInv = 59 +A = 59 +M = 63 + +ModInv = 25 +A = 5b +M = 63 + +ModInv = e +A = 5c +M = 63 + +ModInv = 4f +A = 5e +M = 63 + +ModInv = 4a +A = 5f +M = 63 + +ModInv = 31 +A = 61 +M = 63 + +ModInv = 62 +A = 62 +M = 63 + +ModInv = 3101a89b97a9ed435eebd32e2f90259e6343fa83077ff9288fbedca82d9cd56d8b9dbbb6af414e02b0d7b3d33326b9f4f5ff43b8ccae05bc95ebf3a1dcd0c818c65e565a5f75a955a7f898a99c6d80bd333836d0c2dbf651561a79939de45a0233343604c97d5fcb71c30bdb478fc23e288032dd69473652207b7bccd8e1337ca1a00ca6bc1d5ccd671731febc7e7e7b8893654067921dafd9341d80510ffffa434f82f42adf11a12bbf31fa009ca971b32da9d3154ae224395c7120de268e5ada41f4fb50dcf671b87789a334879bd733027ba5347cb75eee1d802b4bf0496e51e5da203e9038caf65daa7479ec5e3992fdf38ee565e8353a0dfa6e036a7375 +A = -d7 +M = 42af9fc385776e9add84f39e71545a137a1d50068d723104f77383c13458a748e9bb17bca3f2c9bf9c6316b950f244556f25e2a25a92118719c78df48f4ff31e78de58575487ce1eaf19922ad9b8a714e61a441c12e0c8b2bad640fb19488dec4f65d4d9259f4329e6f4590b9a164106cf6a659eb4862b21fb97d43588561712e8e5216afcbd04c340212ef7cca5a5a19e4d6e3c1846d424c17c627923c6612f4826867323a7711a8133287637ebdcd9e87a1613e443df789558867f5ba91faf7a024204f7c1bd874da5e709d4713d60c8a70639eb1167b367a9c3787c65c1e582e2e662f728b4fa42485e3a0a5d2f346baa9455e3e70682c2094cac629f6fbe + +ModInv = 7205c1777634d8c1940e8404207f6bb5c0449c22e1328e99183789690dc3770fceff4e053ca2e3c45670cbe9f266019b4860c8ace723f550f89abfd50ffa655ee1839fa0a40a47a54a5110fc32de244bcda9afa95df03d778d7a3e45632dd594906bf0fa1709811ede9172ead2d298de2369fa16900f3304a5acfeabf3abc135d75067d249e52c176ae86a6c0abc367c39b4e1af4463225f5b179c0dec0f480f0b42ae0458117c7c0b43768d88810a7db97dc9f72dc19a50cef314594143022a5e7edee107f5dbd688022aa1a16f16b0e13591fe965b5d80d19600bffbd19df08c8cad5326b8628b5d75675708ed0c0d39c0aa1c53c69867062d423bdd362a0f +A = -f4 +M = 829e07b0829a48d422fe99a22c70501e533c91352d3d854e061b90303b08c6e33c7295782d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86fe8624fab5186ee32ee8d7ee9770348a05d300cb90706a045defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2ef8acd128b4f2fc15f3f57ebf30b94fa82523e86feac7eb7dc38f519b91751dacdbd47d364be8049a372db8f6e405d93ffed9235288bc781ae66267594c9c9500925e4749b575bd13653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738fcf1822ffbc6887782b491044d5e341245c6e433715ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99 + +ModInv = aa2dd3af93fb22928c8e81de98e5071cb94a9f4fea58a9f54205891a8fe0a6a83222538e31001a0190c9ccb4b51c23c02d602d725d6a0a0795b0145581f2be8d1767646123e3f9da6278966d604aa5e5411fda7e10166eeb7b047858bc65830766b48ff388d2b9d824b8a8461d89e2254d12621eae63570e93addf658d814a32a47a1ed8ac30bab08340ee74809d5812fa46e48444a9349ef04289358e672ea9a043a0c72f590425d922a8b00a0e8dcac5eddd2d22c54e7071c489d293f93b99e37f4580d881b9e6a8dff775891638d8bd0ce4d0fe8e1da95096b6d9223af6a3eca1df392aaf5d8803f5e1275f50baf1b819232893d8cebb28fd7f65fba9d2 +A = 3a09 +M = e6c082844dbc0ca65423a9e744b24e7f61701e1607b1c4b0f913063c02e56756a3e9570edca4eca92d04a31b941f4360908405d45c39a39ec353c162e917d310269470d0718c1afdd9a78d18dff3934223aa56a9b7e3ea1d1d784fb9db434b610b1631e941aa79e6edaf80796d3bc4685ca8af852a5fba444adf42b37f5722051e2670c24f6aa83bf36a147c2f7ad016edc5d467164890d49d0ac1e5b8063831360a4092b850ad7eb72f8263f65da874007cb47cc661e97589ca4a07c15471a4517d6c6694f229359b154881a0d5b3ffc6e35ccfaf00103f584ad4230824d215ceb3a10b3510b0b46ee1da317017a6205738d16018366cf658f7a75ed34fe5 + +ModInv = 3f7028b7e1986bc3c433216493dc35d151028e29e6fd083ce05b134804b7f0a2a39144ecd3c22832b2b804149c900df61151832aca5b01a0fee66d05d1d4487cb8588a090e35f62144f690eb628f00522121651dbc8e4bf3950249f0f5f6784d58a4ed58ea4fd8337976ee93e13fe5563e2e0f37e9ab5d1ed5e23443573d122c1d1e08fdbf2d57a086440377b6cd30a8550d91cca4ef9b28c1159db747ccbb75997fd5b43b24b66d96ef7eaa11263f0dd76b19ae84fbb9b947e141b0d8293e8d03011956bb70b4ae88bb7e381da21088423c8b3f7b71fe2c7a724f1e120493caa9ab4d375f4bcf685ca0d9fc651af2046f63ba5dfb670f41598a6424bbea41 +A = 7687 +M = 47fbb36583d61435bb5c11e95027004448a6a1c5c7d1861674518de3bb41b36bf82959cb01c357b9c7e435396bcb8fac9abb0c3478442b4a8aa593eb40a9b81a070205e323bb2abf00188dca22e4c76237dbe6b03da701c632976a10363c5f972651dafdb119a9ec801bdfdf2965b3819ad93b21e6a46f1c670ea90d243a163cee5e2c2b1e1885283b73a66c2ea417b99de255f386825473b7a490f23b2cc4b4174a672b5ebaa061076dc3ba6ace6c0a78250fb339a4769ddcc6f8efb6fbfe8de4ab47558298e214b044d79acd8acde5f6db1d76b6745180b65386569c803601a5ba50ad38835eddd6ff552fa73207237751aa4462ebfc5f915ef09cfbac6e + +ModInv = 26833790803a7e063143448916a05619d455be8543aad805505ae6e7d87efe980069d2a564257c6082273c69a5271b50760f59db66b33999e643f1be3a786e706d1d6cf8d565eacfc4f5e275183dcd97d3fa2018623461273dde3326f193c74b21039a9397c1417193d228f9d0495423c64a41d73db47a4b01a9364e84e4d2c941e14b31cc3b3e57b6fe60f14b500794c83207829c0a7cee5a31c803a46e1a2a67eaa05c3e11953887a654c39cb0d579bcd195de7ac0b62fcb259e4c05e9bd97abc12f7f86f3991f79f8db5b7367e335979c1057f12bb24c5fa939866a9ef0dce1512484c1a7f16b351e4788dba03385fd1c365c4110d254e2cbb26f8280ad +A = 9247 +M = 5dbbb7894deab44d88450fe8dac663f0e5865031e875ba224c06013c53d0e30109c207953b00b00b54aa22600fecc19d02fc90708cc1b6f829d29f3d4806c2fb7f6f5ddc2c2e2cc49104d074f942cb220adb0a5cd2875ea96ec2b34d984bffaf949e5e2cb7362c74f2e2ed432779eeacca7f0dd3ac535f489b340f6bd7f50361b0ee095ae6a2289a6ab329238123e5dc3383836b9f15c40b680c1c5c74e45eff1e5befbedc25e6f3ebcf12f3d06f863fffc830137a977753e8eb437d763fb9854a965708ceac392904cdefcf84b683a749f9c5470b9805d2d6b8777dc59a3ad035d259766bad0734c2da8003cc0f2793fdcab87b89296c6dcbac5008577eb1 + +ModInv = 33bcb9679c5ec453c8f82ff6ce9b35f8bced47788901d94f5d930d2a94da6f4febc3600f5314a22cada6d23f18d123e78dfcb19d8ff11ba3ca7454c08effbfe8b11e0cff58a97193d78da13ea3afa58da52798179c22d9ae4783141322981ab921e7b86d164850863e0bd2e5925a010a98f2b741556429d0b690ce2894c5ea9e51d488093e21aba3dd404aeeb74779235c6f93a895eeeae4a8990bcea8043cad8b514af3e70acaad31912dcf3fd360ea602a9fe5eed10e09e2b26778bce76c2e55f47bf106b157ebf91f6ce2f362e5d5ae543c7b5bc823505c11014edbc9889604c3fbfe355d8a4e8f526dddc966f8a15821cf01f31ba13c56bebb9be7c4 +A = 5c8cc1 +M = 4b03900977a9f2c943862c199bd3a49d1ce2844948a86c51ce927e89f918590825511600314ac9aee9cf6b978d7d421bb1235c9dc8b64f4e68e5c85bd78d396e0d55fc45228f4bd571b0b41b5669a0729b23994395a774f0147f76f87a640701ad82a1865506aadbf8319b25f81fcec1496e2769e927e4bf156405372ef440e5c51e9a508bb1f4c9da653868e6d9ca0bc36c05adb3fc4f6341279a23bef7be506564f3a160712456de76aaadd6b855c6b62bd09e04924d52bc614bedce030297c5e538f12d92a28f17d83ce44e27424458b6b6043106a85f68b6daa8b2a668d605d4017f9ee6725ed09d3a0562d56abd685a48f165d57b00c7f4781ef86f + +ModInv = 129ab1cce85f83e6b58ffb76edce5a4f822db50e9f559f4772aa1a629c00a3d16dd534e1586d930ce5189c3242d254db60a178ec4c738391f0a8f6b01f5e33ef087ec1a4c14db5afcb591056d1a7dfb22f7e50320683d5cd93f76d6e71c7964d34a93b01ad68d64a820bb1f20b3dacdefc995c108fa58e1dbf3048e0fc5c5409966ac9fe3d49f424ec81a653beb485ca0c8fc7f8a636dcf3e68a365ab044827037c0be80daff67d0b6d6b3a697a63922ef80f3f5b36febf0089a7174babf781f394089099505814e656e87eba8882a5e5170bb1207c34a71d593bcb4cb9b89fb2cd36631bd845d2ce851b799756a61572dfb2052967f513888aa8a3b3317 +A = -85a0bc +M = 795edbd5f6d2f09529af81dda9da14f5079168e06b0c4f27b35c11b5aecda386a3a0b730d88fe1e8a4aa1f9db8dd8a3b09dd54bec7d835c33744af929a91f4873115cd425ec38f1389998869510db4a02517e1ff83ab26a2658f32521553e014be00caa7e9bfd00724a123cf493f0febddf88d1a6bffff9a39142335e9e266cea9fab969ec07f1f83a79af371d87d8a8f065a3f96f0e51436d1fcd68615c80690847dc159e6a409c38f26b68b48ebf13c171d0b0090d625909923fb81d2706e55426eae0d2c11c339464473d212ba950666d8a4996efb447c0ceb48438b5c41f9dfd2cb85f3f4a24e39a5d998017f5e2fc574dad2986ce8349606a06e9ab + +ModInv = 56262c64c22d3318f58c4b7374560d8a0fe1e33ca3a37bc377955b32c228a5d26cab03fb8e1dc4e4143cff63bec3521e252b45542b40f37969b71b2f2cccc6f80e1629bfbd0a747265f33a34cb0316c84425ce6192591ae900f673062eb2d876350c52da88f8e2d1e5b9feb2c26c8fda046219bcc3ffa9e9a469bde5316129c9930cbdd1c962a9ea19b902c2a647fde313cdb68945a3eed3b21d502b343f4b30afaec5b1fe2d3da946c0558ed75e5374480f3ed8197fb489dc0cbdb16a1bd4887019115b8b483be2eb4a6d8f51d8b42dfdb61d93789e7ff7f6c1769fbbf133b227ff1066eea19d83c0ac0b083982643f6999373a6cfb98e0b072f22be085 +A = -2e675f +M = 86d892bdb98e97ed2981588df12289b3a30967eadff1ba23814cc594557b386eca7367c7eeb2f9c6245a57be0cbf01b4a96c43d6c44a4c87f36ab75ecfb53752145c7e60df30d5f61954c18fd63fdf8d53b0e44a6fc9ad7785adcf7dd28333adb83c81fb58929356cc2e5d93bf78bc1d89773341fde73cc608422b456d913c0bfc13cfa2f9f4f1abd893f796ef6eddae9b602ca106edc9843faac32f9525acc10a6c85a8bb9b530e60cb1e353f29b11f0de6e6342c1c40f919043234c93c43b84218e3089c7a755530004ba417007ad25f922ed764b27e790e8ba0d0e9b47d50e092f3b08f6932ac2b623d4fa08455a5b46572e63ac7a95383221f70d5dc + +ModInv = 7d5d68d9bec49dcdbfe0821e90d494000aba071f062ef84a2bbad5e695a08007ef402f82aac8c760c2cc0cab249d10ed11e81e6fd929823c3bf374a3c18101c4ab6b68e7a2a171e4f8c51397ab71d541b9652e9c7228f56a8de68d488362c40ce3239724cea9546988ce661867304040f494e2f82027f700b30bfd77653e819db914c3a9223d44007bedd2447cdf33f28829c214413baae0b2a29a43ec0fed828dd40e5ad8a2f1751d05030398cb09b35abfab513193849d79c8d172a165a103d1b0402deb6868ece7f5035e7de840be43bd58a7390ef517f9e962e0e929c1426fc9b5dcc6d7a535c26dc01330557880da3a9074cf2c3122a0760f8b73 +A = -608099f5 +M = 906748960b1203c22d128c999d75f349909e5f21092932df25ad16dc33307c48265a6c49686a17d2205b3627fc9530d16899bdb0511925535aad952622a2d2d4bbd563fe7ef91d8131e220bb921a9eb423864f96bf782a3ae88384a7f75bd2470b8c7d38462e52011aeb2842b9d326e9c250c4d7db9ffeafc4f1fb2337cb61c8adf6a6c4118327575b32776fead50db719ba9e5c47afca1560936e0b4f1fd8218adbcf34d896a8dab3189d51ec6c90847f9092a4d94e4f86d708e369b041747c23c1e3efacf3f5fa17dba8b6150ada35d1793bfb39a2ef283a4e0433b7df28434dee544eeb36cbb40403ed3511d7ec202ad7f20e07ed4202edc4bb895c + +ModInv = 317506f6f0c67b1da0c9c0dc121bafd009f98e29b5516834b3d9d8a617c7a4c62a5edd303c4c48aa00efc2735dcb0da00f8319434934bdd5f07ce02bc230565672dd3c6679170391979e6946d665b9bbb09c470aede5d4a693fda9f999e4733dead24e771f7b3277ccd6c8242e5efc05ab0103fe29b0b87434b840522b784130ea972d200156593be14c999d2095e2608dc826025251ad48b4e46183e4923978d38a7583a1b662c5813a7759413fb7e8fd07dd627f0618ab212d1dbd98bd061b1edd7ab6d0c84ab579b0cf309cf7e554122688509dc14c278d03be329e4a8ccc4c23ec15d4dfaa8df1be0637f420b20bb9b07a96b3eda4ad2a4ae3c1 +A = -2a92010b38 +M = e58b98e9fd921afe369ef033fec612f348d11107e33d4470fae2bfdd51be78090e574c27dd546c921e04932b3ee0e132ae6d1fc1c3c75de08e3c52ed51c83cc9ed90653147cdad4fd8b9fb81d0b384fe6d17a135ad5ea460bc60f7badc1e980d9b8a7945be3ac93d0d7710a3e61b6aa07f00725a84ab7ccb4f2ba00c69ecc7624d21a23b121e2576a2b7fb29ac445da3f18d394c483e8ef571fc2c397b20872a873c7488afe0f19af758bfe8522cbe7b80de6b34f189aa6f9dfb65dce7bb3348a6d7967bfaaedb9e2fbf496887011b4ee8a8fc75885d6f33e40c2fc4e158fb57a6e04b647a9d969146fc8893d73c43fad1272a253bb427c1a1da059d + +ModInv = 639be17bbd76cb8237dda74a2f504e56438132a0b744c89dcaa8c5888a81300321d3bb43d84300e6d2756efd3af64f2a936d8062bdb21741f40e64482052bf2e22b39a831c9d6bf032da5025e25a5b5ed36800da259dad1eb1df80e163cbef351b9fe00b596420a4ac64b7e9dcc5c993cf0d35bb337c98a9ee23f1220cb4cf1352c5c4b2085da9adc185392ff08ad6c70ff5bcf328fd5d5b7e9327115434c6f0389ccde43c304abbfa2bff5f5a1efc056feba3c186bfcec4f4668db711d673366373ab08c948836b3a2b8030e796ac6fd7aec7af3470ffa60972530122060bb3849444194aadc53ee5edafa2a3d5bf8ac4302015999644505283e6ec +A = -5b87684f34 +M = 6c84a0568b20b2b36458eb40b7e481cb92bcbdda2191ca539b751bf62de04539890800a173ff6eed34bca2b336796a5e50589cc961b0c46e4abdb5ca4f5c99c3a2fe1739dfa01aed96bb17562ab01b1fef0a3dc163015710cceb48b30f4a8a18d6be75b0b477a0778d4d45d6bd64b0f24155e48a5e8416160facfb49cd1d47f2161e84d3861abd5dc0ae699527aae362c6c0ac72006037d09c4f525558d9e5b64633e8a518b3cf3527a280ccd291a42182fd56459584375618334edc57548d5f4e620f38f49b20846c9025f8108797d6f2e7351df45ed8c55d5cb4226399227ae1d6f9f507a81949e60d93473ab434fed7e439fe07158ab795f38183 + +ModInv = 245b3bd71f6e6bf05081d6fa5d05423b0b0aafc1f83174b4aea3f7ddf1de9553ed0357cabbb0ab66bcef2b63df37d45a6128e1abf6d2d4fdc708ac67b24f78ce531bebc01d23993a395e2932e1e7c9d6242666a8f8f9f3f6f9f94aeb901c422d3773bf021d419e309890ad73441e4af76f9467fc31a51e72524a57acf4d8d8c5a615407dc3445a573f480c952fe1fd3a3788cbdd91ef08b881fb5f7dd3f082cbcf16feb755115f855a2d1f5b375dd5414aa854e7730acd3e31ebba6cf1f909a7e6db13056b97d1c8bafa445066f1afa5098d26a4ee4f89159ea099577b9a8392011ad947029a0ce4ec77030f3cecae5505eb61cf32838f3852405f +A = 945975673fcb +M = 29a0644f69a8162760dfe5bcd7f30f3a2172d255ffa25ec1a88bd3bb1ef32750d5e290d2b1983dd7b7f93b0c90939de095d391684a78f718fa1906f9d00763e21ca72685fcd2f2d526523eae481f9183575f0dc804587225120c155336f85ef7316abf401e4da81d152300502eb5d19ad08fa3cadd3e7f2d328ad50d9cf6daf644a8fdd992f7f575ee364fb505d6e19e9cc91433b52c97a42a03970f2eded7213f6d69bc944c3fe56c297e8709fec007546dbbd1a1c00970d5caf6be44db9be137404546f1417059300965c313063d20dd02f434d24c28aa10cae2a318d8b3f637f221aa2078e5484d14663ecb55e90827174a8623121de0bbf37a + +ModInv = 77714ac8845018cca5bfe1789ee3a941d3c0484e85e533b905eabda805ffc3aff1c23e6796e66662779e0b936c0733f0b02cd73d00318d9bf40e7388a522687b0f8bbfc0a2db2dad09107c2d435a60cbfef29b4ae78959bcea85f64832aadf2afe3431483adf729e05734c9e7665aaa58c307e0b6ed97f4277eb1b61893e6f8d881324fafa29598043eacc0ef690dbca1c9d2f18587497c2963b8e45079e30c11d7611aa6e77d83f03bb67cc27a61b2fd4bd89b07ad447b97c4ab1e4e8a6484233bcd0e0a72ae51326f080b70f2ee06df125be12f65943d7ca8dffbbb56a5c8324adb2bc642c40c5514a9a75ebe6cdf47e086828104e793403e017 +A = -1c80a3b1799d +M = 89463e759cde66bacfb3d00b1f9163ce9ff57f43b7a3a69a8dca03580d7b71d8f564135be6128e18c267976142ea7d17be31111a2a73ed562b0f79c37459eef50bea63371ecd7b27cd813047229389571aa8766c307511b2b9437a28df6ec4ce4a2bbdc241330b01a9e71fde8a774bcf36d58b4737819096da1dac72ff5d2a386ecbe06b65a6a48b8148f6b38a088ca65ed389b74d0fb132e706298fadc1a606cb0fb39a1de644815ef6d13b8faa1837f8a88b17fc695a07a0ca6e0822e8f36c031199972a846916419f828b9d2434e465e150bd9c66b3ad3c2d6d1a3d1fa7bc8960a923b8c1e9392456de3eb13b9046685257bdd640fb06671ad1 + +ModInv = 483a4b7d65c21fbc1ad31544b6e4d984b74bfad3c38ff4bac76fa7bc1520549ee33deb1509cfef16d7e62cbea7e268a1cd6ef835b882881fc9fe6aab900b6c0312bc57857a6d51042feabac5cb9fdc4114ce8609fc02b749dc02288d6057a63bd96f5e8b62220d2fe702a7dae3fd2021dc5b04b7d7f9556cd2e11206fe6ed981a6451504126837578ab34aa7a8f373ded643a0a14e1d7431793aafb880307761d135aa95337241c02b8d5b9e70221d892814b06783e8f6c0a4b02e9ba923ed0196969ae8ff948853962304e94cd4b13fa98ab95ed3605843f628c4781e87306dc5c64a83e4b333d585f75afde3d2f4b1aad1cdd9843af38be8b +A = 50c1918c541241 +M = 2360a19f4fe3486cd8f9e61405799236397ee1b85e41ef8f259603b8225aa5e70e1e43d7f5d7459c3ae43d13adc3d7748e5e1847b9c15676dc9cb2ddd7d956ce7284efb847f44ab04b8a8c52c215b2b9a32f0e7d56b620fb877bf35ecbbb29bca53cac1981697fb7009621e919461041dfb66c7cac7212c4ff1d0727ba023794291678c71ee427a88c338232a8ddd9adef0e8e7af51f82f83e7ac323a6a737d214f4386c206fa6399a757e3a82b21b8666f7a8490f89dfa4ccb4ce8b1ad2f7517cbc27969b142a677c0b6f945d78c3117314b6c006b43155fd43815c2a41f03615cbcb0cad1e4d60426388e7e802b627ef1d8e91579a21c3a39e + +ModInv = 22c6de4d67a1dcdcabde7c7284eb7524e675975d8e90b8f86e45fcffcb057bc8b25dd613a57b447ede0903ae314d449e42992ba4dfff74a708f70fb71badcbc410807577f84edc1392451183729c29b105806ad49c4d9811ed75a256cb05e1769a3a84fc131c013ca86595a52ee9f7d0259d7e14ed090d0f9204c2168bb47722e363299034efba6622d5ff1210a28d601d229ecaaad2d4e1f76647eade51bea401c61f949660d940e4e5ba9d8e05b1089d2941ed06945284870f836ea115afe48fd9bc87abce2ac309508a0daa6f1db00b0f299139cc9ce44149ad0684d01d21aa1e9f1ab629b0ef338d45c0d0e7f107117aa7fd36cbd9413142 +A = -582600111f4efd +M = 98828a6988744148fe28902fc85a10c8bc6ae8c2340ac535d8c4a65228ed34cd5c879d35bde0e8fd46e68b5591b9b01a48d069b0d174a94834c30d650b6e9ecb1d5f9d6d4278f234c256f63cbcd3660802aea7c5f31d44b41dc45bbdbddec5bfe2c65398952f604585c6ba9c6e0b6c59d51d1880de8223532e62b9f9f0943fadcd4e07cca836666b98e85f0635a092c780ae49346aab9a4130c7e437eaf0db15976c381b78fe811870038bcd1acba164c2670b9f15ecbbd6b49e746f25d42783770446a32f42bc66323ac2232d710b7880d7ae0b65170cb76f5acec8129282e394bd8dea3aa4c08a607352d095151c4a09caeeee318369ca47e7 + +ModInv = 460d9f6f146457a599f34dc12bae9913a260157ca1dffb41d818d0bcd59a2db962fef20077193b52ea9a0a9f6e9430f970703c9d630ef4266435a690a4773e856dc313cc450f8d63914a71400a10d25c36ab9813c28e14b5cbab3ccd88c5e35630d5e2fd7618e971b15e1fcf04de0fe0acfa33808d1baf1061772c6308ebeb2e114da25122d5f3340837e6d501cd5e86bfc807b4fab6ef7175204584129c23726bff81c5d2bb1e3c2c5c7c3f305f693e8d58c9bfbd85694a09f388cfb6bf71157a60c756f0799aa84afc91c0f80967f9cab7483f2beec04dd2df171d90ddf136101122465e97ceb0f085ca5c5732ac49b6d2a8aa2fea1f5a8684 +A = db0eda7f5e8e61 +M = e92a33797ec01b156412fbf38759b33784c26f35d36bee159babcc7bd2d244246227566312953a2b299501773fd26e27a042d532d2c3a4a3bf5cb0c9ce70cb3859655592002fd32ce3dd9a9a6d5bb17221a81062a1d3f663558eed6042a1ea5723e816c5deada28e9f8b6dca3d159b84bd80e4a78cf19a919f4efcf5f11454340c5edd4053c7f8ed95981198da733060458c38ee2c0651c02d6658f6f004facf1de91937f9a9d34525ba58e0aff5273fd14bee272ba515d25ff68e83a364ad2b6e443971d00b513fbea089daa17b15cee28d547e1371f867f338c453b92e79219369b14a81b53e13272ee40c58c9a32d60b15d357ffe4423f60d + +ModInv = 15d681b685db9c9a658abb4e9ba8c3de7a6d39f637ad35f5969b41c04e90f488af8b324f9c23c961fc604a5b1d47696a3bfe96f9102351b7cd9e735917a084eeffc65f2d0a7184530ee0e191c405f9c1c18547c3c1294699417ea23f36f5500ad442cfd2c5fbe9d22fd67b03631ab84ce587aa6046227b7de28b0112cd8d5ceb43f5a68af62cac03c58cb285b58eb3897b39c449881adbb1fde135a46be090b2ce07de939f567393bbb6206f69354499c84ae50b8a029bdc207f2449444a0c9ffc06a37302de02ede030d640adfeb10256187903bc923a2d3afcf204c7342191c30f30619af53e36733922eb471a43fe2fc18441e90366ab0f +A = d92b0703f7467ac9 +M = 222cf9394630a907682e332c12acd6bc95867cc21c36ea30cdc7b304181038fb0bfb9b152cabb40369e43cf819202c039d628f3320b6abf75d2f4817e871b2760f37ff77028f049254322b51249d6ae87a180ff4f32fc275173f25b185e6e4b3f462aba80c27d77cb7ed8b795f07c4b9bcae0e7f8c627884952306d0648e9699bf94fe0638edfe1b1c0def197b35fe3633929e2e50c250dfaa05bbc887350c297492e46caafe1ad57b41648338a4aa0f71565d0d6b11549f109e4369dd5feb85b81831b3953b1ea24db513f6156baa2f31ee53ebb7fd1548d38af01f82c4855eb54d17951e85f5a4d1a731bb3679428f9802f16d3d8f4c29e7 + +ModInv = b5fccbdf0a8ab50470e2a7579c6d44b3ecb949911a38e8e8a49140ab4cd840f2360a5bbd8c2e988c60471b627d682ed391ae07df686423b57848e13b442a316331a1f4abcb08bb2b70d9cdced324e4369343a3cd08046b9ee8ec766a1071eca6628e3c3d2976b9955206c374bd5c74cd25668fb159832d3c879052ad7e70158632492acaa97951919b24b1429a0a004a3cc4182e8b12363085b039429e7dae6bbcf41b221c1c07653ce7c670c55b9b73bdd714172a191d0b8479bc5bbdc90b14f9dc634e4bc8a9113d7a341bbbe11202c14eee44d99777abe479746cb1c618d70abc30628365a80453b66efb9a7b7a18d1fbe3f99831ff91bb +A = -5e2502420ae59635 +M = fb3cc2fb113840f0cb83f39d8d84a494b9935b5f3d5d7476ab6e3edbb296e7b86e2d42cc5fc3301bc682cd689a6d2d5932ef2a6b129616c0ebd020d033278a3a9efe4882698e6a7306615d529123b14604247c2a1690b5936923ae1c399dc3c7eba5c83846d03c199d4111b92d8bde68de7c5b8488aee8a14495c26ff8b9bf7bcbe1cb9068a7c0350e1bdc447afa1aed9f65ef814760c3454a5f71aada9ab664e7e991c9548446b9e52a539dccbc532a3dddb3e9570509225a60c2e6a3e24cfa40d55abb44a2d2f0416fe1ba56f96678d0fbf047634a4d9d417a343f8dfa057b26523b7841839dc54e399029b404f18db99af4974096f5b0ee + +ModInv = e61f39fa92704083356a97f3d425237d3f7762e834ad09485363f4fc7c9e8c21e23b8ab92f38225fcb9e0016593825c4128ac071d95acd55b8f8ad615e1597cbed6deebadadbdc06bb012227abb95116b0451f6068f379fbd187f686316861df0a7de63a74556d23379f3fb2b07edb0dbc5e5cdce6a34ff483eeb886a8208d4f99dd23f19d98ccb0155a763896bbb25d8fc43075b3e9a033e0c4ab866142771b9efbd06a6f9dc72b2c4aa7889b12d197481582eaa9a3255753c7656b16cbebe9f5a33dddd833a3706437f79c2e829d3e198ee769ad88dd1e9185eae5cd53bd09833f455e8cf10bde75877c4f9325f068fc1f45dca7ec2849e +A = -3278e0a594ac807a +M = 21200f62ad72c46d9d3390235d28a2a5a8135cad9ae9d4f88bae09e983c2e073493e3156eeb9d3cee89aed986c9cab30732c15c8f54f6e3ad74b274812de3cbdbd2f37372208df1cf54d47f181227b276dc718966baadd56f7c883024c19e4ca550fd5211d5e2a4901a8f12fae606c1c33a8e47b398db4385073ca374712cd0706c106e852784f547736a6d1a67d599072032e93321ac7ad0a947b585bdf30b9db48af5a426b4596fd9d866eb2cdcc0a927337ee9ff77badff42a2a94de07e1ef7ce2f622449b515f5f181d8665a7b685d67c84558730bda743141cbca0a8c81db337fdf27f24cdea7fb831e4da4581ab3bd02344734aa53ff + +ModInv = 32b19620cf64712eefb0f61cb9d256def4fecadad0bc76218379826d6acb070cb24e499adcf670d2b3afa3a0be134627ea267da11d2bbe0072f598f9e0190ad00376e12d1b591d2db155a495e28aaa15bf48a95fa6fab8b967a76a6cd545d6e7842ee19baf4b1bed4a90b8938ea41999ec5ef70d130e4fac546648dae40cfee106e4f09309e8ff3565f3277491ad54a1f85c6071312c853e5b3fe80da885421000c83cc4f05f535b64f49fc311be2941eb107374066840f9b383eca489bb8af71b9d8d89843eab2f0126bc3357ccb1de966935588a244f80bc80f6fdae4f4769aa89dc3bfec2f73f6ec432635630293d362697681b8a4d2f +A = -a11ff63c0179e58217 +M = 4e98ce51825bed805bdba1fd6d483bb28cb7c2ec23252e50be0d6c874bbdcdb536b8ce19e4426ad365a2a36c755849e2c509bba607902b9ed0a0b94e16bd0467325d62f58a0afd773820c30d4395e19e96c0e921f3358da90bb44eb99631bbcc1afc52d22cb0327c10570e51ed7a429f015e2d1de96ca3ecadf167436726c87d156b2102064cdc2db8a65eba32c129e670a6383e6aaf1061dc80372e146e902c25be0914f9997523a728f840c73791d7d1c5554eb2db3722338ccb9cc3b82493cd985768a1eedf23cdd29d96e9a60be9b440d80f44c6267afcd40b9d34194e2904506350afd60b62eb86b18089419f936769fc6f9cecdeee + +ModInv = 18245e853a9434541df860b0190edd99a1d8e60ba0e1e98f7d889aaed0fb5d3a61787656f1436beddb47629db436bf5531b3df9c5560d0ca5b06c00bf96605e244a1ad6a8a90d29c93978332e0281d9e493d07a550cde7fe23e1c8f83d424fdde8bd8fefe334a3cfac37c9ca4f7a310d3703dc94c7685ed634a816a5df40d3dcfdc127f2ef8e60764c905152458240b3409b18bdc91ec2c1a87835d8558b82b4de35f4d3d52e6167939d8c1c6a3999dfad49ad643a5fee9df376f271ab5278a80213ac7b55cd1dd4fcc794ad25b1c36040f13f4da55217e4c69bea00f73d88e419ca732932d69001f0d212bb906f12e0a0a3335dca131a7d +A = 4949f1b6106a2ca9a3 +M = 559f9a29dcfa53efc78f242905511342c26123bf2724a03db3186e860ccbf27779de4988731e5c6a65e4370d3a4257f1a29c7c97df0a3485ec0dccabfb6ef5ac3b0cb8029e1ec9f75dd0dfb8a702443993b0ea755e16b68d59bd96c1b0acb9882316097d1feccfcbd2ea73f0af93ec30cc340ced22a2d550dbd0ce07bc997fbc8741ebde28c002181ce72dc741c090f30bb59287b1f1f7cd9f95da6f792c8716a7da21a232638fc0439841a97796606e8f98274be2aa8420126df3f639bd3477e668dec36fbc5701a3b5fc07d36d788956c259feed4392a78d1f5291716ed94c875a9fb5755d2835719afa40384e79cfd83f117e83a52df2 + +ModInv = 2413ad04ca365a492061687bdce31978e41fa12b2f73070a07f7a2ec112466fb1e655df43c813af95793fa5dff3c7bc8fb36bc38c274bb1619eabbbb88f603f55053ccbceb68c60f5adf19caeb2e1b498678030cfb5ecce71e2bd9a520181d61518e7ebdcdc5e27db742354ab88845e5177aa6253c3cbd43085bc0b2889cac6d7c6734cb397844e4656faeb1ef816fc90b6f5480e4681385b35e5e8e3ef2ec731740c73d7bd1c280844e017a5ca1594109a6fed24b5851c792c00b3be6fc5fea8a805cf05d63d1b87be2b901f0008c1e87d77f60b46fa8bb41098e952b6cebc315de833582d91c5242c3857c6b282c0bd8992240de229c21 +A = 6f4fde580f122088a5 +M = 3309f19611cfe3144a86416c3388b1864e6dcd8bf329e95f7ba3d3659a9b09f451854e6dab2d2b83349aacf59d7c2c39fa28ba7077d05b92b27ef7ce34c78522b5c13535026cd9c8e162c944061ac7d45ed1c63522bc7485fad7244062520fe2d7c7bed21cbfa8a88741f18607ef6d7b81421b99a38325f7753be145b4734f80ba69f49c684b77142acf34a7ba68cc085d06e09ab6e6b62511cabb59b74f465dc8c615dbeac97d8920c1cde385c77bb777f216ad2f29bda57eb2f026d7ebb4e4ed308edfdda2d23ebe8964d1185e5ea58f78af9bc8863285dc8a5da4fa7ad3f5418ef89a4b4648a8721876c8c975ccd53f0a3984ec7d4222 + +ModInv = 11d92e1fbe4222803899a51d46c077565b1cfbe88020811081b8022476d62137f2e70cc87f92503a1aea39d84884399460fdf50082f167dabe06b09c868db98501621755db78ed9bfc11b4d80e753410fa91264e7dd9ab266be78c053bc60d4d5a7771a14cf071a7e264776536ed130e6a60e9713b2a36a4cd580d51d7a3729fa45b482639493a8576ad3fd8109f7fc935a45a1949194da92d1a7a766f3d4c9ca76a0a673138d1a692ddf9655ceca1236c47ce5d28bc2c20ffdf2c99a2bf7ea1dfbc85d3d438e3b11f29654dfe14e3646a8f7f0e260c85c93ea37853b0a1a08424db219ce6c936971daed45a0f4e39bad0ddd88e337465 +A = -9828c83edd4112cc16df +M = e7cb6d687c4e67f13a21404cd2cd8c2f4c576fb27e89767f590d3e97ef771a598c10523fafc659a29ca12b7cea3794da06695e5fac4c4f387b56a15ecd059e58cf4b1e44f65b4c41075f0ae20dd29c6abca8e4df767a95048dd84fb9dff24d514e24368175e77c175086b94b9da17ac5bc1b4111aaf73e726ffc96035e5a54cf1c40b8748b9bad38d4bf67cebe865fb127f40506ecd200a23619ff24b42dc5614454173b8650d157c3aee9b1ffc1adb3f2468afd77804cf9e0781b210623929946349ffc55f8e3af7a8e6bb7bf3ce8bd56968c4e93127a5fd4c6549eaa87fd8b41e63bb2ec7273580f58762faf2ceafd4c656dbd0558b4 + +ModInv = 77fe52f4deac5617f1b8bbd1a4c10b886451342d38eb72ec54eafdbe769ef53fee8d3b766251805553a9ade97a67f0d41816df7a4fff7d49427d2a3ed941813e5dd750903b52fc7a3541fc813047ab1c90bfc9e1c75f0b7a68bd7522c7150b0d0427548426b8720ee10e548279735a186a3cda72a9cd219796cbc65a957d1fff390bc447261b65c192ed932bf496d686bd9c70d1fafdb946e04a39470e7c33e6fa62dc645cacbd264d7ea2ae029f989188d5f708ad8f26ec53a9580901eac25f3fd43edf894d5e89fc0b1f5b543e25895b0502feb8714bcfd120e3f495c17e4f9d4df3242525c19cf55c3be4113ab3a1ba705948b7440b +A = 808c1f492fba47a1fca7 +M = c31ffced853d3b0c86a0c3b543c1e4463c16f4edf89dc6455a45c6cdf6fd5ccd804afcde2d841437a14fe006230f063a9eca13215a4348f36f7cdd4bb5c20ee26799f4597c9682cc475e68b77f929576d92b75173f70c7db0c5225b64c807ce00347cec990de4c33d5e11798477fdb9196d3de43dba6aeeff197220e54e30ddafc13092e2aa17d6efba0f4fdb48b3f8d95605b7f8b43706c1fb2918ec411835a28ede26a6566f306813a3cdaaf12a5c7a20213695e57a1414e647505a866cd1c42d0fe736d479633c57cdf80212c2684950c16677de7c67cbb5a6d12d9b29d96345e044c3396cf760198b72ee2002f906bfdc17aeff54e + +ModInv = 3bbef810285a558dea0e531c1e2fcbe5b479965bf14a1752b028a38f624287334b6f4132f7e419b8b83dc9a4680ecea06f207193f9325a8da860e512993969623c349d172bc092e476037c20e266447c83bce41c4903ca79eb34fc1c5f79dc3fe98d8a095c129c9089805e4f42eaef748d93cb047523d6c2ffabcd4637a088f198747a399afda81059d8565af6c5d2284e014bf60706caa453d30b9693f0596bac0db3b7cd054ef9ef3c9499e12edd2867b9689d22b0290e68aa3db24fc19adb46e0792db4ea407a53257ad64d82c5d8277b0cf98b4a738dc89da1209fddaf0d0afe7ed3007b61aadce426691ccfe05a44115f539e03 +A = -8aba6364d94a354580711b +M = 944a9ed1262c5e240a27ee47bbaf4c3891c24a847d128704f689266a41d80104a192bf33cabc04101009a85ab03219f8a91d51862d7a143c0b9fff693651422d0530454385d434340a48f811390efa1e71a6a1d6775e2c4adc0a97b590e95a7483cd5fb7ab5b3b32eb6628b4787fef7905502165b42e9f0b6ba173936cbc250dc0de03d7142e90182bbb8789866bf22e2c392b64f2803dc5e12863a0b4de0dec7c139e368d31f034fd3038538db5edb4d8bf62218d21fe288cbdf39f1708d76d3226c2fc2ad08cd2b805065de18c5fedcced66baa786886507b35d79baf55e7bf0986bb92d99f5668744dce6e87db54807bfe60922ca + +ModInv = 18abe6e867deeb88e8864ebd3e02e08d0b2f985661bb4e646aa6a3d87cec90a9f05943a00944f9c2db76d1b278806ec0c2cbe5ea83c5005b6a6f2e4b1d787270006dd93bf5d3a6be758c984e3ea12ce8c4afb38cd12ea3060a1642cad349693d71325a45f6240d518a271cc8d22d12fba39910abeccb9e886c1c86f821dda5eac58cbd99d99f10a925750a89c7acb53aa1bda1f1a156a6abbb51e233c5276b96782fae35dc1f8cc68bfe5a4975520361b47b66195d8a36c8464ef35dda85f3b6af8b49e0060d4cc256f7bab078b8caed326f92cac9b9832e7d2b58edd74284f5194159903bfbc6facf254be44ff716a5cdf900c8e2ee +A = 740a77d6f1813481854f8a +M = 596e6edd209ed6e8d6c7ee83cf20bb46d66bb741c475f5aaede6e9fc4a378eb4959a04923c6c72a7e9d6b265e1d93ecf4b0772ce906bd2ef9267a67be6743be2670fc591fe22e60b6c06e3bc3a006247f8462f53d04754bed04db7def09fc753dad5dbc20c44fea529772e02370ff6071d668f1e45279471dbafe00e82214c43b249c016bda58390d8c836328e64134929269a6fbb3921da5c3eaebb7fcd4e03769e38ba4b395b9eafa0b8758ca749e6d34c5130c499e7e74676005de8cd9b28f0f8d7b56f8bc34f77a7ac3f03de7349547b261b0d4028cf032c047128afd5a32d777a9abd2a625c4cbc88126eb08ed72d0d568cec2b + +ModInv = 2e2e78f14fed469fc90ed82160abe5b69ce91cbf24d6b67bdc1e217a3b9b044256a7308c2d3a6e0ad48fff5051809a29fc7a74e96a15d98204c4078d052f92b70df8ea75b7b5d75cde45a11e55989eb657f0035c0ddab3a250217c3eb046daa0d6a9ea292d669986d7f78a754d859a250a547993f5cb5c1885392203b84af67235149ed1f3246df352d1a2051e1da63099f6fb016a8034c3230ae161969a16ad3a8db45492b9d8f9c6a74fafeafa251c5834b7ae8be842c4845ddcf1be8ec26563ed6b9cdb6f4f14b3e919621592b6f17b1389f411c2fa9f1399cb072bdcfd656e4483d6af733d629c4b8e7f3c8c8ec8b0a1a1f8c7 +A = -3083d49ef945e4b665c1d4b3 +M = 60b4925ab07f66af06d0bd1d700668bac287094424c8aa5d4974220febf3b9c71e8621fd55a5ce38b2f2c54e0df9d3a2b53c3bcfd7fcde3b0b03d447c9eb7849322d3e65293828920f32ed24f6e10781b171756ade3f595ae2f28836bde70c4b07271b166e0f71660256558dc3dc805677d332af7c76e543831eafb68429f12a754e356a1723b599a26f9683b4ab79e6cc52dcb69f6902e2cb711882892c5eae079a09a69923ff579db03528e91f539270f3ba275bfde2b5f6395eb6c522b0919a76c75c07af9f8aa15764a5b4da3c359102001b19b25cae74c4b8878786d3f7d903b07f9aa02337842f5ae757e706437b5532e8ba + +ModInv = f6efb0d642835ad32d69c7c687979171dd73a0b5403acea2406a7fbcc84fc7132d4ec7fa0c361877346a99d8182f4db012cd9617e9b595aad0b0a002ea2e029d9f70b5d94b8c1b0a4a3243de79cea0d9f1f7ba859a455445003145e36a7602ab24d7d4a6a14e51531f48ef3d2ca0a9b64165be6c3cc98dff2cb104d906b3dd90ab524be8bd7dae14bc3bfc1589e22c3e747a818fc6d0cfb090a05dcb5953976d9b93191fd91e07025126dfe11fc39048912bdf80bdbf7cd5c95f35a64f234ad8894d01c0090e6485709c4c4aed4c3efde89a775c8d6b32132d68f9511279cca6f21cc1cd42ddd3a666cfa29d017a1530b07c68713a +A = -17bac194b6ae4b1d3423bf15 +M = fc2916dd01a6b45a823e624c8c1543c9c700f71fe1020cacb9132170b46c91fea9a94478a41a525add1fb0ca02367aea5ec5168ab4ed6654c049e251a9813b31ac1f0211d006535ae713b54173adea68b30de775d82e3f2a9d86dffcc3c50af8dc8bbc731821a718a81b1fe849cf20ddd475b18d1d5f666989619f33ebd8c660f6fd3e7a73f3b2485da28b111fadd6bea1fa5f98bc0a81d51624d7cdf4bb46be3f8bfd99f11304015f5ea8597445d831da7d05d47843c52a434e80ca34d16324f6f838c643e36c2c0b93891386738617b6ce12e6b15ad73fc6e2ed2a3ca268a4454f4f0eaf960c93f393194fb9a8d3ae7c7b24b13f + +ModInv = c076c2f6c6fa286c3fd4efc63cf7a651c77c574b37758a0c60df00ba81c0759e332624b8ef1e1e4bfef0391bd2b2360c3a1ae26b116feba1e03261426b388908320dd99a6943fb222cf58db5dfacd5c2fcc907a4a2b54a0441e5c3c92c3e7034e7f178714fe05c56dbc50440e079697b7cb04a80fcd351cd318059810de8682bde40ad9007af30d04c0218bfddc7e9336d4645a724bb3379d8b60a5d0b854ba2c5b7a39559944cb08041ea5fea39b8e351a17ea836b0fb64167eab15406b02b12d9c52fb2c78f192de3ef4c82feeff756460fa1e8a6d066d6eb5d9fa9c1cc49a83adde08ebfb43a7e06cd69af992966e4adf43c +A = ace85a1ee9508dbe225edf44c0 +M = 1d2b1b6ebed63c9c96c3091f2247c21bfb0e8f2c1170878e5f58aa5c36769c9ed38e41da8159b6e17004c4c61fed422c0fa0d0f52a1a4b44073c86ba52c9f03583297ef8e8998aa4cc925b30e9ee1f19e19787b1f00e1504e88b663b879af16b58b8da45d6e3f6a2b04e144a3e574256515dc05b71f257bf7bbc0e658b5b4adffb267fe07a6dbc44939b87e2d815c0f402e24082ced4498b811adf4a21b5935846a494ef5b6c07da56cc21c7fe8a00ea414d105016416a5550835b5aa4aec631684040dd2a9795df0595924de2fc885bb2c2aa230bce46bdc23facbc57429306d15b2fad18939cb834bfeafcec9c82d76562001d + +ModInv = 1a5167e326622565ddfdff9ba5662f9994a5191ffaa82aa452e479ae102f7e81ff764c3ee77951166c3e60ae270251df411474facda73c718779db26d86a77e7eaccb2193187eba9fa33a9ca536ab80dec8910cdeecef6c956f5cdf07dd5df577bb8f9a11203ddad63f03becafea0673d2944c6ccff6b6548eb0f96da7b447df4ccb93ea478a55cb005518db613b953b0ed297259526e1f18b192cd60c1c65b1730e888b53c4c5e46a8e0543da9851e84a75e2bd78dfdd632e7680ffc16f4d2ad6897f9bda232bfab36d2010b2209315856b3239edd4b537ad84b1e64ecce037314d717ecf3184672cf18760a7df224195a4fb39 +A = fece5b14fe6dd09a3531cd3165 +M = fa4fc28713a5c61573eb00860fe1b1e6be3c9c9b14d7b40c9efd98c6cd014cb5e83360a447285a9888293f2b8a9f89891076c042eb764a9c1bfbe43a23cfab3dbf901827c78c0fc410bafce720db6a588b7843109188120f3c0532921b77b59adce31c632d20f0d530111f03893977bd697fd9c2c3488cfb409786582ec886f24e391016e6803d1a3e053f1350b67442d26d09c11cf6c99fac348ff078b0b7d2701906fea2fd27c412228a2c06a6182b5e3d22f245b8ab4dd0a7f958be36172fe363586f043d9c170aa5c477c613eb198ed26f4705a2f44b930875550d0abfa9cbda00f7d1135800d78f14bfeabd32645f3f506f + +ModInv = 2908b083361d812927d6671ffa4e7bb6131751898da15383b2ce85970ed52530a34a0e5883d429e1b6a667b6ce5c9da78688f1f708e38f895b14efaee7a13110e252947db9892bae1f46f16badb1d6336dbeee9383c4a2f63b59d489eb1539a2a25f8c151c76be5a4e579289d106ee10a8efec7b3d4026de748c16423326e3aa497b503094fa936a7f2508985d84096908e908b236cbe52a2815d8478df617a8f78a52ca313d614801ff2e16922a87b2f52c19d24da76e904c8918133778615d04b4c2d2fd95871e35592a04e0e37c7dc6e3dfaea9d4fdd9a1443aeb8a639379119c98a85f151a701dbc2cc9ed1665ee41fc7310 +A = -bd4c6eb9c933106745b3ce9b3 +M = b0edb98a323741768a735dcf369f4bd520096487f19bf72783623e4f9e6ca7b744bfe88d30303d9ed02a0b54800586af91d156282db289a96723b46d2bf75f548a6d3713d2c798aad4c3fbc93148def47c497a20fa946995de059899b22ad579bed715dfa45c5d2b0bd263e9559081574dfb4e22c5f574be62204224c0bb4aa801e97c19e4043fe2ca88f88ac7ae2be5c6a7e82c01077c2b5c68851fc293a3ebb472b1cecea06ad5fac86db8a7de431308d7675265c8f8f7322822a1e8fe797f7f3c7ee5c9c4951f108d20218e655463adb183dfd131eea3ba6a185b482aa70a792c309bf8d2074a0f0896d26b0d4ff75a357cb1 + +ModInv = 83eb00887c7ffb4301d09a1f06ce2a77e4040703973fda914ea2bff93f034c1f088c4a8ec919b6daa1179aa2e3f414514aeec3c849dd2f6f26c1d843c18a071e9700b70f54d73bb02d7be7ff66446060fa1917af48c80d7f30e67a941acc32c2f217f6b4a577e7369d5c9e8445df658a0eb2614e8e8f139874267300e3bfe76bcf8482be52f1b73dec3290dcc5ddfbf554ffc91ca9f611c92756c93682d9eb1921dbc6e7a3a36cc68bf3f1f0916f57566b55b67c8a71682af24b21c75c0f1d802095acdb8a89c9f6cbedd3cb91f1d00b8544c97e117ae18af74a3087b8d90084acf06b2b754f9ea8004f24f3a6d5bff99b59c +A = 94aa595fd6ff97611f4ee0cb1e6b +M = e13a6aac2a9afac3e967c9b9c0833ad2bb6af65bb899041dcfd8dff132550c9ff44811d3054337ffc7d58453caff9cededd6c90fa82bab4036d4dfead4e2e886988d1afd632b3dd1172c03ea2f2aa2f5b1e0d64f92ad359cad3d1a2edfe6aefce3789fb50104ba3a2cee23ad36cce4eb9ce3b5df33dcb1e19164337f2c4e0275d9de55d4856e4162ef33d29d9701eb6e1c2a8fd8c746e92b45b34cee56449259ec68e56560d8c2a8c4d4dd19990f5d25c6f5b2e3a9e9c2c0507cab2a681a5d592a63c0d98d572429ee0bd04af099ef55aed055920a9cfcc4b0bf71862745e64fed9189008205daf39b3ce81bc1ea75ca6cddbf + +ModInv = 451dd6d2dac7fb44b850435c88802de0ef523639d4945230f3cdc22812f7042eac51aeabeff50d786b7156ddfaec775909a99d54b092a2a08fee2483125148b7a13576c5fb68c62f75aea719ed7b478fc1342bea27b47e68e2503640913b5201232cd2ddaaeceadb60589a8edd9b04bb4f254fbd83c0fe16e06a680cbb9d6371ab08ef12f976b966f063c909a64b8af8015772fbbe050ff7e804c285248fb27cb64cdd66fc425839f3ffb61c71f059183e5ceff31e6d79177c7c61b2d6e3738701694f71e71ff6e830414e56dccdc7da662bc7c2367b1ae2ed11c8a51c71d07877ff2fb3a987b6283c27520b3e9f021dadc3 +A = -946dd8aa84b6d2d53d50bd7b32fabb +M = a98c4152de253ed005c0f027f310103098f303a6e12dcd76d27ed417e19be98ce2cff75724ca94f568d116532dbee8468fa1c8625554a5a8973f65e7a44c4e96133d39153622ad2ef690118694b110b5757d056bf6304114cd7966251eb59c0861706855296e583f18be853bc37b73c84496bf1e7b5a2ad669afb007b8e9ec829a77ac7078349a50a498bbcefe113a35162731f8c30d59fe96e04340517977e7b60774bf780dba8d87863c785ccef6850ee1986c261863df672706f34b77746d5afe86bade2b388e69de5ccc3f84299ea215a9dec607c076d94a6bc33fa0e6faae7c77087fcdb30eb5b34c81e71b9ead6bde + +ModInv = da2a8ea4942833e493cf26f474afd090dda1e1d3342187deda8c73dffd5134c95614b6575235dd83c4498d62dd13db87271fefea7444424c5547a061d6659a089db7952ab9e71756dd8a1b8c26f8e54778b0f17aff29a7065de8e1865d4b11cc746fe5c0a79205c8840af74c84e4431715d2fd3f93441a6032f8d5193d50c35bb8d950b9d7cef773655148e1ef1643cdc2432c6cf57ea7c91b25f32817affa145acdb2128cb4c1c26be7d0857d3fcf006b9d40237249ab95b079b1d29f3b187ed66bdfff8e287508cb056d2b1e7a524e5a4e2fc3ba6ac0329d899b710c2c576a75c0090101d366c954ae5a1b0b6994ef11c0 +A = -cfd898de1c372fa7637e0807d27934 +M = e4de91ed1db8b5c1a70108c1ae6c2dce7ff77200a256091b4d36041b22c2b07453a8317d1960312382a7ae91072047180f99ab2516b1681ae6c646c411522a131e587674f5a7af2cdae87e731687a58212bc448a1a779b3aaf933843cdabc2c821bb9e161c74f7cd45782c680e4c5a35ad018538fd6e09cd8688da34b180bb12982a4ffc3492f3ba6168625ccc2877aa846c3199eaae650de01256ba3d7c6edec6f84d7f6828480e96bbf3bd66fd7eb38ba54c4b6a7b9938ab07205258044d38f2771164b983da82306307f9a4d3e1bb0b426fbc57bb3d19e971590cbabc8cc8a0f87a77210104936248464f6b5bb8d9f935 + +ModInv = 478d6f2c466b2ecddefc8946feafa6196b1c341866942b0430fb77742050267ae77212885a45260b6adaaa1c7927887f09c0b21603ee3972a4c68fa27e2cb01884eb9b066a42084dd2f63c3bfd362ab7b88bc71d98b385f91e40fc71bf11b572e72cb0ab3109618c2d079ef25c2747a96fc8db5df6b917aa9348d8687df0b96cc7fc63297167af96ab497d60c06102f599ccb560c28ae4000f90c4cef90c8e20a4748f3d83cf7838ca59d96cb33d2df8594530384983380cf649d278c9f0d51f33186879ed600f158fd8e197d833e890f55b08746666ee3c83e65da8354bd26c0c30440f774c1261b2707e831a0151120549 +A = 561b11190f2327900e58363dadf2e9 +M = f975ef567d0d4da24333902a94d655a532dcd2cea32bdd79d9ad394c114bcf5a42b8a1e5fb9cf36717757ab243e23b1c8df175c1e9fe9f3513a86f6f76c4eab69561ac351c9bbff92182fbe4f4cdde75966086b2da4e5e9d1957e26f36b24d2af91b870dfd2ef8832d9eec8479a6c069aca499560a471c485e1c652c7e5d76646547cbe33928e4f7c36b17ed08dbfa499d11d4ccb2eb1b36fba4b4b9ab1b5677cffa5f558c10e5d16cc3c9070530d655e05d8999da0b104b447b94e6a4fa4b4e7cff846a8d30acbb9d8e87d7bcc3fb16e77684c72b83274e5a9b0c37a3d39fcfd575a05468eb3e54521df684ad17aa7a21d4 + +ModInv = 2a27e6c76073d2fa771349c263e453de5e58eedcd79a4959b051641ca525b29ffc056b1f3d7a89ea4c208f1620ef8d746a62693098e558179f51d55ffd6cac6ff8f346f611e6708f310763f295704abe6ec3bd7ae91261e7b32a84a2cc2f46c834b1a4cc51d2e5f02948bb8281e7c2bf1a9b1093927608e61ef882ea495d412952bc0330e3a5f1817f0ff141063a271f89d2b870d8bc44832066b921ed5103534252fd6ec17554e92b055d5b77213e32f254227212289e528202d17e6319c34dcb0bdaee5fd6f2f5d6018f4be55d93ab72f863310b3af9a1cc7c4c2020274d10d1299cd38c7d19187f4b98e40841ee4a97 +A = df947fcc9574725f37d8cb30165963e9 +M = 5d75f78f5d559d7e88e2073db4253da71305ad9390699b36021cb9b8d7528c30e6a6ee2faa2e9bd35d7d0dacb0879d748d6d628041a5df526c3c65a4ffefd8912f5207472a1d8e4cc0c9120a996e03bb802eead0d458dcc06a2638d7ea3ab5d1679699e5e0737c6afe56e3cbffc0c4d4d3e3299d43dc0d35ddf8b4b6f06db90ded787c57eb063eee1321649e45ce3989f96e9121199ace001cdab2ebf4ce87ab6ddf437708f7f9f5bfb9fe8989ad0feae00eee1bd06c11083fa31afb7dd93d6aac2f437ae94922573f549bf87cf02bdc172d633ba585c42b76cc8fcc159d4ea3942d2bcb9eea2736dca02eda1d65d30abe + +ModInv = 70b464d1276c74c38d86c1b5562e5be98ceeb52384f747be62901445bb23d3a9a03cb8f4f415d41b8e4327632c62b66b88bea9f5ef05db0ca2bd0c4e206eef76d485f48517bd1d804137e6cc32603ab59f23f2ad6ebd6f1573d363c6a89b839af369b6e6e7cb828459326217f1034430c40f73fa3796116d08de48066df7a4ac87ff649b917f5f72b499ab58b05f4643d16cf647c0d6eba1b5e7171a26388546216779ea3566f940a6e6d4ba90a4c5c5d4c99bc426225dc39b629cb0b062429bedef2b6726bceaa74299767e9f8e7c3a61b0ce9a46bbe68b4dec8fe461d5e4e83aad1151a953a0ab45bc1999e60a7c17 +A = 8267d9849f3c94f8e0d974b822f0a612e1 +M = 93364c151355e4e910f62c7a263ade4f90136cc3242c610b00a83455d69befbd90e13c6ee996ab0432863bc7411720d0d7bbc7774ed31d1aadac784269d0dfa3591bebee86e4c375520f6f477e52292d5312eeb9786d6f68d7273a2f5b2495d1eb090346852495966643d5c8f8a7e4e12a61d563e8c4546870efc3e0a4fab233b7895f8ed584a285e92195e81f7678795f345ff4c2b90e2d4a7acb31079184601cbc456dc694494e110443704ced30628e0cd071e46ab5adb68f9c7d936d4747ab0e6d1ca10d04b240699a838a1d921ca352a3c35190feda277a4c28fc377c61075dce9e7bb2dae32250963d5d2d8167 + +ModInv = 2815786233c3b02be7573338b04cbd216b918b7ec3e75f63702e7df6a8460076670f2139169815e47a00285412f3feffca01498ddfce42c396dc42403743e77677402290ba25b123c01367be2c3b3c4112d4e1d99d54e3fab1f39fe0f2d7505d2b7d954fba219cf7b6d962c0f1ab7c601542260fddeac6b92d361a9b7015b291924cf2940856cd747bdeeae56ab2e1c651d803445a665b2c5b4e22b4effb8f2d3611d17ea05293d424be31f32b514243a0422a6db8c8bf302df31a6783bdbf4966761a32ac7697221f1b2d83a56c8db09df5d94d5dd9c340215e3b49034079a608815575c791df17db1ccce7366f1037 +A = -45853720c5c8330e01de3720e8960a80d9 +M = 53ae361d4b9421529e5beb1a40acbba80d7dfbbac796555b7bfa1af53dc13462191a37baee6505c62ccd6e19947a4a913d9302b10ad0d8cd6c21aa71e668c1f8ef2b42aaffd7ee0717d95a4bcbb146cbbacd43f0bfbdadb642c31880c35c70f013c7893c425207711a9a7fcdf5580f4122544ec275240b72cb6d61c2986b8a88bae148c77b408b22236f0e26f0e499a9c81e74c83b67a09590ed1b2f46718b25c99c606fad93b9c922f8855b27354bea8c6880c5b5306d491ca3a4763b7d8765d1ed414bdd848e2d5453a00d398604aaa1808a5c6617dd57f48280a5b1dc01d6e36bbfe6e994fca3e26607820bd205e0 + +ModInv = 724c0be88673c21575cadad19fc946e349b5ae4234b5cf7aacab86ffbac85229eac8748aefffa22dec9d8face1984b5296b53d6c9268c0ff7b16efd1da45826266a7e49ece642f5b5b4422e1162b7c6b89bedfc898b527f921fe7fa55609a62df17914709c0ba7d1945c5377089993ba587e9df02fb64dbc0cc1b0448bef60cc3d0ca8273ed2830cab7f8efc5f64d75bdb9679986b741d957b98c9041e26059641da7874371385ba6d8770f89f645752933be7f9654bb64d2b76b803fe3fe0c23abbcfa0afc763df40090316b9bbddc7dd3ed16a9b547d5e1222d9872966eed1fca9d468fb8d5c0b0f6660aca7d024 +A = -6ee30f8a65358731232d6dc8e7fa93622339 +M = bf0a5bc1a1b7ddaaf8517c198a723ddff645396c88474d415da41840802c193449b56f4f42ac3682e1c7f753d891d3f4bb5e1ffac2e0d2e2f214c0ad99ac4c2dc8f6850aba6505ca0fc980be44341307f6f41ac2d0e1fdc38e73b28b8dc194426aa578b7d666f3c3674f7fd69c0504127849e807c1c10cc7c29451b4b28378d15d02307c7cfb6867e700e35ba746d79eb35ad64792dd89c954960a9be51fe5f7b1c550e43a355431e16758331c2f720d655d159a2453d3b48618170ecb920dfec1489729fb1ab30bf3a2ac7f93f17ea33111642a8dd0df23ceb501b207cbcc6c357809339f3dccc3a9b4ae7ec2686b + +ModInv = 3d9b5dd69eaed0d5012371fb9127bb7734af9436607e34e2338d9ec6ec996197344d429000f63e00e1fb5c8d244cde7cdd5fee215337565be53d3f5141cc6cfcf511c299f89ecfed5d8b3c133d91b4314f587e8625ab8b40c4dccd7d8963530a2b56b22f717a2b37b5873cc6a8fee805b13d833ff5bbe321e7f10be2672a477dc025f7aa88029aa024f78c54be7ba94391457071d358391adf7b2e8a5be0ab81eb914f46c4b2b02ea8ebdd92dffc710d19c7388d960808a01064900a6605802916356e091e23da824011b3a47e438a1c1cd07ff561e014f6976dc60936737d1d6d34a17bfcb9882236ef44c0bb1965 +A = -fd81535d918968fbfe792e7cca2112869db2 +M = f252e7532834d098e146880a9f5baf329903ec1e359f1882aea301b282a7485b75e926b9b400ca112bfc225706ccf5664c5a17b23ce42b027d68e5b73f5ea151a987b6536527a7cd242e5c62dbd332f6247f837d7e9d20dc1a4bb23ef2051dcb12378f59ccf3dc2d6f643b5c3f0b02e5273ee27a4c8fc7243ea1a8b03ed7caf9646638ab845093068337ed9c09ce460088575e5468492984b01efa85128e916d5b97bafe238d6f22e0ed18792fb1e28684eeffd49d7984d6e3e6c965ce6e26f637a7085277e6e783df75a1ddd4441ce65bd42b67a66187d215c4340295844159497b657d0451633b1db8973143ff7d + +ModInv = 23006ae79ac6074f507b7b09c58218fb312e024e40e89c553a4142a4196bc5de40d96ff978e143b37512c5c9fd557f675bd69a23a7741885589b562904a35c264f6166803e85641a79a2711cd5de5fb20ee7936810ec4ff557479b0dad0343ad1c641e9a31e7265cf35f82420d24c2eb453cff55b8c3f920474a914b710740656486cdaa5b9d56639fea8bcf4736611870b5c637062d37f56e213604e778b1770dbaf35f3a3419618e1aae61ca551d46a5277c33fa9b5ea918dcb3ed30919bfe6c1cfd6245b3a5231c99d2c2a07293616ee7ddbb9971a109e6673f1f2328a83fb61fddf343894882b64409c47e17 +A = -f1e17314ddd9d07453403009082d4f72c1a41d +M = 64e372c51a70be5188f019e2597a42319a8a25103ee1d01bf63e4d9a677f6549ca8299e3efad2cbd669ac13af2543142b93399176facbb7f643a6e7e32c970df927c160049a6c4d86e996937291e98e02411a54ea4e6b69b832d3cd1f1df9f87655a340b4cb858ca914a879abbbb15c14664ae359b3f66156db50bbeaa5e426bbb77fcb77716be2d6aa73cd6d85641a755388123de51e46d03c13df84e93ed631f681f238edb77c33e3109f3012b6b67077d38bbff552259ebafaf6f4f0b77320f583c0a4edd96702f117f3e17df68dc7037a9fd17d316bbb59e6591e9f6cf56aec42b723effb8d358cad884e6f2 + +ModInv = 10b0faa11939c0102b5ebdad0022305dcd4f0107969d53e6cf2d2963ce9226c641b25016698a3a97485a2cf8701323e484fea8069b5245c204c6dd6920dad3c78b66d103559fc99bba7f7742a63fccac659dcc25a326154d3fd01c0f19fd005bbd8010fd02bb23f39be8bbc4d5b4bbf04a363c2e1fe00abf2e9ffef75b7d37ac031950f8ec52b719a0315dd68e321f127c51887b82a4d477d1d803652a507f3daa6ca7d03e5bbee4a97008f6800e87e54a1bfa0539defd771748abcfe425e0b81fee309bcfc01ec7e3a8eb5d1493392eda509113967622e0663ea0e0c0f8f65d1dd3532f516f7557828bfe78f3b +A = e965376c3a50e8ce5ae5b9c1e97f66ded77f2b +M = 8aa3bc5323dd755b6cc86ed771419b71dc67b6217d5a70450acd0b049f0a3468e3b9ef69d07d926ea8190d171cb3feb4520e2df627f4dbfeebd9c49f0608e4e9949becd8e16009b0a9ef7dbc5a4a83463cef01aeb9d852a63232bee257f92fa476d5e8440a656653e4a14167fdc346fb0f21444676de9b7898720bb14fe871c5bd09b47a2db3514106a69b8b85210f5415ab2fba07dfd4ab02df43b901261cc7c6a7465ac00282dd51579188a699783c3d08f36be8ace6b2a3f3b89d5d79ec7e8767fd2e7550afc742f9a68d6e47cb4ce6b1bbbfe4595221b3a5a9f8218c0643f5a470fcf2ad006e33f585e18688 + +ModInv = 7495212fd6e2f7af09c718328ed0a5f33bdf7d31c9d34089f30e52f8626e55e24a62b32379561a5d411ccdb991e44ba10efe09c06c466ae5428d46884db2897d17f56dfd81fd084be9bdcaf091f00695eb8278fd2fe41842be5bae8aa914802bae0d0b22aee4be2afc335237cdea94bef34df1df93b22c4f55a99773136f327a60e3614083b7dd5346786bab75ff7289ee45ff63a4960d97c46ff873f8e0b8bf7e616ba131925bbc6a20f798d16859ce81579391cf84299dd532c698eac3ec7eee16c8c0abe2032ab8bce3921f21c91bb068776017d4850c068022aa0bd1c70ec6718ee4138813da0a64468d8829 +A = c5c9f25401b8889f91ff8a23cc438d222240eb +M = 7e67597c43f2e27a7df97a87bf13ff877bc57202d73273b2efdd5672fe38a601d69c6351009963b7d7b6ffc466b7e1e8bf2ee68807093809d222dad729f89445c29577aff17331b89a0b99648de9c67de5b17050ff4ab92c1f3021a53fa4f3419fa3648675600859b72dfc5d48eb71a1b824f33175e2e9a277220263db3909c5a42ae544756112f2e1e95573bae9f0501f1b49d5199cfae4a278278fa5766d297fe4dc90fc22b50014248926f140cb6c12774e10e69769e9b940a8e262b5f983c4a936dcc0580a1f73a8cf0c15b958d6b3ff159c5866e5f76e21483b37689050bea128b26d6310aec98cceb407d2 + +ModInv = 26d63a529eb5503de6ae42178e41f3bed156d5c90aa3f2af8432452081f752627185ec6b4d1a585e1381897e5a44206a61f1bd8b1afd533cce2b02e4052ce73876a79ede711e0260d4f2b175bf70cb596960986353b9033dea7668ed83e99b55e04f0f1dffdb63351ec0ae3c819a2f58ff3dd5e45bfbafaf6c105238a9cd208852a7a3fc81dfea5d97407d0a4d0098f4590ad3899ffb5065cc03af79f0c1f6db33e04cfbec50a4b81b643d1b493d6a0ffcebef722c8bf682b3f4810af59dd03c9f16b922af6140332308cafd73a6ac35126c4a06d53a005806aa7bb5d6b3eacb0271cbed85b1ba94f702b0a56d +A = 256c25aaa0a8f9e764361963c19c728cfa477ce7 +M = 6f6484b9b02ed73e19da94935e10f0e16cc2920d891f7884771c4b8f3916c6ff48fd9448f0ef209f7c19640157d230b76e08a012276f9ce227e190940cae1eb860830a6c97ea05425437018384ef7ea21443f9b33d5365b78a759bf9d552c55a7bc3fcf585c08bd32698c09ad74da89c6b9baf2eed085274509c26e8368bccb082ad8772f34b692280124b28c7b919fb593c546778fa116b17e7d3bbf53efb2b0275251062dcbad06d2decb2579a4e70cf7db7cec7c28546e55877a33006a05b351d84d0daa0514b0d1f90783fe744f054046d63949fea8962162004b1cc628e5c333edd37f8bb20a861c4090d + +ModInv = 6a235aa44b09ef6c468899a3dae9b89de17128798cd8cb49ac95b69c2c816df4850d298728e765c1e676d07ed8c9cc84abb797935e603c74ef6f92b1a721ffba26dac718fdc8c16db3ac45278c439b71ba75e4bb05f73e6c2ff7a700557d7d9fa6a0b5916615c61ed68f82ed0b152ed54a160afeeae8742a79a9d47467f29b303e89cdefd4c2782f265da002b18f74c9f1c22f49af622155d0e2a7660058258d2c8d518f6b8642a1d4d8d31d3966d99d705590fb613c9387128d1ab23eb625dd0e17e722c53f0f764d2cb784cd69c3a81328ca9a9aa536fe9245fb7b4880744bf3968b9652c320482b14f16930 +A = -60220668ca477c71ec12f9bdd289046d34012259 +M = d3396618dcc3ef7d56445afbee83ee1ef7e108d46109a0e7242e673d197ba9c28cc0b6e5ba8f6a986face997f41b523b5f4d0b681cbe0fd7dbac4535f65a446b220864a64fc1c978c02a5fa2474b97e518da8a2e924356e06c12a26c4398b6f984e7d58b4d77fa96b173447984b6d2fd1d68d967578a601d07bdfaad5e632cc3f4c298fb290fcce46ee15f42b4ce6f02c88622966a725c57b5c3339675c390a0b6b52ce25b0c601300b0eda8f8952ddcc9a3cb1759a6b6fd9cf0c674ff6d1e217c659f727ac97f1f61427eb475739e8718e2b287ed0159be7b823007527197eba83530981bd4b80bf47c859493 + +ModInv = b85aae6931b7f24edcfb33b8867df550447a1706e2d0f313a11d85ddb215a1ebc98cfb8de54be1efb4f3c17e5447cf61af330454373633dc90ed4d32c45db47279c0f064f56823617dd663416e0d88f47aaa7ee131993a1a6f2a15496223b2e4a15103b316ec062b8837991ec7d53370eb8d68cbdbdafeb55aad1b4752861d6fb80e6ad5c5bb91c553e4a7ce3c50411bf655036be0efafbbf3103c8fab8294b7f1f84bb3cf6be1103bbbc37aa0ab41a0fc8443b5ca861db1ea6b379ad8515706b972026ba0c92c295f9e29ee833655dff617b6c925f7646f2ff352d30f165384a7a8c24c50747d7550a8c86 +A = -eb2ca5839d6643fff157daca62811880da1f5e95f4 +M = b04c5bb2b52c62c44f94a5ae7567e592694bfa1f2796c4a2265622f83074225213da0110e7eb050bacf86ffebbb7274ebd26525074bddb572e65147d48767e00ed85e9e1b5d95bb49ea60127bf817d7d0558ff6d33790eadae1b4813bf4d2c65f06a00134e03225ff411a62bfa3ff685ce607f344824fc66d53b17ae4a02f42b744f44755e78463082007172ed8a14a56b67b0686ec84d2e0c61847e3a87d1740c22608c54a484581e182c39d267a93d47d4bf6003b3049b781d48306de91b1cbdc32a7036761292d1c1cf57e84fe74689f7583d7e24c64f85f9d07ae3e9cb25b60868a959f9da98967aac8f + +ModInv = 15c90790ad3a5013d967034d27b5c473cc0a9dee8b5cb72793ad7ca80eb8a30db7ff39b2425c06a86ae0fc4a49e05898fa711afdd608ff9133e498b1b21d50d5d2db67913deed841e0faa5f8267567dea155cca4de51b9a4b90b9d30877b91c9ad23bab8abc2d69518fc34b13c298b70d6a306f748aa5775edfccc6b40ad8a8ea008cfca5365389f863ff1e39995f5392195ef3231f90887c36b5fb80c940d1cc853cf17aebb0635e038fed58b54f098261c8951be66c589531e2faff772c9761fed93863720b767ac61a393279f34fa41ab57298eedb259617c9ef25feca0d36abf93d939187a06b65312b7 +A = ed3ac480002b03b13a8ce2a0c03444132084a96a4d +M = 2a3b18097d95760ad0489fc00c21ecb170ec7784275769d16a9178af42f1c5ea887e509576d482f6b2a46a81ed286a07592e3afabf91f77335abcb3e782c072266f4c753ad06249be7980f26a50e0727ea0d4598e82ba2c1fc757eaa4694c3b186b4084542bc88b2c7d82ebac92b5147d4ae57d903068711e43cbd68011b7568ca449388b6256fad795675239925f9d1131ed8b7f625833e9f29227fd5f9021c7a7ad7230f04a0f1b5fa60d775e4f61f0c94f3c7baa8006c7ccf664e7b260823e295c5d0bbeede99b3749facecb8d19bc124a09908c417c77adcceee97149c72a3096fabf2c0a829e643c31a + +ModInv = 7380d7111ee1def49ee20d0daad08d4d87899184f5a8a1dc46d5b46a8636bc5add888b98220b1baf31731857f326d0276efa710db01f6a7136049986b3e43fc55d59fb119b616514ee920c9ba181114f5a04f3aa009dc07a74c4b0b0f0a37336f663058c7dbf416b2eb09cc84f5822d8ffa99ff951fcd1d7f5c6c3387d734f0e0cee1569af3abd76e5318bb4a03b27b735710ae5268017ecea5033524189ea21a1bf70c294b784fad429c616e6ba7f92fe2a83aa905b73d7ac7d21599a7f6704ef1547c5723a63cd103279dde482fb7cd1eb4f0f0e9036d097c3a806d80166d33900aeba3bd89eeb8e2602d +A = 8034622979a0aedb35e727468cb0ac5a8b0dbf8e69 +M = 66f5aa9637cdb6e7f0183ea34517dfea8f911c2539921ba240f49453819972b772c2ee011ca2a8e39f820a5600558136f41439aaf1cfbab680ce78b12c8bfab7bc1f367ca74f5336f487b9d837de3be1ea2224930053bf4edf1af2050ae96a52fe345c7dcb11398c75ef67c269c73cde258714e71217afb846699180d53fc5c4c50c8bded146b286a6657c680463968a93885da1750f1534101c288f8f969b48e8bbd1c9a49dc5c8516afe28c9502fcc6bf335141e147f4b2eeea35306ab650875ab0548733559b24b7cdb0af567ab63fdd63e27f9d843179c6c1044c51671a97fde684e69bb2edf33d5ad77 + +ModInv = 1e6ee806cf51f0efdf0b72ceca2630b1d848967e37e58cb4588d56476cace9058b6db7b0a4b3646b98e41f652b2e26e578dd251c7c85f2bb6389fc81654ba84439a8797c672663ddfee063ca1f4c44641f7189b8bd3b1bb218a9bd2e3957eea4cf8bc36a201bfc805731b057449dff0a318dc637151871ef771350c6116995f4cc81e8e370f995d5527a4af8890d7e10aeceb362aa05801aa54f792a5223a2e2b2b1f91f1c9aed95e3fb0afe342c6d8655e061e019b917402c429b63abeae01865b50f728c96ff16a6949155b94a32d41e48143f5c376a8576d31d5af54ff6f4816a53427e27b321339a11 +A = -2f2c612f1e885e92a710845c7c871d68b6d8bedcfefb +M = 69cf42abd99fab682a16cdaa28fcda2696fe846fd691a64833b09d5108f8c46bf483c1cf874bbf0491649b9881c70dc5d218af726eabb96842ffbfc376b47927b7a6aa30b3b749af9a85bd523693e135c58c2d0149e1f20734a41e7478a01a41019e5bd3a53632ff2d62d08dd2efbaf91a2b4fddd10b03604fa2152b5933fbf1ca671896f840bc530d845b58912caa5814454e87dfb9a06b72c4dc1df78a25e201b17fd65da8951d1ea91e62365e35ab4141e29dd9edfde4a2b86137d77ef59bfbcd857ff245d8c1c96083dc0a2e3383313e278bc03cb9dd08da0932a18f1b30a67be9884ff43138bc852c + +ModInv = 3faf5b9e407610cea605cae47810ddebad57d73bd422de6d7372909f314526e318a6bcd0a470b50091d27f31b15b13c5552218a76518724a048a961b7c1ce9bbfad187fe2a2f540e58861555c5a3033dffdac4e9cf9baa86aa530640392889be4b855480edab6ff8df3cf7ddf3bc6d7963346de43a80445bd10c1259dca2da200fb4cbec74fc425f84bf473f9a0397a4551ceca00b6ab7e087f36e4b034b43d2dada58ec2a2bf5dd871514577b9ea29980be36a9b1e596f1741bec2fad21a22a83dbc12d82681751d2a92e518f7242554fdb3d0faf1d40805e9de677d229915cdacdbecbcbb2c667af5d +A = c7041e393bc246f1a01cc0c476b6fd0e38c53a079a5d61 +M = 7074191b14e240e5a28b60e756cf09f743615e7d01de684751ff51983b798b534b5642e37186544002d5bd213f7b74fe9d4460935df2488e01a40aec943ad5feee45038ca9b66cf46957b06f9d08a46b5c82d58ec9c53bf5c186ea5a0921736853992deb5e41040d3e0be1cc2d76bde796dff7f5a8d178dbce6f6c9d0ccfebda970ca323316e8e61d0a453b78b6dde88073c43a700944eb26628798e0b1e50955ddf5b72840af5a182419d50f0344f1fd38107b70415f9779b9801b6720e197796757bbf0ba592316f40a69a353da093fc3c513bdabda2cf32836287b5c6e527284ad4aa1acc1c73dc23 + +ModInv = c9efc095438aec509208d12f88dcb78cfb5376bcab8e5da7d648e6bdd03731ee4328b492b4333ed12f18530789ef0e5ce9a7a00f233c5d1336297972a5e43f7d5bb7ae41f3b1d5d06193d044591adfa4c7a3ffa44cc81fcac3bac0e7d646f1fbf29b8273e6dd1219c357b76b10882dcba18e479ebf8db40f1c6b352d0fb16bf1e01f021a6b7b9c1bac535193f8ed5de0af845981cf125855de2824ade46bd419b7d22c56175bb699626c3bd142a89ef4f0221f3c23d9d89888bba2385377a63238d15726a289e32ffe2f853d08cc07e88582b6870e931ea8279ca794d1c98b835c3db08e53de2ff0b2d +A = 314eb895274dd76b934c7b7fa012f7377ff64ff7c45fab +M = 13a3c85d00f86e707b7fb68da48728acd9854bbd8ff2b8b85976c1bf873f3a855175c7bde37f90e55b8e19624294db50cb2ff7d3783513525c3ff99f49e2b91ca2f1e67aee3e674b90fec9a8f0fed05abe48edb132b97536cbb48c71bc72fc9e63e7eb74e8245e89a77ce988fd9668b5522ed7b696d85bc2e7edcc9a764eb1fd921f8d7bfe07d0d75ddb1a89b2f31f4273bfd377b507170d4b16d9cbb2ff462ee3fcd1b29c97bd10a1e84c82c386d182917dbaacba3cd1298809e94020559812c736a5600a34d6fdba92e4506d80d4526f796dbfc0b70b16ab74674a828ccefcfe39f91546f5b5a781de + +ModInv = 2ea1203079e49c2c9f8ecfeb393685c8d6f3e3e79db409dd605fb8457f8d0a522e9cc5cb0de9e291303151ac8191930955ac37fb1b49803b174422ea5cf26862ac196e77291c3d6d33c71bfb362b043300cc70c8a64b9ad479ac8364305d618ababb308275cfb993080bc876fa23d4940750f6f467731a37d82cd4a27725098d6a215b154b4ed242ab35d46d802007f330c47a1e71ca0689131120b282f6fd730aa2486f26f715ee3a5f6c4d9c2610ee607f3c1c8abe03d8ab70877f0f2bc9ef2244f94fa31a6f429fb0cb972b1b99a02a1d56c4e838c0dd18a1c31c1fe139176364e1bb908f9f39d2c0 +A = 77f9f2e4916e468e810511f4d94ef91cd835baf2d8e14e +M = 5c97f5c508f5f324f1e3e5b2e7f896168b0dd70c207e410842a8fbdede1984a63eb96c2f5ba78d53ff8094e1bf19aff44910dd61e8580403d7661424883ba5bbe97267911729460ebe43430f9a8e1e3223e4cdca6031be70dc502c593ebba8496f15180114291d0c9a4d778ba534620b084ad5120d89816659b085e8e4cf2ae9d47dc58d0289ebe13fb73cf5edf37b29c3a04693e664f93be77ff1241a9938f086578db08f933d73ea0ac7556314d8c8730b7351257bf242aad8144a63ba2f6450ca48afdb92fc507cc67beff800badc2b4aeb6c526c56135969f6593245c14e482e3de346c7a50ea241 + +ModInv = ca15dad56e2292dfc3dce42bd29f8c132fa1f02d9946da4462db59ec2326c5606631d36d6d0e1e1a13d5cfb72c50536bbc163033d998de4e4a5a6a3495d8e51221bf67aa64c8d0460c70924d30b97aa2f9bcc7677bb84fe077b191568b81526dc83b5f77b21647381310fdd7fb186c72f27891abc04ab5994d7c90b9b36a7439fd941a4a4c09223c704ef8542d82240529955c4e66ba9e0130e6a260e3bd1cca9d812ab74f3cfaa7b5746f70487ed5d87d8c73f7c07a9ba8c59c150bff9dc83fdcc0d25c0ce78a7c76b8bd2ee7019a200ad0611a96254fb4e13391499ac2f64df6b46ecfeab8909087 +A = -ee0e3bc4ee833ca7b1e73bec3d90df5c01ff2f1c46a28e7d +M = ccb3105af8c5a98d905c33a83b07ac82d189872807498d0784ba6b36e312d9d314ff06af50983d8ad76b4cabb0c8ed498c529e7b5ef9224738036ae73251ac4429fa137f73c4366d94801888b312ab54548a03089cf6115739c4fb60781a7894abeca5226ec8036ee0a5941b8627fcd34352f2ea9ca0c55664d98610821155d0973bf0c40d5bae66862c2589ab55c342d847b28dc8829f4ab3217963e3020211ccabdd076c95eb6c90734e0a3dd85e511e35308dcfed587cf288600d3a9e5c7a2db991fb22f123f32ad9bc7d3fe70c6371ed6a2837cf5ee892567732435550d5df5315b733b33cf864 + +ModInv = 7bcff16a655c948ff5b87ce010a393441f1b468c7fab256494efed20efca25d86b323dc8fb35380985e02f0aba57893a53ff630a25093f6a416fa98f92d954d6793f1358b3f23741da8970139a7d813f9eaeb9369eca54fdeab1ae702cb2dbf3d0037bd4e9a5a3a123ecd43468c78d8e2b6d14812da7f7050acfd3f49c64b2e9b7c4a09263f3738ee86bfad757606a8a37175d1a264a6c68fc13303fa2717dea1499bacb751c51b965e1b1c9763b6d85564dfc56f81b3028199e8523167aefc5bea91997111584043db5ef7599a398682d1aa6c869f3a3a2ebc36dc15d41aa36323f7cd426e51793de +A = -278e4dcc26d5c61f1cf13d14ce042465d897843de675127e +M = a620dc97c5f530558aa6017aa40ced6dc55a68d462c715292879cfdae3673b45e6ceb60f660b14af73c5831150803c41bb2f9468ea2ff8a60fe4f1d4381fe22d1c21eb1f9c96b08745cf4b052058af578161b68ae28f4f670db69586f52f220b78b371177b7aec6d1943840be09defc1c7873d06594286b724619d4daddc66be36c0e24dfb354403ccf956a0efa31299afcc59a7ee06d8007e88802dcfe7bfbd116ffd0ae143cb5de3b575c39ed89a2d893dd5ba3be977c2fcc6bf57a894ddaa3affe3d829005f84632c55097066c7d815bec7cf6479e3a92c7c40c7c997af687dddaef2fa4c7b2f39 + +ModInv = 3991068743d98db1727aab2824fa64c1ffb1194386d40bd6d881e38bf74c718dd0e3cfa35557652ab3441a88311737c021a3e4837742d7b556481ce8f68871e8191eaf63ebfc4b6d259c732a88c7d3ba8163b6219cdc33cb9e84e943dee1fe626b6d07400ffce962823bd8019ab1d6ff063ef913d6f523e2c4afbf9bf56d77ef7dccd1794e012763da9e291759d10648289e9b47fae313921c1bd96c2e8ae504820c203b0612a1c142231255ca7a456564b696edbd06e8a373ec67c1b71583f8c7eb947859e0f64ee68c8630968c4c2b9d5b6de858e20b88d764d98d4af2a33eea799f4679e46e736 +A = -c5fba1508c3c5a4add1652e26a22a12aa9346ef357a0f337 +M = 1e3e22c865c262e22f0f85baf8f90e5d4b45ce8843f8d67c828cca7d4d89e79c8701427a06fcaf3968a1f6099cc649a763a8fb359c0975c7a999739b503d064b242b8e1278a3e7327ab4b43c8b807280161c723529fb7583721c75ac48b9530f77100a26f8f6f315a94ac845e3143f68bea21ea6495b3dc7c9f95b7f2c83f11f3219949c9392f5b829d7dc7e88c5e0cecd227414ce755fdf6dad3662a778534f0064a45c4173b787220aadfd195935ac777157a0971fc1d44f8e8ae93c56a4d2a8cbde452f3282620d01cf0df8f851a40d1eeb4c41aeab42e5790bf02a1bc74715fef52cb172fa7c4b + +ModInv = 199d10169921a085bd0a107b39407bc9cc9ab2e111ed48682c8ebf0eee488b792625b7927cc5f7c2085392faa8171fd7b38d942c92e8ed10969d5f2bc3e78fdb023c143699f8d9506ff37f12ece51e1541dfcdf1e3d1162ed505a1e8422284125a5644430ee9655989f943bc9073939f094b810b3d4c35a64734a2b674ebbdc7087bf4d71e445f5122b51d1efa793f1e1a70aad131996680b3d07136374b67a1442ec22c4475d64afc84a79f902e9455f17c2382bf080ad0715654e0126dab88094102b7922fb85f46f81075823507a7f1280445b97e2a1f08515e5df521404c7033146a3ce4717 +A = f14e98df43777f3b33164b87dd4ca31882d523c6ba5f92f5cb +M = d31e98c635677e6b1a30ba71ac66dbfbc9ae21f864f56afb4f01e9750e3a39567c0cb3acf34c40c396b7455c2441e575c35d5fda84a45472893740740c22bad39766242c9cbec1532d074378397f526dfcbf7a9fb64f2fafdf4c8154060ba0c3a685641a2b11742daceaab03c583a6aa15e32d664450c3eb36da7897f6ce12149007859aba67fcf5747822742e0da5ae4babe43a564859fc944bb6033a02fb2741ff60444793a962b5ccf62b8af133f2f3366d165b13336f72434292066352ec570dc402fbdcf0a5f17815a3beaf573ae82b14346f5432d6d1cd107e7ef14bc558622a86cb621d9 + +ModInv = 8bf3a7d5ebbb742504fe227364457836a6f41b39065c689f2312ae7368edc1d69865c3f749a7e8138fbc36559f29729bb70de10f500f6dde50a9ee9192158ad9bdcf0988504f1a8384a7f36fa26b2dfd9b6bb6105fa4f91f9e8367fd238beac875b97760921703f9238a143a5ed8f7c6de39b9146d852704692e6144b9c376780e83795a03a7a014d6819f587c4bce6b27bad4c78ae4547df9e0c3c00dec8bb3d6bdf1ddd58e6d4666c3ff15b9fa25c576c0bcf0ec53cec1b73153d854d3c086f03c5b395ac5d8e0968e817cc54dea57d0e6c602b3641c13d3befec458b4bfbb518ee06688c96e29 +A = f82c55ab55c3717022ee753da6e2dbb424763a1cce8fd1a661 +M = 8bfafee3810049641716c5a5b6efdb2e8537e1e8558b9d5694ed6d45169f7d07efaa530f5b377f8aa66137afd8c100c2cfce8341c842fc746e16d40ac373e484f14a14e648721d542e590fc7b627fcb242779e94377f8623ba7c202ef65b937b3b4ee1af8ef960d5e19cb83cd0543689584822558e19578a52dbb148a852236447c1553f8ebe542880d433697cdba4aad81347ddcebf78ea372e60c9eff3eff23561ef2899b16f3aeecad321bfb05b59ff1519e1aa70c9388bd6813d743c428bec8e88db27c9c1624fd8a9c1063a908b39ebb0c6e7e6a48686aa10f94544228e8ee53e184c055244 + +ModInv = b5be0d07e1bcbb165a5c62e2d9947b065080b010a96c23c5ef82798638648771286419d30a3b626a9eb2cb6fd56565919f491e6d85f867a26dceaa84bd4ea06a935ce1c94be937cc24c90419fdc3e6d4f29a44f9bd2f3ee568c1ed7327441ca3efc0478ae677c60de2fe78f1eb4db267242d58373d3d7f97a6548c2ad77eb3fd9c5ee57e564ceafb3b23e59d073ca0fc2c8b99961ed72e595e1ce494c4717562197b792f3955eadbc97f00fe2e291d11a13386a5af44a91f6587ec8cd9ec258cc62586cbb89b75665fef10dc3e36a08830e88a4a5acf9074e583c867a0da13f4d582468bf5be5983 +A = -635a32b44e2707161494d566f01134f1b19a439881d09cbb51 +M = fc7819ec57c996e3179569bff431035ab2e5513336d8c58aeebcce73eef853c8786dc14b3831b41eee3430ad71400d032aaeaf36755005c2b6e3929d66dbb30bc2452014e520084136700dcc366234f5168255ccfa3d536a46554b5e77ecda6d5a5bd94cce9f9d2a2598f4c9ee7ed52f8fcd4feea51bb62f1a73fe2d8c3cf7aa37d36ffc9110caf3a129e9a9c710c9d41fdbe8ea6ad9e6d7adf3cba32b11ba0da1dad6ed1b89495ca2d2b11c24a097385fe4b8d668c22a25fddf4f916e35ae748b9b65027183d120e6f307a2c9a629a3bcfcdf646ff39440d3a1d9a1bd7650f540724e72cfbf22ae + +ModInv = 7384e6a6fde9d56f138fa8f958bcbe1f9303d350c61529760103fb646a8db08995df8705e98af49067523d97b5d360e7e15700398660a3df1d79147fa05251689aaba4e956acd550cae406d782015303ea9482d80bda9954cc8ba60300afa9805a636d931422b36c2b882732fc2367be04eeda24eae576f2c0a00e9788e9826a3ea1426797557be99644d4643f52a82f92d10b5a0487f2bf2c37a8d44879fa6e6ab7e03dba3b5bd7ddecadfc43eacaed6fcf22ee4076a338874f6200c41389c3de9068c2c8ec3d6787b767b0aa9686cd024cc3cfc4354db283f925b9836d24cc4b82c4423dc91b +A = 249107c5dc09b5892655bc087a02341519cae6cd1c580bad0d03 +M = c91c6ea64a1eaaac5c76f98c11fb7939b2f87a91291acc1c77ce0df3226158d1fde9d87cd0c27362166f4b3091931ddc6955852919bdd67dddfc207b67f38521506a5fdceb309823d08f17bc55bb781f2a462ab729f0d7a466f20c4b5ebd4a7cac8f2cf2362614af8716d93ad7003b6f411c1876a3063d19d757b7a633a67459d7dfbf6325c73eb369649eb452bd344cce68a81efe2b59da52b3f7a5f81894315f08f73b5b5f1075b572b5707f63484733f7117048744404276554b7f8367c2ace4d06b5b9b99170a1e8dfb11cb37202efe44cea96c99d4447412dcc78284cdc29ae1f9e2248aa + +ModInv = 3bdd168531443c2457167562192df71165e00ebfa457d6dc67e4c11bc87a1d3c17304a600d5d7413c04cc5ed64559a56b4d7f3a9fec959c0cc4f9fd7be5cab68c380fe20a07d5c723dffcf2156c50ded4272bf256624a3009cd9c0eb75756652fea4d05330dd039b976d8d8266b824c3b4e36ef6aa889c4893498c14483e574393c98a3020bdcbe0868284e2b77cfb52fc424b88262e60e00b75826bc394c35b0160dd1de2544613b450f32e118bb5f1d1ad59e5de21ee1a2d09e597955f6285810f319dff014fa2b403576a0171ec4608f9c7487245e216c8b48c74735d6f7dd587ef0ccd1585 +A = -32b5df81475368d0ef1c780c4b16a51059fa62b2bbd1c38dbe31 +M = 42bdf06145b70109e771841990469fc54c92a1a072a0f6de83e5b32d5ed2a0e5e638e2ee18d8510bbf2005f7cbf929455a4fb47e07f580dc988149dfb993b178b9722e726a44e2411cbcbbc0b9d65a3fa2617085b86a9e096823a9a82de0f7b53bd822d402ef02b71a6bb4bed1e9987706c40f6cfb9af520df789379e1575a53a7cfa066fb1d88de6c3a9c3136165f85e116c9a48ac536db1ccd8dc130c5d79c7b0ef4a137a5d27e8837d23cc8d9303398fdc453743a2d871cfc69e62db17f093c6d797387da67d9d2ef5d715256ba6d80d5580e60df92f8231d9965e382cbad3c3ba1322b7d97 + +ModInv = 2789ac34b547912edc3982fc9863845c9849a796a37e54a6d712d575233b4079b51a5ed331db99cc0df7c1557271d9f8c17b300aec4442109f53d0e1d7777e0929af1a0b84e7d57386074c1d625fd6257cf7a2621281bbb370eddde16076d1f543372ce90156d076c2064102f359950521296896ed02dbe8052e2dbe47641f99c7481cfcfa2f588b5b2048171740c567034bd99a3b0ec98feadf130642c38575bbc681bce9304d8678f48baab003fe6f68a1ecd15f3e9e22d2f1c97a2e75e542c100786c6c98bf1b8dc23f6463437f774be504fab3fc7ea540fbbf9c704748120bf58ecd6c +A = -3ff33de8b20a9e75406980842f3adacf3c508499496090bdf5d7e2fd +M = ac0fa8fc1293846d10e35c2e3f63e0d5dc4e5c0294aa73ce7a4a6777e398e5e914298ea9e2da790f78ce379484f7352d1b643cce108bc1ad31dc1f93137ae095a75abe5ae929b15264f448da00df05131e6ebe35b24a2aac6851e0c16b40e64306c9ccc33612214bb3f76b4d1dddbdf6965a514e0edbcabcdfeaa469268f75e4640c3f9b9814938f07e19a020a499eae36f2a98de3cd6eeb73d37f8dcd1500401b17d8ed1b3620e9a18c132a82b7058e97ea4fcee495742d978cc3b4066c8d24c6e3a3835dc4f8bf9ea85e51ba52f3d305bf9a041a44cfcdb326512a08574a524c1f183e6b + +ModInv = 4268df0abaef95dbe132112b7784f268466e37e5778acf71eaf13ccedd1d9171efde424e81f07a05e33e590fd4437843765796aac71b6d8c85e5a684d57ed899235c124b62523ea522d3af90f17d2d8200b2297b0e235b2921a4a14ba83d1e270086f8354172a4e360dc5543e577695fa2ed986115fa62ce143a7471f07d53debd62e5ec5a33529816f3f690e502f5b409996e60c3176459647597558a46b445d9e7989f88fb9c066f5f9b29d131dd1621b549d1030d515c3c69835f7320da78aa94233aa55bcbd72db32b7ef6b3a41a0f7c03a2108b5149c6d708ee9d44df6ae33f52d014 +A = -595cf43b99c1c506f2b51462c3565f1d1bda2d132fc13e734ce48c7d +M = b50906ab5044060f5b20b3f908f56a289c08639801db445fd04aa6fd6b2e8a699d74c6f454dc591d5ad4cf8dd383dc49c01e1e85e4ea26beec475704bd41aa5b65a8627fbb76084314d32b8a7e96bea3581208fff77658612bee784c46214b877d24678be1b89f144822b5ee76249243637fb5253d7ad5db0cb751b53a3f94f05ea1be1871305e9fb67697f702764dbc39ab49405fd585621d964b819ea18bfb4c3cb19ed43fc9521d96b5562e549112c35abedf01322444b5780784b2597c7dbad8f6b9a7bce0d82c801d8d060c88d27cf0c78198e8fbe61adafd328834b740c554119083 + +ModInv = 1d6959084904344a80c2bfd9baabfe0502eac746dd58b8915724b0a6e40a5f8fcf43f880467aa7f2e53549700a7570769befc642e97d8573643bb8c48251d441e5e8550b0655973e01ab1b370468c2239b5e9c502cc8412930acc1b18e90750940ba2d1302510cda79c973967dd1c1065b197f64efa3f8f4432889809be344b9ace0f2d5352be91a4e087eebc4053ba67ae707cd1329e334e88130115c6f568254c71e8360712e5b9287f5fc3ca67b5864cc36c50d5b031de0e3fe23c8a3dabef0c8fa0726bbf52ac8354883dd33173026d78e8d671117fc89c60ae3b7622293132953c9 +A = -f88903ee18fddf8b7613aac52f76f939de30a5e6ccd80de48610541d3f +M = ea4fba332f75945c16320eab4732046b66dbc245742ca7fe0dbe5155a6a7b98ecf3ac5990d39534df0bbf2180dfb4d4317448291b3e27a00a87a550f4aa28ea6cd9a19c182f83b519f37929bd5413fca66c3632c8a8e66b2e82e55a56a28fc5db9980d3d2b207e9db8b2125919443315b5ca2fd0499480e0654c964c60b4360a4024f66cc3d682ad6ba37e4b31f2f6615a589468edfec83b6b027d7dc5bb900ed2921f1620aae0da1aa294cc3ef1dd718b4001ff406f935353fa1efdfcdbcaff065e9ed721b63c7487408289a9f8b065edb4ed42e956c8ab6d22ef5e199a62f73a35bfd4 + +ModInv = a74adebd2af0a6c6ee21147790ddece7320677cf7dff22b845edff4595a7eaf04950b0b3d8df686e70d6dffcaad4df9d1a03a1d5d58bce1419dc8ebae56b7c0485b85ca842ad0601581cc2ddf276ea9f680d40f166f7f656dfaf9602a2f299f9c775f92494bff8a9bdf0c06ee94fba6b7ee226b9af223e6e7baeaa585e648ad4963e0381b6f97deafa1ca25e1d436eccd98433a3ae43f411aab55aece9175063f97f6c57a865ae3b092dc508475ef9c07f2334cfbb3ddfcbacc8a0fa366102c2158ed9a3da866786453a34b17d70e4ba8cdc1741e3f30113bb135f1454e7f7c3752c3f82 +A = -9beaa970bcb10d8d36ba5cbcee2d885f553d4ee2bae6b53b4cb3362773 +M = de8e61b8c440f7ce828d24408f990becff1a7b0e1529c332ab298399b9010d50d067a03d3f7fd9e14f4d6930519a0d659a0ebf6db33f6e3d9f3ab8125f9f782d215ca9675ee4c793ad7f672e6a6b22a8c96cffd64bdef32a0df60efe9757e5c32330a2cab78c2fb3721c57f96d29f2dbfcaa79ecfaf43091192a5a3b48a619164a9c2dfa8530fced36d2d3b3c8485bbdf0ad822f3db7f319822dd382469c0d34b13e635989cbf3ad061c0d01cc1110252e80462e9e17bb96022ee1fdf9c284de246c564ff57f0734c37ff700edbeb60ee1dfb7a85e0038fb3084a7ed2285baa1b39eaeb9 + +ModInv = 92c8eb6f5bab262fb08f3e2173aabe77c9067b9cdd3509cc071a8d2b5eae4395718aff5e563f9f907ffcbda11d2123ebf7d65f694f4a83d16a0f5d1b20db516df2012f878f6d75ac330d5e9a41537d34c31a6bea6e8d081bc115550659c4f1eefa4ea9b6b4f7fcafb9c4fcf255611f6dbf0ae29eac8c031bcced98c30cbeb152d4b2c726c6500cd5811a228f002ba5cff0c5d58887a078a69861a9cc34b4db81b52ff0c4956db815d08bbcb77891b50b7b206e2e12c413c228b594c553b2f35ecc82cde65f65533348743cf0273215cf7f5bd0adae8607211012871ba7b32045ebaca1d1 +A = e59801a8ea96b5034b8cda72b9a43ec79ddb5153710827cb5e7beac345 +M = f4e866b5a8f6f77989a4186609376010c247eba932556b4b6095fe2517c23b24620a00a4464b62a0033ef1bd5cc33db78ff59ea4ca4845b468116a00fb2c51f9077ae6ad0fa0a7e2bff18cbdde61550d677549e776e93b4924291731d38ef3a16d17205b162447ec8e2398696de33d5553ecb3c95bd3e46d8b0e7e79b76976962c35fcac04b0331d86a7e909ddab132b5a78042c9c754dce16d62d0bbf302d5158bf7626beef69238e2e9374b240035cf07d24b0db79ed34d230badb74ce7674f6c385d88c0b33b4628bc723f022bacaf1659a5057dab7a15e0175452c18be240cd3c554 + +ModInv = 73941cdbed5875cf5a4ce3ca7367e93de287886c92ca4590a2870efb96b4f9536330a6def7f5eaba3625e7a98d4a72bc71631b5984c1c2bad2aabfe71fd13363327f43c7f86780f58c742219ffa39a94b0c36ea131d92101f2ba783fa17cd537604d386f6554d0c903303c714218bd35f091d064e8fe2bd2883d73a050d107602ee25d51b4d5a3e56af9fd9469bd425a93a4cf18724f3a40631b0828aba9b876b331aed8e3bb33f1180c29322da12a5fbaee621efe8cb19fc220e43ac4d6201192ae909140cdb8047d0f52078f5e3a5bdb198dd7d0a1bb5a91483e736e055876622a3d +A = -f3f0dafad5d212f54f81149a9bd4dff8494d3bb3bb251f8120c447f0e17d +M = fdd97222bcfa3834e499260312ab20425f8f1260c0dafa8e544b0eb6464a8828adf55eeae4de10f54bdfd962ba9eda5bcb5d2b96427fab76b6926b01becd7f2c49811452e3755b12e627a3479a89e911609e43ca4d7b7898ebb856648c49c7b05110526f57bf60fc637920ece002789deda26cbfeba47d2c5c4c0cda887a19a724f705d1e059acce7907be75aec231720ab5e245324bca3b37e423cb562f7f12b934c6a13086295c91360d5fadadf245309d3d501e90931f4840e5f12537bf800d1b69296118c76b2038df2905ebe7f1311652f7bbda8d47dc5628d20799ba459570de + +ModInv = 6e0c25a79751daa0c5a74a31f01323e8dc2da4079384cc6cec74628ad8b8fd4864fafcb7403dff01a001c60c602acc341d3e999795d8659f06a641e60d9807983f1f2bbbf11cc3f8d483808c104e9e9075dfc1c8f3bfc41a7a4108a87579385ac2d3ed67328310674831823a4b7c88d57eff89a239a796d6036824e569f2e03dc8383955ff2d2649c78ede5ebf772a6fbbc50a83e9dae258c546c0996cca0fb7d985402ac3c889f74d2e41193dbe6f04e7e45f200c89030bd5f5bc4decfaecee36ef2acda452c32cf64933171acb7aceed42b3339eb82d91904a81bd8543668e257cac +A = d9a5ccd229453b1624388671d6242ca20ef1a0d997e9cd6e5c0baeb6ce87 +M = c37beac7a35984105ff811c0103e490e1f8a8c2e5e7df8bc398a7c66a9ed1109396134ec458a476953f83345775076bcdbd2f573931cc7809194d919a82e92fcf626734ff0614755bcc3edb4b954619c0e2a95e067d3d62654496ca198a9e586b514a97c2d8e9c4adda41aeb74c329d2078a771656ec1e37e942c552552f517b45133f1df7f28948deb35bbfdf3e673a2fe16bb563ad19b452dfa19b04a3befacde1cc3cfba4a6ad39973eeee8aba713b1a60b03ae7fb5b7471542f8ac1fd8b1803ec53be1465d44c763a61a3146cbd542255b155009233450fb4d8d0002857beedebf + +ModInv = 2ad0d2e363f48e69cf5e483add78eb906093152ba7fdf6939e0d20425cd0de0c3762e202b8d2f5480cdef16663f520d429e1cb0343cdf28ae39f162fc88467c30e1f2bc368f3a0253fbc9e504cfa03309496f430612bdf2ccf20b3542b37b54df3f5c40e1dbbb2b00e02f38913b6ca15448ac5c3679d9db4ee4cc0f146f2e1cd7917cd3eafa4cae69950dc9f675f85469754f3dfdf39076401d6b0b9df9d923ca751e202fd80bb27e413709217fd7ed894cb5ad9a72aaff0ea755e8974ed7c638ae170e8247d38971c08ac24384686718f3c49d70b6679dec9b91e7830027b127163a8 +A = -6948ec5f8e7c9498c984dba062040ebd0956dd97a69843c7520f5783b05f +M = 48c2dc0143f806f3e39d27fb4be11e6debc2f4c33b88c0d4ecc5b0fc607a4b9dd4b8f8288b1907da748a2c6ceca8053bba6a1a4d420fd93eac2b464d75d668bfc1df3ebf4981c796567dccb829d598b22e3ceb1d0a39051c7243194c631305610db43fa7a4f96a049e875eb84ce66848bf3451bd18931b472c911aa9f0c8916378fd49c743825b638581d406d17445af4175a69947891963c876f66cb20f1043d37af913e3f66de0d4ba219cb0f02b7dfed6a45c18337a58c0ce6142dc8d2ff7d5bb8e3aad1b4ef384c157c9ff42e5e7c1b1c5dec635817b025b09b5955ab18168e07f + +ModInv = 1c2747306ebb96f61ff64ea4e8b91a0925eee5235adfdf7e8d80a8aaff5f2447b34403137a6ef121f80521c8d38965bc3b13976ea1a716f24c97ada193565e575d41c7a879664d9058e0a36aa2ee409b0d58d54944ccdcdfe3282906fd87f9091fb235e9e5d6ea3265d08d2f02e9f2cbb20192a56813e3cae5573a7e4556c51133b6571fefeb0c77ab9180ea02df43def1ef343f9ece3ae2f39633ed1d626f7a29d811bc574761e237676f9c137c7d044e7b86076027aa946870456e10004a18321b7f2afd53bb9ea3dc1dceccaa7f584f8367d8ca9c3b42ad10c2154fb729c358b3 +A = -2522f750de7ce5f432e6ddf44d9dc6097ac32f0f045b429dcc9e88dd29c0f3 +M = 51afabb2d3de7f30e9e9110b37a505b4b0e94dbe24cecf7f783ada3a8afac2718ebdbf75cb82f84f967ed8fd62bf5bf62b931698f4259e893140ed7d6ddad9bee6d468624c979483c27ba1eaff8383840070da15623c660a5eb20047f555d6c1643cc83bab7cfb1fffa3ceeb85af8e872779f205dbac3f34a18d3ff5df34861183e2f32fa51029d015859dd945799f8a95c5dd6e8f2b8b307d9aa83964e7c9e7ef7f4cc1aab777e796f25fffb7f0c4422a55005f671e3fa897b01cc5e9665f4e4e1b0955457d5215b23accf4e8f3a4a2c59cf1ca162386ffed1fc2c437309e57ac3e + +ModInv = 5bacfc3b3654ffd0c75c95e5f3db56c308962b2221ff44b9904824594c4a20dc80f8d513d964f5c527d7cd9663f3c042fa0ac849c8574acbc8f354a126e13c735b2969834a579be2fc7248834bf7995f62c7020523e222b6bf2e3b37f7617255af1e435bee687fc7a136437e1b187ae491f06c1169bb691021ff5ef36b09499c407069a78a902ca98e2da6975600676a7ce575a229d1ba0aa639d8a66792a0ab6ed621184a96c64463a876852b375bef84a3de830508c3af333396f6322699c71e8e68248897e92e8d6b47edfedcdbf0239b0da99a1efbddb9406105255ecdb4861 +A = -d2de46b39b5d20ec7fac985aa652291a8d7c50c0d3cac588a43616b02b0cd7 +M = c7c0878ce719cf7fd2b3c9d1461578594f8a862062fafd1cdbae7a8391c2c9017445ae24980269eaaf022163015bf66c145271d6e62d4577b0b18f76716a7b3557299948cb7f6ca41c4f129a3010debbaf4ca0c9a3d294e76f25b47113d892d2fb139afe8d492a21aa7f6ebc8ec801cde02d90b5faf82d02e363bed7e1c9e19d261fd19ec2af49c1945b2b326382b3d8765039733acdd78a4fea41e14a9236e03f1b8bc2a4a5a239f14bd36b7194474d9b1d499ba62427f2ccda11fb46b2a23096ed95216e18ba2a2dddf3f82fca646f34b98abab293c71c8bc107bbbb7b5f9e524 + +ModInv = 4a39222219977e2e66f4a1239b0d4782fcd9038400c901d2029683087eff4bcfc7ac60a6a63aa42e2b928897f865f940ab5ace8b27cc4ed3cd8011a941a8d3f8f57fcacce495886e6e90760eec0397a921d4bd4496990d2a2c63ad6a21a4e5fa08fc42124097c6a5ef924b79eeab020137dc902f38da04556e08eb7bdb0c7a8ab54ff989d7d77d652c3704927188060be976d9fb0b595bcd87bf4bd2042b81f0b671e3204b9503eefeb3426b3f327f1e50ed059ce69e76edb67c1adb18a84172bad4889eef6e6941ccb9caf122dfed48df066af2711e1fb5a992107d1c428d3f25e0 +A = -7c52819fdbb743fb966422f641d45887bb47cb7f0092640706b39b55d9e4b8 +M = d78b54c5a79a3dff4ca8a57f6db896c51e3e9d7fe38789aba0345b9fa2fefd1bd5f5c746cc9bf62247cefe82943b2676e220ea32263121dd3539bcb2ff5c9d352accc3efce4315782982170d15d53a3c1a3f8a0694e525f42e9cc29b2b5a10869ebf5574cf9c558e8007c97ea9c979663afa76bada09645c55d88cabf9ad013f3e2d086420af389619c0556f13dd6e253a8ce64a6c1e52663fcc9d06c7b4d728b15b0a21ddc2d90801b7cbfbd788612d77bab95502819b221fae32f33f1535ba319d884ad0794171b98f33f8733200285fd72bfd6dfdc68c8f94b6cdf050837ae239 + +ModInv = 6a87459bcc85f7da29138a9fa45984fd267fe79a04259e007ac360c36fd0f24f9d4b001b21197c69c55a09e070dfd28d7914acc2c8154d3e4ae2cc26e264f23f5399b20b858c76289edd11624bc359119f6ebb61aef4402fca6c51500bdfdb01e014410f2515c85385a930ecf86882dac983e96d729de25992ba6cb5560c15ea467f8af31e77936e7ba7ea179733475e239be4ef87b8d67d4288e637baeede7f0e792c13d24d12890c342316e67003b035f5fe033571026f43b7aff1387f4a23676f8e8fb1069e3e96085323751febc3c42899263e2c4efbf8b01739f816064ed +A = 3377fb46b7a3b52d7a3fa1facc61535ced146fe6b96365116a7b4732d636b6cf +M = 8a60cd01aeb1a77e58ebf67dc0de38580301f947d7bb6fcb5206f92681d01bd5a031ea13f68db755a68958f15931a3068e5d0a49c756a851a313d89f675486658299fc8d89dd7a5a19f2919c48d37cd3f42688feeaa10f1313b4bc2c093e2297372e1dc534724018e4373807e3ec2401e2fcdf0fcadcf73067d22888ef986a3a79b1e4020934124327ff4735af248240bdf8b836ba6eabea046d45bbd1b7b74e6760203be9cbc860c6bd14c0616187a9a5ea5ce0e7e16886e70b0ee85b0ba399694ee1193d91cea7b42bf7292531b52d51a9c8b0daf23e78e76404defb303b79e + +ModInv = 31086fcc931bbfd10a802c14d98b17c69e0a377eb249e6f454f33bd1b38c60f1bdeb895002150ef6dede139a806da343156135c51dc32446ce3c141e0994f0d409d6ca23988d89a296ae682f57df4530df8b92e925ea6e38aa28de9c01d946e17650e257312b69a30f908a70f8a188f3ab93bc224e0b58680a63cd007efdfade5d0c3539a77504eabd42434a089905d66823e5a46e30a272419460333a5f30b0a513a9769745b925324e79eadd8fc50420d135b4bbaf4f6fa3491d35d9f8486e3c97f75ba64b042c56794a5222e603577c11c93d622bd602d114b76f1774b3e25f +A = -b404defc117b1538abe3b0ff8fe8d3bc2838f743eeda4f4466de04ac6336e3b1 +M = ebdb18227e7550226d52393c0eef57c68c31e94ecc372704af9d281d3556f866c379dc84d2942a8d4ca8a5f561629816033d9b5ce7abdb3481bdf5128474daff0df69a82b56c49c86abcdfef28d769a185d6f31d1993f2d213d0149b2036b3d64246bcb10078528344edb3867d3090dd3cad4082656cf083f42c947a58d18ebf03ad5b5bdf28ae0edbbf7f10bfcfa091d5938abedce49d060ea4525fa74f5c836992b6ea728beb6cbca494f9c2760b2c7a6c028066f2f9aa1e437fb86a68b20cafe90027be5fd051e6ed4366f42a8e66fdef1dd4213dacca3d8f2b23e60a045e58 + +ModInv = c43ef1f47b740978acb66eb0bc8f343afe57eb8ef047e5ac8af786cf8c37a5ec4e79ed1af1d6d63ba8fec25dcd2e08024a0bfbb9d0197551fe80107a07c24f06d193e1669a341806dd7bbe3ecd3aefcc6a140fb3d8065250dc22a985f04f42e848424dfce98530027b95db7229dff131bad78b4305f78c07829c1f63aa1d6213ae485e2812b41a4c1d518a70aa6e942fe824ac238db7253f65d3f0a3a208d2e662750285d18ddb1c60e435359a31049e6dfe5844c9b4d5fba2c61312151d7c45f0f55e575becea728abfaea8402ad5df98415c946f9402bbcf1fdd77bb50522d +A = -c5750b79840a35e888cea8684b60033cd65db233956ea88f4b4f72fd3f7d254db7 +M = c9cc3e8a7a0e0583f37151c4d7bea6cd4808ebb5723bdd10f425233bff64e5945d64f7d65e0466a76c3472ad2271615630ce9ba502f93eb042e9c091a7d0ba3f0605fca2d7a7836fcaf25f54c66f555c240a97759009eb69b50f9ca5376f3052c49915f5fde9c7e9675be2b6da6f2974beeb65d108c25300fecf0c9277eeb71d894a472bf09b30460cce5b3445fff12fb4d7a20d294b97d08e7981664997082c8b7e20bfd2aeeaf914c7d3fd9a1ac067541b8ee6f0969fe15284b2bf8e56916a518a4444aacdabbb49c9c6072c54a01283037cadfde8ec5e3e1544596ebbec4c + +ModInv = 14eb895990047532c0189ff2fd38eeb7441dc663e9965907ed253d6e3e41295b3928128cf04bc6f76340c3ca7ae80e5a5f53bb40134398738c58302840785fc91d691d27baaf862abb6f688f3484e680b6558ef3864ed7940accc1e697efbab79a19d7bca4946d36cadb603bb549d43db372b146d4f2b2911f66cb3752006fbbc8608eb2d2a18d469d6aee3652820e5c65f46bb57666f0a338c19aa122d020b58cfd46432180acac5edcb3f0c107b1cf3e3638c3ce65b72cb3e4ce0a2e68e12ccf303c69a34076382e81cf2ee4b444d9159f37694c81f78960828d17e7823a2f +A = -33610c0f1860bcf5788550b578804014944f27c7719ff747b694ab6e3512b1c51 +M = 18c59143ebbb150fad4cbad88281e3a7a3db14dcf723efb222d8f642103c86cd3d2f06e2afbfad51fe9c625ee2953df8d9cd4ec5eea97fe87d2345cabe9fda9ff4b550ec61d0d7ace993413d2a0ec38a62cac46313ce942d1cc031db146ad826b454d8fd7463ea93dea01c1e0da9ab162978eccbd6cabdacf9d804a38151abd506f842772e7c0fc9d0856c222d0adbf1c80fd2f2f94e2424d80e3de0e88a1c367a5296329f9955a2b7cb8af65fdb96293c210ba6db40de36dcc2f8d320afb7319ede5f8bc34a25ee763d2b00b9d8fb8fd417bf7c012fcdcad63bad439dae7f10 + +ModInv = a5c2e19d2ae5828d385280964af1ae11aa2f2182e4836f6373d004dff2ff8e2555d8ba39cfbaf4ce80fe2a8a620318bcc77cf8adc62505b9cb31c3c245474f516613c9f67d1dc30a8457c162ecf5faaf4ac09c4e24da1edacf82f186af3538f28951843746758d02e30551993692c134a69655ae0c382084d3b4bc13341a41cfcab6dd906542643c42c804963b9168ee169f8075e791ffaa0a05216deb2d0a99dfafef7a50b9fd5c60c794b591fdf490eeb960ee11d543365567e09e7004cbc535ac93367658a2490d5302b311d53bd3251b524e32a2c45e6101399ccb53949 +A = -2332b302d46e3b2539881cc51bee766d812792fd1112a8ea3fdc557607a756203f +M = 6c34f0055505ba32ad3c3c17986f62eea94fed4d709e766535c3223b4ed66259fdc532f1a074da7c8a33555149919e434864c02cc4898ce5d3218e9f8a3ffde7e4c4996519c09bd2d87d0a7bd8a50c059d82aee0c74dc254e0fc02953e05c3178cdd7068eb774eb9fa8071a96eccf5c0d3697118917c186e35d02e1129f0d5a3c2b133d51405fae41eaec077fd1e3aa6b8b2acef36352802ff8f2033302bdfc9f89874178a665be2fba36b442ede89f8319f4d03c3a57ecd49d9198095b7433136f462815aad0432618b786a00251ee9977efce2dfc37bc63a9f6d58ab504834 + +ModInv = 953b7017bf3512fe303b37ce978dec47db7a978fbd4ab3fcad399ebde676e63e9b9df67be33723cc8e156deb221de95f239f50cd99dc0496397fd9b265248a40363d681930b45b5c3efaaa188c1b91498fc7e90bbed0660c46b8ca711a528041d36841133090cbf47bf51e2ddd20834c02bca94c0efcf9a4881ca59b5b830e0d82a4ef972a015cbe5e366552915ceb7b5a5ac64efcfcf2f5461d196c8d2cc441927de3d126719c932fd490c18ecb7c7a79b5899467ab5424f1fddeaa6d90f909bffc45f7c3d1d079bd90d19ab31f4f6e66cf70adf558fdcb1bcfa89b70a3 +A = 52262aa6d40b849269c03170f5858bc976e44adc9ba6ac48eb86c610d98e9f34360b +M = 591d1e08aed141ef34f7e0e96133714377d8659a3914c35adc573a354c17f1ed64c7d0c86ea14243ec43a0f9b7fa02283da808681068939ae7ca605923c8928007297c335fd92f18158331d9539430114247f94691af83227ecb8d51dbfe5870396270023c4fdf6c23bf51e8e21181061e2c3125d465fd8dc3dc193629c958609c9a9ca0ea601df5d5a287c62c82fdea3aaf330246c898713db611d63b1e4699d655015de415c5ba2ca45d8b572d81176d51bcb2ea8f7b9ee45d8153e8c2d8dfd048abd1bd7ce5ebe9855c03712b4dc1d10de7b9668789e3ec3e3a38775d6e + +ModInv = 13a30d5789016459170251874ac31fc807ad4b44f9577a4792a9b07e69fdd36a574772810c47718f5defbc46e21131c6c2a8d3b620c7846d5242946063b81117c4d318094e5a1cd6f7ce604da4e452b9f488b7c8cfe937ec3a9b5e424d258709881d82f9186010d8dd19ede1d642bcdb9867a78137e361f88c9addb127ae51914499d3ca09fada931c5f52ced4d8ab8ed2f685996ca0e5af39fcbe7e7c3e64cabf7cd5b4b2cf70a2246063b2e04553634dbe7c7879a9cc6d7dc7460dd42d6c28b26a7bad3eba6034b74afbdbe8450845a67a1d31039299f7a98192ca30061 +A = 5045fc30131b85df97147bdc0aeb50691220d44a128b7a62704d6469a387cf2f4e88 +M = 1ae8e2258c4ca60d661cb9f888b3bed0091b1ffb59c13567b4bb7c44a136160149c5e89721e01aaffd8011dcfe8ba30cbcb7b6730712091f018743ea2685f0b5d9c3557e0e1ad130a6d40bf6055197076a46904b9e4839023e24f8674f2d56846135e377236d23812abc2344e235a8d1f5cf690bbeaef9c1372241551c11248099ed49e94ba7a8592c14c7aca9287d958e02d3802f8bd3afa08857173cf73685253442a15ad12ed3a4fbe54db14790b710198892f2378c54185323b0907c2a9cf4013e2a709b247c7e07831749ea1ff65aacb39b80cdeb4980c1d34b7407f + +ModInv = d197f0955619d79b8be6684eca3d130a226b70cd86ec8a502091902e5ab7dc8d1bd6480a2425ab8b858c9fad0bc03488a60a9b0ab78334b0eef0ba3f196ab626df657c83b0296f3d14642f18bba4d99a1a79a1d4c49161c51ced612d3b0035b384679ad39831b9316289f5f2e017df3eb7143e28c7b14e6759d0d83c83405a31ba8198e2e9e31b231527ab41121ce7b0774537dd6393359859a0a6e95f0f2508c8bc7c9ad6388db21f9a37087352478d1c42ede533384e2f111410c9b10930bf409ee1c33e3e6e718fd3fbf2fc56ca444ceda3968f96e4190a649e524e753 +A = -31e4bce325067219ee6e19b3c540acf1c2c9ae80ce918ab6064f11de567df74fb43d +M = 22be02e6ba63946bc80cf0609659419ff55f41ed916258ea13cfab0a3ab7f902baee80e621b7076ec0046289ac45b8b262b662647424754d1e0e884d35d47f89b69ec9ea9e80a4ae8c067b2454edd67c10d60dff55d813a5d13dd0fe530865987452d6463d169b2a9f5cd042fb95f1a584383209706e00ed88ca4bf91d446417da7dc723a30c6232d918dcffd6542053cf5d54f8bd143a917d7c68df44420a0757727cd3edd10d866de633f27a98e7cb7a15ed25ca73fd1662d65a1bbe955cf833393cf07e8fec0e2f4b7ce6b9356a97bf2cc16aebeecb61e8f7da8c8e78d8 + +ModInv = 15793ab805c468d3fb5f726008b999f67a0d957b85e3232075c3649c1c6988591303f6e7d3668ac6e22463a3c7b299b30683e80cda4bc51fccab779ce69586059952a30df32b6727779844cd8f8da0cf5ecf9613e6e45413f6992e0716dafea080b4824c0e8f3d5fc8400692de6ee761992181b865bd14dd3d8fde818862dad7e0a26725fe8f56349d3cf3755f69262232df72e06c22e3963ab17006be71d2b2331c5dcdbf3df79e9b518759f922341e4743fde4da4169c4aee335f9251f14ec9ad187e75b0b5b84cb32402b75cc488d2f05e86e8ad07eb10f4a27d66b65 +A = -5e36ba570ba8617f87032ee0aa3be7a6f95479100204cc5bdf8f407a128a26fa9627d7 +M = 2fa36283b519ae8b3f211790c182e30c8e9ccb2b0db2913d748e272584479a7b3158b270395c3388d6d569562cfdfa975e07ef14198472b103f177dd5af7106a555178eb5a6f23566478a4f92b6bc47cdd20a7113f39b9c826a2b11f898b8fdf76ce84bb415ea63e05ca3af8d758f8a38b2b9acb3b1f83fdaf343ed61ed5c96cf34ee1892a0e228919295b2e55a6322d4dd03cf511d9058b24abfc313f53c83a04d865958fc22b2368e4de493212d157adcc574b5127f662dc898255b94eefd12b932e05c8599c49ea4e88f29748461e4d4098f31c68b0a2af67fbdeac2c + +ModInv = 17349c3dc9152ad3dbeb9a3331094f2646ac39588b72b9449d3cf8c457c0069f1e73a6ec19485c64ae74e5cc27dd6af7fb5aebd763d3f74b3820ffe368194cfb8e82f298a259feebbe761ae2cfb1861e0f2db00a00b3fc2442869be24ff5b2e0910884b2ca5533a6553fdec9b1c56f29da56ed9b36651a18b070efa67f2c62ac61a7ebc24e182bda72089adb19fa0ef80cf45df53acf7121d7958bba33556863330abc2e905c335e3abc3987eac855a77183a1f50f2907fbb1e596342ef401d8f047bd7dd431471a05c1fe767fe1d1e7bd69048e39640975517cb593decb +A = -94d8589b31abb8bb31eee24e1f52243d457dfa97fcee98a2201d7eaa684ab4312ad555 +M = 789110099fb76b31bec9f2d09ad52fb0697225b30f5a49029cc0deb4ea9d04ed02d2b53985714a9605f2916d4c02978bb517ca76ea5b7bc4fb2b26f5abe65fdba5f7fae0f3c84a5598ee80327c1e8717721c9426875a2d020a4a28215d62af4062c0e69697629b3020d03c707cde5c5936edfebb51b56a4d1451ba08325a26a8723bef1b84924dd6ff7cfc8bc043eea505efe9cb868acc3e2714c2b0437dd9286440b1c31b84d40de63164e391eba7b8bab2efb8fd7b7aad0eb210d56d78847b187c30909b0483e7a65415636a7ed827d15d383bd3e8201fe0184a4e8108 + +ModInv = d32d37984b35edd5c0294a7f6e6b5c539eaa7ffc7b283ddf0538d28941d6cc5695025974e22a23f5509ccb2806124412c546fc1edb24e1dc7b5b541db6ad456ded715fde4b4280b68f41fd789e63e83a687b4bf072ab04fdc18423fcf2bc63fdc9fa9da6bafd2820dd86cdda22a32f850f9628e74a8121614300f22b42c3609f250f9098eb013025b0973caedefd5afb5be52e494fef88884f035aad388efa8cc7bba5780c5b8d0c413bf32a19257e2d56cd759b7371643bba24edca48d31f311b7a80e0f58b44fbc60ddbf077a6d49551162f0cf828563fd8975e89a815 +A = -a9041706a7418d35ba3584cb4aab9a0b59daf26b2f9a1a5e9773c57579cc8d24fcf17a +M = dfa8f92f3a2eafd63d0205c5f2d7e8a0bf0710fbae7b9da1d33d1785b2f1f837f22c6b40b86e663baeb98488c7f69c0561de8e189950f05f26a0cf43f5b493e7e34fdbcf310544f0091e6e1e007c71943488c2e5148a26b3223739cd27725bc4fd1cf0702250c3d67ce50da0341ab1e0e8c1963dca9cca8043004736e1a3e330193bfe0146e1951801abd740a0ec8f437d028e0fa1115ee88938eb51afff630cda9467d872cf05d4fefa575ddca1793aa09e662da240ddf8570355ba644403bc607637a7eba2bb60abcb9a204a2dc5d61d1699ffac70375598f84414f8ad + +ModInv = 55595a864259a12d764f54f220722ac3503b0a8e479a84f335cd99b8fbf34b68aa1300e3c20cc190f77f4ba9f2b4bf679030238fbe818d0b28ec4d28bdf4071bea7d1f78443ec965e62af368689eec8a18835256c58555e354eb068f8a8b45592caad22781d4545e7efb1a89f83b23ad3b04ab461d697c69c7c37d3ce410b0a7a50a75bf3331ecf5f9bb5be80786409fd47ab8d785edb2bd4c223b4dedbd48628953e29aa33228fd3c503fd25ddaec84ec3c87a76d3fe3e6f91bdda70e6d74a2ceb8fb2d9df9f8bb88d213928c978f15e815497a1c412d20b923ace88f +A = -42e16dfcea49c3bba01d7da3151df09be5bdfd5ebfac159ca7ecc8f1728c3e914f40fc11 +M = be7f5e9f70f4bf660ade3ea830d486b2c1694170626a39d507db8c23f72417eaaf5c991fc1b2ac5b6471837636e564ff8a63dae51e1883305b0f6f1058997fd1eebc47f6c10564a04c56dafb1b8a5f6587f7aeaeb64c3486c1b58b937c45e5ccc95fc0a7c65912ab7fb46364437a327896cc98be9ca653cb3c85188562deac7b1462a4405bdcb927ed9dcf4649a8e14d713973341d77ec43767b22e462c2e793873ef983aaa80404549b0a827cf01635410b95f8b0a71dfd45ac07a44e7da09e3904b77742c3bded8ac20eedbd8e07903b55e0cdbd8c7f8b7873b3d7aa + +ModInv = 66639f178da1638cc49bfb6c30b40c132d2a2d277cd266f4e176c8c6c482768277e1ff0e413351a509060cc69f32c0b2ab6c7c067bb9e8d1fb3ac54dd61a1dbbfc5e573d3522bc36a9488db7e9215b4bed63652bed5b0af907d121ef35a8e8f54dfee55883026c7d9b426bad0de26be12478a16535fcb57e0f55d9b5c91692b119a641952b142a58c6cc4f8ef11f09ca0785f311c0c37b887f4ebdd6d005b57814a4920770ff4baff0e77f6f6d2b0b4936d5c7d7a20663ff7346d6b887a8fc874d106ae39649499006a2a25d4e325dff5cbb74a40067e00eb0e7998453 +A = -ce4e0d1381cb5dbff3ab555071a21e8d7212a4471df88bd240a260c54e7623f20514ecdb +M = f06c6f1fb33f404c829e5af92d4c3adcdc8929cbb9b5a97261de8e7b38e0aa7b5f243c94737e3aa5fd59fa64330c2cb4d674ac898dcd2497249fece36f8502b4e9404c73a9af3eb9261f504fd63260816902b9b23ca463185422cf48dee3d8f15184547e1b8897aaf8dbc172746d6810aad79c51e877ca46bff1272c810e49d6ce43dcf7ca686a6e1e1899b2dbca772196f1ab2f5b2226d929241496a5bc07ba619f304626071751ff6b97fcc3130bb8befadaec5628c24a728729f4884785902cc1c0cf4a8f879faecb19e00b08e396cff49a88e6c29749063fae8e36 + +ModInv = 1d046b2ed325ab1c2be509432632757634a88387aad3bf460b6d943fbf253a338a8244d032e26c6d527bbc50d5771d34e5cbecadf7c379c27f352eed11c9473c99a4c83623a5f7f63d9829a114c7cee44f34ec18d0252c8a48700b1eae5c93f736048893c9445c61dcda6a5825958b032d87c32cbc961fa99f82f50f2fe84005a8c57508545f5a0571e81ba48e9c261900f8c17475126c9ab177e9612dc42f095604e553e6ce0c641eadc6f654528bc856c3ec22fa9072294a1676941d56b3c0e91e6bcd762959980c5e66a064ebcbd8e9f7ce08f0dc565dbf1e579d1 +A = -aecdd757dbb070dde542e49fb7fc262e7adfd26baa5fe310f09aed060a0b644dabf5a915 +M = 43835dc96cc2acaaad9eb4ac793a24440db4e114e44f58af5616c5587cd41906cb2889415375d4243938f4afd5d0d7d402493ac321d03010ad7b92b986f130fa33f8dcf0d16a43a03ab20237de44d0146d3fec7e8e63e6a62a603ef76557e502536282dfa9b9691b99557eea98cb655784aa196a762a653c4c4ae8ed7bc57a06df9297fa1523a102257ca7296798cd071dbab4a3669e8d28c8a8de6cd271b6822a92dbe38da7ff626478e598cbda007670515e137882496ff890986bae51fdfe31365269010da89aa41fdde71526c41890504a4f03f947d02d60878706 + +ModInv = 3745b5443ff39577b5cb893512555f2b454a110fa2ae33abc0f3a87a815c9a85fa107581a8d302ad58f22649ae04576cd9c4666c1c0331020769256e034c767d1c2e4e5c8eecd7564e259256dc4820645deb53ca4b3d7fb812e42a325581addb870b431777514bb32110ad35720defbf95ca11944abb9aa3317022c7a5063d12a2f81a39c34f3500a910d300a3d6ae6d38adc00c41d904fc27b57200f1acb57b725692ea1f0c9fb484e3bc745a01a662ab40472a5aa324e2ed8ce7c7c9f87da32a9f0ca0ceba62425fd840be6a7de6e5265a2071a0c19062371a76c3 +A = -c80152f2d171633b3b150d50472f9bb610afef33e4cf6d24e045b160d2c0380474d973eafd +M = 47560e486d0b00c56ba9563e2a4a7aedd936341891ec51c4d6a3fc9c8ae413c72aee9cbb63c7342b0ac99b2ee5ef55b09c5df3bb3e1f138c397d6122f9191517d977612c12c6b699712904af862623770260d462982790eb8a3f259821e68ad4eed83d8ce3f5ecb4b4a09a5305ef9462089e6b6ef473843d082dd58a29a433c2ff04f8e811586953a91febecba2bd39d29e89e60f3e4bfcc6af422e2cfbaf954b563a3d8cffc282e999fdaa509f608037da0dd3c1e94393dd7d8655379f7ef8a6ade5abf07428ec7e14fbc6e63f23885a6acd7a56046d4b40636c473 + +ModInv = 14ca6c3fa726256843bf33fbab12b2ebe67af20b0d4ac1d6ad05f8b7a2400a8269ef0ea9bc8c1c70fa2684b5aafb4ae18d6246ebfee74c15eeb99caa460c56281e36265dd13a3bb75fb971cf72cf3c4fdf950664f754437332f99cd1f9b7d248e966b84b097a6be72051db96808a69d4cad58d5764e40d5cd394bb376735d66fc29eee5200a2a91c2b2c67c801cc77679aad55932b7b6d543a280db05c48a8f82e0316490b42dc73ebd2a137801d13df8a38415aa36e9d6c802ccd43c40b6a5066aadee335fab2ec1d8ce470a3001f83e328dbafaa36d7f66e5c1b85 +A = -a3f38370821f29ba50184805597d600bf7da18bc6e15cc3d0569bef86f133030e8aee2619 +M = 421a6b4987c3cafcb8199bb6269068c16be860c48db0efb71266714f5fa6505a2e3def19ed271798cae2fd85542702fd9b363efeb61120c5c29f37d084b49b00e3e59a884cb238d946abba56a4f015ce4520d00f87d08cf23bfc9e5f6843114bdcec2a50bead199f90d35b56c7f090ff91d678e782ab5d3ad14b874a23a1103d4ca16da0ee5c96d67f49c722f74c8844212d530f4fb3bc3e07db59c8fb28e0127839a03558f6e59e6964f336c5e5f10a8bceb3ccf713653ba478516fdc3e3531b2bfbed5d463408a1f14cc090cc081001d6019837dc4b80c9363cac9 + +ModInv = b85c1c4c83b8122cdac2224073d301d5a8f679007f721f97d7e701f49cc5e59014bc271d2a9303049c6c4bdd545b7c37fb39b3d82b3377b0819439feecd767ccb9ee195bcf699f4c14a364eb757768589216ccd85a095d30f2344f7b87a3ff579e2d2ee0bc077adcde1d71dafaa1719d4407d25b4dfe94a9ee3e2df57d2b1512a0287b7059d93269302573858aa424b6ea21ad34b8107b54e5a3bdacbe104adae910eb2571240ae1a514e33d92743e8c28ae8e8aebaa2c2e24a71dbc3f963234d7ee407dba5f264ac35642cfb5e261754f145d1c6a4c068d19441f +A = -da91a1cbe0250bd0526aadc63b09806757ad5f05e1a240e88b44ed998b59f1ce6cd712b4547c +M = d80b857372f02090136c96117808ce48d915468863082e458015f98413f32231019c96cb778323d4805dfbc11ac9cc884e113ca274ca8dc4e46fe8579eb8166b16e9f9e64ea7d2700018349dc321f5f8d7d0853824ee142ebabb961ef826b5ac987a233e90067c9f3c6e3ce4f2eb93c43b091c25c4106d5f1061f98fd7b801f7d3e635cb89b354b546a8ae6942491f01187ccaedd42b7cf77f4b453b8facf3d34a740dbd79deae2b5e688bd2a9c1b8bd5ed0f44a5015ef0aefc173cf80e9ee1eafef82dc2010af2a2423a2e28f73f16d61342292357674f86cf5f3 + +ModInv = 600303f5653af078b169bdd7eb6c04c26de77d741fc20d16f7996f51f3d54afd31741a302f710e3abbf221eff2f025cc3f13c971caee5c7896f024cdfb9d55616a82ac204b445896243e7fadd618a7eb7d191811178181ebeee4717e8e62c4afa223c9312f69186c7cdcd62c0163dbffab20293f177643619b9c24d47e4a5c9944ce9eb999af9fe65905c4b88ed9c089798130545514cf2bec8129a34edb1bb22d8d04adcc3c35cc177f4179ebb5a3615b61fd60f51c20ba82be1cb399c3028774f029db1f7127ce45e1ce2f9155d271a85f776c3a9946064e6418 +A = d7f8525731b0b8b032080a595df867199488fbab0c0bff1bfb09bf8b6f8a5e2a1b13868301c0 +M = f996834086379b761c68a93c2452efccca8f7a417f3e002d50bd268cbbffe86c74d252f265cb28050e9e216a562f9250eaa71b7e5ca416bd6749ff9c8d821af9fafd2bdbbe8e94a3c46920eee48cc78b85e7a939124ccda96ea2ed89d799b26d4764b8356fc21c4540bfb930fe0b88e3da65eb0d57db045ddfa1ecb51ebf80fcb04d48f16d1bbec081cb56977483cf8bd8897f64f8fe508d9099454ac994bd54cd7d207e9808716516db2df38aa7b4b5cbac4bc61beb19742da98d4ac41c2464b2065573611d232b8d4e5905d2da962a9dd9b1188e640f1c5ebe21 + +ModInv = 285b6173076b22cfb1959c014b431cae700aa0ebde25973ffc07cc117ae790cbe41f820cda16a197700f7b1fab150b3b29dc881b1c445a641bd93a9354e6fb7f1c3889e0f7fbae265dfada79a8b585723f63aa0e320e5e640211a5c48309adeacb9813e83dca4146d20b04b396fc5f43554358a26644deb1019ce2cdf92b10a5fc64c6fa576f77f4b44afdec1f652f3dc24d80dec05f1312e9c7d2e48e0b5cd31dc63ce1c646ec2fd8294dd92a187e8a97280491fb2f7c5449af171a1cafecde449257de22f016646b67026b3b2a4fd3dbeadf621fb002b42101 +A = -cb26d63b96894c0e381da6738fbbfff10559d6da23cf4280abdcc16d498f3d350daad92245d358 +M = 42942d27583c4ab5b730355c8481947255dd5a692b9318764816ae0d5620ccfecf1b7135e064ff6559c6af41961065ac765584f18df95148f05a9a1a83ad44af622b2a284d9919f059005244279b757e0c3299413b9bc3c2fb7992160cd64f28b7253564d80af29fb3249a40304df4533acd5ff381c190ae39b17520c61c61a0dc52f402d67b2fb6162c23d627a063ec47424cc73b531631e2a3ad31436eedf7ce63439285eb4a0c01320d6658ff0cf9efade0fdf60fc1820671fc7529673ae92feabd38084895869a6d3ea834494e548ea2b862306dab266b89 + +ModInv = a1b22e483ad2f7bb83dd006108855710615f9e8467846a29ed8e810883b1d5e47cb62bcf37a23b8c39c6ad1464b632434148979761a51805c3c1ee0f292e744af7525328fab7cd258b5e4f17e16a941a61c67b828927a26b5714cf2696aceaaec73d070795d4c9bd56359c56a58d122bdbadffaf4fc5d1fb5521a8b69225596e3b37d6645d9c81a1a3613f545847be07273a6824bd994228e7be050e6580c4a6a0bcad6b02a71c2781dfd2ae15ffe0ce22a369979b4d46855ab44c502dc2ee73ccaa090d6d9dc091e3a15e6d4085263ff3132e418a201e6e817 +A = -b7539f2c581fc88503af6b488432dba9d9f694a1983ddd640c93b5910ad4529323f6a62ebe4831 +M = b284a00859b210c2a0d5fab73df5af67d1578f10eac4a76fe016a58779109771759827e63f317f2a43dc757b916f3fe1bae1feaeebeee20bc31447d2fe8bf45321d27d99fc3b5a71849608c30b19e8bffca6dce3332489ec687e907a8ebc217f8067f741590025ccbdc603bae4bb446319fe3cdbafc5ec8ef41bbb043241429bbd9238028c2a7e4f55ed9c1246c7f967703b754b1691aecaa6bfb093ded3f3bfc1150f399e2bd2d1ff952f1ab86fb376931e311df36bb15e0d084df5c5a691201d81786afe552f4a75ce2b197edf9ddef937be7f1e12c6a2c89a + +ModInv = 7df588758ed4d274828901e316dcd0c4a40b8ddf28bb57c5efb8a6c2e33052e3905555a1b5f6423c28b85faa026b73120ee3c99c0d952167ef5bf1877c9e6500f1ac06c00bbf856eaf05d21cf71d13a999e3dcc6d846bfdc4c0c00c29660bd1120e20f86d435a4cf0f3045d52cc0f6b862e1bb6dabaff9b81bdb1601e6744056d1e38d209bf932baf782f5af8f130ffda28ba0e9cb9b4bac0c467a2ba8227997992eeb2d75dd9ba585f65c9381167f5311aeccbfbd18461ccab5cde72a47d627b2fb5fe915525d7eca8dc13d88d179e7e30955cfc1ac944b0374 +A = 695392356e33fc9fbf6b0fc3779b0a47306d0f30947856c9b5dfe5865a86bbeaabef5c6e09ff05 +M = e14e9572a5b9e1a69a1171bed8fb394b19fc47409987667e454447174f305483b442dea1a31c484f05718fbd993ac1599539d6bd3618d2d84ed9ea6dd9e89c7b3a790cfbf2129a000c8deed126f243deff8b89f304a60fe38d986a280994ec7955453256140d6a2cd8cd483cd8a2f97e26e640f19fa7a8337aa486d361bf994448aaa7d1b2ec93ad221faf182cdfdd9523dcd79be06812ee61915b865473e6957b7bddc649a00e82d2fd9a353adbf17b820d98b2fadf0937ed168e81af75c7cabf6cd46a103cac897b4eac24123261025953cda34de9b94a1345 + +ModInv = 78622e99c1e2e8588979baaf81c574447f4868bd858615182563be632fadcfd19d9bcf1780963c285cc8670dcfaa9723334bf8d23bbed3cdfc509e11dd35ee9436e166f437b868a00bd84923bb33fac7e81b9d27f65c97310dada0e6c00e45ca7c6031c5f8d2ee6bd3db0a403c6aae838332b0ade476667c5cf2e406640bf7c05c97e64250fdc33afd5e374234ed71266777f6ae0b907c336669d6751d02348ceae0f486b3630c11ffc96aec82e081e3b4fcf336a156aa7ed93f9b46776ae87bc78f16afeb17853db03d09173cd54bc7d9b93d5d96c593321 +A = -d6803d21315cf261047c47a6df4d55df7a38bdf46d3f03d2aac4971ef826399a29ccd1439089d67b +M = f23adcbb1683a4d827e159a8f2fed246802c342f193a9aa5d1e8707ec87dc2dd2449cf93c81437271f9e769f7500b6984d6185dcd1e4b89e3ec7e6c72cbf4bffeeffd98058c10e5da9d7b39aa57e6b804bdec8e251496e59640ac514f53048dc59e2f4f0535651cfdcb6169be53816d5c36b7fe3bb85a4ca4ccef0220d3290ace680814a5ca0baa5210098e5818079faa615a7e10238fd19f758b50aa920f03042bd314bcbe602f93565eb95379437261f78a51fd9671b63c6f86db43172861eae2534929c0507a9de5409b2a8592f4f8b0d9b2aed23e5841a + +ModInv = 91f657cef68126c87e5f8e874dac6e80d40c8c62a6d270a25f9a84ca6a87356b8fdc866080658ca462efc4de8fa9d9590a0a1a9fe7d15c23b38c1d2a081a355d12fa8671b500ac5af4f56e19a13abaf5099e9d1c5a0c3c75e5a8a60c81bef91cffc8eff580081b4250af25719765feeccc8aa986aea33da396c73e0c6b9fc250bcccedee9f9dd30c70be0b840f07401b2a1475587b1adf6f57fe9c44ebb01dc4f8d5deca0d2afaefc7a9b6d64c209d120364406eac9f4d20e291c1472ad459acbd2741429eb648d54c4fa142bb76b3199f63a4984d571bf33 +A = 66bb64863bf69a614ac8724ea0cd86afa165f1e800acef182cfd77c61c89052774cfe1f6324951e5 +M = bb3c3166a8a9a8bd7517bae89f6f1f6f1313d57ea88248c2d550e636b9df44dc5f63085ea70e273c6bced3f710d6b6ff27991339925fd56af708fe155a17ff52af355b1f5f44c8d418ac5ed7f64ef026da79cdb885697bda89d452a21372c9799bf206b2e910e6329e27a3480845186475036c1e0d13076455224e48e595a81252526b3bc358a831d0d4e6d644142da839294f3f83cec3761f21df5dc072a58e1e59869793e649b12d051d8db1b99dc38217f792d2dde2956a0c233aea243aa640efe8a3373265e45e3663ca88bf97f2167f7af89352bcdae + +ModInv = 8553aef4847ee073fef62ed7c8e9d46fa5ebb9e913b170d0972545277e0c8e9f7055c57f5652a660efbfb6b92f34337cd2358e1b934a7c2eba3368a9eb90d0a1c2bec8e50aa785f9123464d054197af9505789e8f3c6522d63d13e0d87ba93922721569732a0304c4f8a2ac884bd3f3b223a41f4c7371f323a0f09bc96e673e8380d8f057c74b8e91f2df5a8e7bd4996ddf62b33660a430dbebe30f553be9564513173cb62a852b57b3ef5c7c2f37be0c969c053b369c32562fb100b5c60e172e7763a6ae9759a2a8eca3b0df7f68c235afa587665bb3 +A = 1745913bff6b3174ff1a248b30527c5dcf8bfa31bb702aa65916c8dbd8a11e67e782b332fd720e3f2d +M = 7444cfb785d44ff16153c782eeff2dff7adc2ca0a17d3169a005d1a771159d9690100fb6fe1b9b2015aca4c2f8ddd5f96902d577201999712b1630730ac1a8d6d537e5e8dc62a7dfe4f86d85f08545ff73c3438d5d6f4d15db250508d35e9626a1c5c69f8d540ae6410dcfa733e00d33a0b3e0c32f259539bcbd7a73be3cb2b6db83385b7951a2b3060dd0d836d313c07f4d2aff3d3021e27b06d1bf7f20b82d2bf0d2ede79c0b9d7ad227f0c18ba39a8efdafc13c6a8b5e9faa1ba69f1ee3cf5b48b237c2cdf97ec96ca359b548aa6783238cc6be33585a + +ModInv = 13946ac7c31e52d59ec74fe2efceaf2c066fe858e1f14752ec42ff10007494f2ea68f4a15f533d2bb96d788e80fd6d8b7f9b8bbc994a4c28d78bba218e4e67d14778681c05570930aea736587f40885e55f2a6b4a44c3479de694608e1a282351f902a46532e3460c7957f8ad245a15788722babd7b14d266102fde8e54e6f3d6d63ecb851fdbea0b2ac73d204cb8f712a62301cbfac8227c7a325745ff37b5ff6a2f8ccdbd7f99b5fd939ae8ebe943abf61d17b299631ff96cf96a0a1a3f67bb5b0ac1c6026874f3f32bb045d85086c540fd7ee9601e6a1 +A = -fab8cba86ef6b17ca857539e047128b841f4aea53d8fca83e75fdc6e4920243fa16414da4f468482ff +M = 300e2739cabf9adcd6f7bf8ead226810ee47ad955cabdf2fbaa582f67125c7db407239bb142d7a4057e3b51e839b5e01ce3297e4a7c5d0a6fe4dc0fa6ef30bc4b7bb13225eddf6a3f4c0954e35ea012c389c5b6016327277f7e6148031ec59ec7d568c4cf7a7571cf7957caddf04d0a794f0c7c1635f03c308421a8bf6654190eb239542e072407bebccf68e6ee78f7df79147d4405ed4e4e7ab147382ffcecbc374b2f903de4c47397d4131743b10a66c289e56fcd7cd11aa3a39fadee3d8bbc51782cc6ca92fbf7476e7969a454b27ef33c3343ef905e6 + +ModInv = 1a512626e7a706368f8f73a6cfd98fc620e2b46709a9788450ada7eb7614f5a84074faea943af9b26a1426c1f400608ed53aed956a3465dae59f9e18842c6df6cf679c385d8502b62b23be61303f08d598e628e6e4198b37b54141e405d58bd9a6ca9e1cfea7329c32ec12ee92275ecce13092dbe6b4ba05ff44275969066825481222fee2b693fb3ebfc62eeb13c3c039469ae3cf6f89193126456af6fc29f946fe6b049dd0671dff62032a7fe966f07bac136a0e7dab0b2e9818fcc974fbc71555e2943e7a73bac2ee4f7dfea454118f2b0b96b8f094b1 +A = -fd51b4013b486511643c91d7e01074234627f205796b7d56ebc6c0b32dd0611695b5bb172bdf9ff433 +M = 3a4de2cad85a4c742123ea960a14b48998e6fdceac6ac536cc820221a3c91978f4f782cc1c947afcc6dcfcfaeebd6540cc3cb8f4b1da78fbcbe818ec95bd43e4cd5d843995b21dbbc153e80bad5e2e074b0a1b0763154d4bce83e3c81d0b36c973f7018b185f888ae4cc98f153d2ed49e13183a65b9d27eda275d1c6d616e2eb78df321cb900e992d933fb443952e0a35b9ac31d8c5028e0d58101f3ea27de82346d84eca299c2823b7c0bd0d7c9b29939a1bdf78ab690c6cebbae8db97e755d8bb8737ea3e4fd802fc73c514f4c52c827c5a37f91cd2447 + +ModInv = 8bee6d17807074730c54145196f2cfd5ddd5375baa62becc0b95d520d74270f9f251f4dd161f6737fecc653d2cfdaefc6e3b5804d863a730e87f8beb179c2efa7e29685a67bfa4444d707b74de711f10a18688ff95389dc235f0b03f6d7891569d05cceb4c0c7fe1f39b82afd3e4bd139b04cce23a7812fbf69b261ce9b2314247f8c1e63932f128bcee21e3e67b11b5dc0f50df9d66d42f5fd16ef2fed2e8f783f263918a0e7ca0159a57e4c27419bde737b9f6388e4dcbe771fb69b3ddeaeb15dc7afe3272851919a03ce9f62057fd923ab6ffd65441 +A = a0b57c972b7dbf91189c145d78ddc104c5da7b522eb5773bd4e553f145d0c0d5e91780a35730a45e9501 +M = b24efeed0f06b6563799ce634090cead5b70c71c2c6ad3dfe88c8689307a46594e3ae2906ea9eafb540edf063f0afc04a0ac250ce02e19a679a2ff0b3807e118de3ca55edaf3dd1cbcc51bb73865aac87f8e63326c1a1b2f1d97672eeb4100ae5af5d69bf77a2f803ef96b55bc78951fb02ed4ffa6bb7d307d522a6a50c349dbdbf69082391e093532bf06ae0b79b645c4f6ef517c90f4b5faef56417c45a4d660b37751300c00ebf3276f89970e63f8efc84ec5da59f4586945d58fbda14a307bef6965819671cf7938fab8480fecd112e2f370a10ec0 + +ModInv = a3467182ad1b291dbcceb9f1ebc3a10826b2dfc223651bb1cfa75573d9072450d513d9092592d5d79d985deedd0d61735af02b83fcddbf57af41abd650638a692b7dc86cb4977349560183963a65170c560e658cf87739b40215391d554e8770e2428ab2616f935b7afc7d28bb59074a9815e3a14426af67fa224cbaccd8a96a32c1e5ef09bcc3396b64795b2fb6e8b5a3e23c80933fd43479a6cf515a04a1b0d2fad5306ca28dafdd21ed08810f1a6276b763c14f0e0a65bf3c1181a66d02c4d5df7dd8566fd1a3e8571abb8ddbfcd3aaa4aa0adf2b7 +A = -c9e3e4ef0a74341d279b463d553b6413157438d24dd455edcd2882f4c8914f0e7f5b79cd4cedd476d2db +M = b3736bb7641272eb00105443d57f3800013564a973cd447d6a1de871cbe88def649e16730572c7c360476d02710f3dcebe3cb893d8d8b2ad81538760b1d785970e64721cdbffb1a68ffcf5a7812d2796be05b1c30a09c3f70f019ea390655cf420af29e1ce4a32160db55358a5ddc3851acb333b04b9e1f41085c77b3ceca18231b49ed9d144bc86af5e043e0124233c298fc7204a3e0f778f10ff24f48ea80ac2dae3097a8a4e1e9b09467f37ca118743e779d7c47e10e0bdd7d798fddc78624d46bf0e8732bcebc25c90419443b7b46addf11e040ea + +ModInv = 34ec0f4554be259880d4fea60a552fac74a77ab02e6360b30b17dde5f7fcf73336c5ae880a4f8669eeaecca30ffff332ba47889232e7c54294193cb6e6065c0006c26797d63bd29494c330d79e8e7585561ec486340bf35440842ef4300016cc752191899a8dffcf3796fcc62e39c665e73adec32f8d32444b70a5ac7db69cb84dcff8cc4a308e6350a91c4f34b250a5e4993414848bb535bbb316ac3af125855056adf95e3c33ced3deb7646241d106fa91e9a7856a1bc738470d0a9a62e1a2576adb69ad3e55ec43f7369b69b68860097abd262e1e21 +A = -9df3554257bc04285e338f8789b166e7eea50c8cb8bdef458b0b124287c49e0380caeedbcc41f378533b +M = 573275414e24f9e68e200c740fd07299dc1a2d764466962c18d0dda0777b988e4e341667031da7ef0c249b8236e976e6aefd5295c3fdd185196f0aa8106900dc2e16ff79ad8209929607182876ba8d3a1e01cfdc0096bdbdf85a35b27c9fdbbf78137165f84af2e9eb443a71291f2c0ed4bd198dbf49390de2914c1238fb9492c5f6f684d2f01706d9d1598094b32fda83d7fd8bb0fd983eb897886ca4dc24ced6f67af1df27b315e7b50820e1f2811eeda4923dd8ffd3d2fbe75c97e61c5fa24ada21bd9256e2e2659107cf84ee1956412f4e83534cfe + +ModInv = 3b25934f80737b6d6ec64c12ce3a832459426ef81d6e8435933c326c7732dd466b1d33d42770bb42b95bf7fc4c12a0424933e26431c184c62d055d8540cc370e16d4aa4c4716c19d21ac534e6e8508c97b6418cefbc8d24128cffbc04c94475ec1630b6a75771b51adbd680b0b1882fd8df1ebd7fa21251ec33f01cef36f7ec8907e95b7e73c7f5e05e2d82f0aa0c8eeb085330868328e0274038200b626a77174a25c2e573029d4a50ac26aaefa583cf9ae1a2dbfc819d0c3b0f9a9521f8faeeb0e57a78cdc5a3227aab530ec58aaee62fda1762565 +A = fb3d6cd3f7dc625db51fff8a89584024cf1c6c31e091fcea37dadc888d8064bfff52bbc65ad6e5019e9965 +M = cb727298c50a12b4143c9227dd24b936930beb7203cfc68542dc6e72914064b12b9b037e699a5d8af46037b901ec7eee96347ed5d32772ab77120f19bf34641b87c137b3388cfbc2f56deb10c2953da31e45120378e6a04b29ed98baafbc867d56b345c4cd6b325c67d3dd147e42578bf9655bcb163ffcf3a592a1cb8c14e07350afe6d6f70c2dcd63f04dfd7a50cb9e9a53920bcb9d6e9cd6297f6ea88b16090ed96d89ab0bc2a8f3b81064435857b39e06890577fa7e6c7e0406a58f3fb8624026744e6807dee734432ecc7b93ddbe846fbd93039a + +ModInv = 36a09a9f8b02243142a6c9cf31442adad8c104e7bd9625add593fbc205370286b5445beef6ee683c4a9331d558941f9d0464bad9a1691efb123181098b67539358d6d3d54c72b979c416dbb8ea097c201b83da5dfbe963fdb51079c145feaa60b6828600faa831f9ed66e54fc4776a621a3de7c9b373a8d801cb04c9074b3a439a0d49717dc9972a2701af504e804fdb38b2db412dd242ee1a3829dba1aee27b4a6714fa53cf1e453118e8a4b9afb941051d61cbdb5ce421f660e5d5d13f295626f2153bcdfca2f81f94a020c1d8f12336c4f5e9e25 +A = 4094f75c4aa7f5877878f48366e235031f6a35bd6d369a5c39cbf3850d4aebd6cf2a277ff7bc0233ad09ad +M = 5a8b76cbed2a9930d2e9ff78a2b2d65e4e451e053c20f9bd9a579c7231283d39ca817ee5aac24b8c25173915c0d98dd358a2804ec0f8775dffc87d863108e4dc3fe19289b9798de550f8da6ac3468522b7722e28f2b8775483633171a26e72f446565b7e295333856ae97ef5021f9c98257a892eaa63aa78bd405baf4cfe97c39dc12c905c04be86f6ac22cb3f929500c40c251c3abc27d2e91707c94b2fe774f581ce92fbfb1832c0ba487ea61d3d125632061a1d9ab47bf5da7cd25cecdb7ad442a24a9c845f55833a0743dd9a703ab3d3d3ebab50 + +ModInv = 991c74dc78f71ec01169caad344dc97d7b97bab5dcc781c2b12818ad689d8cfa817f2b6b9ad0aed8096b9c901da6c3b108a124ea25fc075f4bf182f974fa3aeb636bc1c823788a39e378c7a5fda55cfd0e71417d3520423f3bea204f7766beea81babc4f5ff405267f2ca1fdf1c6443a6105c212d8ea96bb314d2963840de47b65c334295a326911e8cb545886c325c3771712c371135866e9725bea9392027b40f35688ca3804ab871c4b196736471843260f162f9fb616081ce70a4b036d988375a74e9e8319eabd14c17bc57147fbe6c001f1bc9 +A = bd33aa0f3d01469a94ce83b3e109dbd4b173e0332345a07effe09b778c5acc47cfe95f6986e2f21c0a73e9 +M = 573ec83542447813ede5a20477f294aa3f305dc74b9866e0fb1b6aefba9c786f6e74512586a92d3ac80a93c2eeb634c548b132881b2667118b4cd2be4ad57a186362d8f44e4d4ec1bc28e45448af008a89fdf160cfb29c1d65dbd4e0da363b10181df3d12c4d53bf90d07359fe24fefa636d29f1e733c5477090987f6cb02ee921d921955adc492e51df11d24067ad7981ae6914cbc98c97b0d533e204280b1866871a9a84ba9f3b2b3b1d6658e9316406a4c74485cfba68c900529bfed36432d560a2047652f4bcdc1077bbcfadb4f1b23f4a9ef95a + +ModInv = 332fe4921db02d149a15843047702ebad68f6763413cfb8cdc988e4f04ab21bfaf4969dac3cb421f45017b289100053dec2f9bd869ea90f97ff5ed72ce54940cd34b620cebffe0c7fa9e45ab18872273dda104a29afcadeb840121636d2b990934f1d28804487f7e8d8087acd715fb2580385a80b560883c29bdf518cb9b570de1aaf8194d7ce1a77156d9ff58323808e939f5c987bb4f032969540dded3720adcf4712efdd776d52a1e4429c559929c6221567de532313c59ab4602ad4f80c995ca6a39c07cc56f95bdea739b511221aac4e870a3 +A = -f4bd2eeab0c923775e24d383304415eb1a10d3d568f9cffbffe27f902a22350f017a60b948ffcebfc549ec39 +M = 810c5e155c8103665da720e587a0394d9013732eebbca12320176d42315c6cee8dae6fd781b785b752cdb1bf3cebb0352c0eaa44d1d783e2162610c5b1b79b9b9874d08e490b39c9b73d9dd874736d912645eb2c54a18ed0db43846deb9614e43f2c87d023a3430acb201de955a5f491e0712b4c67dcfd19d3d299a8627debab934da6108bc7e2101524fbf7e4571e177300679ae557e883989dc1fd10c91862d7174b8f2224d5c1c7578f53a6abebbe480c77f93f4b44aba7e1197da7abefc40c64e075f44806aa98fba4cd3b264774e1a636beb2 + +ModInv = 48df2238b0355862ee93a1668ac5fe32b2e78f23ad6c012c57060bae90d61f34728427592b58d52f98412c8f44a853985a26239403114a5559de5703d5a93f91aa4c0d963f32ba4400c446f9b51cdd9942fbb9c94ba4020cac6e30556fd470fe5408660f327e15cef2baf2698060c67a2ba74f444e6466123a28efb0aed73025880543aa49bb2dd068e70bdff8dacd5604c74bbbadd4e60004009c02afa6589d7f4b9772d98d7606fbbaf6f7019a33a8c6112b42126ffb578a0fcd96e55d0b556425bcc118bf7f90d5d743e76b96b793b4f3c024e7 +A = 87c1aa3050247fbdd2aef75a8edf675e1dfed26684cfe8acf0c63021f1031d949b9ef64931136e078f5c8e07 +M = 6083e281de52acf942d417dfead9dc98918dad03ad77de28a60c1ca165d3036464ce1ffc04ba388f2a5d48220b19a49b70d389b54074db050720fa5993aeac18f1ec609ddb8260cfd58c7997074d8a0dd6c4f497b870b334daf0deabc647c701eef8b676cb8159eb39eb2cd32597c572ec63cb4891d0e8e660ab97984065058dafdda7b5b45b4c8c5e25db3edc0bc7214e4733e80e55e91846f745636018b9e42585b4411c6cda931c242cc3e7f07db957175ca98f1b1fadaa93f403432759e5bc781657f673121bf28e7f4f3ef394fa4c898e5698 + +ModInv = 1290703f96f67606ac47990a9e49fb14e9df567f82001043361688abdf1939cef10d25973a2307590930503f471ad34b938d0729cf6e784c1d1676225db9e6d122260e520e931793e85f7bb4ab7ee45637f3295cb6591c1a88df6f7c2dbcb716ab39dc82449f98d7eace0791e04a63f94feb9996c1e3aef7849a6e16ec400f67b4e2e1bcc61cb6ec55313d2d8132dce1b937c2617635dca5d0777e4e49c338dc144cd36960a51c9fcfbed1042556ac7ac801027d83612ca27d65bbfff5f268aeaa1554ec57f8c0e01de968a1cd13b12c521e539f +A = 32fee2b98f97101238239644b3456a6f20f949a73aa9add2d3103b6ecbbdf6267024b0b59248cb0e31e36e2e4f +M = 5857ca75db4bf7ce4a6557e711c4b5b049d3a760b8c78394e06f3dcbd2e4b34da618a977e9bb1d4bd8611395f5fde5756d9f2b720f2d7dc598741fb9f024886ff9d1af0144c8c038b157d34c94f8d52529434dfa6f8beb0a7038c95d0e531f06e560bd98a4e062f88495197ba95bb9222277d611f6fe7ea54f5334f1ab5e33371a7e1c7d0ef037818bce35a8e040cde76a80a434d2427b144bddf26add58d9fa2e9a8d7ef474f9342a8e6ad41d6fed291178958c1d05f0a6bce9bd44b773407f4aca22c8886bfcd4364960d1121309837825a41e + +ModInv = 4ed2f3dbec471a5c5cae56cc0cdabcc39f3df26d2a0a6629d673dec0eaac2f79d7c2848d3d637d3081e01b151a6ab76c9e77cf66034e812085ca85bb71c0e9cd2d65de1db4afe354d8744d4d38f87e843e333bf436306033d66bb11890d280b9593ff943f6e7f512a787476bf93ea330ede03a5cc9009fe544e33eb24b2e0de387452179529dd6f6fd6fd1f35935356c7f698128e27b02fbe477da9da4232e8f8ff36656f9818b488a1a2dcd388abb0ab2de209379e97d2830d121e6b4b099c49ac13c1b3b7b6f9aab7abc223d4f52a8000c28e0 +A = bf1ac0c6d38cb47d246711406c7f69f538981161df16b86584b9be7d94cccefd1060924c9316bbb4cf18f924ea +M = c3984a95c6927fd8067488e2c3938690799faab6777339e98e4f355dea280d668c7250df230a188ee79f9ad05c9f3609ab42d6044be27f73449e7ef386b43160d76ec6b8a73734677cf8aa7e6c36143ea81f052740a411dd45ab44b96cdeadfd709a8136249eac46ffadda32f58d4473dc23a090dc17c280c32ee1042bfeb34361d36612e7c18f0fc1e6d1b49fdb67b85834adc4062264194c10d4e0158eb65450dceb257e2d9da2354c3387fe1245a1f6be3a3e95ec9684c399f48f5b5d61ebace830b388bff408622cd9587a39111f93734323 + +ModInv = 64da1665ef1e366bd39937260943e5d5c0964becc27948f8d36e13f1af270a307579665def3c7017ef26cf6624eca7bc6f9181d04a4b9f55ce3fbbe8892fa5b79033ebbe5c08c3f25cdcd4fe82d18b62165ed6e795790d34b96671a91bca0c95029962b9549e3aca47c5d98d19d1e89434db34b2e156d769932485321d32df0fa414af80c2c64388ae4d908c92131e96318557ef81be65a52b66a3434243317ba1025e51bbcd09fb2cff5181586fca7eb8f25c45c408d501e39ec210a8d152ed3c358ada94d622a67fdd336c696242cd687eadc3 +A = -1b0078a6ed26a6c89ea2ee3ef8caa18360c3d00085c6d51f7a18acf261ab784e83162f51cd32a4c95a36c0e6d5 +M = 88a2ffaf9b1915071af16001c4b1812b3b00c9b5fd9ef44e030133e102ce83609cfecb9ad4e389039741358ed3eab98a2b24339780f7b758d96f9cbe88510871b5fce40447d0c1cc7a4b2a60ce65d9c99846d25cd19dc2f23db7a5476bbfb1b6b9b32df17e7d09e59dd5fb9c5c7847bab21f44a2cc62c432394026b1eddcd9e894e5b887e31f795048c78c262addfb697ad0c428f1f5084be4dec7e36bda465c49272f2cddc21854d696c8564834da2e2bd9a63d8b9e71856d116adf99fd9fcda887ac7ba00542023ae6469afabb97094e8599b8 + +ModInv = aa4c32ec2e1ae70279c75269ea2b61bdbeb088ff0b7bf32b111914299ce46068ef119796e1ea09ee2db05a7c362bae5154c512708c4fef0642a05be13ede96349a36aec59a4423c02a4674f77e3e88da0adca17bf79948efe4cb02ff6092eca0797a86a86d43734fbe81179e58cf7b014f6065d6b01c43115f570b9c3da27b0bd1a5356e6e6ca2989c68d3009e5b2ff7b443f7a71105f593d036e88db280dca793eab4f79e4e6822ae6d27d412cbebde7b2b3de921634980ae526a18151ca5034cc1200b27bb7e2ea2465f839a157924192ec +A = 8c292518c1c5ada807b83508b5b8f6d3042815d151e9a9520742eaaa5a313e2255734e78b8c83b08efbeeb795c22 +M = 5493d3e4b195295733d72100f1d26a8b38107b9b21516c27d5007e883a46859f79d5e71e60afc74d4adf8b6a4f600a6e47325ef6a6cf683384877fb545cfebef95c8bdce88f312a6a039ec13ee7829c12ec99172efc476e11ac11d51d4a60032f770a64b6969675d6b1f9b46afa6bc26bdca0ca6d782a1ff2277ff464549f27b4b3855ea96b92c622966469ef6fae8d37bd2c19ea8ea978a84e68a2302ec7d74b2a2e6536f7568c5f915a2c758d78f1e747586b6941a4810cc965d3f53178bd2939bd1f9a72a3914221a022f97906ce79c32a3 + +ModInv = 55f99170f433c95838a550a346e1ef74a7d791f8fffbc377f0ffd61b17712bf24552546325527f9cf5aa394813f4a555b4a45b57930beda82437a9f3453f8866ca319a57934bb2253fb294a116601cdd3848ea941d9a31d4deede0115997f54d5d8562b970529250bb4ae1fe4b2bb664d6f64c6c3e847cd03448cfabf1af2769b064cfd68c83cdb734100d6352a34c65587739551371586df455e623cddd887d9b6754374a465413c3edf88a8c59e1d42a4aba2af5833adeabdb5836bb15349d33fd150a8ef4c7fb1e0fc8129c87a1910a129 +A = -6c3ded3ac94804f46a77e4de394f70144b8a6607118b660e8051c59103c3bfbd22b1215ef62a9d8ab392e9b37cd8 +M = 311b0d20027b837ca9c27462dc2a68a3e987001cefe89e308067c3bb730acb8087cc5cf647181837141eab5f84f98e89099b0d7f86118ad5fd97feb2ffc0894d4f029c676643159117387a7b4e990fe07896bb05b7981ff9ba12ba2ef9c602e1f26c51f01928b7c8a671571d5ae936d7b1ff520c2eee6f4c22de0362631d7d1163be7782f891e68a0e72ae77a5977006bd3e9d6b2b727f4eff8145fb7d6ed2967b33666167e3f25ca60e4efc2b22b79d6a0d95f296e560e6fdf5989ecb4b642a7624839e34d84920b8c403f03e9891bb9a7aff + +ModInv = a6fa33e59689b837fc8e0552e1f9527119cb8187a6c7d486c27dca023086fadf550223aa8ac4599cbc98afb2a5b0ae34b8476851e334eaa3ebcefdaffdc6efd8acef7de9be301166a554b614c6262da90e7389dad8d62097aed8e84e5b622bb9e4a2e364e26501e603dc7be48e769c338420e4e67765697eabbf734154f1a3c44600c9f73a5d32e076f3d3464a401afce4f8a4f8bf215be6be0753e20f99206a0f117c5fec95dabe9634efdc33b1ae849fe8f5c85f4926640a24bd0c33136d72a47f7f378816e3009d2efe1d8ca057ac30b +A = 98cd9d9c1f405879d9787c1a52aca5c14bb3eceec984b73316d02209bfb9050d25eb1994ef10c97a0ae137e083cc62 +M = 8eadfdc8be518f08957264d2006fb19ff6f9acde8855f9e07022c09044927dc22a859565dc669306fc880d1c1e340d0a94fde437112d426cf30aa3262168688f42c079361a19ec43e585f78be2399289159533a365b77dcff1b5220a922e22ced86deb39f1d179f36909dae3409f3cf28bbfd60bccd3ff6f266b03730e277b68c2566b54b089afc93ad487cdedf9cdf766be5616f8fa6be49934c78a9391be7c5c0e199248c3fc0a25811d3087eb621d0da27543175955da7525e004d4fef762196c229977894752bbfe8f3b4d8e9ea557c9 + +ModInv = 3a3ad4069e515b5f4d7e0eae7c946bbb01898cdb51d2feb04722d1dfd1054399338738ebb0f9d888e9a6e0d3d5cc24ac33b9cef93d6b86a879369546d15d0cd56bf2ca51c9b34533cb38e82fd6f99ff7b73b6226e78bb8d276eb9e4859f8da3daecb1802aa392e623fc57a855014f991c84a1d927474f64c5e6f8f2cb6463b197e51e85350d31bf843339560d92e2387dc2f595ac980016b0c315c781083c2c7532e54bc07beae11f66abd0d029c7fee3b3f6d390869a747d391291a612b95da1adfbac3fbd65b465a5e9e8e790845a36329 +A = -3acef082667409d19fb2e3d3455e3b77f9132f2d8d4ff4fcb8815e7343660c6c4a3e6fe13d6e65dcb4918c52215d4 +M = bfe2687dde083385f1d675e168b47a5f2f1effb6f5a6eeca194b65f1289d66a0050753671a103b7f82e18aa42c0dff8d01773ffcc9a5dde192d4d0207dc817651e727d78dc77ccd7f1b7a5703c6fe48f8caa0ab00a0c8a8e362d518e24f2a52cea10a55eec3db815706d8dc4a7cb6ea70b670c434f8eb8dffda4d9a108150008941153f03c8129a835b7631e1aef58f96c5511cc4a04d1506eae7f8c2a668f6a9febfa1e0ff3e3cd46a5d412f282e1393b5126f23decf66d9a93981f5bffd8f0ddf31c42ed54861c5dcb354e45086e7cdd17 + +ModInv = a815d2d7eeaa5fdb35cc62fe415ef77ff13bc894ddcbe597678119b07e1c51c0f18efcc5f93a4079e98b70d392898c86b0b4337379f93c9afc0dad22614dc52ed1e63a90ff4866411f47bf64955042562dbf3df288e97207a8c440a1e3416d2aaac11b63fae84f01acb1b28e488c2e576f527b49bd78e56fe00d770ce2f190ff9ec9b19fbfa0139681eb2bacd9dfcea1779fddebe44e742a4ac386be16d1d5f9a266ed8506744e28d30288b823936933ab3bb3ada8b7436cd5f28573401e6d04255e76fb0b67b2aab38d2ef3296e752b3882 +A = -15e7bbea9c5718aa3eaa134784b122864b2aaa97742dba49aa078bc523e6f0e895edf9d496f16da05f0edf1fcfa0de +M = db4593e42c58a8bc7c843a706cf4c43e3896a4e6e4cc8861672c2919c7855f8901178ced240d5c66536226ffd52ecf5f59ce9f468b6043130bdf1f92edc6ebe49af439e9f602e7c433b9a5a9f65cafefce8ad38c96bee255701bdaa43c398fb9f9544fea942e6189f9837d872cba111fa891d33e5d6fba5fe82f59e80e24529f09bd3c6cf10e8c7796e2a85407ed4b9fbf74935cbe969908d6705294ce1bac61b6c70cc2c373fb734f287b01798202b572afc68418acf1ff470fbe347e0a940253b824b5ef779bb791b09ccc497148d69f9f + +ModInv = 40a176ede08596cd0f281fa51458701f3eb8c25cd5f9a467985b6e224090060acba80de8af227c446baed9d62b58b9dbca2e7b4e89db6f540412c311c4df214de718690c49c733f534b832b7bc0e531d5d8879d4901aaccda6fd34d15eb074baf37da19b0571337dec4f1ad2cb4cdb9fca4a9a86b83ba9699f63babf5f949de9ae2b48bfa77c0ae7200319505c5d4f18dc7f4bc773b611b95f7f4f3bb991a7089cdd4aafb433051855acff96298cedda941f9ca8a48112a9c230fd49d80cc5d6396898ec4e03a62bef5f46b1b87be504be +A = 4f4d058c0fcef7dddde40f2d58a4234c9aa53571485619a3e4dd793f6ebbcbbb7d01b8c18283b0180b414d23d9b9309 +M = 6a402014e5a32ecf8bc00a3e5bee81e251e583f7516e94ee3d32b8654d18c6e27d545406d7b84755f50f7e7c803d6aba0008c15655f5824049f6854bc47690296bd0e0b915723912541bea1669d411bbefb16dcf15ea8981069925456e86f67c4bc11042a42eb0c784ad9114c351a1143fa6e0c5b177a9c77502d758a1931ffd75932edc9a26a0b9acdaae68adfdb8d62646ab3252feb7ed510b5d4e0f4911867480e6de4109b3252f49c64d8f897b1e5f570b75d32d048b2ba3f89fd5d778369f7f72a88756ec57d33eb112077abfba6f + +ModInv = 8df0637336b59aeb82028f84123a1ac103633b339fa3ee64904077796f55c8dd618c611427021b9b7d383023be1f6755f825d6d5bcb54bc6d56aee7582bc3f9840cffc5fa062ae6bea3e2e37d484156313955bbe2738d6dc5dedd7b9525805add68232b04cf6fc3a5ce6e4cd2cf4907960a2a4697b1e4d76f138dccfeec9f92bbd3e94bf97322e5498f8f0639c329adfb2402f6cdf7277ebd6a4f675c12f13c00bb7b2bb3b85bd6ce8241457d02e6dfda524b4d3187d8efe28bb6964a8d4202219dfb1a400e240e12a528ec0f627c7aff +A = -cf3d95e26d498cb370dc5e90b8b72ef5ec05f438254ea383741da5e4b372c48b67ea6fb9b56490d14a31d91705d1bff7 +M = 491c091208e9ee58b61fb630796d6e4eb1a831a4fcaaec0bb07e4e8f6199af78d89f35e4ac837f2ffbb86ee66b89d02fcc94f457ef3fef2a92c3d2f1432b623748b9358f20aa007aa77a0181a1819984ff7d0ff450eb0fcd08b43ac20edcb3402ef5517b00d6fc5385f31fbc295e046469a7892871669ca362dd4ede38f6c74829cb35b73245ba907e74670d4debce729013ac30f6f807ce1c01e4151a79127424c44e4ffaac662dc699c94783181c6ef5c8c9bfb75630751bd20a7c183ae4cd9025f4de0dfa0d1e03e9154bf50699696a + +ModInv = 977468a9f3cf342b1f27485ea77e5be0fd6aee631e63d8d229603b95541c5df4726c934838de255ae2cef39270533a1b04f7bc8a96a5a345fc633828e346bf75d7cf3263ac921b96897cf179e4bfed80b1d5de3d466029fbdda06806d0f74afa102e8e7ed58e96fe077963bffb452e97e8b4ade2ab1b1a2b1e56b5ce8eb526e7d4ea9418dfe034e11e29594bb2fd89a7c4b8e36f3c492b8bd099906c11953e88575570d1007729e8a53f74b94f0d6b8ae965afd05bf3741a99cf3421fb81d13960e4e84bb2d64d944bd17ef8aa784d0f +A = 5fa26a7bfcf51a7b45065ccd08ef9cfe25c46f8780bdb24532883f678ac85d3e870c4705de623958a8d7e77b64a4ff0d2f +M = e352aa3a71fb0c7372a559092d5e298ae1105f677ff52902fba8a814f0efbca52febd01bf0b991c8bb99f33d4b5009f5332ba39f40e17ad5477b446567baf4d09af211b3913dff386f0ee379e7dccbeb67235e51e011b7627c43365b7e6c6b03dee43ed7651afd26eadeada66e7cdc0ca244690794f7b3f7b62f1e12bada78d09420ddf2b93d6dfcace2007248f85dcbd4d9c5252eb1616a726c1f5464d4af1422db91d00e128a2948ab7279f209d61c612a948b3b9acd1c8eeed390b2edd3491fb3ce3a3f28b6f47068ce063e421b4c + +ModInv = cf1586c68ac991f3d495bf128693dd2aa2f0074fdacc50880c5d97340dabfdfe0f93258ba7abcf51438b2effd24012881bd141fa4120e34c1635ced692ac25b560f428386d9620b2fcd69db8eee0bdf030381860ff34132e7155b87f3bc0d250e7de06d4db1da59a733f5f504d9a9c6f793979b4c5f138935d6d21a2163547a117cf253827259ee8363db2fb83f8b1cde7b1e27918ab6b003b0837e76876479adc22df87d5cbde973692a68a5570890c495d65097ecb08599247fbb252b96c3ad948576bdaa3fe305859e4d33df24636 +A = 6092832ae4344c8127617273ddec94fb7a040edf424ef40fbc854cce3c653460747f4a81fed3fea71610a2b7b6ecf2ad68 +M = f5b3e714ad5bdb13329a9f598c4ca59186b6dbd41194ae763f6896db62db23eadf453287d9202fd0299edea872263f0748c507b91a9813721a29399d962df45f1b1ed9be4773c270014a851bda1236bb21e679e041c2ce76b6d56d4fed92e7b015554c38bb5cabe8b432bae3e903e87d289b54a4004d6e1444bddc56f2a2353f6ea3c09b21a839e7b1455fd236cf6c66045286402896baf715ac98a8db2b35706893181ba0d6d688d0490875c25f0d393da55315d3cff5ad2689fc8fe91330df847b5bd45f91cc80cc42253ce1ced8d9 + +ModInv = 4c656e7a1b7a6dcac90eeea3ed392b569a360812362c84beb6af0ae9df64d91a9a1dee3ceb22659622669cb2ca531866a710332e71d5a7f66efe8fe5cc2627562b94d87ae45b1f7420245cd0cfb1e7d3fe5dbef533e1e7b40de083c3fa7a5124cc2be84b5b6a7936178cb75d9c9b076f72bbd5234bccc007784f78ab98996fdba192f461331d67db54fd16abd4737cf867c147a4c240d4bcc960bbc8bd86a5bcd37baa9b368f96099ea9561dfe0895629a26e4c4fced189be6014aa6d4300f1b62e054e2c7b1605477ea9f0ab7bfcc21 +A = e6cb2b248a0692152b86a5eddffb7ff9380c81b8696ad54969712a651e8961dbc067072115b01ef91d4c54ae8f9f38c8c5 +M = 5606926c602f2610d15198af2cd1c939395ac3abd6a7525710fb4d8af1d90d86e869e96585fcaa0439b61a4084df443c749baf6dd9bb542b1fdbdbce40860959720e1cb83b2bb16dc790b01921328c88333cc6daa94ee388219a42c89e9bfba815731d2cbc8e19d206296305d083b61bea9acbbca09c6374b524944c8693a8c92ee8ef206eb0721cfd5af9442705853d5578a319f14bf32aff4cf60a7966c2004b150f99a2421a62d388ff34cd85f4b73d067a9393255ef8b0b865ad40be8628c79fc08841189a2a3fbed894dd5b7f12 + +ModInv = e9ebb9fc94bafc7fef6dad653478a1fd07b52eaaae34020ef58876308386b4663fa59b6e665284b7c08b073f31151b573297818eb3908838c202eb3810aff660a4ac81404272724c15accac07a07f236f961c58b398296c9b9a0f4fc3c2bace5fd183998122f9099a2c11a783556b0f319eefb7b209d0fc6ab9e3349a8243d9b9b45e997d4a80dc0b0b0c5bef8c14d5b07de7ed8c52ebc60791e3f5d819d27637d6b5ba9f6ca97269e09a1a053b3538afafc8180251ff6772ea5ba13afda948ebde529d7661a55ecbb8ae88fd9ed1 +A = -36307d171915347217a2ab00935be562d8ffb9d124f5e40e58ccce1be0329bfd878b75caae2f741888a8eb26eca99d82b996 +M = f30a1d3737290e912f95cb91f8d74cc20fc8136bd240bb52a576ad05cf797898d1789311285c234a4f9b067da4b2e2c9d1726cf0f8c33ee58e097c3925883213f28c0048bfb9b1ee28018ba74aa180ce0cb70b2c966871eb5fcd7914cb02f5180c7db5abc8f1d57704b371d00a4f375e79fa021a51f71116f023fe671bf61b814448009e9337723fbfc37fcf7a954d5359248aa81e78ea3da6959fcd1eb1a97e258304d5ec0b0a5fddde737e87a75c2239fdf4effcf39cdd8dab7da8301ec100feaab86b6b27233612ed45192a293 + +ModInv = 3a212c79387e4bd8108ab1b1af3607a76f80770c7d6ab5c7dff1a2fc115486d4c71f40f1e03a925392d3fb620227a122e2b6fcb02ef2fb8c9b3eacc9f309481947fa2f83a1b3374f453b25058881eb6b1e224dd355fefdc20351b137600a13446764a3f73395d7af046e2a150cb705b3f32de6ab25fc41eaffda2ddd66e03d54f615784d4bb78935e1985b61a9738d922cde44c2418c504c7f22ffb864e1a5d56d6d047152c9b73908675a4c4dfaf54fe72a89a18950efc9acda738d8e8c495361e4e9cc007ee09f074174be11e3f1 +A = -39260d883d662308450b90a915b37562cb036a72d57ac045b3d7f0087b0c00fd7a40e71922d72b3042c65082d6de5fb7adb4 +M = 8eaec57515c39d78918b6c7cccb2e5cc7ac6e0b4f0c44e383eb24670cacc29c0d10d89b9b85922890a24f51bf471ab738e74317fb7d4f49b1372a4440978a9ae7156de4f043adc7d9ba3a9822dfe8fc9efebd6ef122cbe8d95092d2655b897d52130df566d2e62a5f463fe79e910edbc0c6ee39ffa848b9b2bfb573a44549f242b11de62f2e68d04791308875f5eeb751f13059fbcf972961205f39e95be3433a2d2b134663bbe8e9112cf8c7f590e7619ce253fdb45c309b043e503f195f710717f9cf48d926ad687b5a13e635dd3 + +ModInv = cd0f8c451ce155d930be0027da9d5c5c096d4f5f7143be7402e01e6db787a53ec344f1a692507cd148abd6025138fc59e5d2cc9ec93a861371c0de236a6555013ad315bfbf88d23d8c527e8a43191c64643b81cc1b7bed75a85a4e2cb17cecaab836f0dbaf4c7b7ca0e25e433cf6d570f6c202b806f9d77235891afa9bf62cbd95a45fac371d639275373a9f90132dafa444fb944aa53d27357226066823e5521daf985b42c321910e31a1e4702f2393f2b2728413a86c9ab9af32f4cd5beb21fccdd52209eb813bc51533ac3a89 +A = -f427a47b65196d6472e938f29a977bcb3a20de92052a0fcb711eaa47b37e47d2e70abad28cd9496d7ccf5f19f0adb07f68607d +M = ee0a65b66495e03ff270048afb06445d3ad0a8081fad6380fa535b5659dd7799f795f06c25a42a56bd1c66f4fc468651cf04ed69042c3b13b026f5edd54985efbb1049e5325428649b62182fb4d7aaaa87fc026120654c15e9881284e6eaea5f11babf4c92c6f86b9efa7e5bbf1fa8b8f170d407c46a03026862b4fc558786dc0fdb1b2a0043ad5400b742e8af05c1184838f8b407ec12e906ffa61e9f54acf920fdb6c4aa79f190a1801fe440d02ffd0167704d6f5fab52c8d9eec9ec12ca9163184ed413dd2ff31a0451c77a56 + +ModInv = 37912d29d9f0161d717ecbc3a7a7900b8fb75c5037857122ec544254748475a9fcb8851228b562c5ae78a9f1248ba5f8d5f6d29e0ce75dbad7d35ec5e7505b171f02597db1792d45ff05294125c4908bcd70145a6b11f9b999b40988cda52c67e535c59cea5e42f654f54bea973a0948f895358882360590d083a191cc61f2893cc135dbe82adc747c5e04dc1ab519e9e5853db12f067acf308508f8fdf5d6122d999616c2763498395efdf4a11dc6aed3b6df5bedce0fe44f1aeda2c4680f01952716c9de8ad5c27d10b8a18141 +A = 67c5ae906435f968b9569774a19c098cae2cff4d79917167d789846ae5395da46ea784b19fb73718e9b14a7d5a4845d2687d0b +M = a6e84c8bd47b39f35da88ef6969c5dd737768874d919af88a866e0adb99c4838c5045027a91d90a232cb05a2c670bfbf28d79a29bd5f1e12f4be95faaf16eabba23e87d1a80f5ff3a579ade9030d43c21361717883854af78700a10611ec26baf041001a0a837a3c3139993198b0c5df933626826959d2ee5ae818bb2df27c59411a42aab397b0dd2125f5a8888cc2309b182d360493b17214bb2b0c717c7a421c49d17c86f59f694c1e79d7d959c49e1b0e018e0eb22bda1975ba482aead6f353e6a3b0ab91aea0402fa152904a + +ModInv = 9ce473cc73abede5ed8462c0b42a224777f1e66e85f3a3faa2009175077f00bc91a6f8cfeee1400259fbe976afce9c2dec52a4f336440b6139867fe7c954653eb4b0a47750332cb37f5d5af7b47399aa738ec5c9514f2f9cceeecd41727bbbf1c2ac07f891ed9304c03845b42990cf4f5a113487ad766a490e8d8a468f29ffe1e2e485a930e50849e46fb464c7657a232a55a48463dcd264df790f1a969037e47d8e7572c3efa62c8a4ef477079a07e4feb2774391774fc9c6440200d8139ae0c6a91a1d002df2535663f52e5f +A = -40c9450280a99af96f75b6be1840d0839208644c94f48c5b3c8a59978e82419df12c89a343d76a4170bf18b7b6ffa710cc5ecc79 +M = d1a78878350246ee38b9378bb511c862dce9d21ccdb339513743eeb97905b1fedbf7dc4ad5059a3a78158d78e5cfac81c37a34d4b368b244b3e06a8352782db5c387cd835e4e9460ee9cd79204985e300acbd00c20389440f3a2eee8520d1d75ce7b8546e91e0557440d54f6672d564b8635064dca0f298a5427851c99ea53e70a99d3c830ee790e6723af392db38041b4465b606c43158951ad35f1c0c212788e1b7e9aaecdb89cf7a66db19896cda1cd8c8053d487dcd0317540aec1c3340b5088be71bc135f9317f74507c8 + +ModInv = 228b8d5b9c33a43949798292516a7f34ce9342ef1cb15518375766d020bfbf62484499bb22252283fb346f0184846fe93aae3442a1888e0b1b90938a229b67855a36c64ecfc1bbae7af371656fe23b1aff0bafaedb6083bc27fe040779a1a88a83ed2ccfe0f2eb4d83ec1b6501ab869e7efeb0c67305673e39e136ad4a627ef7a350c435a736001619767e08d8b8cf52bd43494d68a3c3604edb24b618a8ff57d3d68cbb5613b031ba3d1be9abcfb01898181aa43cabfcab328c6ba1c6df3f2abd80806f122749306942a43aff +A = 768c89a0b5e0642fabeca6104cf9a54efd2b149d175846ad54188078aff3c1a30483feb54f851924f4bef723af7e95a025a74d21 +M = 89751a9c8b7b112960beab4e14d900580b5a80bd92498d7dede0fe938ef40facebfdcd8c6818539f8a21a6ae9a6ab52aa86c2fa689a1e6307791db25f64cdae210770cd96c1735666efbda5786ec2f3bbcbfe043900105f9f48df20f2167221795d2e9e162d3a662a42ddec458f19205863b80104eb78216e3b5036d4276a4e323de50d0798fbd1368f73530a727e0c6e78b427c7619d08d0b7372b7e6ae666c5869347ccad4ef1c3e3bb6c891e395879953cb09df0cc2b99a7900aa8229005a4d2ba592ec320cd8ce350e730e + +ModInv = d33148e63e9ccb0e1565bbab2c4248066eba4a338b41ddc5ed849f02d206a6d9cca4e67a379b4461fdcbd32efd92aec73e2cb8e1a8129adb018308c1586926b8d8ea17535c50ff88f3baa6ececf852bc8fe2a9ca163986c007513d2801c096f127992b02e9d509bc32e88f6a7ae852a0212dc9540b1245abe5b82690a49527547973fb6641d585b96d7ad9a4241db4f95b8409f76842569ae145b4c3b5c2bd4acc6d9a1c60e95744bca2aba39aeb45b4d62b1b5cc92f6859ef209b9a6372a73353154ac0f63124185fb45f3 +A = f9508e6f55823860b34b10b18096a03539bbaa451ff535728ba9ce037a9a0add38945d90408005bf0e01ff52dad67e414840eb3047 +M = 38207c84b9fbde219a8b485e9c3d35197d7b753db1bd2968b25a39a1292f2b48e3fc39f97cc765405367a3de015a23fa9cf9a9655ad4cacccce9ac302a0585d8c07a709693073b09122a48e27fbf56234bde9768cf5bd8c7d1a25b25021101a8e91651429a8fcaf06384990bffe0305d3943a2ec724a3a8a8300bfcb7da5957837ef06dfa941e7580c6d06afc712ea3dcbcc32b0ed5e2cfaa0be87795500a6a5fc875c1d8fb686c109fc01d9d7eecf54c4e616929f3c700aa493e279e3909963715dad5db7d498c4b742da5e + +ModInv = 34d15766fb6335fbc5238362d8fefebeb88e1914124e4804e0e38713aaf7e33f5ffccd92fd90372427b7942e733c9d93f08353a69c8f5f4f1f924838e778ce87a39fb26f9fb2c5bee2f67d6d9aa66ae6df21770e0e3abb076b315888ee7cffca0717f2e182649b406bdc9253104c6179d4157adf04ea174949a2d9d20c0bb6b891a0e2f004ce9f79f5f7444986a6758968a33e89cd69a465c4ba6dac6a55d8be9724a24299dd376f059280f9eb731a5140be1289f3e82a48c6699b8da7b7deb5da9131efd6f7325eb02f6886 +A = 590bba88bfe7419daca9a3212f49348b2e634e0331be8f29a20a3fa7b81477f374b9194bd4cf9f194acd2255df98f5f88eee58ad6a +M = 48f5bd065399f89fd523952c2255f38f5b5d926aa7de88ba478057e29a928fbaebbfe7156c53f83186094caebac91b7d6ae744ab204a08e325d3f4025da273f5b75c20d94043d83a6ee96596d24067ff832487b9d151de6b1c6df4c1fa828245b3df0c356895a843941223179b5123cf06c240527ed30cbb78525a2a1b5d441fe7c9b42c6b3b069555176a1702c6dedb41259f335a41b58314f139ff434447e70154e79362eaf84251696eea07efd163141e4d7d6340eb31c4baa78c001529f976528f05a73d454601a1d4f1 + +ModInv = 9b9ffb08b7425f2a128474c2ee8e845f9217551b1211917b52456129587bc0526850ff2bace725fb1ad182da616b23bfc0e669339d7e140416d686f6ba350b3bbdc413dca9f256b5ab2c3d80dae894078d8ecd8fa92ed054d794006eceb32e1fdda8dab620ed04fa98df8a54066a1a9a6aa560e6d9ca96d309ba5fb63f28fb1949df7448fe63e6ea32b4e55621a034fdfe835e84f2cd6ec5f68c521ecefc6e16403f2b39efb6dbe478a29c6365bc97c70d0d5e64f390e2336e0e1a9769e9638d5d7c81169054c9fef1d58b +A = e34e39666f0611b34e7569e5fe06a4657d01b0a67497efd0f1ed0f7fbeec2388dfbab7c26e89af2059c3cd4b753176fc7bb78fc3fe2f +M = 9def815608918de2677f7d423cd841916131137415435fa1e518c7ea00cbe0d0c63d8db8d018c46c89dc224294efbdb0f3b5655ac3be2b639149f89a30a10d820fdc96d4e6812d947f2d1b3a533ee244766716760bb038ba5d39d4e91b7454d5e18d77a49733b9615b966eeddbd4cbf5c15b62d548b0db725882b6da320c3fe5cb97721ff25da646125e306cc817d5a0a83a053b44188466fd03911b011174316f95da34c595c232f7d1a18834c4c9a93bbfce637fd98dbf5a33be2f3beb5bd9204cfb02c4bccb285c52a3 + +ModInv = a6adc124eb2c309772866ab84eff143911ac70919cf9b806b080e3b58fe1c8f82c14d9a9ed75a4318e5fd30dc028ed64422fd7742434b6adb0f644f01ac57d4459013b23195d02f94648e7054556f60c34b093d309c2f489798b1febc484af45085c1c2e198cb164e9561374514b267cb6e3e97869d108886b73d91caf7d9284515fd7806b4348acc8dbeee96b2fabe81d7069354c717657772d927e712dfc03033fdc32da03b0b3a9259c99a5d682ba24cbc36c196260f2e7cb7a933d68076bcb49c15970ffb011263f7 +A = -d1f09a829b1e393d9fe28d331f48cde900f5bbea1cc98d6c9c24bd111d2d9da3d48a0eda8b70589297bc2bfe4a3c16ebbc526b449e99 +M = fcee7fd38f4ebc7971303ba7e9cb78944a3d5ac9fcc1a33c3de986985ecd7d0911850d2b565477e31e61a185db2a76733e9c95d4af4b260ead434ada0a1c72fb315a676c11ca2536a26484af7129ec16a3344303af37a7c5189536818c8aca9e5365bb6399f3d0f6080ada2b270600c03b47ecb114ae0ce2a17af85c4384e19c391d6798d4913b868730cc1d1ab8284387bc15f6a5c9831f46113e7a115d30d01a3ee8f3c081189964b4fd905f3e46bb27a5c5d592053ac03360899fe757d39f60016c9d404a0be87d810 + +ModInv = 9a3881fb9de1cc9ec7c6803175468d87ddd1862fe73848582be9f93c24cf60d7dfecf925b4fe900d7b179566fc1d88d8050f249aa68ec84a8b5e5710de37e2f1153ed252b49eeec248a5d6419e3af4ce39207474175177482f958838f97a701aad44b6824cac77669938f7131fe7e204fef11f45011048c0c58245018a0eb6e20a8f33daf514ad9b0b845e486dfa0cb31e75f236ae4f2d7d2206c7915eafdd63ccf054dfb246c433314e223d70b7b8e55d2d19281ac17d060ca20f7fa7043a94e9cb7cca4bfae2b11df31 +A = 868ca91b152877dffaf94e2da8c21fa10507f588ae0bee48bfdf33a58c8a13ec7fec59ef1645bd85300fbb046e43554d04b029d0d4e9 +M = efbc5f0951fbf24cbb492ed3d6515f17fe5fedf2d19588fdba17d851ffb4a320940a0d570c827454b0e7428423f3cc8138b0a638e7a411a557a94970ecc576be70c620f93bea29ebd210c8582e4a160759e034edf3a6245a512afc7d84ca0d4b15d8c73b607feae5926b1b4523e2b8c39e28a8a97e520b177a1ae0cdcb1a8f59cb8d9f593923d276da6ca555d3bbf14ff86511f030d501d4c0593449bc7802bfbd6bb86408de41c9a14f08a76d69a79d8ab5b00a222131e112b66f54616f5fce39ee10fbdc6be88fb2e7ca + +ModInv = 40965be8a381348df4f2aef947be0bf5dc6db0d972668b7b7aca54a6ccdaa0023789a7073ca7bb406fd7d37a5c9ddfee7a34b223a44aca26ccc21ecc15b6e1a13d4552de77d85041a7fcccea24ca19dcec4931b3fc1fae2bd8e05ac09795da0ad7a026d833f42b2d4af86d000c3e9398096fbd76e096676cfe2f5eee5d12582f4e82e2018d6e65c485f589c9a91293f6fb877545659683c07fb39d8e47093f0aac8ed58d439b0b9482cd35cb279a50da2a78bdec52fdcf772222cd16e4065974e177500229b6047e8073 +A = -3f53b12eb058e8e5352f24b4b12be07965cc0f62f4ff25d4eb75e7ce20dcf3c557f300106223c47cb93175aa08faeca59c5106955c1459 +M = 57d7c9cfd93afae21463d7907e01e3174a371d829b3553965f90d75f9c6f1d620b751e8fe433a50227cb60e90a8ccb2763a9e33d07263a0d87beada770bae7370410df8898375067f4dc825daa17b9fa80b51aa74d854df2532011fe1a932935a73375acc835f2eebb41e286be23d0f9d779c0bf2de7a9c9c4f5369d6a0f3a68003f77913fa4b743cc32feed806649749cecc30f9a7f56a598c935fdf1403728b9a7004a641fe9e59fffd4211bf88319420b7c7ab883ab8219fd29c90c68a280753f8426d3e5cc9aea84 + +ModInv = 235be9a3bcdc17ccfd8b677114bf16859feffd7349653d71300564fb7ae87376745fed0219e8ac046d8b8e82c5756ab2f863677ad55736136a9db5d97932ec5069ef5ef3216b40d4f0a16c52349f094577a4565ea8dcaf2e20b28b6a1c2517a1f067369f5fd4c7487f4e2949bfc450a244ea8751508a705d9d8d09abec83ea437bf8c52e482636d4ef8aeedcbe5032cb43ecddf5aed7dd557b2006bc453795ccd8f8eb5a09ab6b77073cd08daf04ca4706269b64dc01992c98f560f433864f27bd74bb96c9c361822b +A = a1bc864f8d324a3a534f58f40f722366334df1933505fcaa3be6d8644ba2aa9ff4357e094d1c15e8cbc9b2ae152fa2a0c055b8271fcf6009 +M = bcaaf69b0fe70c9460875665ec2255d047088789bd1fff0ceefa9c3af26c028142e338f7ce635d24f67a3162deb3d7d0aaeab7ee858892cd81635efd44fd37a1552b920b95f9dd2cbea36f46a24fb88e56af92c1bf70e9163abfe77fb066d34ffb5bbcad1dc8524390a7c311fbbbbf933588e40c1bda691c360fc531e5658f4b5721bbd4db4aee37927700349019752333f09e73ee3e2ce4b46957dea61596e16f06092cf2653a5d86963543bf3ba33e33236ee590a45bcfaf61d430ff9b4a5ede3d48a9d490ef1e86 + +ModInv = 14221b11337de07d6d91dbfa62c12ce7d40bc980f92b991b19e2b7319d015535f5625fc9d81f1886b84119f06b3da6170fb8b5d45f762110aecc2201d7c285d1af66477b7c7f430ad0c0f7f68e26a5d4fac480fe249bff8fdcf3e935580ba37e84a30549fe101be804d27fe19f70d4f83b403b2c20a65d0aff2a0d415368f6fed8ff3e9fea55dadc37b20df80e0a746b992eaaa347744a8bf4e34e7f071a1ba4610eb5e39fdd0256e25667cbd4fcda4611a30ca33ebce5647405c9f88122fe5a58d29825974a50489 +A = -bf82fdcf736b1f5f37e30578d49495dfc526d36278787628271662b49d049a2ec2a01a4eb1a21c0766c3e22bcdb14cd8ebb3ba162d82f9b6 +M = 8a089edbd3d8a9675d9d0e3bc4f965f856876408c41ee2a90c93f6170f093d8e15ee3e6b83b727c0972fc038d0efd8b8e53ebe023cc50c14ad2137aab76fbbcdb8947469cd0ba6c55b47499fa0bfe1d610f1aaf169e10cf40d87315a6426624245b11f13a5039d0aebc3310b0385157b31ebb2712c5c8f5e7a3c0baee1243fe58613f3b9314f9fb9516f2e518b237c25829740a367b89923e497df2b805e1370858266351b18d9768946dab9b0686105ef00ab2638cf23927e9b3922974c34001defc4f1f1e83539a1 + +ModInv = 3dec454887bd53a1b7a93d47fea1a7c5afad2b151e4086de9321ac8d112d2ae2fd5aadc0782e64f3a20497ad70cdffffc9f1752079725e1b0479ebfaf6a9892326e9069a547c116fb2069dbe1b37176029b8a27f8cd0df208c3480ee21e0f52ea586e731b0c8eb4938ad0a6e893803877bf6fb2422031b690bc438b8cef364dc6ae8d1c2357fa39dc1a4176c034d2e17fa21362afc62b6b38f5cd4b864e2b8a9ec6ef819cd36b748507c86cbf32aad8d51ab16632a5463bd591dca29a34b00953433191bf591a1bbfd +A = cfd36823c28e7ec5cf0a692224b785506225ee3079b087bf6986aa756c489121ddcd9efc735cb6119c4fa82971f4d678c5cd5adc5dcce581 +M = 7a2ec3e79c84d4ad7f2cc75bbb014bcb8a3da4d22b7ed5752ea69d9861cc8df8a6f84b1a39c65542d368475b99c76f8fa59a26dd7b335c76e1f9e2644565447efd928a5776b4935362638a42ad10ed0c7549e31e29213dca9e2462fff266b154d06fda2d0cadc547e2bf8eae6deb9869a733dc0639f00f0fa4d61ec6478e52249c616775eabe61f0eccf8e5841db35f8b1707ee563d7e83a6e2dea281b3c5b02a554b44302dd3673433c947be1159bcd6267ee05f353ffd5b13e75f9cbb0e8a643ed3071499257ea1a + +ModInv = 22fa47024e4550c4251777a91e5b73a9190f064133ef2251c880c7b705ec04ef64bd1352b98f32024d2af77d659e813d1f86a6dfa9b7cb22b6ee46f7350aa49656f1f633a9404c8c6459b59e3f7556b6277420265d3ddba4c35e06817b4f0df32c124058024686cad0e02aed8759433bd987e23d4018a76b7bbab5569cb55df3fbf82e4252c5258bb326d89fd1b1ba34e40e1318f8f4481c882643718dcee50666c56f046f86b965f73a0d9fb470e364a214258cce127e400a5d30e60f6ad73f8cd66724484c8b3 +A = 1eaee356f2e7f309406d736e23586d98968cb9e84695699d7bce2c3243007cbae22854c4194b445712f28406871e33c6bd3fc32fec47c6b78b +M = 2307f0e83be074baf3b6639ef299a39cbfc8d019b21021930d8fda3fcd6918e5a85ebe248fcd486018292e2c95480d0f97b1d31b7efad4bbbb7d1c80fbbf428da2d87c4bf6dd2099b6de4bfce39fecf885299dc1e526f63fd97eba5c59e8e6f582d396bce72a5dd68933b5c5b68f079f8766f193ce98fc98d521b0fdc5a58aa4e54fe18e75592ec783096eace0d9682f457da87d035540156a420245ad29d36b71e08de500b9ac958e330b1821b4a5bf6c522caee1a36a6c7fc64c1315631d29ee1faf4d4f9ce4c + +ModInv = 952e3ed4afca9bf39e36fe96c3ce75b3813cf8db43918062dfd617a499e85d9ec88b934d517bbbafa03393214cd896ca38deeb38e8bc23647f1e478b7880a25f25e339d20206d1cee241339ff5de3ab29fc0ad755244b03c892a436dc674c3c9aecd2e7156b196effe2864bd23d14bcc1dec45e478e4c8e7075df41cff41d85245bc5ce2463fd8f85b0de25e2c91c181b27a70f49325cee680a5770ab4a0e931fd36bd59d34565c189a47ee9ae8b7697adbf0843efc3712deb0351d3c3e357d79aa351ff5fc00cab +A = -5ca59044ec19c21ffa7cd4d13036ad29bcfb4c55d99485627f99f31573ac5d79461fdbca2362ee1d41b70909d130eef2a2359f5e4230c3f717 +M = e30ad1a2b8d083cc081a60f23df98bf3c9919f6989cb709f4249afa30d5c36a365e4e6735a6802dbc3cae92ff31148e98e75456167b330611792a1b37cff1454976cbdd961ce4dd57c8eb8689e386f1bb265122c214916400dae95365bec5ef11a0ca057bf1603eb4971f813bb56780e3fca33a3e81833f04ad5bc2a5d407cc15aa7b8fd60fdadf861996c82d19c9a9db789f4895544e04914a227ff6d91c7aa3d84c77e1cb4226c8a4b426fd5e2b5fcf2da6390e7170a129a3fb544a968ad55730c3c9ca1c01b6e + +ModInv = 2a5276e158cb79ee44265f0d24dd1d667ac63d37316ee3b6a0216b62d7512fefef7216ae521104105b04592c775607acc898bc63ab97017b21be9d304ee7755518d9cb3b43d04459234ce3271572243194cc9fd05a078b9ecab2d4458f4340b5cedcafd33660c2804dd2dbf42aad34965a8d12a948470cb184f055122172bfbfd40e1df3c8a1f59ba2743b89c086668493ad47e878e4b3f54f48ea03cde69113a4a62d41ae613c4818b6a3167cca85d18c729b8fd360596f5df140b0868585332dc342da5ca167 +A = -2eb52a22d0420b3747cb5758e63ace44dfe7f2d95686a638ccb8bcabf25f75cbd42144eac51d8d512e7057a8f9a9ff30afc62ec012c7c0616b99 +M = 3185a1a90b9a4e3a5009fa95ecc774a6cdafc5535b74f4639379ff39267bdfb95fd0059ddb51eb4988e630936e044d92ae9ff994abef01db100dd219ad87bbff7bf09b1ee88351edcd6e2ea54b8e5aa7ae7dd7847ff41312d06703522a9b62c20b54a5e6f824419d7a709f17335abe092e6e1ec676be53b2382ef0ced768629f6b695d76869f569f5e52316b0fa15b2e58c9336ee1d7c5ada7a69eb10197f76a6f57d9e1e56f84ca3efe6139fdc6c420a31c1dd196f6978dec42b334b4445ad29f0177bb9f4f6d + +ModInv = 38b6ba3d173481b6313fc7aa887aad0ebf239688490b8432774c74293099673fd6c1c0c1057fd46eb9a15d0342832f5caacd39cfa6b939892d3acae7bda3786fa44b161e8e387c569819f7567c5add5ca74dcaf88aece19923a9b043d97ef3bb61d0bef1e98eeb939b3b3ea8b57945c8fbf79ced2893c67004945a20823ae7d5de38ab638a9b70de2e0a33e485feaa07e521c6c7a98a7b315f41502ded57dcbb453fac085f423ac606d0d115b69b1ef70487826034c6fb5012593dbbd2148c9c3917a39f9f301c +A = 84d6b76c405d5a8582467c19d214a91e6b4fa47a3279821a731749383294fbfc2d6e16bdfba310d053d3707abb0987f3f9489b3fe076123f3c27 +M = 463a888a16abb4f9385cbbb3ccb14a5dfbbc62002c736a80afdaa86d936dac4bc8933849483dd77ae9002e3ff742709bcb2d4c76aee37ccd2ea233a1f936a3c5820458f463770b0e6a859a68eb61a10e25987be99094dac8982fb556ca3433a628ff983a3cd2b41a3f084046c01d8688f52fe2ab4cb1f9f3fed51128a4e2204b999de93dec51435c0ac5e3bd804f5904f68ea8fa24e3f6e33e10b4f95385ebbaf3d6cb12a4d023532e764c4c66068774c0a9b0e654049004bb044bb0022b8093a19d23d02c29e9 + +ModInv = 82e980a6c0059eb825c2c5b79575c2c91317e59339967f919a011fba30fc6d073f3db1480dc40905b8e91a86911ad6021de3e5931d79838991220272d83fb8a21a22f541c8fe83dacae4e2aae7cd755b11f6f640d4d4ea8cc900afb84b6773ed89078934fc935015f04ec53503da73db3b4b8b7eb4f88298b02ba302078102ed6999cb805e4941dbdb161c244dfe4626e2ad7abbe9a1f59c3ae57ac9c7277e10c46d54369b3c4c971cafe02165bee308d0196a6d18a7a8bfd9c82e33ff833bf8c84573bcdb2 +A = d81309de80db4957fd3254e7e42a022a39fa078d2c4f754772741cc933edde3af3f9a43d21ddb09e21fdd0dba8f2098c3cc4ae2a071c37459ca087 +M = affd6379cb66bf07e8ebd6dbf6b6010f4860618154baf87ae6b6bce43a0478700c5c35a8ebb53f3395a480ec97612d1a272336bf0009ae6ee4b1baf37d0ed14754c7c10e9b52038c0ecdd638fd5b071b7ddfa70908647b1abfb2d02e8ffa13ce9d30833ac6f914f2d9be2dd43bbbdee3185a95db72e3e332f0baa4d3b80360fdb706cf4ec82b0ce3b3637ebdd6f085a94dbfc81b0cb87224a440c8bbe88ed06612b6d217ab18dc35d8ac8536981cc21017444e9a29566f5e8be61c650ddceeaec1498468ac71 + +ModInv = 4446cdebb06eee26506f631f7428eec3e381de854f623dbe538b2f452db7b7a72ffd600a2dc11e8f7019511c52a959a89f20caaf8fc63080361954c901063fd8cc2d29f50f9014b8686a48a99e33ae2c06fdde6598a07b347a9358f6fdae2bd0313387c1af67d63b7fd2763a23a445eceb768581aeac9cf1d1b88735798bbf35f57c710cd1c82bdd4f92802693ec245963a9bbe202ac4f00564607349d26de5f27fcce785ecdeb7f3b46f57ba6e8d43caed9f597703a056ac8a3624855b7f25d5214f75564c8 +A = f93f8aa64b4955b6e243a7c71e326b8d8f028ecede1b8b3a2209952e1a478006efc2a9a5f29a16d535b6ff0fb582a838bd346af68a2c6f3111bf01 +M = 4c1d914782072b6c9b3613d33a9c00adaa63ca2340da1ca755dfcd3fc1d07e4d0fd0ad707a3cf9034c32bb294809793cc2e69f3385442285ea6518ca2b717452fa1edf461e41a341d8ae7ac919bf0d06d8ead9fa3d4da9f7f62ca9d48561510fea8f854de2e26068425f29e713a2f43ce31147db63840ce9a8f2ab0068b2f30530c95de5c7b4a06cae1c60ce46006ee8ad1c9b07b12b840104c0230c3f493e48b3ca3c9e991adc43d75d7dd0a4d7d56bef5730c98250547a7efe161c286264b7e71a2dd61365 + +ModInv = 14cc1f70a85c265f45e5d199ef050fcb89bd887ae4409403dd057d4f45ae8c0b26bec0814a2dd0eb6f1d766fd385935f2c989f23dd71c9e5e76b8d63877229b7dbab213f392972a904425db8cbd5efd6532c8b5cdc13873c107db994a59cd7c8061b69a3bfd9503e10baabab8173d9b2debef09165522b4cbd53ed1de39ab2a53e7c00c579a72b40d18ab6b11937b4c8c197bf42613439104c31a6527371842c24352b71d6fc984ca91c0bf9b896cc6f41bd77bd0a6a2ebd97263a7c5617fad5b04b0750596 +A = c6a6507a48835083fbcfd939d097c12227d72eead2a6a6263afbdde39c91cefc309236ce044f633079db774adaf09c1f6c35590d84ec43e62aea69 +M = a3a0668dff9d28dc69b506575588f2406df609ca2f8ae4221ee1473f58d38d8a0ef67a9b81e030992f2e908c7447153b3d5b9a77774eb313631bedf6fe3f86be5207eeb956a37d6b606aeaed41aa741ab5bf40addcbf38fef405344e6ad685cc57ab0bd4f9e2241cab0d846a8815925bd0891e902036491e6e381a873c73e5b88c0347b5f682484de0cbdbd5f17cdc52cb72cdcec12467220c0347484f851de64424d083b3ed7036b78d7bdca51866dec628204063e95a0d0fd3d3d712c7b6c08137e306f0db + +ModInv = b8ae86e5a16c6bb4feba397f577656c7fb59a1dedb15da19c1de69b5c7f1895b8b14b1b0812f22aed765cd67b91dc10d5870eedf0135c3bd73a8af9bdc527c8a3d49c6f3e39db4a67cf2dd4ebf6bac2de5c500f2d59f3684d152a1f566f19246779fb5247d629d39c92354bc98415226d5668a95527b6b022f4f18b83a22575f27d44cdc92875aca253f273a9a65953437187d21414e3320cb58a18d69a778e4c1de95fee396a332a62965f864a3e804c50615a21838204c9f7aa9361205fbf72191349c6b +A = -d90f3ed145058343f81d16f9676ac3d11c94a7842cf50502abd0f4030ee4a80274582540a2d31ba0fd05f953320abab9f221e52127940b03e252d43d +M = cd45f665d293717fb33a30d5b6c306ee182ef174da405a9cb93cfba825d21ac1e57f5836c1ccf2fd0ff71991a9874a6c21ae8b8bc92754be4f192a686240edca52b3684dd3c7d88882db6aba8bedd00dd110189d165e799979c1a7a58e3a0aee90e98a21e0da952a2afc2e33b6362bb1c74a2bf0e90bba5653edeb80f3736737f745cb7a39c306374a535f36d11c74ce5780a8a60d564956783ad5d7684c16790e1e8a5a950bbe9886c3f190e34c384bd125da23fde0e12848f85c4315228854e62400fc9c + +ModInv = 5616c57d7b15c1425d892181a193a7411c11c2c58686c6894c3600d4dbd10fd70efa314ad62873dfa230589c9433057263a5d26f9e05f59c819389c2df9476527f5e2a3b9b6614787eac4a17a488542c371077d321fa81b637df0ad2c51b0daaa3cd37dbac1210bb0b25589762771f13d4482312980b7a0db4ca2d149b4848734deb631bbe12bd94419dcda36a77c011832181f7bad03f3bd7c981ad09f057e9e09cea42d087c49c119316cbad1241b579dcb80c834bcef88824eb1a20073896fbbcd300db +A = -96c45e7ed41340c52617c0b5fa1f5cc448bfc3594c0a8c7cd665053cbb6455961ca49e24b66501ae5f669f4d01c49fc10dc7becd57bf3cef56199df3 +M = 8c3d2aa87f698eef8a9be3ed113926e0b6fcc9517f3ea34bf9923c8c763c22231a4a56e8b9c164216bdfea823a395b4eadf1208237dd5ab4b2e488e90eb00b4a767ea75970c7136df19962ee238395a339df6708dc49cf7c3bba4f05a2e0fa2e21c28a11a4b7e77e4723133660ebee9be0d0dff5f3107218b51c5fa2b1276d18bd48aace495fdad0efa8c6ffadb444c4f37f402d7a931983a2ed54b2a378762c58448122c37490e0457da4e89a5105ee092cd78768ea40596001b310a1e5867a9c74f0796d + +ModInv = 1fb2c1fda12e1200802c2d14bc0e51cb6a12cbd0dbb4e3199627bb84df205e42beb9d161086c7dd0828cd755aa7b1a3fe853f5f086bbbf2a9c2ab1efc59ef99db23b12f44aa7a47eb19c3315663af3c3cb24869c661089167f958678f7dc0ce9d05c302ff698b7b10ffe1e9171fd111ba6bfba463cd5c3e386324ca08869d0ecceb68930dd41a6a5fa0ebf594c49107adce1de3f0b14e61666ec8a7995b21b43fa2643d39e0d10f2ea6be9928dade2996c1f5e4362c9dccdb9270aebb515325862b15cd727 +A = 35293f3cf517e6275eb08216f7d968125cbaa8ecf3fac9a4ec9fc7504c5be3d823c06bc5c993e044fee2bfb26860fbe70c93cc9df8f19f9411d29827 +M = 31a0ff964f6a3af9b73adba77bcee591260042fa586719973175341bf72099152fc0c2c3630b6155b9d6b66e49086662b8f1d53af73e254ef092d67d5ff455001d0b49b62f366d35aac90f32e88333454c9ae4dc946903c0b88f4d7e39a35d620540a3ef37c173adb3156d3512d0f5667f76090ac7aab4380a255bfe8f55079f4579756d846f53dbbdc3b10b1e69e09a6207c7f58ac2c85c1a3e230636e324c2a8d98c111e83399ceb2e95c86d093d99d532ee981c3001ab955e15dc2f137cbc882ac7dfb8 + +ModInv = 50ee2524004b607c8a52ac695b4b2f074903593ca7c57d2aee83b97d2fc388104d599eab5f32a43c59a600cbe66aabe4e3bae3202d8315efa4415f53a422bc3cdd43848746a56b9a3bc7edfb93a92ce587491f5a0ce1fa74d997ebeb463a7a3504e82f6a88b9b4a6b453255347ce9f6fb51b3fcd86d711daf93dc4ca1630e78ef34e0ef44a58f6423020f32d2e1372f9a1cb8b02f16003d58be8e2eff02d9997e4b7efb47692eaf2b548c98b6044ea5978578fe146f5a9ba2fee68a05833d446d77b7bda +A = f24f24033dafa0b1c2f3693b91d71c5757be13ef3e35f2fe0574bc20dcbf9f501caa20c9ac858709e64a78b237af81a728d95c3a399143a2f96491b626 +M = b0a2fafd65242a8a961cc5e94d154a426d0a90ee6d8a1f4a9741dd028f6152155a76e41c3b25302bc8bc0abc30f408841542e52a9af1cc20951deb0dfbb6a05fb374e173ce2631759ebbeaead249f05e6ca758ba29ed3fcbb1722f1d472bcfe1ed6e9f970141f686c1842cfedee62ddb5feb0f370bbf6ace22043cdc129e0ca2451f8ae00b737c1853d279270756e815f8b5a9ce5ab08ce421077dcd88d5bf8f42136d802ce0fb501d046e943c03c95cf579a558d1bb693cd74241783248d48d1781af17 + +ModInv = 43c8a107305a2d291c60dd75f33148868683adb9ca63b662984b0d662f3d854332fa6fe96f33f81cce8f720fea08888fbc52894a420aa0b3aa6004c21899e4374fccd0ecfac2711bfc61fe1e384c01b838b7d9120aa0ce902f859d04834996eea4ea049a0165640328734a4b569ae868067cf54456d34357fbf2525524381acd4bbe20a53e657354535a0964909bca9f8525b57f6843be999696e11c9424e84ffd4e5beb6145f65fbc51b0355921453f942bd339f851633eb7a43db5a87d0a2e747c8eb3 +A = -571f0b1bfef723e993317303bb9f86041a769b03f84ee1094ba4395da076147036239a9af3a899da936cc3f5dae4d79c96792792b8b0ef6299ad909092 +M = 5fbcea185228783cab2e12e801995e61761bbe8969c046d87f57459d732e0c4c28f9e046687f44a94cfefb643918c2242f21dd9eb9fe0f0079b8be2b002f2f4f16560605885a54b0cd00717241ad7fa244fe5ed1b9157128151715f2e179db7d2fdf9b7b72dc54192addcc89a491b970793d98a90d14e05503ce886d5cfa29affc2fb9ebfe6b59342e52f6ec87f102f643fbdc456400f780d6795102e1546cb54f9e4a90022a60f23f591642574459bc1730516852b5fab7cb7704dd09d8480c487d6081 + +ModInv = 3223853a5a8507d4da6e871e084a95aec938eb5f442de7bf1f7e009ede908eb70622fdd5631b6d909fccd45eafa07fb03a19928ed2edc527d1324d2b9ccd615091355d45c93a4894f5f3a277762ea31cfd47a642459140fba4854fdb0830e776ad80702f65ad1a0f821c112f2202f71e5fbaae4e7097416e0c70e3034a53c4717e8f2cba4d653fbbadbff2d8d4b0f0a87dee6056fd1ac94f83725372ff6bcd99037ac3b9891a71ab3cdbf076d05599198ea2985ff195b343319a86d0deace70b80b466 +A = -22665bb397adc6345d0060028d8a833faf8648ea60ec664c4ee988d0c118a6169619868c9b93509114c0e0fc3c9abd96922cb9ad00bf825758141cb673d1 +M = 7ae9eb6ea9a636d1467eb465323a0c32d14fc2c887588160287f84f0434442b7f06a0bc554f109bfe8050e0d47b3c6f12fc563ec996cfe11a2fc924f3bba871719c00e8e01ca564461107edc36049dd6a9cd8bfa8d30637ef4c36412bd5eec212427e84e166f16c64ad6afdaf5b9845cecb6e348bed6c5acf0a4846dafea64215e3bd34c5f3e3ba89f7a367773b57681f72cdf00272904b49d72a240704e6a4cfe3f879813997f77290af7e595f484a9798440a0fabbf7cea5ce6612941eaa7b33cffd + +ModInv = 396bae1835fb1e759ad86a3fd2abb1a2747ce95a8f2f2bac1003f3e8ec1b3dee19556fe8e79d893fd75714f0ad125cea982d3192aa1388fd6b02176d37cda5e53d5505dbbfaac3bfd53b910e2b04c044c13d3e1a3d7111b7c6db10d2d529acf389c7d7608890044cdf1d0bfbbe30b7b1f441b41759b1b383d53661c2dd1ac28310cd709c9284c1bed71eab2578168f8aabbed1ff29c963c1e79988dfb1b2331fa9cfa3947397560ab401dbc76d828b2a803012cb29eeb58184e63d81d8cc1825634bc +A = -3c9ecc3f121f494d4776ce500069f8a27abe01a7552b59fa508d65d5c7610681bb8e149636f819996d66ec005ca9de7c55d2dff8241ec73b666f05c8756 +M = 58486816478fd9e1f8d440829387f4d6b436bf346b00b323feadf05170e79139626af84926d00fb934bd7b0965ef381d2e60f42b9f3fe61ceca50eac5126b009e59241dc8bf64ae2e544aeab859bc213f32753e0ff1c132b89b9eb499c1ffe2ff6c411ce325c1c3fdaed5bce81959dcd1d06f4686581cfd17d6fe6562824fc681ae93033d2aac1400d29d096f3d4927559f6b38f3dd3a362983414261c3e1c1cc4dc97d34d63decf4712d83aaf76cf2d5d08d0102fe7c5c5373e08af336bb0d6ed3c5 + +ModInv = d85c2fda98c6466dc1f19bfe113287d991a72b22ce5695a1df1e6db2c876633dbd1ea5304856ebc03cccc4673f13700794a9e161b69f958213821ff78991370392a359fbef04c77ead9a0e3a17b470c219ad1f53a10cf76dade766b647e8d941ee890ea1512dc13fd0325e3182299afae10ef0acdac889388b9fe2aa19c3ecee7924752b08f82a44f26e5cde7a9f76a261230fedcb20af5c0fbe67304be26891077020545ceef038e6cee7c3dcb14700116251254f7941b0ae28f92060eb3ade9d9 +A = 97288c2d9e94e7b559bc31efd76abc819ad3eec3bbb9003d9376fba2d419ca516775e1cb5bbdf1c40b639f1f1bdb22608aa0297393d859f64ed094bae119c2 +M = 63cb91e135b9755cc2cc42de13cd38a283e685b4f9d9ffc1043e3670b1f12ffc5f9ea197880389fb6a1eedb3ab0ebeee40fc4f0d9cc2d00db7e29bb89499b228acc0aeb9d3a9ccdf8eb9804d5ee9297bdc3be4bfe000387727153bdf50bd2cb50a398f98f70749a34aaed912b3b0c230894c1bd4b4423a025c860b372136d74a9edfd4d72d4cb018211ba8f471476ded9a516073994952113171cd1d817de90d6447eb216e2c823747f7e57f5c9ad5ae3a032484596a386c0067ced527859b19e7ff + +ModInv = 6a42c61c1a50ac7a6893d926e4fdb021e9eb3cc30dae6696af37f69711c012150472bbaa2829f8d2992148a45dea58ad8f90eaae4716298ae9ffb899cb8ac135518372b585bb20411b9f96d172854beba60c5e99716d768fda101b495010fd70424014f1c3bad02aea954b2e6e5189d4ed38055bfdbbb8b5edcc42db34cd17fb6561615ce193418be32671e8ec4f72577d97659aa479d25d04c70342e44886afeec34a55ee4a46bb4944e6b3aee37b11db418f6d22b6eb469aab4450091ee7ecd82 +A = -4cc911125254dce812ca8f17d0e9381a879f04a5efdea53cedda3e48b038de328e64f0558c073a285d1b5bd54b1a12ba5de1a7f517f57199132c8043200676 +M = 9ee843e312a0fb28527035cc558cbe6c7c65f96977db041b1a9443b389400ab6fef79a0bde4155562f19d27d2df3c0e4a0e0bee7d428aca4bc8c34c8ecd1194d5109cbd648ae9a0fe18959259dd03e6924ee90dffce785f400022da12052af74058fc8cfde2e5d374eaa25c1fcb30c3aa5ccdd2ed4f52dc7d893ee940e45a4ef6e891cb4a7240a9fb1dafe63f0d6d87908cde061fb6b494e68e0764b118db6b2b343faa6dc811adb8f94d0e0509c521693bafba7b59db8484b44524a5c34806248e7 + +ModInv = 993ae9ce38a047b2914ad607dc92fb60b232d2f772efe5fac00bc67b724d15dbf304e0b208d831d321fd51f4db4d8e5a0f097acf07cda8d03589c6c986c2c31b637c12ac58854a74efd7d70d665349d9ea7a9c390d2dc1eccf3a99dd8f7bafc5c276995095ec2857d177a6729a674a8c3fccb4e544647941fd8ecee3da8fe14039471f11341de41d107a470508905adf4a7856445eea1d349b92edc516944a91114f4c3f913e5bc9b7310f826db5a5e46ac4a35917ae2ee6ac51a7bce3471724ad9b +A = -f42090437742b8984f194ef0d12b5e7b710eac9965fe9703ca96c56190571dd6e2d2315e8e7af23fbecc043f6f51bece4b3b709c66351b6a7d75657b67943d +M = c4a61eb1cf2d6bc60bb213fcdb1b4d311235648abaf357265cf65d0fdec9c24cd0da838266ee5ad249825051eebe8c4355c1cab5beff3476df1940868d791141c53d4e71f35a8d1c208fa0c61e133c99dad7fc1aab13392ace3965a6e4448d0ddc92d8d075348c5700c18bfc8f7167b6d5b24f3320ecec0e0b151b0087c1282bc8f88d0b0196c6c98874ec3da8735c45bc5320d0ce13799b9260739bd98a733cf804e78bf9ff8b3cdc09cd2d54809cabfa06a2e625c420f867deae80c385d4d56e48 + +ModInv = 12abb940ef9e0c27d1af2cc30bc23be679bbdd83d4c33c55f46d47ea268de0e2504e9aaef1a3a5c32f00d3b715b58b0c7455b734cd36ecf4977e475eb0bff56562d9ed7927e4c63cc269fc2055f9c412e60ecd7e41c6df2d4aeab07ecbd35faa409964c2eb1b916393c55ef926fd7ae717abda7418b579dd6feac9dbc1c66d6f6583325f472b76e9a523f26cc0c4e29ad9130b1a0c330b3f0eff78c04501be7e26483905344681b9625aede40acb99197b08f1aec00712ddd1e80d4246beb3cdfe +A = -8070cd9bb00d25225fca5227beea483e2f0d97a626f7c1a20cee3308310753b7d6fb9192c0a88d02032add06ce3d9f565df1b0569224446fd2c564197681d135 +M = 2c7590953366f90f70e3fe28d219244d114588b34f120d7ff98210b14df15c00cb0eea4193ec021068e495f8b935be87fe03e628c62a681cd6bac8bd1babc7fc95e516668e1571c1cd49638f9fc2cafce47280d84bba295c07d5af3d410e80feeb1e72b0906a6034c91dba4818ebf9b5092f9b62fd25588600d33a60b983999de74ee8f7c9682cb9c53d9335b4ce5875fcd5f7194e086622acaffc7122549c4f471b13ebed4cd2f025cfcce4998bc36a5e93e357fafaf39b0aca5bcd5f9d8962a9 + +ModInv = e75729e0746d5be55f78608ad103dde1ba4bc5e040f17e88886f4d25b682d6348dd0a602ec812ae8a4a7db4e0d5cf219bd7191ab073be2e640300dc907b97c6a7f17bf8681d72d91c80de5f52dfa420f957f6d8052add613be26c89801b26094f85434fc9782768c8b101707a992b5a1f373f8404d4448adcd9ce54cd4360ccf26c30f39eb0bfe90292b299f9d6a1158c0030074ed75175dc1b6d74bd820078b6a95cb0be1058741ec3235199cdfe412b531c5ae6dc0e797ffa9432faf4ed0ee1 +A = 6826d0c50f7c6c6f59aeea4ea50202df88949dadcb85f68988a38bce4b3c26b478656416b39f77cd5688d53247ceefc74ca67353d824b44b41c156cf264ca243 +M = 3fee98c3384fd8e935dc2f5f73d28289144a8fdbc8cbc9e7314cb9a04361ce0bf40d9e40d2bdf09eafb90c755efdc4e567455b231bc6ea2a69869d7866db6681d9c9c18713fa1d12dee3db5a88c56aada56e77cf25c35cbde21f3d1c053688c39b24ca75ac47c8d5e34bcb8afb05192ee31f1cf1ac3fcf3c0474e553dbeec7ff268d3daab3f7d1a84f55592bd3d7712198e436f226bf146a411965511fb8cb8754a63d3d24891e15d797f2fa9c6787ff819c6b3a21d7cb9a98d1c500f2f58a6535 + +ModInv = 1086403b3d886f47c25481d36d6fea46e08fcdb7931152581220bcc96dbdccdf6c82c39160514c591a2975587dafc6562f9b09957e7083c7e74fb001bcffb117eb167504a97caa03ec19614ed75da9baedbf43c9ebf3af4e585a794bcd688b12819cb117593ae25fc1d7f8edbecbbbf3e54299a17bfc86cd9718cf69decac78cae993db34579fd26646cee9ea5c6d309db0484344de99edaa4b219ea77ba2a34f47afb6249390ead1988144bcfb317f718f01968ce40138b8daec7da97a59233eb +A = -2c5134a8b38ff380e3d527d18661f745c702c7ea3c691bcac91068204518d075e27e7bc26a24c41492bea8ca6226c70b44af23df7d89655dc8a0c5b7c1e43a56 +M = 8536273665dddd0984c307ffadc4825eddef122f241e5cf6a25a0be3137f1a517b985bf90518a84a82f46bdb28e96dfdfea70202e17625f7c7b95b85b8cf7c7a218bed566ce34253a3ba2441561c988b4406130b8495f23c1837c85f1207b22ec32a92e6f6c0c9c1dfa6176fe5db09331f33996fccb85bb4482509f70c9f3d7b3c0a607e8e209e8ecf61197cb5db572f21a76f0de5cc01007f067233e6fee3f39c1b6479fe245e2c9d7dd1cfb5f51b7949583e98826d20f979aa7c0d2acb744511 + +ModInv = 8381fcc5886a9ff6f52afc6b0631e3393905d178a7b43c863572ee77da9fa2a4c85396e199c8d3d6cee304ed60384295d56864dbff685b48dceacdfbd2008f62a1c16952d22290b04954593b550820cfa53be8095028633031590b415ac76ffa225bfad990aa0109743d6e97da6161c35f0b5468004d87174ff9615481b749f99796d7cae428ecd812b370010e0b22cbf02b3fa3816c328e6d0d31a8db1e1e74e8054b90f14c3e3150d641ebc046607cde846e926b84c8344cc6189c4db59bd5 +A = -13da59d843dc6eabd385c88d92b6b8429c85210b167d1bcb29fa4cdb9ed6ecfbd5ca1bd356978ff81e3bca22c5499a1272453562e70732098d091fd7a04dc5434 +M = c14c52854e54299772a307f297b0dbd6c57739dc24f7f9d0d8400971029c6a02d69045c12d6b0c6205b59cf88a03464d99c88fa7b2d1fe6b7e48fae3b53fd9e9732d25852d1af3f5b719e7f65cdd35d8354a2ccfaf47f8ed116cfc343e2458660565d6e8458d33baaa7db45499b4e8c3da69e8e39fccf0e6185e9007d0c0eb22d674adccd002cdc2436d0555fba6e519e4ba7f4404e50eb7b64b01675b8d9ff1855fa6c41fa8e4016918ae3c8fa7dc757fc1c99b196eeae1bfc10ca2d372323b + +ModInv = 2f18e6af9444aa9ac8dd34ddf064ae76c260dd1ad7f38933d0418ec544a8e30ac620e8add4f3426429f35fb3418a12065a4b132c3ede523dcf36b61fa8fe26d217dd88e1e24315443e699ae91f9580b7bdf0dc814db4c7e801d7fb8a426ce827a3f124e8313f07e86bdd9c529d86bb111aa9dc1214ad3be6d23820a0a09c20455cc4f924dc932218c0d9e59022ea6bef14adca6699ee712868cda53fb827743d71a27089aa9c13b153557a7313695e5938e5b59cf0e33e12936c02691e68200b +A = -b52e774aeb002f285369af9562f52e36515279f82a497806ffdfe11e83973d4fc16fb236deaa36ee312e71b22c9e28bc14fcaf42d521bbef6534797e7b0436a592 +M = f1712efe3f445eb53f18d44a9cd9ab3b79832cdea4a9b7b9647a798327d0d09fda7dc0028e4939bc23615f20593e167db5a726186ed59b9588bc95d6099ac2f6966e3fb77d7a1bd03e55539a30fe01d4108967deee1744ff38a98c00b97ec16c10f80520934ef0710cc262b82e871fce2599d973b7ab0a1dac03be70da513b05d7935ad0cf8294895d77e055e48a8c0df5ebc6f01bea80bc81d519202491c6d98c712b94013c5e8df1f6218a6f6cba9fb105e86fd252209dc58d29ad4bf97451 + +ModInv = 26de145df06b771e384ba2f587fbcac5877af8584ec74e1f136c90de06f6f4967439082a370fbe05b387629d413734641f840329f4a8df4ba148bef14aabc2044da1a1e9c843a85c5cb63282712809ce46a84895d8102079ad3344fa1daee2bb6120350f717f2d4c2ba9fcd656b0a67874aae839ab4f6b2b128ce12497907f3b9f3bcd7f148fe33c7ace28c882ac2f8fde5dcfb38f911b31a60f74aa26d0ea526621ced220d66c29367d3d8da41f6af3a9b53f40e226a3c55af4141610f7ff68 +A = 52d2ef5ff950b06636516b4285921b5d4b45b6f25d6e45cc465d8bc334a59cd4fa6a30fbca699b400527cb03803547cd5fa7668517a1d19c311c1ceac55baf86e7 +M = d0c70a8bd5efc3615d70579b26b9115be1211d11fff2a61a23d5bebac47146452eb3bc32f6603775f948448a58ea408f79235f26171688ff40597b6f34849e0d2d7d295bf1938510e14efbf59feea1ee84f5b1ec239ed335b21b23e71adaa066fb7ec15a96a8a93debd4510c8b08ce1f63bb302283bd3a0068d6f1bf8037636033e2229635b527a360068ff049401e515dc8e3f81a1d7ea0d557d077b434c9b01d18b57de5d509d3ac7242d1ec5ff7f102ab3cae4209519bdb260d017b081bc1 + +ModInv = 4cb7d0acf580dcb802d59fc9940a5f98dc6e85071bd1d13a5fdd682e0a0e8fafd87cf5e0ade6fece2d1c7905e1f920e2a9c03e837344145a0ed7a1e6138d687e496a281a89de914b74bf6c70af7fff63da01536553e123cad85df93dafd390c306b007ae9e544ad164e0aa469e74001cf8d7d4f0b12b18f612119b9ba77d14764467e13bedb0e2713ab0c3b08346affc9cbeb66a0f831e746f2644d9acb282790630ad4ab73899fd85dfa46f9afa2d22148fe3dee1ac95e0af75abb038c62e +A = -3f143549fe3be2c3acc46aa5d1dec2285ff2e35b99f46f6ea19b728eeae62323e9e9ef9380d06720af1b6549dfe2dcf890a4ee8420180f76c0e3037aaeccfb7d107f +M = a280f6910e5777fc7a8fa5f1419392b1684aa3631c4515d08f9a6ffebd1d176b88f28fa513381823d5e1e47828c9aefb60a8bb2738dda8da477cf08c530653429c66effc60bb7fc76d95c7c0296506b220f3fdabf860821cf03b02f8cbdba6ad36edfdd7a8be52f19b50b22ac2f5587fa8405c7a78a5062fa854cf3d72ed1361737eb80921de3d36af7aae84183ee05371118a5d04903e1dc3ae06d1715d5bfbe2a3c9e259aebffb42fd2f6c786ba29a3d432d2c0225026ac55b6062599183 + +ModInv = 38b82bdfad01a0ac5aa20a0b2e07ad6b286cf8834a7ccff613f960d56f5d4003c5aa0ca34649ed69cf757b7c8c3946d5db772089f8b2929e810508b4169154e4689bd2e4d2dca2ef9a1419e282c4f0fa5e03ee1c8c6f56048be49c175a7cd5be79a5972ac0f7f6c13883664f89a73224fa5004ad6954a9bceef2a9e2b5cb10356863f4ff2a0d2f9a468736f5e9addd3a4f7caecd87fd86d174f5fcdabb5e841f87bc181708f11c70a4a754dd7c4183cc9bf89787eb835352dfb8f169e18482 +A = -f8535b246f35de30f5385b0d046ecf58db822d736535faacd706dd88272dc63c0cd6b66cb7eacba3eaf468d8fa9f4056c2b44f0f8fecdbbda10600179ea0198f7eb9 +M = 88d63ae9353709c2a23ab0267b952bc32690acd2f4be177cc5197cef45fab3d6a34cad9e981091d28c5d7b1ec720549558405d0bd62c550bc06bf78b82bdb08dc6ee3f9b5c55e20fad19bfa8cf45d9567c7e58819d0e0c1418a4432d2a82180107864f7a3275c6bb3e5b19460b3f64c9e16cb65195e98c63f93969da43d82f142b52d321a5e03fac1f5de7565f03882c8bc013bd73f1a96bb89e7f095cddc920dd0bc88d36471a4f71360b459e86035260a73ea6bf38c9d2e1715219ce6a4b + +ModInv = 17c698f6330b558217f061d4946551260c25bb36cba2cd035ca562574872f884fabe3c488e81429e207ef6dab5b47b6c31adf1399d4f81305ab0a68aacc31758bea84f4d4195eaadcfa64488a87f799b9f52f3079eff2e4abd6f4304ca0b007dd88d7a30b55597da2cf65a27c4f22eb6cceaa6b210b4dca1b0e0e508ea0430551ecaa2abd50863a421cf46ff6c27cfc7a616f1d95784a7c6218f4509737d70d2f766b5f8661a1f624cdd681c5749d53bce5015f4e238f81ce3516647ccbaf5 +A = cf55849dde0bde4a6c01e29f3fa48814455a1723c411bb0e0ad722368f3f0566ddfdc37ae8149c436d2cfb6429a4db0d85f1c633960a62dfa8df3bf40ee4139ebba8 +M = 80231ac55d6cc25d9a247ec4ae7b74e55cab487899aecdb096ed0b9b66fd8af7489ef77050db24abf9169394866a4663bbeeeb99ad4bd724d6bb7f5f3c2ea874613062c508a5ef783ad63493e37c82c6f839ce12d5a87867d8cda0572f4e500274100423e29eb079276a1ebd704c7fb3ea8205680d7c793eb9bdb44f2c1cf0f6bff7fb4fdd6a5c81280185dd8711b8926d3b119238d42470e29050e81fc72d8881fcfda19a18a90ab871c5bc1a63762358916eab6aaa31300b6ba6e1712e49 + +ModInv = 81e424cd9a67c3e78b8c9c4686c889d5930071a2a5ea74a13573d70631f58417ed31cac92b632d4be8449580d7b1c18934e518fc0c7e22011f865d685f16419d18e0a5d27d9fb07672d2f8bf8f1753be73dfe7958250926cfb6ca4ccbbdc19439a2ea713dc17c3beddeebfe57beae0ad4171cb33961dc291a41f4964d64efa6ae30b7f83714122f76fa90952f05c9e5f799902b0d8cb6a37f79999e7cb66463ba611dd403ae448278d1363f6b7f9b74459603b8cc7ec51d15c602148cfb +A = f82ca5b5e2edfd398e6cd86d25e19b3438184abd04d81d75d7e1fdaba3f158b905fdeff88731a13c9b1836d42a48cfc60e8b62be81854b26f8911fee2fa92fa66e0b62 +M = 2118279d4205dfff5d314e30c3d4f75b82e12027db7bb5734367d8140198ece4b530fb62ae1c6ed66fa357be51ab2b47b831f57bb75676ecff466a63af8afe9b78f7de97d4e2da26c84f20cc8c371ed20072e27716f4cd4878f37bef5c40dac90255314768d7b8578dfef29bb41b379d207a58a8a3ff52a0307bedc4e45dd7960cbddab1de858b35588b68939cfe68a32a815ca846a028d127aef60256c1a022c0176a1ec91594e004ba24580c7d1cf6576bc0abf49c620872056d543c27 + +ModInv = 86c6bbe9903a7752e5cc8559015d2e7cd1b7d01f94593d2a3741785113f3614f4f686f339dc80e772e735de0b46fc37a6a3487b70f187a1cee08736a1241b21f84f08d45e1a2ffa1cda8d2522660403f1c2fb9d64221d1013192d3d17164f14b4a7274ae002f43a60b2d38108d6c5a0c5cf1f3dd185a9dec36e74db3c60f4140984bf7b06d488733f686becaa5e06652cc61198032fb7716fdef2962459c711caa7ba67638a6205f899d9058fdfe9563e013f0c43979dfceae1e962487 +A = 2fab165a7bac9d23b95dc4836e4c76f3a1f50ce26dc932ad60530d58ce1907dd8df85f2b00500ff3cac2a15fdd72b5218ef71a4b8856b19ba15f68f430f44d52be67a00d +M = ad886a3aba788a27d7022dc4010223a222315ef57bcea9ae37a728c94ae92d3a9756fb3374aa2886871999960e31ba171269f496eaec6949f01b91fe619f7fe568567ddcfbfbed75731aafb79ddacf4fb2c3938218c7f1daa1589538d514d364cd0b4c72220f99165a7ca81773ef9df6187ae4b7878deb2645e121ecdf5e7ceb08575e7049ea7f7993f818470fa8ac8d83c6f5e57b3ae2848d291d4292176baad160900c69430a75401c312e130b4de71366c1550f557dc24d70657932 + +ModInv = 71be1d596c84d8fa09f5443e3857106648de53532fa56fabb2d82c4efc8af029203cae8fd07f3978be118de2a21dde8174fc4dbfe1e1d3bcb57b17a36635cc08b0e9f7a40204f7a51ae0d36890e58c687975f7d1ac29bcd8a07a61fa3096323d96d1842633afb2f850652c3584fa4289fcf73c7d10d01985219b0ae529b272a4a9e3b544c95471d67d19abd3285826fc56b191532a9db2972ef63ba786b580195d9e44aab24fa5712230fe6e4230e599b8c6fefcb0a2470438c87446a6 +A = a7dcba0391b0e1415097ec6947ac7534886327c3b3ff7d182379098e6e14b789b7cc4c2c84b0889075833dfe0ab1e421391bacf33ff06db5fe04b6fd71b82360ba0ed922 +M = a64aff27263b6844d38f7ab08c2d32ce53e2c7e318f54e65a1567edccb34d3bcf03643e81353acfa2a866897187f6840e8aebd0eb76724956ad1be4bed351a709a03105cb1de196183b118e03b614b32fff2f734774be23f1dac5c2fc5fe0f07cc247a21663ae6460fd137eb91c6d41e75beba72fac291e4003205cc62446c5be419d1981a11ce028ba02c89e35ab60a247eefe0d4647ab0c96a37285d9aed73aa94e79dc40e95409cbf06d9ebff4f75c3b785af3afcd0b37daea85c11 + +ModInv = 2528a5af7ebd30da277afc0a371225ba7aa6ba92de625f4e72abd6bc4edb486c71df47eb5018cae8cc2f11490e04459eea0f505fa87c8ca4c5c6a79e94af4db369652c6d70b4a6746ae33bcd4be25b540f12ece2e2af9820477901b9974c8fd4b429404bc8976864dd9f8dcf98f4a3092da37c381e666b1b9d2aaa8cfaed59a396373352f50a1d74a7f5eb7af85de52cfeabea6fc4297043f602c1213f21f44861cb35a2f7fe0d97c6412e8fbccaf11a7c7be7ba94e7c70af78303fc1 +A = -f613db02f2674391d069367e2d21e249e1917405191a7d4fe715ee4689e1302d5296397540d009752a0365910a78174a66504627ca9442ef0c4fb76d4bf4b17b4554b452 +M = 16e6e6a1cfcc0547fd220f288939c7f95c69ba29cd504b2de04a0621245dfe4500dd1e97e6ecc7c91e4bb822fccb4363a026a96bd42e727a68196a8709ee88aad5dd50fb8cb1218392faa435c54bcbe91a28654d8bd7175b5a7d376e99747fa1b8d36b38c5eec4b5ad98de96da786e5d3672d150cf40e3720f74f8ac9d4ae7ff58e1ecb929ed07547b975749d9c443067025eb752f6a331031676db846745b86e88aab3a5b04705666bf7f883c62c32a5623c68dfdc5e3680ca1c44f75 + +ModInv = 1eca47eee9c19ebde3603a375588b93b6786642223ce7be8dc78b59fdd62f73eeeb0c11ac7c7070615088d9d6724c875bb4641029d39f23ea2025238c31bd45f920f6eadfe75a7ddcf409fdc0641610f78763f80d7ac3b8cd909403df8bae7e9810f263837baf0ff70d887dfbccf0b8c16350809cf47431366e9bb595d7ed87db528bbd00110ea8e3216c218f817a3f66940409a3acd335bded3165aac5399f6a224755defb916394503eaa77ba71e04e582949362149a0ee58823b3 +A = -99b447f6a656bc04555b448111622fc45f13f6e25d7fcda3043b4ca4fc0e0e3da8ff5f13a2b2fa12a2a48b707dabf3f38fe2c45c02b803ce74e4643165a0d0cdef3703d437 +M = 57e7de4634e16d03bcd022951f580b7de5a4453b1d6c31aae436ba7571f6e50c5ed4f05ceb81e619384ae5f0246c9704e4f4f89f2bceda9cdb12120125d7a02b09f7e8e2c2a9dff5cc67d20fe735742abb1cd24a45b3835b11d9ec7fded14637deb00d8068e85aa467e7133caeeb1b40c4fa4dc7138b825d4432ea14cd8369c72eff6b96e5dca82ff2e6a9951e631a4bb1756e8174285a5f4524d240b53b14981e382eed559932e9d07ed78e36fe0a253aa34ece16c798568891ee51 + +ModInv = 931333b868ec1a96e9786edf867b5e7ba8ea9eb9f4fc87947eccacdc488d9b77f041c3e07ccc21fc112e08f705f25419682f18854d6852d87a15f81def11f7925994659e387e37acb67b16cc8b52bccad58810c5e772a209f62e349adfaecdb409bf68713f0b3042d08fea9198025840e45248e8c7a6bd7e1373cd907fa5561d8d018033a692e88b27e6c9f40d0142bdb4de52faef4c8a52edc9ec42d5f0acf5177f3bbdcab8480996840b254e3053cacf26b38913632c33eedd59c6 +A = -8efb27f6285ab7f438f867292e3597c857212d4ebb5386c132263a6891bc8386fe61fb708c5e69f2b4be89b6730bab033ee4cf81be6520e15e658e7ae546c039a003a0f2b7 +M = dd574694e8d1903202644a00b48a153537c9eeb3dd0facb73efb0d6f731afeb8bef9a97391e6ce245ec0e85fbea75f6514c319c25309d6f74dc587cce19a36954553b4c4f028fd54f7c367eea4e4e9d554bbd4b937edaed74f068d77f63bfb691e9bb0f3f255023b38d97f7d96fdef976bba78f49bba220d0fbe2c5a34a252b8dcdceba18ed2e59f48d2563a90dc6303943d7db026e400c35d82c3ca3ea4453bd39f6504b4f33b450d9c1621e3da42d00fd8a17acc50ac905f582f17 + +ModInv = b8bd50dbd4111eec42ba09dbfc0108fb470b63c015aec156e50e62d9b4c718e8b0545c08074b375a44e0506755c29f18f9d185f13e48092531c361d99e63f9bd2bc8b7b54f9d4226d7ea24fe9b5edc64fda90e4eb9f372ae2e1b4ec484492572a3e44cff9177f4a85631a31037b9250bcd509991c275ff5e499a090576574f2882f15ca22c6283574f931e30d5dd4f907f861ee6d63d2ceb50f2d6e557cefcc6af49bb860d4e9c56f68ab48405e4094030f5228a0bbd569c1a3ff4 +A = -8e6c9184dbf4cf217c5b61c3033cb5fd2c603bac7d2bfe6a3d53b384eb730a46dd51b13e7fa462e7518ec04fb1b5c74317088030a1b7a9996841131b6fdbbe0e7b05056f70f0 +M = c858943244ee03a295d8c8f1f15e64039426ce7e8ab3c9f3e4b81ee4ea47ca372e51c1e306e8166e1bf3a487543628faa80cdc363e6024e389e15616a487865479e3facca8eda57d7645c6c19481e4eee64dd8207cff4500f67b1894c0582ed5d50c53b92beca164c80314194888411e02a580203a78a1f751b6cc544baab2b23959cf5065d6d35c4adc4efc4cdd94eb20c01fe3581aa79a6449cb352d20d48364bec63959bd2d1b726dbada05d82ef7541cb0967baaf57a04adc7 + +ModInv = 5ff3549921e34953697ced2fafd930037a6a18dde0b2bdf3bdb8121c8665bda7e679b155da1ceb99dd96686638045bab72909534b81a359c04c4bb5fae20b9cd79eb621d1faaa27ff09a0df2dc4a54e5ba2fec4855cd42d743a0c93884635139fd7823a918660e40deb08f9c1eaf61864770e7c8a3b908f68c4e34734fdb8d2dd421106b7a9f352fd8dda89329a8c8a7b4c8f52179dc2b76a4887fe9df5f39ab6386c6497a978873332bedf1d92bb9787c8ff9008de9004594b445 +A = 7342e3724e5af29bda32ba91b0eb9133fea3ab2f0588bbb3414085fdfb91c647054fed3fdd07629d410668ef80fd06d330fb73e92d5c22adb005746674e4068b95da78cac281 +M = a9331c3c3fd1263b8d6619b37d5c0da4ae70709d72d06441500e7d0c6d397a0c97db62980680778a2979676a7c9cb7352d026902be8d943a0240c106d79c43db4df0d012d2e6e02fc56e77b07d79adf3718bd8bb73d91db84b298c62474940eee56a03d821c65d463e6c1402d64af157fecce10bd5c9f06d089255e9d504d58a8798baf9a6c28eaface17293d6b6472d81860573155ed0072a68a4f03ff614922a98f8bcba0a399eb4644474ed4b85d2fff94b2ebb8a5a2c992982 + +ModInv = 196ea873cb470ead4e5ab554680dc2634c73aad8c34b1aba99db39b465f17ae3af0b7f322b08610f7daee0fc99cbcc1b04566cdf112a802c10a8973d4243c6e5d4aee1c7d5021f507b0315f7a85b04e0bdca6a7734291b84d179e7cc37ec83e1824362ae3ad0780c8eca4cffb866010ee164dad33c8d8d494e983f31959319d0d123514c7b1b3b7f8c15a9fa81720c47ec00dd6928aa6d976c3d4a393aac1d3b23a552b818cc7b25f725533068a26c371229d4a39342fd41a22f82 +A = -5d06dcdb8676e856a3ff48f3de46b612e93542d261bb009ca6482639ab5ca345db83e1fde77e601a39443561abfdef1610005c710589dd14f46d2c248361579741d983ef00d7 +M = b81e6aa2003024905f16019af03c9074c03206c5afe4a68e4161e4fec399a44f3ea10214ccfef73c136c27d8c6310e9569cd3295dc70e6c7e51ba710a4eecd155f7bcec3ba67ec6892a971453aac6f455d094cddc13f1094876fb983d6c2c52135fe9078fccd45ec2b5685806476e9fa94da992aa95e40c6ca726ae22f22b33189cf1e9518165f15b6f0ad7bd7983b96a2bc28efd4798a30ccc3400ff137daaccd3a384a11ad6f0ce23693293f53e8de232d39d34c407311093731 + +ModInv = 12103ad6d5c1e109735e1240fe6cc4eff5ee16109f0b2d6558f9e5534d5be68b182a904a7ee724a2b9d7056efa8cf107037a23649f23952ad27823a14c4c64211e84d3888e53c258de856cb1a8d1bdeaf5f469d2f1ad63f821629c14e44c031f24b062bf2d27861c3b37c35b747a1f99c7ff86e4e78399c5e9a78bcaf92419205b4001ebb391bfeca73aeeecfb0372e2c36ab78c3fa8c35c4bfad1024bbf116e158beabb389d592ab5059ba87316d6803c8d5256aba5bf10c69b +A = 3d8a77ed4d6ef1e3b57a2b3d92a0eb5a5edef3c9d76afb6229c7cadfa2b02f946b0fcaeed74b21b6c9680800f87321764f1f2bbd2bf1b779f4d0930b56dfbea3717c62c2c007e9 +M = 188a479eb9536d7150f29d14e29a37e7568952fa5d21a016e4cf78cd53edb27cbe852d03632591a717daa14053d2ac0332bbe2e96d4dd1ef5c0ffbbbdca1710523542b62bc5a16839767948c7dabed91f1b93988d2e5fbc0081a730a35feddccfbd4480ee3bf2d612a9aa892da04cbe2ff79983cea4842f3751a11e811d311dd41744d28c3877f2a0674e8f825b6afd8c3c6dbbdb9e5232a218ec2d7084d7ba2888f276fde093da385716caf3f521bd11f1a6cf90ecc13cb8d02 + +ModInv = 94a4d41627cd98410792b541432fcd81f2cc326308a6e7ff762a8a36bb49643c35148cf8d17da08464742e01dfdde272bd72c23fce422c99339f633c25ad23f6d175fc52eaf54f98c77053ecb76de9ad15cce754186b3935d064fbf24642cff42d5763b8e55881ba8d48cfa1cdec94d3653f68a004a44affcae7dbda3acac74279d5a3339ace4404f756a755cd1f978091c4d8fdd61d85462380fa1c3eb9e5f7deac9bdf70396961e94aa3b9f9b4af75af8f7f9872f0b1e83b58 +A = -712176e2a0808994f3b71bb5982c99cef2c6aa884b6e34c12a80cc59666d519e3921b4399427e333e0e28e3300e9b44990e9468f70ce5f2de946593251b823876bd1f597b28ab0 +M = 97e94ed38f83877df7c51fe369354891339df861dc3514215915b2c545882c396dcc15886528f0eca49fa18b5cac1e46935c47d8acf8bfb2b8de356cc26212eff41b33c71217c45b2a5acb61e1bfa41b1d76725a71ea85e66c2204b785d7fedb7e30dd2202187e1be1e32144a147d3dbb2b9a5e649feebcabc2cbc5e528af7220213b04a0d77886a348cc9313330c70734f7b5ecb72a9d5317ad131759f6025b917182ff6d926f0acaaab87c391a35338a3da074920a8e4fbeb7 + +ModInv = 50cc6ddb35994d05cadfaea216a4e3ae07719730718aa2550368755845c0bef32702d3ba34248b125d48893642ab96fe48bc994f24f7dce3de86290bd6b7410b1a0da89ef80a076e7bdd7cef6eee877179d06482f2beee0fbf54a7b2ba770f33e6edb99243b670daf67819f218dc058dc860eda8e37c943b34e4defaf58aafa093d7391a26bdeed34a361cbefed7ebcd2d72e61ba4800d1157976e495e549b80587129c03baece370ede2d85baf07d81b081950058d562eb49 +A = 189e9f4e931e16e47d2b6ec5a9cd02ea1369f7e390c4b0f843dc7c5caabbe970f5da37424387377f54e359b70f6fdae055be4cde0f0e053a89978226ec50dff4dcd675e09e818aeb +M = 6bdba8aa0c921f58312cccf494531dfe7a29a14b021c121b6297609a9bd66e590518026c96245aaf27e7c3dccd3bb7e73d83cbb0e3702183c461c3a75c7fb5b02c8c970f1018775243ad698c2b34ac67505799a51e2ead7f0652c0efe159fa54e8ed53947d06d4099fd7546dcd740abda5d1e61a7a133098ab8f060d3ee5c1fdd07f6ba37da1be0a89e531d25722e34dd442dd2a3c05c49c8d4fd143b6cc34d97d545bdb00c8cb61aba37637a32cc1954489d099f87f8c115a + +ModInv = 8380349874fb15d99237d496e016cd8ccb02d481df08549418aeb442ebfc38bf1d7e87cd723da27f19fe9d7ffead7217659f08618ae02e189ee0b0a3ecc2d153533c2daf7a4f57e80880cb023eee84acc0000347a45a3bfacc2e39e903ffd2bea26698b9120ba4d9c52a8f864a81843ab59dff85fbb3bbb48ab6da699a090d8e1b6c60dc2442637c4a6a0644d6c8deb3bdd78901fd501789c9ec74eb5d2e0d78c78cf2985de4b4848271c3cb5019c5e0243856d395569a5753 +A = -4240916df4f81d15cac732f5f10ff8638f0334b3b1ac51f97f23bbb8bfab312555bcd7342e09b8ccf6107d6fe375f32014d8ba30cbe110454f480aa03be0b4233da4d3a1384d59d +M = 8e641fe97bebc5129cdfaa8ba7c712306ebf6bcb57e1f66ba540a095346f791f79510c4e2d2be265f13c05dfa7fae9313f5d8be66feed9e63bb8ed59936e01be9d91de488c02ce7e3d9655ce14b7ae1be7442c552931096fe580e85f849636513efb7a5ad36d137c2700e704ca87f8a27fa0e0d54bb0e66255efd973d0f36bd7fa571a8a807277f0a3f49c6f9ac4656590e58135f3b65d15f20232a87eaff9323745324d9653f758ebfe3c21f112a338e7cb3f3ef965a625b3 + +ModInv = 217b5c109bacdc39d2730a50b713cd73f8b2749aa560d13b5cec50a85430600c423069e13598ec6fe4f02742f90ca198c98d7cb6b28df87f500f0e3624c3649f429d8008636ea568e67dcca0aa5ca74b4be8837d519cd977c5472eb4eb3df291652707b5fc5ca5727661fc62b0513ac5bff8f829ae2dbf95e99926dcc2863c256f13108c19882ca884d21748386beb2eb34bbcafd0bb02cb0dd7b43ce7e202fc26f0671079d0ff43b050a661717a4620af13725ca721b367 +A = -abad0a69fd417d77e7df0e1896331f801b1658c0a2e894ede387448f0960ea9ab3566f0bdfe813619197cbb832008205ca320438b47d5413f0ed279215966d604eafe51b4ac3abacb0 +M = b1d59b8282071b21111ce95d45e0401f4f8311be6f58ae29baeef248b7e65354dabed2b084c7b96fa96e47b84f7e72506c2df7d22874d55fd41a24cd1b4fdb6a4ed68dd57ec33a067cdf3583e8301890cfdf5ee8fed817807e85b1788134fc1224cbcd6826ba05d6c566794f6b7be834b26cd3645a62a177357265a19652b88249d6011f88cbd66ccb64873650afe77e010871e9eb7fd6a4c9a93e1f27197ca0a911331543840cfcade3e2a5ac270750d502404f773cb8f3 + +ModInv = 4b0fe28bd8bb686d490d21c663d517c9695ba671c4321056e76a3b281785d08761bddc147e449ff037740001d6476e03422d0df8f983fcf0d1c95647114ce025e3e3fd685d16b37104d5c27542a3a709ae32a1368d86c45bcc6e4a9b8cbc8b8708e718f9b2edf5c57267a8f11c04e2fc858fdbd34bfd5ed18669b2ecf2b786d3f5d470d9eebbe530486218695d74ee58b0ec073c72cbf72939edc2567f3008de0b2dbedbf68fc930e35848c982d40e30ccd35e4a26eb5489 +A = 66d0d6b615b1508fe03e4445b0e8f492eb4aa0c71c7f5a532a8a3dcd2adf86d175c5218b13195c36abe118e7d66a6785ad76218e10579cf38d147d04adb3a31748598eb1946441f9a9 +M = cee72f474aa0d8fe46e1d1fc6d6b30d87fc15eb885ea6d803ef9286cb4bec0bf6c956b6d3cfcce5d840b69eaac9609cd4f808cc75a52552fc0e9fca8d0f54d69e217cd4330851e844428df8d4d9ada1e314eaa25f3ed7daec4a275d8f62b7186b079abff1c2971a8a9684c473fe596a5abc985a7c9b2048ee05be4bee3d6cfd2e52c3907cdaa4cae90ff1133f0be8a5d6d8208eb7b69345f3f0fd93cb527179fbc89e0878d5c48cf08c8efdd00d7c0e63160f385b3ae27f0 + +ModInv = 26a8d7e09b49255ff0332584c9b4b4743568a3866c551907e15e62b81d2b67a315280348add19170dc4d45bc7d57b6a054ed309fcca189d4000bbc1f07b7175ac1bace215c5d74d4a4d50ff3c3dcec2bf37cb144819e7db279773dfdd8d5f89e829550b3de00fca37e281f2781b2753613bd474c6eea9765918a69d9615a3263d3248c4d641f64a27ddbdcaf55d4e3f569ddf1492b5a4d3e347af6f82df2bd902da6fb38e19a74ba0433358256409fd5032f03178d227f28 +A = 9df0abbf402a33b603a408b74bff124c6b17f27943e59f578cd33f68e45dbf4b09960438c95b62177165b169b8c6ac7237bf5e5959928f5663abad52b629d7eb8e4a4d769cc379e603 +M = a66cb9ae8a56956e46c6145c2e286d3bbe3da5d7e0fc38378614c54e9c7df7997d78efdf3b2e16af2488067806b3af4953b32cf88241b71303196313c196c54ee0f68b4ae49ad089143edf668acd0b3dd79a4974ae9d2b6ee263817b5e7e1f73678f4268123637e38adaa5dd91aefa7640f436dbc204288906110ff2ccb0ec41abec3eed53f94f5b0e4d2fd8a0b76ddf63c435f7bb3d9f0c819e916b0b4b25e4f01aa4cfe23948ba667aec2a9bcef56c9a1db428587616ad + +ModInv = 68d84dcbf75950425b862cfd237585b2e57b8c4bd6f10a440ec981290eee2cf4e8b4a8fe1ebbc6b268e17d11fbba650bfb8c7978a0d168437a5d298b959ae28ce566f727b8b6f1c0b2b87b07d683dc02eb68ab5d5e06da1ea4b803725fb233153f316a4327b1bbb99ff07edb05a9aff1aec15a3c12dea0e15d565b323f45496fc77e8c038dc0516095db8fc4be5feca36112a39c4230de09ced4de653a181ac697768fb78635094665af8f425ca256fde7c1cbf58dca9a +A = -dc157075d817dfd2a1e5d3d36b669f611fbe953c909e3edfa68ed505f3e3181ab10a15313c2b1e70281a9d2b6db24bdc2edb7fa99ef4136bb68924c72b23405fecdcb4ad1a1c987bd4da +M = 81884da2fca8ad1b086cd324b6ea985f434b948c98050714d9b54d8800cc5f1d867f1ccb9fe2d0f5a22cec5bb99fd3b64ff4fc50ee24130f82d0cddc74289c63e60b4e84a6424b94f0e759a8bf00bfa13ce826548d311e3b0546fb6df76b09b38d15687c8228210bcd3640cc853ba6ad14582e8e54e9329333dd2166683164a279b9b47057670595f95963f92c99c8ed31224cbf5d4b1ba7e1e1d96233b700cd70740a4452bcabae0a3d1f3d5892d4fcb2d8fcc0fe4af1 + +ModInv = 7c9f5e76431d5ea80278568a84fe2bbd24e48bad31cb554484f838595cfa09431d0734d6eb4be836ed07f5f28a1de676eaf30b0b65adfbaaea2d294a4f66009374ea204ca5b5c3d0ff9eb4a2252f5e6205f39a8520eee35371a8278bd7d6651f6f48b15ac9fbe434c7f965705c7d4ee65415d0dc4a2f55e85739be00aea600e9d5c8cbfc71bec45eb076559856a02269e8346e6376e47a202a90e0df5762e003a8ee8cdb1c1dc6b9e25c451b42c8c6d4810f6dda308ab3 +A = -476d77c866c94330e78b00eccfabd31da42e37937e5c697b42337fce7626c3914cb08730b7435ed3d08a5b277d349f3ba3fc701f6af7303f1e38e5266cb8b8544e081609b8c10ffaedbc +M = db9e1791cb1ed8dcaafbefd9bb2124d58a7210fba7baa5cb31aae997b50ae77670a266927196b9319749f86630581c0f41056d771ded984c5ab97dead87f4b6b456d2062eb724d667f31248380a1b177ae469afe7ffcc10df1c776e78e318e94945c62e35173731591865b6547924aa2a2ee8cf0a5f2b3d689c2b789c9f350c6f2fe1b9a8a6ac0a4c9a8208d51f2878629d13dbf765f427fd815892ea158a5f8227bc6d663e98918a04d7f37c9820def2a9a33a1ebff3b + +ModInv = 188147c084b230e739380f8c60fb76916cb9a148fa8d45cfdc1daa92e88e9535515b8a8d79ed0ca103fdc46c768771bca5892d71f20f5956a1ca63ee8e2fd88962e4c72da8e1d01d74455544307705bc2084057521cead33e404912e4eeb37652de8a6313b41d7d9bf0269440e12202a3f95b51dbd846ff0e82ab83a82a71d0e893dbb29aad44cc766c2c2660834a28e1777f39bcc8b165e4a00eedf558433c8cd2aeda471d5e45d9a97f0faff6a46bd8298aee38dd7af +A = -1d31bb14571f4c5ca14882ced9d764f7731c0e9046759edac3453449fc8b7ac17bbdc6f12541b0364d861213663a5e4cbdda9ae14167fd133205c28575341e018544460eec4abcd00cd7 +M = 2260bc2df9d1199d1e1ed72860315232b917e8bcbb4091fb079ae7723129513fa838ec0a0eeb0e5a2f523120647e3041dba78a2d94c4b221bc38a661aefbd04a35e7dde604b74b91e4868ea3e1a6fffb9b794af16cfa98bdf6cd4aac1d63e2d97b6053917c2d13bcaf7ed01239049d3fc3d5316164e09721b35d44aa748381af97045ca6744b2760a123b3267d4e15a88ef06090ed143c98b91889297ff971f9e642c39ec09e5e31bbd5e974bd6c217783878b31e4edba + +ModInv = 114fa382e4d51f46f3d1dc04739c8bad9049c2f1a2c17f9d35d940d813245b3a51e482559fcfb7b2b3cbb6a44cb7ff70b7743702ecd5de20789fffb65b258e21712b70f41793f6c7a8118abb6676df59b336419cfe8dd31e165540a55161ceb246b7f0aca7372c85132db88931a6e2911d02da6712f064a685e3b468f02aeb136287218e4ae82b2d39059b6ab17252f33a9175147cdffd51b6f21e525c3f47cce1f8bece341e08213315e4cd869559e1a77bad1fb2dd +A = -9f25566ad97e62a9f5008ab7e9292a62d07cf4fbdba766b30a46bac1d2214dcd8e2d987ceffa35f7bf8b5aabfe592c159c8720c8fa2037a8306afd5831cd7f5df35e7850bec41eec50647b +M = 36f668fa743705bf07a111db5ae47d2221d9cdf2bef6bc2175b71378d6dbea155387a8e900aebd13fa8a0a8ae68d0cc1edb30b2cad876def94ab59a8c58e2c5bea67be23949c8102da30442cf191edfe1dece628a34003371046e9205528119ffc24d70937cd198272d8a82a39bbc2cefe27934dcdff6bc27837153b7a3835e63b6ad454a4313690b638093e19c74646b9a3e68a93cdeac0d41d60441f61fcb47e6c27b773432d663a39014c7132f773b615f230c19a + +ModInv = 5f8575764df6c5daf42ece1bfa444bf859fd0e12baf96d3cda414d3b6d353c83f75ec7d257778275c7abbf18ccc4489f33ecfcddd35a34393fb252e5b02a794f14a7dbed144a872071c8b20a29f049167f2f5eb9f03ce62a863692a03338218fa6b65f2d89bd3df1ba9ca39b4a30fcaefbdf351d83b6051b815acd54be07ae74c7687e62441951a421943403f9acfae97e650354fcbfd882aaa26e006c9d59b58d05847d1469580de5baea04b73b9918fe79ec62761a +A = 2d4ccd87edbb361791718e051bcba101b3413835215a36a96be7ac73a4dddc9e8bd6b4e9450198bdfc17130bc6e3ff0d28b7944bb6a9a5317e5db39f4818efaee71294780dee5820321dab +M = 70f03107989468a07599b6e3b376835ea29da278a155600bb079a8a9ab2ff4a5c8feaa9843bacf24f84159c3a1b1c9e4804a843ec998e541b5a59d1f62d8d933a15c64f3514b4d5dbac8eb9906148f6a444889bcf6627c2f9c6538e132d7f6abd2962b976b6fc59660c7d735f4a5ae3223ded31270828ea9f468d9b90c946a87df85cf16f8a06c04b30d937d7e24816060d87a8cab620583509d58ec2673e599113bb854f56f03d8314a0dd007f8e15f559d6bbe5dc1 + +ModInv = a59c6e24acdccc59b847dce2b0aded9ab8ffa6d9e0143472a7f93b41f3265ab5ba08d1c2cbe8fc2f149840734cfbc8ed1b5f22b84cd46d7fdd0f206e7b1759b7652025f713d22210db3cda1f09a409122eb988d8a0092502ce1cdc1d1ab5ef7c5b1387ad5e39cc9be1b0c0c7540a109f6fe8fd77c4d791546c82f7c92b807d6193e7079b79fa861d0ded4ed6228c79ae70a60692d172b18a84a6a64621c09395216dd57626ee67068120dc9e3c783eef30b027a93f +A = 8e6168e0121d059ab15f36f50f851018e9ae2b946d97d1a1719680d2672b7d5c63f9b60d1a4f9e26ee33ec849a69bc6bf5038f41267b1263708159f5a1e17d9e5810c2f443bc2c1bf0c8a307 +M = a7c7efb54e66e66ced05f0fef6a386128a8f0f8b291bebdc6452b239609a43c79710a4b640485203fbae9ac0dbd18f26dfd24f1f0d8a30d6546897d125b0020803804be93f6e7c47a70069204ef02d0bff770670b220f8233f824a0a05d0714ef2ca3d1a03b29aeb298e4693d663eed2c50b0c267c238629eab88eb92d297752a51e44ee8600bfeae5f870b34c2ae032751f00281f574aa0985f1929cda013f856614751e8c29e929eaf52645102a32cb8a8dd1238 + +ModInv = cd0d4acf1030ac036b649222f403be60b05034137712d08e2d30711e79f6144f15a28e19d01cc721e83f7b04c76bc3193507a482a07b1bd430202c048d7e8a6096dc82045e06af5b62975723b8d4a5654535a5dbc04cce5d2532ed92f024cf42e4f46d71c8fd7e2bb328d88389ab668cc8f6bf2d67de152fa0fbd952557f9f5a8d8f94377de37e81f63d81510fafd80b667a3d02f3c6be51cf0b28dea099d98556393cdd854c091f4d2a1910bb409a232ddce98043 +A = -5a6f6b1e0a0b0739fb25b2db93064b888ac2455c1a7876e3c952af4efe7e9133612af3677aac2eb79a2506b3b8c586787659ed664d0ace49bc44ff1987a036cc55b32f872f5fa6b966ba3138 +M = f6113e1c9e2f3de7c0603617d31147ee49a889da44a662b230bfb2c7dcb49f0a00f153b7f7091d9709c328200fdff4445f308a5830182c4d6164d4667c5b6ef5c18ba3db4d253e540227930981c2733893081dfa7d1629349ce5199e7eb4e3b3c8670172f12b475507a52553ee3f3cd6147cb55b8b0fa9afa6816350b3223780dd20e32cca23da8bb1819859dd3c2dcfb0f129fc9050a9032ba56891abbd5de3233609642f705ae5b49d2c300b73f3b41efcab0823 + +ModInv = 3c77e143970caafd0e2cbb50077b974e7ae01a250ed44873759a8320585f40085454c1949c3dc4c847c499d4d599fcbcd774be4d7506f55ad5066e7b83cf3fbbb3d1bc4b924cbe6545169ea22b9950a365d0d0f94c81731485424443327aba02d5433bdd662d8a5ad521a863eefb0005d4345e559badf7731d2c370757aec073d09def85598408a0d99748c28fb64b49df980e3633ece79793432b5f231bafccc3943ea34bcf75dddce14b62fc18c2a3c8dd7e15 +A = -d6c18805534d86142fe88c72aa1cb795cd978e0d5c701aca8c2eddcd731ae519ede632cd9b160361eba7f0baaf05e9917c1aa1ddfee05b8cb4d58b233448611ae29123afaa07ea19219e3a1e +M = a1a5708d8c9a21ed1428f5afcb2328c227f425cf55f94c789dab247a230cb4e587f7bea06dc7a6ffaca1ffebe3f6b1326ea6b7ef607154654046a89e8cec64ac62f1276574ebbc700b327efb65f83c2865bab0312bcfbf49d3c8dc5ce8bca78dc71cffeb42b0a66e72202d54bcffd27f289af398f5b0eab69c6ed3119fca71d269b4272f9a334f4ca3dcbdbba3ede71771f0f4ccf88be4b6666be0545cd73633e019c3891fe68c7862beb6f77eceb950a04a646f + +ModInv = c06bb115ada6ccfc01f13eb8f7a2daf8f7d9ea70741cf4279ddaf1e350cc2b51f6286ca40b49b6afc53b29491f1af4167d0df243fc9efc06f9cbd9f748966edf1c96ca62bda6e69be6dd5be30ad8343349c2c176d088ec75d83cfd98f5911f3454c8b2e6b7c1d2ed2e63de20cb627f490db81d4b130d5e31a26c5228ebf812983e81135c9b22b013ff516c43dde238d74e42259663a858b8f8d89ae90306854bf3b73107bfa093c0106324692c2a830100b9c2bf +A = 8f0df1c8dcb64e98f7f3af0daafda5c56e032107debf2c0a864f474c8cf3edd9a72b1576baf041693f3bc005fb36ca17f3a5c70739a375a1912cb644f00ab901264f306544905b4b9ca1410b4f +M = c7cd31cd526cce775cd71562bfae3a15185d4d24463c3c16055b901ddfe0f860ed964873f43993a3b77d99951ae7c62348dd8d2ad6c67230fe030db0da2abe385e26d8d5a6a1d511ec3e8725797b0301d8f41d73ed67f25d576f66e3975839d73af1f37dac727331f51aec2eda8705dd4ff189754d06c06a44014ab7affc3ad287ca9b151964307c7bde510878d6b38b12a05b6e24439fc2ebe7ec9c30385ad674b55a2977412f885c1bb0da7ab9710e595c4fbf + +ModInv = 110ea606e9d376ea88233de3f46a96927ade4387758c41117c5c5d0b30c76a729777e30c73af8a222b7d770462dc9f024f769d03fc9937673312d427437fa13d83454329aa804b6f824ed253859b743f7a36eb138d2ac542e1d6e87b72e2f74aaea204c75c6e7b96ce642722beebfbc3f505f7cfe49b1bbf3e78589acaeb42da408d3911ad7f32f2a29cc75f3ee9c810c05c070c7ed602488da5ea60a82cee256dbbccc66e4a15f56b8a8b3e93731b80001e847 +A = 38d83a222b01c6c981264cb2450d9a0317db49440d9c05b584aeb5870ad06523e6fae67c735d0840a131d4b0445080c2fa5c1da9fa490db5c4fd9e92a8f4e14e754ea224f568543d8871dfd963 +M = 242fd81e85874d9b2cecc9ecb10d8759e3b56d7f1d5235e10dd43c6f3ddb3ba79ebfc328c075388c70e5d0090b33c6722e62d08d5c418fa9eab89dc064bf1ca8163c240bd068f010b951187e45e5c38bc33c55226f39f6b7bdc4ceaf141789490741e6ee4155ad053da0345e548c6dc3c1fd2ec64ed13dc2f3a7a10f19fa0a150fc669bde0e9c27f486383c7bea7afe523e9f70f407b9022d5ef5624d6eaedc994bec21b82ce653547530da2f766b137cf03aeec + +ModInv = 1e095c1157246f2d9b5e051a58e967b4a9d68ac9b75289fda7eeec8700320c4633cd733bcd9ab60ccf4937b8ffebdf549bd47457d3e26251d8b5fdca03469ff3bb500d0604ab4a06b7f16c4d2539d2810b28d61d821dde772f89bec8fa7d14fe42a709353526edc365a524b81a7d0f1577405f065ad46e1213a7713198f1e1892d8527aab7b4887a0635d3741cecb2fba4cd4dfef01a2c18d0667e70c6e1adbd91aab1367172236cff42e75564cfe66bddc785 +A = 2267a439a53c11328a3932b1ef0e87c9b2d34916cb75d7131b61345b199b32e2831f2276acaff1ca7a19851e680d574bcaab2daa523089fa4d85d117267585b9cd7972acaa9ab04d48e506d4e1cf +M = 30d71e1b514a37dcdb45b181de7b074ab773fffc780c611f1b4ab97a404f3be985eb41c6f594158040078777aa06f0162baecff065643be63449502441f18331d2ee99167285fb136ea6a606f8a91f974405e8638d876bc1912a30095798c1b68919e2f86594e4556b1351cf3c87514fdd6f62b457436a9ee8803e9bf15e0d313aabf2cd1c2138e1af359e3d8d8ce5e03fd6b3b995167c9e752f039ab0bc2ba8473c51f26571a9a33a6ab5a9d3b97655d4cea2 + +ModInv = 114db2371a523dfa3328c12013204ace7a110dcaafd467bc943ecb3d276b1f016e1fa868754017c6f9f4989af7021bf069b2b9ad7e835833801b158de0387f8d8733ae140520bb2d9aad8d25cc375aa2f2f9203a11052b40e987ae76154403df7cba131426fccd7d3c0743cfea29527a2a06e6d496af0afe59e8f82f32359ff5a487a49a39229ccbcad26e3507c973859cd939d6637f71a62076f854973a7fe826276027072b940d1dfbe3efe43c3a892956fd +A = 4f572ba39637ed2e43d2fa9f07d153e42078bfdcc7982833d3170f9f608bed14cc4211460856b1d4229d2c5980c5b14e88a0508d1e621ff3a4d070efe4e02e8438fbe41c9681abf271da75b240c9 +M = 527044727119e55769c2f69e4c6a3cf0a7da7bcf7768133330e75ae23816682f786a4b5e384c3b7db15e8a7b03b55238ca471ecd369714a85a45ab23cdbd5cf3d05fe9ee38d3302463eb829df1c416ba217ceac44a73498136e68517e8cd59680eb01d738deca170e6effd7e1f5376b04cbc4d0d2dd511207c18cc5bd3bef966a6ce40396dd8cea0bed0ab48481d9ff95219ebfa6598efbc3afd22bb7a922bc945695327492f8ee9f3411b1ccb798842b7916a + +ModInv = 6de6d8fd91009601e7b05a494e22d513bd6f10c2d9c38e872d4a86324f1166a13df4328a6a150f7218008b30c8cedfa8b63d634d04555c0bf3450368ed5f9d4b9f4306a32416c9666a7534400686d4115223edc291f3fd412e6b11bd3efd434e593b712213577e18953da5a468811a7c0a880d186ff6d14741cc1a46525fe26e9df9bff0d991416bbff0d6aae374e82c48196301e78845027dfdaa6e2e4d6bebdf740497c2be0e05a0e9420606941dad9849 +A = 1f6b09fe8d79ad290a97dffda3a7d9193bb7a156f5da3ab7cc92141b5678b99e0dd1147ca15c3f5263914467dc680b4130ac2c1709d1cfee643b009b6f8f8d993d3f8d410383f468abc3feff7f74ad +M = b42dc2850b1cafc6502f0d3332d6c6d65a3c9a975ecb9f031ca5c97b0fac7b5b13a3f22d2428a9cf96ce48efc970119b12e69c33523a8988690906c72fda62b4738342e11ae616f0fff99309bd8c29d1f5729e9557667e0b93989a36c47decfb4bc9b9e5a8a8715c42849ce3d6ab7ed8925f8a7da06c29dcb8e79675616d3844df82d6dbbb47f543042bcd5093463b4e7a6fec9cac4811f501adae5780e3946aa1728c8d687fcc0bff8a59b603f2bb3df017 + +ModInv = 5a9480fdd730c2c48ce2f23f979bea8b0dfdca2d1248a0d4d69c8b7ed461482ebf3b1ec3ee1241f637ee3da516d990fe57365295e37077998a0a321b1ef05da7c1bff2c068cb3e9b9c7086d6bd5b9963344214a1f075eaaa25b1b67100986b0ff07a9e50df0dad1d8c8e8fb2854081a0d81588f41fb18a8215bdea1f3cd1eda46a4b4a99fc94cffdd8f728048b1437ba9089553e4f8ef9840e4ee6564e8398d886af3c6dd4be63e301979fa0df1a6f223595 +A = -7fdbd7b409ebb6017e0a34367f2832fea089abe5359314f6737fdf6339d24df7542ab4804373635331e32fc453ec88a22ec95f2250c6b0abdd50bf0528a3e03992e1021f2e1780c6354efc5d8f90f3 +M = d231e8b69e22029ccb3187062b0de332931f0904b1f8f66b8dfd8c1bdc7ee63e7692c58bcba4de15d6ed27f303933269de284892313a7fa69a2eb73abe57f5acd1f6c12b0658bdb1ff6b44d251445d367c45704c553c7b06c78d1f9d34ca11d5c29fa62fe390140824d8bb3f13eda7be1f1f8310bb91ae778093013af44ad18e5a541d7808c1fff821947496b32bbf8a64f9c0a3b262defddbf94f38a9e49a6f35e53dee0471d4063652effec45fce126098 + +ModInv = 41cd16a707afae6c5e32f0a88eac7c4a2efb7f9e1e2ea9742dc67994e536a90e42d79a033c5358c56a59dbc0f1b2f1c265daa74d7b03cc2b155729dc05745a37c7dc6d3346d2889be97e97962a57ae233543f134cbacf4dd3a9f1e5aed96ee697a22ae4466bb24c4b51b7a0386cfa01033891d85961d3dae8cc63afe6870946283470625f5d509c1b16bae34c53aa1a0357d26f6b0b7668d1b7000a69c360226ac0161597b1306317e93b41414461d8b05 +A = -6a228c81a53ef71bed57b8069fd53c2afd8f1d4e75e2c8515cbe18fd477ca2eb36981fd2151102aa9ec89e6b4d4f53cd0097ecafdb7d1f10dd8a76f5091b9b8b88315225f2615df13b8116135dfebb53 +M = 43814ddddf830c1c72b399cd6c4f1e54be89bb8eec86fee5630a84fca305d4bed6604be1b06d8d63207daa2bf71a35623dc57099e403e424e9008137fb7d5d41b07dbb77498ef0b23d50387fb56ec2426753da37dc2da66999275305d747571c2ea7cefbfedb91040d29022460181920e50887d1d69cfe08633025d035db4e347b72dc92cbe3982de366ea396bf92fc9c4ffe850eb6c0d16ba100305a602055c2b3c8312462ba470a72cabcf3d9d134db2 + +ModInv = 3f66a344b42b3fa832802c00462579d837b53a68a4211886d9a518007021326784a6b8ac98f20a22f1597688b95c7c97268d5903e6fe024030dabd97435e9c527b98a99074a565078e7799bccfa96cd37b3511bade000e4d26a3d350048078fe75b87d50d2d48f9c7a16bf66faccf302ed12bc896b30ab0c637efe0f745546c71501df18759b95660a1058b14317f51c69dd203e117ddd6206b3622d59e6eb5bd2c7295e9ced1cb921d7f24c1da1a820f5 +A = 815bc9e3be0fa363c2e38390ffcdde07d6450e552d0fe1b3c8e9dd4bc8a6796330d476eb5d51c104024780b51412ecb10345b73a5840fe470dcf0b3bd6759ed2eb7cc146fd815a7e5ed914470b6227cf +M = ce0557e7c6b68ec899b4211ce627d8c0e61aba4d385af0b1e0a3ef1d1ecb02de74327c54fc66500a9ddea2b678fef2aef9fb99a027c2b33c2ad3697cfca73b2bb03fc6fd11ec83f7a2f1bab57c2c959f33b1511bd8653c1cbc2e7e5083afb602e8a0f4e6a71b371c6602380ac6aa4fc48d0caa7a530bbea01373c73a7898e30b990d5517d07283fd88debe33881acff96440fefd86c0085ddc1522d025d96232d7d200f44783966d986b45dbb670aac5ba + +ModInv = 20a314cb72396388c50719ec775b523ed3f08aaf3d81027325718e3d93da3ab7f1d501268db142f11c078c6a1b81e9a0991eeac594244fe64369f2ee7365439fe3583e534f275f8cac244b2f38694c982c684a619a461c045ae9dc32a8ace2dbcd871a0c49c0dc4be2bb0065ec7941fc405168fc9286be69e233f0450313245dab337b3485b2071b948c46862410c1826167f58e55aa3e09a43c227fcd4486e2b0d6b334e7bcdec795278c6c291aaef18 +A = 876a48d95af7e5c061621eda25d4cd6bd8e2b70b20c63875c74c22bec54b57db8b4b6b7e3846df7b83b23ff38760dc56d23bfe537096bd8897d9b13303ae9da9bca0b5eea6387b743830e31c20b33a0a +M = 58ad658d5672c96d4c4d1947e5e258e8e77b2056f8a0670d87eb7cdc97c206e6ae2ecdcbf0c45efd3364a87dc8202119bcf44993af39fa8975887ab7ebcc5e4c9dd800f316bc8412b4a8717ace29caec70b5f14a17108afd2716c5726f1829e3c0e960dc730eeb72b8f5fddc0d1488be1b1543cf97ac3f3003a241c6320eac18fb803dad658cb40e60f11429feac05cc63ef8464715e683434976d750d1fc448f9da0667a6377a58e23ba0b9a89ceb34f + +ModInv = 1002e6502442388be2780329ca9a2825a3ff94987ceb18a6b010a8ced13d6d1aaa883b8cac6c28d5923428d07a727313995678da6bb2018da952c8b50904ec0c7a466904af0350014eb95abd6e5ec2f546afcb301ed51c5a0e5699f41b0fc91529b404667a687d730f1606db6c8f76dd57330885285bef6ec3aed6c1733bcd93c1fcacb375ae99d88658452dfaff9c0a365309912e118879d4e2204cb3797f86f45344f5a6b5178ab6c3382922cb4b5c +A = -2066821075466e5ea062a67257b703760a63ee67897f694ad94674857bf5f5b694fef40d1a30e1bb9ea9b68986d43336c03020d4d3c282b6f95d7d68b00ec8bda62d9a057c74a205d2aa00973404a3de5a +M = 3d0b5eb25908fdffdc610fe8a5fdca14e4b2e5d1e8d7c4a8684c81237923a4d0272305a8b9b312c02ba748b0e7e6466dfec0d140b6c57ac3ecea7865b85839c024dd27b91b15d93a015de8d1901b9ea587584497d982b4216cb3e7d3c9e8372b1907acf079aeb7ea9bcf5ea2134d822d1c410c923a07e43c764dc82305525aed2c78b88d5941a4aa86f28c7ca27769e9ba451c55189578b93088431e5a39de21669baf95d60be8994d96aea69d33f9f3 + +ModInv = a074078d064cbaa90578a423e0b80c3282d6eadc076fdc9ae0afa41eeb7b4542c17b6504a08d7d14c88fdbc0e50e403041f7881909e01d2e3f2c01394114fadbbc69aa611a0da2e3910e6ab1506b92bbe905d6f66c71c5fa44a06e2555417d8dafc2f434050be3209230e2467048d12d440bf313e97ff6efd6b14e21442304c72795b03ded1404efe4f3323a684c9c8879b583a35846cc2e09daaec621f86b31b5b88e2f7caf88afa4881ece160590b2 +A = 6db9d496e06768e23461972478092ba437caa0fd80cf6c33be65e98aeab04d404798e0494e87d868aa5f9baa30c3560967d20f997cc6cf42316dd20119124ddbf9956993bb033cba55f2183b7861db2aee +M = fe66caba14ac136402ed63c6567027ef035094d91dee0b10c2668c34ad1fafce788ee4e389b18a4df426260eab3907503241a2564ff8a36ee2fcdf00b1b1a26c6108dcc79eb13a080acd328503db7a8b32330e5b92ff4624a57149ecd31395a60526125631ca4d910cb03b1264d4ca205eb39fc4f1b445a2315ab11a8f3d940cfa082034ad99619388ef2a8c7cabc7a46fb01185e3031d65cc5494f02d5e355baf1c5567918bd3376ebc988ef6d84531 + +ModInv = 4a6a212982c45ccdd02a17356a500a061590bcab88cbd75c6bb70835d0b2369ea44c9d729513d9cb5831013984391aa0b1f7b866659f2cba2ece1abec010a54a15a2006964b73546432e919c45d3bbebdf151913388270430e04971bd3e1b404c6fc1f337207653d470bc78d092b6f90263f38fe9c43b473279a0945cbc12a47f8b1a3b2573e79becbfba1bc8202e3c3c1057453ac25e27606a7896b5cf80c65a956c3ab7a47d9eeca4434676ec894b3 +A = 69229957ae5cfa54039037e5e988ab1fb24a27b3926bcddccd553a07bb1686a459b953adf7c63eb0f3e5681ede78d6862d97e0e52ce19fb27981447cc26b0a833cdd8621544087bf51f766c980a913eecb +M = 61e7fe17a774ddce35f3f2b8b304171c296f72b9a440d5402d2ee3b7e61c3ab30289c3966d951a17783b57e373fb1c16248ddf83e67007041d064ae3f9b0621f740b656447768f34d0bff5c80ed06304dfc273fadaf2ee22277d54f084d8ab929d5b69536816eb1b1003c093cd8ae34c73822759761cb184305112a1173f9eedf1705c6db6be038de837101519fb58cd6ca8f982a3ae543f88f3aed90a77c9e168637bb38130ef44e088eea9ec8a7da8 + +ModInv = 7415ad84bbc3bf66f3f3ea15897194459de800cebb282fa1d4f09397656c8fe4e0cfcefb4a86eb70c53eb6972a98ac4a4d3e157ced162ad1155c6d8a54739e99a6134883293583748e3eabb3b70f25c73442bf887fce696f0fa61c6673c880df93c6ff1cddd554fe766669387fbde18db845971d80e336eabf908a8560a2a3c87534222e1b93cde320b31ff6fa555ee88b95a4a1b7db7fbb45764075088bc9c4f0970088f6b0332e9b0d74cc36913f +A = 97cac2af54df7ec4da5b9256ada1cfd068367d5e4de857ae97a2ebb34004b558b787e05739e86996f5a51cce71fa3b1f40c1de6990eec52f22a6fb92ad3f8c2f38155133c68b920d61c42db5ae42a45a62c7 +M = 912b0afbd9841e9a2a250732e87cdac294bad8441946fb5a5610a82a786f811bb6ed12d767edab4d55499c1d239e0d40b2c199a341e59b4044d0770776acb5f033b150a706e3a6613af6436114ac52048297cd44c05447e9be9bf25479ae6e8615b88521d4eef0fc88ba9ccb570791058374aae70d812b5fd20df06a5a98269048527b5881930a04bff29520db8baceb4317a21a93314bd3d58b9558451995133587bbfa4cf5d5fe5214fd1abbd94e + +ModInv = 14f7fa0612976945be4a3d20fd7023aeb5eaaecd55dfcb3effec6da4b94b270f98368816fbf105be6f0df41d9ac6d66326a1cb7f9bb9ec960b1642ba7d7b2c8a74678f35d628f1951fe7cbcfcd7b8b39c3ae99750c8faf68549e567ca0aafa61db196133f667f5b2a0cb9846487aae337ba62b31e320063c6d30efe27dd0ee22c235efed39913a289de821ecd2943fbc23d2816565c4cf6a526587fde612b9235a0a34af82480c3513ed8d0887034d +A = -3bcecf5c107d6a4bf933e1ebe1644aebbac0c358ddf757139c8a0853861a4802f89cfc76e892da528109ace0e79116a45206f57bbdfd99cbd2bb9e6a2523738093af5b4d71c739cf2503fc0eb4f65bd6eed7 +M = 179da085f30404a85bf5d8dae37b86f64fee7fdaaf37289c08f29f326d422ee74b8faabf9de4234e48bf94cdb9f082ffe59fece59084e4c99a5680c5087e6830721d9b59588589c751950c00abaf5f23500a814056b7fe943a95c1c42acdb250955e1bda133b95b81d64c5d596d30391e410f79a59b66b4df3eb384648b7635d88018a0dd98072d3c6e55ab512e2cc987999316fd2bfcdedff5a8ecba35aaedc521498efcb18954cfb620fe8b45857 + +ModInv = 52530c56b801baadafbcb135fbcffcfef3eb4770f2952f5173b89fe367f33387c906a0c47517111631273aa5e1788359659f2de7d979e0fe59782b4b725859f5be701ee7fd2fc152f045269db21011fca6ef9c2a6cfd406700d482f010aad21cb78b9867cff6f94ac64c0d861690434f123cc1d5afa56943a3eaed296e02e951ae6a60149ab2e549b5ec2d51683bc1d27fc82476dfac38bb4cd19d825799d1afc844a1995bbcd0e4ab0cb2ab7ab1d +A = -f2fd783aadbbd46ecf132b153799cd9fd5848e52ad51dc0780784347b5402004e85435cc780b7f03e60dfcfe15b0ad7dbfa9708738ae72eae58e67d730c9e15d43fd2b23a752af02822eaa0cc3ec505c06bb +M = 17e825380b4c8e0f952d5053fc2fd1e5bfff4b87bc4999f65e7a2fb5225f36e283f3eb6659db21735be7db7087439ef8aa1df481b871c53306e9739476787a77bd22d5764decb0287c351f072a657d251b8330ebd8277329f587f164e6301abc9b5e9ece05d8c51120f74747e02a9724837d4e3549baa3f6d6e56b9743ed173c7d4e0206c806b9582d9cc2055360348fc5c446c4755ff995c0ae3edb5fcff4fa392acc3d4f0c161623a6915e4ea512 + +ModInv = 19e0d56928ee3a4b343962f52d5075eead989adc68d680e55902b5005416b3f994c08a871982c107e27c7c27b8a16d919baddc0d219ff8fc2b0e0fb0bfc4576c51bd61c8b69872b46f85b17e94c0b1b90f6bb5cfdf26942ca0e82b5ac437ff73998272637f1bc0a14024b3d1f7bb1fe5edfc250a04aac074fba32f48748bcbb15abd6132f4ce4aaa8074467bc2b7ab180f5240dea49df06ed07753e3d5a2259e93d9177fe0ad423bb67b8b59678b +A = ce08fc3478ec029a375f32aa84eedf8c5113299f1ef5c339a6daed1613b09a8c63ea889ad522c38364265e10633181785d800b8a3b90430c400bd21bde23259213cae772d60cb7af8e1757b5b83155aa6572a3 +M = 4bad0bc873dda6ec39d37692ba9c411eb7d9f9686bb0d991057360bb4c5654203c389845c20116952e5acb14e72dbf6c4653624785ac38d785196b7e2f02e0f14fc6e33ee44050b02b31a1c29b13fe83411102ec296f8a3c0aee0c844bab19f8dd5486b64f9ee5a510c44087054c261e428bf968c65ce359e8a6bf07ebc1a1a365128cc4648eab85dcbb04d467c4914108451d58d25d24b081fecd1b6ae421a56cccfb00673816c13da0a128f8a0 + +ModInv = 33d4cad17e197bdaeb956478872bb03bab89750cea80cf8ef47df0c488d83140b6d4ac74e6d57dda837e62b583ee395eba3ba92e5bd75c05788176258e4800e2949c579137ac74f01de58f006f5760ab99d470d1dcd5a5b6a232c5789467a7f130fb752942a6acbc3c6fd837eff227c0c0f37e18ad1713b9fa35f9c7c6de8f0b3cb5dcf7ddf16c3cd8c3d3a5d1d0ca2595cc9e905455e2a1f36b1e5b06cb78b7eb993e51b8f0b6b91c4e33e4e2cd +A = ce2ae7d4b3f1ee4e71457ad2726607b047bec7cb20cd2baf95831d0e10302debc71157b929b36c35f1bb2009f79eb6f59da38488c4889a3280e4a40dcd0a950e7ae374089a351c9ff019f50c7c508985aa66f +M = 3560b3f7018f4811e659699446efcee4755854dd86fbc4ef892803419ab0f1426e6c098eb6532d1afffbc966e4654ad2da224dba9642265b96ee69d6ec585e64ae613f5e5cfeb3d80c444e24b4a50e8dd2f08d471bd369a0732bcfdd4814bc5e6471b3c97a9991925746e5f56bc0c5ca77f6d62cf1714855389192d24a99512eab4e736ff3a09035646d0b87d242b408bdf3c7fb194f0f2f11931e840c0d41136ea3015a1153c2d156660f463cb2 + +ModInv = 59934db97de16b53d1fb8c823034997eef1c349b89afe0489085d5df8e09b46903a60943f560c76cfcc1810e57794562c2ff1cdcfd5b10cb67840ebd7e01a916b634574bc0b5211089fc10e5b1fbd7afaa1d289455886dd9ad2606fb18de44073c2da178cf2b3323603ee37de27ac92e4a19c772f2a024d564319b3ab408122c3667193ed94b7577ac8752c787b63fb5580da27cbb51b0859d013486e4b2e2ad2476976ce22065ede082c0571ab +A = adc5760d5bae34d7ecbf1b962418a864c3d750f4562ec602b071183b4fc93b2a29f06b081f5227751ba94a679f665c0525f22af9b74a07af87952a6f332e6a84f4c7b7a4cae65c1023150848892c9c2722e92b +M = 72a2b0991d4d584f83e4035dfdeb77299b90c28ea9ac8ee3ee838cbe4bcc1332847c73d607f83512e5ce6f5f4e784c5a6e3ecdeed49e4a73bee1b07a024670312b189eb7d0c316129cb22d4fec2bdd1cd95d479a68cfefee3d45c3bccb4b8b5137c6cc4d1ae085352f48874cca9ed760aededebca196200e0e0aac27d1686f11eddbfd5eb73b503cee4c81b545ce6ce8d6f1962e4c61fe9165e7016a0b3cc578b2c736f218fa0482a7f14afa888c + +ModInv = d516eb8eef7d2ccfabfc6441614f11c79e0634f3f574cf37b939789dff2b5fcce335dc2fdcffaf8a61ecb1cab0645f77023d2749c0da0946ad93507dff459d01ff36b77fafe48a331725f0bd1b57f51a6e6b5ec5e92dedba05d71ab2956ae60767116241d3dd900f146c07261fcd0dbfd78eb38c4b797845ec2a270220ab5315da74d41eaf09a4114693c05f436162f5414d7315810273bb013c7f962e458164cba3aa3632bf645825a9070b40 +A = 5fec1c57cf7fd79c1bc25a610bc5e3fc671519b62074ad83c89a36ca6b8f2a7769724fcc22fbf364942df8a4bea08216a123ca9eef00c67a78377ef1ed4a5e8f83b4ab71ce9a14a0e8516c78b673a2fec9371849 +M = f3d6fce75f4054dd578041094fc86f0c0a22c5ab1869b8cd26dcfc1e33cc5f059dc8e2e2c30d7be95f4e757f0265c0d97b6be4fdc668857eb79b285632c2cdd56bf01f0c3a3bbb485997986b6338c64b3eb20ed889dc1f6ccd6d3fcb9e9f2a15dbd386f3c782a462eda01fb17767ccc124ebb98b992c715c83ac7374bb5afb0c0c155d53e44fcb9bf851fc5b17bdb6a193daa41087adc4e8b69e82de8f92194c481fe94bc2b4f6c48261757c1d + +ModInv = 287851341e09db15ef0d9d4dc01b36f13e736adac86029956e338e5c9c426b860a68677cff3e214650b724c01bbb4b86279ee89f28773bcf764d4c42004083049a304dfd0b1e3742eebc85be94559dc20c21c0fe7a12daf05584111fc1034127ee84b0fb3d5a2ed101cde5c93511fec673490f0d697b14987bfa340d24928c11b4aefca13b1d948d578ba619fc0d0df06e711fc26bb0c01c7a2a7d3aad66e391e27333a548ddc98ff39f3f5cc9 +A = e6e730e3294a6f0e4132e5aea6f41b90c6c2c8e9a7392cacf8f3cacda134705c6e70c753d2d290f314e05440e5cfcf8741be1c237e2ec12739fb5b7c5fa6215271e51306817fc5013a0fac359e39c5e685709625 +M = 2f20d073c5b664408f6b4a6b3119b1eb7c3a17b5f94957c512d178e1331fdee73aa1b7d8f0090092626abe76d73b992bef9c4a74a7d0789efb6ae6fe980ef0b0d2c11e096e086b20ddbf3351757268323a29e60b8b21c54512419906e6aa29d5072a46d04298fb5cdb243ea3a14d6643f67e6cba2ab9f6f3895c9bff2b7b31759b7b3b7a06c9318472b4cb667099c43bf2fd8c8ee89c9b390723a7cac6dbd8d2ddbfc6ff1218a1b4493412e294 + +ModInv = 622d0941bc880d7aff65216ce40b10226240116e7b1c19ff15e3fcc2012c604693b3311e2f1145e9bb2a4380306409b1aef518eac0f44b73b01fb99fe729a68096401c5d6ec0716e5350b9e0e3d9299c9443f88eb0968db4d1aa49300a8b1e52c6fc5b44c75a1585203b63304ce287f29c986e515019637a6850e06792f4551e7d4990ba365ca7d9773dc72f59ca868282ad1304ace926ab7536fea2c0fbe39979e6bec57f30abba3674a2624 +A = -a10d59bdfa355d2762afb68e245572fed09418850c9d7fb21f863d8855480e0ab65115f8c762c7fd8dbd8ff28c382cb9cfb5414003a41ee68029122048936f196f333b8a6084b9e8e7402fb4fb5a463f74c441d7 +M = d6ec61fe06bcb59adcd5fb373a0d03ef16028ae7a6874c8acb0581a3f6e6b6b94ba3bb881e2156f1de0b549f719ec80dcd36af50174fa7b49ff8083698f5ca3e6dd834bd64161b9f42ca7c1029845d348848f6adafb3d7f7a75e73f1126b896c148b4579409c4a8e6ba2ed3b08ebf1d78f45724f6f2b761b1a2711b1c2ae7a41cc4d69446d1970fc1a44a7831ff7ab31321d6a78d3044ab8a73fddcfc6fd232a51942ef357e44eb02b7795893d + +ModInv = 1802aa8c9f136a466199f12e3106bb0d2cc771c98543298a800257e2c54341d985e47464bf0f742c4170ad94a47eb3c9adbb4065bb8fa556289f2ea1aab2a23e1af150fc0e3e362575c61d55f22e02ecdbfffca9a2418a112e069be8831451f8de1a99183a1cd9d6cf6e8eaffa1970719f7fe7961e731915766640df4ac020e7d791bbbc4abb0bf22744437bd09ceddcc2f475fb491fac70aac75967808765874e589a27a9e28d3cbd1da659 +A = d52db474b10cae9473d0d29b6401463ae443e79e07e0691538dc1b5c5904ca8119eaaf5e6437d7b20a17df0e584178631e97e523d5f2d343958d20babacce2f9772c894d3ba7f31d0a36befa6f1b2a539e048e602d +M = 217f0bcded3c6ce825da610dfb1c5a6c7de71051d0bc9a22d28f1eaed27e5a50c23837dba354895631bf85fe8f0ed8b7ebe416b26671ecb0429f7d55f5e0ede50685905dffc59fdf8624d6807c581b952c2a10ea24d6583c56f5068b5b8b541d49de344700174a6ab33ecf839ebadc803d1aeb59c4724a96486f0b8453b3f59f6963a5cbfe847938e6f6d2e106a47348de73b497c06ae44caa1fab8950f0e3317e2cb247ce1668b9bdb6d26e + +ModInv = 3ef9b8beb98e41f65f19d3c6e662be0d83910765f85df4fbed3b5baa5dfacfec78084e8af5ddfc922a06964610df044500cd8f73b3780792b5bfa73c6ea1a68914f37e884cba2b0f2311adf356a003faa776571c13abdcf6b270b391fd4eb8ae223166a053095903743f28493b0921b6c89baae31ec20dd569b0941789f26b64c24e8cc7823b232a0d9bcbbb6c569fdeda36678237a0b26ee3750725870f040aaa86ea65a152056177280954 +A = -814f3a8d28b2d0016d8222815cb87b6a6923fa80909dad532cc879b5b02b17106f25880b8d39787d42b09c70616145d788588a39c85eff63b0c9966944078a17162f375bc261b15c6772685a195becbf9c879c3f50 +M = 7d6c2d2ccf9eb41cf763cf343e35a94da2fb7bf18e04fcf63b4f2c502d06d00e83a0d9c5459246ed186c04dce8878e79199a2c4b2037fd06ee74a6a3869f2e5f01bdd42612e56d3e301924acdd8d910532f9cbd4f744859ce4934486b97471028236a4120ac0656927309dd4035c326c697f98b00b2bf5314d6a71edb6ebb77891455d597dd2efa9f13f5251a3cc5f966a59490fc124297f21704239eeb95a941b59d8d7358ddf4c6fe4f3a7 + +ModInv = 1e8fb5f3a3f85b3531908548b714c294ecce2cf845e68e907ef4dc5ea7483a1b84cdaef0e5a4517d7161704e00059c3b049f62d42854d81b3f9e01f421cab9c6822dda6d5ee8fcd2cf27535488c07d3eee8a2d9e8f48abba02255283396461fd54e26436ea95b9e884f2a40c99f5d1454e4128d538a7e2feeb04d9c322fdcdafb367c92320e38e8c9b53f6b066a1a35aa54f85e94b50170464630d791169951026c993db55e9057590744741 +A = -bfe88584fd9950c32d6251052fdf8d3c9df9b20734c318b8e933c0403b11b7909edb8ad6ec5610dc744becf09e2dd0206adb968d82a2a24b22245883abe9f41566fb6749b3ff0c105414e21ae1156848c667e7db0f +M = a66998be10a6c517eaac617fe437d46af920633cad5c049652de94b330809e9924d2d4a06224bac3dec45ca65d52da1c122e110dbfebfd3d25da4ac83b6dfddfff4701adbc98115a5f6cf04b2777148d525aab5365791d76e95e11fe50c72d18839c717e397881f1573baaa6247b29e0ee1f123e9f06d89ffefbbcebb96f787367a26a3e9a2ef12fc82c0656415a6b7ed2fea79f4da8f30a3202c11c7e6b38992de3520861501c0e33dcf05e + +ModInv = 6aacbe884e8bfda0e73e095e74250aa15114a719f34493087ad4a5db6b59df49d77376f9e400e4fcdaca6320b04fb16a212ccfe1cac186cc3fc66a4d588366064bbeddc21be197b7b3a0bf52485e254bd419bf92af86179fe73c04d6f1b508ad2bf15eb65ebc58718fa30c5e75103bba7e8b100791f22b49300e397231dcac68e8f2f571b49300b66f8a923c6da933104fba611c54419d3bbee347ac106f322ca7892b8524c7436354962b +A = 71a7ca9d89fbcf18192a5088928cc1c964c687fa79c262fb7832b7c6c5f8591d079afc92e19b5a23eb998b652e66d75b67648335b3e6d426d2becc8e53f0cf978655220b2f6e968de480d9eaf6927d6f68fa9ccb62eb +M = 99a87e96321b98f741572796c380f1a6c131c86fa1e021541ce4041b5a2ebeda5102b8a42d52638cfe395bfde681bc169946c5ddc0d7eb22edb1b7f3007c1b47049f1c9ec21d4c77f7f02687f676cce64c17499ddef436e1b79485a7cf498debe5c9474096f8fab417951954143c8aa6a7236e3f4e82a544616f799134c90bb02cf985a39e6b5583748b1d93cd5ef8d2eadd68cbfc8a5d70d1612aa4af6979639d3c1dde7c151722667178 + +ModInv = 2f13fd0ee526fbd80a1ed8cffcdbf22044c7259277a247bfa579cacc2aa9902599329ee116fee499932c8fa126e313254032b2957e14e0953fa63c483d54dbdd60c9bee0a0df0f686f30cf231ef2e4dbe7c9a1a309dd69f16c2248473240fc343bed0556c30f5ece5d52391323f571ce111722f4891141ef9e6ec62cd997df69201857f96bb381d2336b84c8686e04d8bab46eec59e9763144be874b5c1a2d6b4ef1b40429f1ae768415e +A = -ec3d9db792a1eb2b808e6a69d4f532c483693b88069cf67783584a2d8c5a6a9baafe750b4b6394f068acda99a606ddd883cbc52fbc95f5947b86a95bc040654b86bb0d48343294ae7d64333524b03bd4f9fa8768d835 +M = 60e47531e76da7c79868691b23d4e3f47171db773993d43a8cd2947f20d15603059c072220e3e87b8f97772a03ad1548620d0fa14237982d9b5d99fd064286fce7a288fae12440704209e9793fb50436ee725ab78419510cdfbb40206b3b9f24eee36e54a6e55a6bd8a59e195167cf3abec7b03737a6b52de02d2d52fd04f14e1a7430a40fe7dc71c43529cf6fc49d162dcf940465769ce56c132d3df4e40c03b6e422ac90f8bf14b7445 + +ModInv = 6bbbf773404a839da04ae444cda8cbe5a03cd214bf0390f9e7b6d4cc2132be614ca72fcfdff7c962e950e123ccd946e51ef67edf03dadc453272f36d19362fc0bddc549675593f81e8cee75ef9f01d16e34e2d744ec50587067459ae389b00646d50dcb65926ed3c58993a9d63acefa2dbbe0f3674dbf13b6abb21c8ceb0cee323c2d97f9039f2848779122e63ac4e1eea91ee3c1fbd8ac8fedc53edbbca068a57a8c3063a6345439adc +A = 81f4347958b4f820df5c471fe38126744bea1e07e7f8d71260df4331f321fe41d2bddb26943502c794819bb19b38f782bcffad3fd9f43764e1a32ff839e64852aa02274491c4edbc9c6612eda61f33e60d4402ce67b621 +M = b4567707bc15a9b863f42b900074ff9015ba629fbf4fc1d9f97223bfeb7c5e39a17068fa8658e94b4517c73d608734ebcfc931a4da9e8499c75c0758cf0f36afa8d78c0cd555860f57aaab9a065bd48f2cda7caac505e056be7611b9bf6ee68b72fdb3e631a2dbcffc52cecebdabf82d64ee2a2e9b2fcbd05f864270544ece51ed33b438e772500379ba88be1df7592a8235be76dcce7500b0d17e3dccaaf1086fb44e5a266076f1188b + +ModInv = 36fc64e8f0107a448e94843474757fdb56aaf3466b5c6696eff542b4e0d0ef3cefb56952f2276f5aeaa0b6326dee185263880166487fc6eddb92473d9946961263557b0de0e57146a4b429f626e7c8aa1ca06b2e2271e473b5a612550d41de2ec9fecf9363fa815f51d073e573d40fe10827150b9afdbd9b29363ce226f4c6f10799d6ce4ed5165be71650464e781c1d8da72e8bb7917841478f10c9d9e757653d3d79dee6ea1b5d3e7b +A = 6bada12a10a8c5e1190a56173922cd34b89c82d983d4a8b19554fc55ba4ce48ca57b1b976f977fc9f6f0c9fdabfbe1cf7b9552f06c24c5f15928847a6aae5ce87d348b005f515d55343c68dd2ec8f028ea81139bc422af +M = d0cf75b9f582ec469ed6286af57d7b6a47e73c333c06e223659263c644ae15e9a5db8c7c57fd33ca06c860b9eead77de474f00fc0446901d9d37e8c01508624002e3a615fa24a4b8e3a0000d152d43e897f9482c78600d25b0c946c63339cf2737a2e343128edc10421170b8fa08ff8c8156f6e5db2965d7d48bcd4f331ad93fc9b18bdca6f3eb54b3a3107a192ec76462f9e0d3e2dd65ed43dd96b802121b140593fe5843367802933a + +ModInv = 4a867e076d6d922298319fa68dd8c4d9933cee93440c92847dabaf33dba63988420bdc06250c3aee9dbde35a39a30a68572c8a1f3d0f4605b371fcb5190e39e5b7bf6e097c00f699c4d8cc47f1f2ad6a207c4306e3354c68607ac5d5d63a7a1d2da93b1fdc389c3c6abfd5f587157c6fa5a1d2cab56a8ecac2aa63bcc01b7c0d2a21a5b83e5586068820ed43ae0058c3ce77dcdffe9f84927c13cc9e8e1cb65b6e2f48df3a73979d8e +A = 7782e733013eb5b88b56e2f18084ab7b5d4da187c998e44d11db5c2a2e6ec3e7abeaac29400e6806749573ff536c87ac15a47ea1afe05422fb81f86ed1a88619fb1df24ec5eb2ad2440ce88f0e4060fe8cf644ce23047005 +M = 531fd0b23ff2436a7ca82c70a5303b39dc60cb47c8ccd1652e89144dc6218476cd5a8e25751a2fa707a10acfd239e01ade8cb269f60b74f00c525717bc5445bce46016f441a301dd7871ee202cf009bd6aa0cfeb80a9025bc344587384bb43ec132bd1d1ba3f4d4627a8fa6b14e22b39dc1ad9ff8f692db2994d9519892f5e0c77b569e728657e073d03cc1510ffdd4da33018e344516859c24692eb4706401df3b88855153a83d9b7 + +ModInv = 1550849b9a47f8d36095b4bbc9d289d4f0c55898c55d28c04edcee2de26ebb1678500c220f15ba640ccd948580c4edd0fb24b2ea397b80e8575d26a99763625c293f7602946988292b4fe536cf1a57b7e0541f90e562d1f83e42f37739831a10934eccec48724ac67cc5e8bb22e83bb8403312b61b130bab7618e57498d3be58403121b18e5b9aed49621fe700dfdbe4a7318db0691556d10b0e475ddb8c61339a4dd53a6a3e4a6b +A = -e4d0839fea1abb18e1ad4a501c6879bd0103f8ab45d6d7e81fbacb9881c915cf94e805feccb81ca17b86472779f9cfc21638ca83df4cfb79df7aad1c1b6e8c710baa1a873a4ed2f3344b9458a702016a72426a5621c7ae467d +M = e2346bda280a5bee366d155d707af60bf2fe9f320d43407c049a85ec7f3c9c189f4535d12a0650288761ce6d8ad7cb8c9b46728e3d6cd9dcf4012e0c7fba3c70170521ee40a77d3d6efc04760030bcf1580104068b8a76d0657e42bc4218d0997c9c5a34d424c89085ad8a44f2d31eb98ba94ac8fa34d917672fe90bc62e7aecaf3cea7cfcda797de3f2a1348e03f1df2e738eb25213501f4f632ac1c08da94f74c895c716a1e8e8 + +ModInv = 25c876a3eb84ddf775045474924ab1ce4bcec043ad2bb03d71fd838207dfb359fae3da7432657054e8c562bfe26c3591167dc444789653690731c40321e5dea8dab782f7a0fa1e3033a4105986208f5b664e5a2632a9cf74f3dd3c3f3565e57bf0a643922e4165ae95447b914bd99f47d2adf5e55932e351d56b46d4805e06241c757ed682a6be6351dc590aa11dd35190c664385d27abb77fec61148a001d6fd7edea905e9b1a48 +A = 52de9a00415ef0c5b6f2361aab4519ba82092a421e6bcaa58b98d526f78cdc4139903fa6a01f7677c079e9828d8d2c206d91b9835f80830263bc491b38aad8110aa9c164a1438f07e0e127e49be267ebcee4dc68229fe6cde4 +M = 7972fe06bbfb2b693840d022878489401a1b16fc3f7bd5a41a044545ce970821ad070772de2e956c407abf83f5b67c70e15ca5e089e7391b46633730afcc1d7927414f3af6c116961ae93c71946ead8da1285b8e2dd0029d7360ff8493f041d0632984fd893ee0f0355d8b62b254dd63035e6d005f59ebdc6e047e19036bebd86324fee4e94cc0e141aea678192a12f00af1f2f9d07712c7e8fe72583c59d27126f68cb73aa68179 + +ModInv = 3d235a9adfc64449aec58159024c952973c5b16fb0a08c6a65de257d4dabda5cf967d8f6d0e2bf1071f4a4b2ff5b293b2974d0666091d796ffca22acfaf5ac505079ccf662b3071e0831a47926962dbbed6b95a8dd286acffbcf76589fb7c2f30f651a6b93e9188cef304f308cb4944b5c002559fd560e095812a78553833a422bf72ead43d1498190e7ddc040f558fbedaa36cac6243aaa6f6cf2f35b962e13cb55d413cc21b +A = -fdd3242e3440a5f5fd99f84a67352c8293ab3899d61a0edcd666dd65ea068e606ff413ce512bfd64e0a1bbc4b652e3a9b2a5fbec843dcc17a9c76b97be784df606441f4a03dd5205b868f3a5d32511e8f4191df9ecccc5ff043d +M = 254dfd83c8b5b634da0d30eb405fbfd6f8eeb889598deac42d07e122eeb39fed04b4997ba726e4b5f99b700caf59c78bfbb54bea7e3c8af4d1eb9f01297bcbb8e5c1d6f5b93b03310915161a32fa0da36270fee38e68216755e3f7182fcb19c107267152fe2b760723da7b1b211575b9d660bcc1fad643ea90c3a7b181c85f09081f002cb3888998f7a7ca36ea6a286a684ef6c6b39a13cf126c678ffc2118ac074f06d7e33fe4 + +ModInv = 5b4d2300d18af579713b31175ff921a88ddd768dc9f833dfb7329cec0ed73ba5a53af4e0c3480d95fc9ffee1a748ed83d550868741e4ca31d73538dcf55f75e7a8dd7932019b20f2481c1efa7ef486f9ae8329f854e3c9573bc2397b933d7c64fc98bb057522167f0511471900d78422820e47583b3e29a3c127163e7bcf93f88e0e03ce79ab8803712d0af0cce71f152cfa15e4461f49b3ed610732c157b120f3dc50380a6e +A = -4e52bf4d12c9484c6a597d6c620caa9db999c5c2e1120f730410d1da3560599b677b60d257b9520857b26478ef9140159b5cec76183d0e70fc8fcbc4aed82ddcbb82533166f232bf76dbb3033fc84a27ca602bf6197596bf54589c +M = c5f914b3ae980c11f39fbbb9c6834d9a38964f21c22e87bd8bbd697cc38d3f4479e7b55c6a42481ecfcfaf74959c61496b435168b96f27bb8f6592fdab338e7cd7d5c57bc3a43fb87c7372af334177a1ddeea01118902912aa0c2a4b0161037ab6f37007fea0dd28c24f40a62aa0ca888f6a8686150b75b1f470bc3f69837fd6db5b4bfa23acd3f6bbb45ddf44ac3f5ce1867032ab57ce2ffe6e4ff82806ffdd47a25bf46335 + +ModInv = aef3a194d42b14fc117c244367f3facda98110cc9909598df08ebbf5f79b3cd629116384a5b6166447b16d119e08b036cd218e8b89a044b23fac2b08e3c8b8bd879e317f72dc3ebf06ef53c50e60584ef8a2d9d1b6e1c3236d2c13da78cb3b2f28d395e653f18ef34fb988eeff402a121ba29770f615c4cc52fba2a5c433e2738adae2d1de8de4319cdb972906f356cf5399bb29e1eba2e19aa6a797e0b8857c4b99688cfdf +A = -f962307227588030c1d9adb5a856480029be204e03bece3db19bca5a8e2ab7eeed8d822471111376989cdc95000e4b6b5940d1a376b1cff66fabc37b98c28958443aebb74befffc2a797de2f22b60d69ef4534baae20312743a65f +M = 858944b2e72c1d9c7c3008fd9d63dd3818702f2aad88022fe2cde5b42892e6ff5b7afffefbe93cd95409aecc01bca4149b9a0c085b882086be899a2fccddee2c065618b72104dd6130274bf272da29e903812cecedfd0261634f5383d5f7a2053e2ce30561348e5606feed631f22c5b10013ea7a7e2763bd929e7267680309001c83765a5d58933415c08e2088dacb05fc72cfb6d45cb5d1b299c3016183b07392eb71f11399 + +ModInv = 54418ed5d2d882d98176bab7d2e676d5f26afe828ce0d0d5665e74c22d4f214168ec4554dedd61a09f744b81b273259c2b0992c85e0634324399fbcf69cbcabd6ef37be619e4be41053e81191d3660d0b8863c549b2fc486fbb6c9fca4e9669773711e37a888337eb9cfdc865a56dbb0edd95bb7eae3c4a5b32888039a3a7e33caa99866781d37f8410d27054e6391fda3bf88e89a7c04cd30610e03bac03822b0e85744a240 +A = 2aea29cd0643cee65c0cdb2d381d88418d13628b2ad3bdfe1964f3a41310079e207ad8b8155015bf0be18c391a897045f1ec8625d87784475295f96fceed7d885cf0f0e42a4b894dfc2e9b2ea9f31e26cf84a7b252415c9c430da4 +M = 837dcab3575bd8b4708ae0d598e7d705dc88f102fb1304c7cdd0947f7c1b55e941a03fd8d5308a97dedc0969b89bad739f573d532c4aa988a5961a31fd7b0e8a2f50e8c9831038c35c89f4b0fcfd9c3c4be23bf7e481f659a9baa145dbec6c88ef12c74fede89719f289fce45a5d66aaf6e9f8c6d3875621b7565d3027892cb9ebde07ade2a9c0e6bdfcd06974b4144fe1d51a16efbea197691d78c255b2c6b0cd774a76483d + +ModInv = e0a31f07dff22dc7697e73a8149107f2d45829af030147bfb00d03baf332cdd4da8a61cdad3105c2d521b304a0351bd7e8c254c9cb83eb09eaf9ade1868b8d1cf952c5d7c5d24dbd81cbd0ef3627f91b44e5ece55f17fcafa3bac665e52cf05d1211c80b0c3c4c707340024a4cbdb9b16d4ba61ea87ba4fa6138393a4207d02a5251668899bc5d56d4086261fa3bf4fe53a575d5a6c296129b0c94020bbd5d94b1dddacff +A = -123f42db596ba498e1cef237103a2fdd5b021c8f9dc81155277efa2eb3c64277543ba5fded8ffab3583629af00e8fb23b11af9821bbb16bca24d56528fe21db0f2a575f4b6038bf89f6f4241db16f20870c647ea0a6580d7eb2edaf2 +M = 27a380fba0e867dd3cf49d671c49e7bdacc2b3005907829a64f71f6f991893e3acbf2299b8da2c0afbad327e561068b6bf89143d32653b83c5122a54033cb9baddcbc22adfb4d26c12e717a2d8eb0cabcfab64bc91c0193e9a5cb4db267c053d18a4fc0f0cf083145063dfbe3156a581da0a2494f2f2e942827e7c0763c4f22e5975f2094ba97a2bb6664254e678f328977e2839b33da45cf3996661d38eca0720824ea1bb + +ModInv = 78d7740f7be82f6e3484507676e2aea43d9bc1c586f01bb8137e2d7baa90fe5a243d7607986f6b62eaf8a0d7c1125bb85494feee87ae4c6bd9a438bd0eeaf1c1ba56db4488626be34b7f7fe70ee5665542c09c8371866b11e38c27732e839504e773790206fe97ecedced72d81511df62d995e5713c8df18d934d0f65e70b0266b52b67e2efd2a3ee3acc2fcf2b50861ba7043f58ed3a7122ccbd3e195950f628b25300095 +A = 15fdf5df02f98abd9c33f11bacee7a0ea27a14fff6eb8e2f77d6c9a9b59dc10d3ea27a78ab819b9a499b8ef64847452b2925115628aa3b877c90dbeda2bb938f894208b39525636ef7cdf4f749f51ee89e1a21f41f4f31754da2de05 +M = 8b0430390294887d363a5db83a4caee904c083bc57304316e67c698668ebb525b4b1a3c6c143a4488fa31375d48c4e39642f3bf308a894ac0bbd563368655379a907036539e9d3b9ffaef4ecfa7942a543dab1502fda05a45513c2066ea41c1176f9674bd9a5402022b36fb3dc3c062e1b453134fbd4a5870d8f2a7d3ae973f99c7571764d6a8fd64a352cfd7e7f9fa2fa5fbc655eced16ee21c9ae0fd5ea7d91caba625e5 + +ModInv = 7d3e1251be6fe1aaab30546e851bb3620f4de1ae79dc5938cf334b88e7696ae5cd9d8ed6ccec6a44ad4bbf5a8610ffb605f3718e95591dba47801870e9511a512438240a80caa9067547901ceb032896cfb8dfd4b5daf455b3049fc7a0d7421b52290c1624b994639efd41a33cba374734a526fb6904b5ae889a6906c293c9c7fd0e5907f7a03c18a493ece7ae1ea9185014664d14489e0c49069be99ea395a97eb4f3ff +A = -71cb6047e9b2f00b2d0d403225b86ce99f563cc92dc6d11c494dc7d16afb8bab6924f19c9c4a12d4668128ad43bb96453211844683862e7b3fe3036d4e618dacdc19013f2e7f0245c9eabc8f0609cf1c44122c6d8511da973740c426f1 +M = b2f0a70137ca797a7de2e251efcef143088ce5062a37d5b94fb122cd010a06f8d63a1bb9e195d4463873a4b3eb450abbabc34fcc75497a28ee26874a5eb78e4b35707ffef2b9c75bcf5094e4ae5a7e736eb8f9387ec83d6a08466c0391adb1ccc29002b63a278b90a4b5199aaef62fc41dd0fce57e581355258516e8cc8b6bac07e9a8fafc40fdfc995183bd41e0afaf80496915159a53149954b823e07ef72d1bc571ca + +ModInv = ac84ff7949b5d2f6b331d92f54c09a644cc51997f9e02e6254bb21e25a62853b48b7d22f9e45529da7c5c56f65dcb983c9dfd854be107918805d9cf1b3b6b89a75a3580375cbd937ebcec899186ccf9da104d88f7be61839f7f74e15417ab0568f88a850a2ed31ffce25397edab6af58d46ad008b87d6b02a71842a339b25d4a24345017ef98081eddb08020077dbba9204b0e02e93ff66f46fa3e023d2c7f4a31e85f7 +A = 6f4725d6ad1106ab9eac16a3729190e2431890fd2eed79898bdd04249a7fe630b4d3bbfa5fe245f8339369da35c04a720e4476e704bbad64d9562ef263d9da64e630d82788eaf84f793039d27c01141a8230732287926bd02b00b61a47 +M = dea7eb920b2755a6b0fb0d7bb9882ccf595cd10aece5985fb9de2ecb3b80c820000dfc21d314a9403e187b88a48802c771c73982b2e74360baa5881d026ac46ba14cc94ed23552e560f37f4f2801351ca3614112dfa2c020f2f2180f794eb0cef59224d43d759a3b611977f53597a1e1db86f0af30bde6f9c6554d1bb93443ab23cf2c98399f709c914c57266dbd448f3701e5379657332a967803da3d7341e0ef2ea032 + +ModInv = 35dce39ec1be045383e3e131d6b9f0c0297eb5de99b7a9190e102dde964cf08ac38aba37c50e8456526ccbf27d50221c08b1415c8ba069ed134d199015475b4558f68c60639d361f8ace3c289bcda8df1ab528307dd486d35ec4b7d2282ce284e48ec0eb05f8303840a1ec2b98a981f99b7d5f8a6d19ff90d9cb660c492becf2ab38f5af8d3b3ac6391fb85072578aeb0664f9501a68868b56bfe5c3f1322af6d802e2f3 +A = fddf6fc3c54c469f6b0efb3dfcca312600482293f2d6d6470be56ed98239d6aa867d8c0ab11d628e19250050d5010fc19ee2446824839d561a32d8b10df64afce2389295128b4e1d5bc28a5d74134ac6517af629529ee2572da24bf01 +M = 381855c1e14a17a2a95763a65b8f37dae5041bf098821a29df0f0b548baac6bad63e97809b79ef1e3310ee765658af9572620a66baf4856776546912658789a9ec29f0a2ac55d79ab06141a33558cdc4b0fe390deeaa54319e5158f032d7da4ecdd1d0ebc9e627a4e78b29a931691814dbf5d2372d624495a8e30ee98cea40bafff7ef6a631def691eee67b54dc5d23c1b9e16a0f6985086d091397d6b0eb77c4c8aac11 + +ModInv = 5863460a87559742d11dd620c750e60fac6c1df442e6e551eb83688afa539fc730bb14eb647e6812ff7a6e7ee12244713e5bd91a384b30c6df884c69357764ba5fed5bad5b7bfb131a989d7779a8b43ad2704bfbb11ca01a39ee22b8f075ee5a7744d33c3e57ff3c2097a99964e885adefd7dedfbd1f254a208e28dc0056c56ce526304247543dad0027559c32cfe6fae7c699b4ed0970560d8567e01a0a19cdb9778 +A = -51198dd5216e1eb1c7bb51f181af23262226225f3232ea0ee4e446e3e7754af2dbd929002ce94b47799c43b9c5db53334eeb5189694f5bd4da7b009dc684d4c9a23d19c1a79c8527a21e56073577d1484999898f1edcc8993c2e4f188212 +M = 7f09dccfcf5eeb44158ef96b351ffa29f25b807ff310cbdccde28e3431af5395f0e9ab61be8bcd60d70159323861a67dcb03c0e95e39ab6d64af51dd33519740ae727784c6fb7f0aed57897efcd376defe40e2670c9da6eb86a1eeaa0ad2ab1c7940c824e92a522b6862ca1911717971cf9e457e933414319efe18f555c7085c18b16fdac19f1e80f119be66ea037d73fb0fbfc15a6adaa9f3f5b64d930e0eeabc4de5 + +ModInv = 474ecdf9bdea17d96a750493912d62e54cee2820d2c6339175d8fe174a6c9b765d2b5f8a2427fa91d3450680a58894c17a3804b323f4090c42048b396ae2fa6613409307a7b7090a45f0df8e47e239d45ca47568facf8cb9d2840b94693e2604bbd5016501750ff1425f7a0bf86ddd99c944e1db95eb78ec190acc77ec6d1b53da11f933fe4ffc848d072a8e270131011fd0a5f031acfd2482dd65baf6c9779a170cee +A = -9a98f81ffa397a39cc36ee7be13986e0a1689229bfc7a6b24d3aa1d4e1ace43c377c6cf97fe2e5052abd64bb7623654af5de8ac9cbd369bceb2d077582e628663940e7d2d6e4f5977b375df009628c5916ccaaed4550b1231fc5387801b9 +M = 69a9c5a27411165848305a496f75b772cb2592cc7fc3ff95e01888deaf43e7cdeee1582787be8cbfbc8d9ee113b8e6150c67e71ce3fa480a4929762a50cd539a0bb843d2ccc4c10695b35ac14a9455de08522d538d5d25ffec8b58aacdf8be24b8f73d21a27024356d49adb1e9b6757cf6ebec4f62c3f64a164305098cc0b485a2d8c594d0cc2dad99c520e2caee61204fc619c95b0b97b7da00b5ac947a9eb8109a81 + +ModInv = 11ad10354ff8f1b0d56e86e529ab146c462477bafed3fa292ef06651be920e278de659bd3c80ea1eeeacfc86820be942f8cb9bef11121ea8840ab5e35931e74be8b29748d4d28490e9c09d56091c465c5e30d67d6a97cff5bf1bcbf8c3d422246b0d566b2a77e5704131218e4ed96fa50693f366ab1e37e79ac5c04febaf48ec4a7a063528eca4c31b749fa049f5681f6148d757c5e5bf8e35da2d48f17c62803ca3d7 +A = -56c4a2315dd0c063fd442b16023ae8359cdf390babdcb1488b38e518fb88b164789bb42fa94832271b16a9f25ccaa74e532ede6a7bf680a5780fbc8692affe937395909591c2765a2915ca5db7f2659e7ca82851d4cf8004a2e06c7d9d11 +M = 41ba96d8749b8a755375c49093571ad50543fc25b9480546572552ce2323f44dd3467e9bc9a6bdf702796663f597c0dc7025a5c869361ad518061c9af3d8cec43b818d910649fca8d80e3d3de07246da7200ce55adb5d0a51d07ee874cfcc7f6effefa838ba7fc225448c80dd9d12bbc5043abd66f0047824a3431fdf7a4b199ada7537bf060199a87bc2ea94dd63fbc5008a675660d866c800dcf243357c35bb01218 + +ModInv = 23b627878d0215741c7ad8c8033901bbe8879b85e1e5bc47b538bc141d5f678cb79745b0830a4af79bbf2a7ea84bb4e4b73b7d229d6538fde1be8484a5d573904cc6d1970d4c554f33c8e58239de9125f34cefaaedb81f3dcd35d73302fc5089b2dff8582f11fe862c3fba39e5fbe605166d64186512bc5b77a8728bb1f7630b71dfb91b1e2a21aa1f15164f4e907bb3a5306ea5e12da1ccee9fc5694127a0d2a91b +A = -7919caba778643fc74ef4c7456d87dbe447ce655913a9714e9c128600819c54ea663eb264e3400e5eeebd24327f336bafb9c48b8d86e67a6f673f216a33b0e64c08f13567cd5cde901eb58fc2756e409d0767db84b49c3f8d78cb084354ebd +M = c26d425c35884ddb6ec11813d18e104858d136b763b748e927ad4f45b2d1ec15cdc66a7586b8d8459ba91c411e7ce566dd1922d3a07da0e62cb0734de602c6f836709354c874e4ce1b4d8e181c863564be0df72908c1838efa0d65007af6f71a0fbf7a0d46ec696a9d7c2e14de8c072b49e553506286db8845d8adec893da8a4336b4eff7be5c00040acdd1dfede2072884ea8d604966a098562046244932c74ab8e + +ModInv = 13e8ed1b2f5a3557ef9f4b1f7688c23d122eb0842c5bf3d12bea0532a201af315f53aa67dd825531f9b8393879147dc5bc7cc6e19d0fd43322bc7d76c65f7a5d3de95ffb06ca2efe2a272fbedcce55947bf5956c96bd2ea1eac5698af677e8616e22fd4e13f290d231ea520963647b78614cbaf005b6cc7af61065c1b22a69c47740b5485ade2923749dc260d6829be19b096c28ff57387854507d81242703d8300b +A = -55bebf932456ba807ca8db25e8f8d45e69cac747b8e0d684d4059e614766778c5f24d0d5fec4ecaa904f8abae34d2ab99cf1c898945030b60b0232879aa5df3c0a8a6a9a98182522c27cfdd7ebe84ea95c31a123958545d680535c3c7b573 +M = b439430c79876c79228523f6024e9e86abd19d150b7f24d2a0efae45e3f9e0e5f8005f6dd4f97d8f4bdb763ad8b7e9ca414ec3a8216b0aed99cb34016e86dee14040030f81826a92cf1e14d94c90d2641ae4b3a94c1a166938123a0f7a8fa96904dc747b2bf5c33add7a66f91176eaa199fa7166b86dc77ed4d8118f8482068b42dbeb1b06b04b80789f960e34772e6ce71e42f01bd70a62145fb833e5e0c8d16ebe + +ModInv = 1119c150aade15701aad902ea27dc7df03ba0a385c345af69250504bb5123f0ccbf4ec159480e7076f5c1645bce96584ac5e6e6a498bff3df5399b30c7ff25ffd695e1303a7bf11e59f2f63b75cee783e9c161a45068c81337302650497347a38190f6083e18a68006f00ac4c9b08962bd73bff34eb81e7005c174389b5b58ae27d0cc932733375cc0bca88cf8eb12d25636dda8319bfc9f19f16b651f5cf4d9c9bf +A = cb9fecac20f7ca6fce78bf1b6a121f77353122b1454a5236b4f1fe176f8ca78024ed09ba84d72e25660c543f5406fd069b661b1f14bfceab67ef0a1e28edb62d46b3e9e258b819a098429c23928e51e33711ba7f5685c8be4adae72deba7eb +M = 835808eaf7f3055114bc7cf586ef546a76f14abae682633b0ebe1e5e7fc201914f89e028494c88df2ea053fe5b78528aebbfd6f417d2e3ede41f7db9c89d43770f8ee2d50e841b2a1cf8eed83a9c4767c2c5054eecae3e3e4da158a2cd8f8bba6b0822b2b681ff9dbf48127024c26b9e9dab458fac287fe0a042a774ed6c58c717852148c708777ec7565e0cf75f2722ad4c1d045a3f69f468bf07543d20b36bdec7 + +ModInv = a8de9d4bd35915a9a11e4a0be693ba5ad2a1303efeb2ff4342e6871050c8ef8798c439fee7cbc3a4a7654f2e9ae99670959822ac5f33cef01d86856c3807234aed6db473183eef4ca953be65401d7fe2cb01248c9ecc626049233103325ab87ccb86f30b57b64ecc38e596db679ac8f0729cf6f26e10a6a38c39322523aa341fcb36564c7cac9987d6e952e7f8cdc23d701927318cfeea2abb60a090ff32042599 +A = 4de30170b4d749c4d841a66eef8dc74da879ff488ce31a9b19eba50b01a9edb0f6704dd835568ca55409835294cd7c941c53f7d7c0cd71e35147289bd97ed27694fdf22341f745ff9f155870388e13dcacf58acdc7e0abf39d625c99399c162d +M = b6ef48dc4f3bdcc0ef6d8d0a3430246b36aa5771b510e9ae7cd7311cf6d77242f346a54af3e3e2e0af03812f80f03f38e014ff855ce7d7ee01f1e0202c2588ae25a94328aa4c5fd017378ae23b58a9912cc3f69a2968df7d4196ac2d04e2a9b4e16325fd83a14c60b7282789238ffa327ceea0e4dd60a06491c93c737c35e9c1c511725b334c3901e631e28488930b2bc264c1d1a025cc0dea6457d186bf54ed94 + +ModInv = 91f021b2f149f69148b6de75fe5c777460183cf2b89ac1e9f65d3f648c1024cc4f3e26e3eb5590985f137840972a1e5f37c88c2a63b3d3bbc07939c21a7c44da94286f9871db6f8f6ba9c914ed6be16ba37acfaca665935eb9b79ad729d01b72ede64765967da6edec62a2264d568be682140ecf8450883abcdbd14a751392cb4b49f0aeec3047e8f9ecab1726d258a8f5904ad986c04a9c1a5effdd9fe83a7d43 +A = -364daf870fb78466d2403fcab14bc40628d82f271bb34d971f41b6dcbc0b016a3eb0f324d2ac9d48076d2b29314222a7a5793093372e98805528e5d31713edbac5fb8ca13fccd08963c2bbb42874dab8fb31036a5e328279a29432a3f60d59b5 +M = 963e92593cec12b9fa015ee812d49c3dc2be257f3e24daae9179a05ea48f0529b9f96fbdabbff1dbb6892f0f6d917f4671feb807da0e89c91b9de09df4e5b8df45acb730177382b4ae9d1aff136ab12bfe1b3d74e5c144a2dd96c4812377b1b799f23339e1ec6ab33d2114c0fb095fe9f46b9b61e181b417f2eb1c7a831d394a0cbf7ca8f74d0049645a1e808d594f49c3016cb3495186cf83880aede9b6945fb0 + +ModInv = 907c9199e777a001d7683d7fb205cdcf1541312d756403e2cae58ca621dc3fb203fb8b60623bfb547c7266312eb5a1258d4bbd650bb443c472f07ac09fb3407c01939d0f00908ca95c5f9f8a04905d25fc60ffc496230576b1443aafd6c262b0c64202a182b3b1870be8457e4746e332d8eb238ee77a9c7820df68076697f0c3123ae3faf16fb70145539d29d194192a9f7b4b059df24fe1710b3aed316699ef +A = a0d2519469b2cce00346b7d3adac716d73351408e61e39a6cb485fa9900bf97b5e30ed15b4bdcce27300a497cf8fd5955fbee04579a2287e0825024d8cef3d12467f9a1edef568f10d39a2b21ce57f9fec4a6f2b2e74e251ae4337fffa16645061 +M = ca2a246a502235fe9ca29de057bcdf4e49c48d3bf8a434569e83231abf0344d621d0efa93e3157646b3855fd46107f6ecc5182ba2ad13f19a0651732d741d1bf58b9ff2834a73a1fff8875522cdc41530288c7fa140213a89676aa3eaab960bbacf46861caf2de2513f5fcced5f90d37e4b80ec42e17e129828f5d8e32a071e1807f864bb0f2c4b9eae28f704c22970885ae2b889724d8455c88de8a086eee8e + +ModInv = 872213aba7b34ac9be985a8eb7b87dc9edd9a48c09f5cfc4fb20b2069d43300167a7ebfd99915590e334adeae5143b86fef773e2d3d64e3a26c8cada83e07472af040f323b98bc4b3a0bd97edf68deda6d3f10dc484a6608dcc26a9f650cc8590282b2b567ca6c47168c7b2acab512c0487c129fc1b59c8a07db569cbda5343b1dee6dc650879bfe8b229a36a5aa93a0ce9d8c42f4320bb27652d66b75f0a2c1 +A = f3fd6897f9ab99a9e929ce8c406d89547ea65a2fc6e8c3f55d76ccf7a9015a0b2341405af10a7b722b2b55927298688a083bc952a8a8986d6d22472a1003847ed59bab85589dd88dde12a76b71a194c4aa1e946c69c3e94422a03227e02ef0f01 +M = e75a59a357a31c2586053f790a663b01378b2b8676628753cbb8b91ea81c2a7886346f1be98dd76f91a951b57701493b746d4d4f3d8ce00c2540626418b2c436d7743807b27b42ab55b776175e03ee654fb5b4c0d60a7882e1ca5191e2ba45d46df94f65449da4c5809c1ed775b9fb3d40ded394fd20b1181290e470401d075c9186f7bd7e2fd40278479def2d1bc443968fc087e92fce419b0646abafafcbb8 + +ModInv = c8d9ec8cbf44344d8b909e419bb15a3e47faca96c0409ffbcfd158f9e204b57c307a6e7774f9d087a5fa5648bb25611c0d0e6a964001b936b3a255ced484c4774dbf9876f0e3754089def5b9953c159d76d0e5d71af56b1aa504f2a75349e9b21b9977e67a38a84a417600e0b47629e5e05959c135bcbec9a4f8ddca034875a547083ab25a470b31dbeee8fff3b3313d7eb66ba473e8e4f8f0f852e00c14a115 +A = 37dcecac94e4e45447b8c74aceb077661fb044d366a799ca20cff15afbdda7c4de86aa6eaf96c17d890bde48a454151ee9d2aae99208f69705bd3fec052001c4f7c605c62ae277e790d78fb05e73c3d7c6c6d52d65e836ee5f2d4e0b626194f80d +M = f9c8477292d65a463021643146c946c6e8c9bc76eb61319a84e272cfbabea49031e4c6f6c986548a7868e3407642b272931fc5492ecf75dcf9bf692a7f051a7d081273a9e75f5e6bc51d587bc0e5b77206044e4a8ba8da06dadb5b5dc37f8bbfa61c6c722472b880cae8fee1e7b63cdbeeb6a298d340f925bef215f4415ed9d999ef665360d2e6e25a6164bb90124c57bcf7a141bef2ac346a8b17c36764252c + +ModInv = 242bd131eb778ec958a3ef9442dc39eee824d944c162a9ac74e8b5e8314b2b76b2751ec4ec8660376ac1d17bd9f8190199cec19008f171edf967cc58809b1de610857937ae02c24b024d0fe334aa59331abbfdcec1db174245fc49fe3b0cf0da9e06299c77027e8278fef4b624aad0fca8af096eeed3be4649c3b4d39d332d8180c58a43178b2b1435b37ebd4cbff17fea693fafec3807b16aa44c443eda96 +A = 9210a777de5a6d09e783bd2acbd970fa3d704152ade8437d3bd9771fbb68f1c41f1cfaa5e0caf83be166cd7d471bfca641d778d1e579e0f6c8b908545c30010a543792276b31d06af566ffda8c7b1c65a08ba3b2fcd9aa1b9b1cad68dbc73539bc9 +M = 6ddd9fb8b674fd2af547f8b03072da91f9a17c08af5497b9708a91713b10221ff237c86eb0f3591757d9383007e1bf288ad50b1b5f49ee2f1cc33dcd704e6bf4675ab0687b8683f6257f94f34bf45086157c922b587e025c53111912e97b09a97ed788bfe7442e7d06e471efdf475f0c942bf62703d396c6fe628c46c9ad55ad8c5ba3e6b85ec829042cd1170619ace37914f92badd50d64b8390ffe80b977 + +ModInv = 2fb8c72834955ce7e09d3a99e294f724364ccb7b66c22db158ce63157b1e1d99b6487151d1d5d51dffb10ec4759ae0ac5446a0479b52d8c65a572de51aae65d2b5dce6580bc2cb7e9a022348d9cb299a30618a24cf05d3e9eef6be6216a0215cc0a1e21799f7298de42e8bc48867a737ac6180bc1c2569fd1a34218dd8809e43e4a86ddcf2a46b242c4cc776c4b6d6552371779f417c101f5e760acb4c01f +A = ede11eefb5c0fe3f7f14e06fc89649f9b43a99fb6ec663bc45c18c1a87369f4b56d2ab00ca3ee9896e777218d06eec35bea10a3bf4d9c097ce1389a5b1d8560d8297d4d495104513e9a493548b905e5c7474fdec65fe721297377222d7283ab5a383 +M = 138b7d86a09d76939d412c25d6e1559c10c03b591e8c2308bb2028cd8d4c489635f0716a3dfe43d27ba20ecfae3e63d07da4792027d9dd804b29624fefc8ef35ae2cd6def04b77aa8323f6a17739631b6ebfdd447364c8959f352e4983b1175698042793a9ba74a4ae0b71d637d8f2005075e8e99662adeefe4237fe0733f5bd72f56ddb589bdd1a845f0d554949efe35fed0d13f6a1e7b1243c1b1d3f578c + +ModInv = 5db0c1924ec59af42d030f0b72637c6a427bae32963602b1b0104fb2f81d861167b323576bdfcff39f33bc4e96d5d4b6cc9098b05b00d5da32e412f24fb2d3befe4f8a453cbe6bcf1f1e45cb0b8c3598f1cc3316e27bb4b31998d1f0095082c71c2eb10cc25e3ecaad022a83503077d9dc60831ffe928b7f7043cbfaba19b25bf819672d75498e9641227dc89dde56bef1d33e5ea4c7cd4c7b35ebab2723 +A = -974cb0f01695ad172171413f8c5eca0664032ddbf46e69217fb7fa543119cd6caa20a15e6e1d2c799d841e7b8b4bfa55fa9ee34a6238a7f90ee941a79e0cbe4e52817def50f1663fba72814e767853097c9ffa9b889007ff42f1bff5e113d36ecca3fd +M = 7d227b40ad06e575727fb008598e3035afac034348ec21ac44d9547867ceee8a8abdac712d7381d4b89f16b223d0f386ff1049080b9e7a92be3ed8bf9594a818f62521602bf850253c9f71757b956a8b5a48bbcd5cac8d6d963460198382c4f550bd9e88471fa81493b8f2aa505bda6e7ed6ab731e9f2b0e2607d85aeae0f7d9c516611185e7d7bb748cfc9a9500b5cfe43f669004eacb78da4a56c09f48 + +ModInv = 70a7eb6e6b46e3c30287c628e526e44a1ccca69b175658eb18ba89154c1c4ab36ae59ec448781d2f1fe710b74d54c4aa5e96b9c57c966a965b4f54b5daeb83029a6db6a54f4bdaa922a43818fc60ee60fdf950f6ccd10631d06368fba9490711069d640605197648e9ac1379acf21defa4d7d0522355d857fe5d5383ac652bbf7c29d46ce5dca34f84308c713e5adbd1773785fba0459cc815c1eecb90a +A = -a421f6c5ee1d4f40f52fb66696d2974684649fd8d1044920bcfa1e62ddea5a995abe3b94da3a2ad716d157b41b52ccd5aa33c824133299074885d9f68eceb3f859a954b2e5fcbbeeaf52ccf09ec15a642f9cb22f34c2a4e70589b118235ed583eae83e +M = 5a5995feb27808259df473fc9eea8858ef103ce03f828e6304b87975aa54910831a6e96bddcb26a14d50687fdae7669d85357e2a5c7ae8928ca97d189f47e83376b478a953bfec4834daf33dcb04c81c098e8f589d1f809c29e2f09809806f014478f061b278ff716cdc414e8c2c64bfcb43d7f33a6fa62a82ff6646697f1f6cdbe60e54ee202a80152611c13efe411199abbab6df4cb20b9e71ebea4e91 + +ModInv = 2d93eb07596996a831cf9a3a9565054b1968d9399db5ca809299208523ccafc60a074e97deefd126a39e1b8532c5957b17a094e10e9099e0e9a054cc531022bb160b1cd96304fdfe4ff717453e77dcfa5f6452d3d111881ec80e8caee4201ac18388dc6bebf9911bcbaa61248282c70c06332915b6cba9fc497c0f648a5296accf0dc95a7bd43be0cc292bfa0977b0d66c2633ad5a3f7fc9d00b099392 +A = 90edb54f33b33287575261cc9109532514a20d0511ebca25217783d282090c70e3a6dd7e6fd7094be5be6384cbc2e894f21758b3f7569f70e73172ad1b943720b483492e82694a546cedabe6f5bdc0fac0cd8becc7cf5766850b86c6fcae3ca8924ce480 +M = 3635b20dc2e804a1f19d1960b575195b20345885220009c7762f3800b681f57a51faa370947552aff68d548275493f7a61580a72ea9226c3fcf5f348eac5a25b934875b2d8b1248439521152725e9044a9746724ddbe2be6a04a47eee01b802e4f804a8f67e4c35ad27b913042384b0ab780e1d43ce2f9a13bba89e99d0ecca9db551dcc177be3366e518b9d493437fb3ccc021ab218f656b7d69913bd + +ModInv = 25d712e8796c0534f5ef5b5a751f5d0531cd5e3f5710fec92360d538e85763be13cd4a3198601cb5c834046ed50ca39320f78e76cd4aa00900bd89cdf1c5b624d4fe95d78ab7632dcb1a7c8f18fce204f7ffcdb93cb4bcadd75bf5950bd9fa5001360bf34168611b0fe76a0d98aca3e225b37cf1552c5e024e8125698c769d48a844c83583ee824144d6fe63ae765dc59c77c1542faef3770b9e68a3 +A = -6e5839c5648d43f0bfd48b156124d3f89b89d3bf9c0e82b81cf0df2355f640b013368839549d1a67eb3676119e7e0b00f40843e70db4579d3950561d9beab2b6bd82c2a8c6c6c51e4a73fbec8d7905308e0c24983c976c0daef32a50bf7f14bf9aabde6bf1 +M = a90a7592af1d9624c6557d439a3557916e52b79a44c10c9b98179a7a3fd3ff068551bd97a484ca638bec15caeb78732111aa91e326e6b8ce9bf30d6025b9ce683a5097eae2ee209db7a550082d44b48f836477fab055c59a00ac8af2b645a67619248f6be4837a35bca070f738732cd99053016774a085aa2aef4a032bf14e940b79be7358c3a9ebf985f7b351b9b3cb4d1decc258d3acde2c8d7f52 + +ModInv = d17f5234e7c20786c8d933cbe33bb1f246d6ab92a7bb52e45ddb6484b7c3091a996d7f14dea398317560f4c16e61b6d9b433820a4ce6e1ee065791d14e72456eb89795f41e188b7abc84275e75001daec6a188e54339d1d0297bd53debad1da6d1a296c2f8c531435ac5105e4713dd0a5c1911f43c1707c834f36d44ac08b6bd43e453f4a26f10438b7df88857073e8b81384019bd29b4957ca5ac89 +A = -b24c92658fb025e384a2d7e7a827eaad417ae27427ee566e35dc883526cf6a58bb3584ef7986dc099d54ec566ae0d31ac622104b23142cc0e5ce24c2b59f12cee57f15d67e1817a34e7e619dccc5c72240cd032d491d2250de5af52c0c349dc9be1aea17dc +M = d8ff08346a93bb77fef77bd709348bc1cc299ba226098153ae088a5cd31ae854445d4615f19c6ec15af795acbb6876a18ebb95eb6732396462d0c8808443181e4b01917072b77d2ff8fd07edf137d9e97f28652f952051bfb6b318eed843fde69832cd0e9c1121cd84740935a199afd3fa2b66b3f7244a4c47f79f3feca1481d55b3ea4d293d99a5f298ad7ac2495be61a0494ee483aa74e956f9aab + +ModInv = c0c4da1bbd012acae7a25a15e20ee0bbda1025ace2307f31fa4640d179b00a9747e21dcafb56389c88b0082e27ab28d6e187c072eeb4c431ca4325831068bdb9f81a1d6e6ab082bb8408a09f8e009bf11d5615bd9e00acb93e5194abe48e5eca5e3509cf0e660b9748eb0a16b7e844750b3ffb0a0ce06a9a22f144c02d811478e2a0305833f1108ead3365d7f18e0b5ed00b7bfebf41f0c409ff41d +A = f6bceb6922ca89f2428f60f27a11d29146e040d8e8612b230a795afbe4ce1bb56ff03eeb3cc0356befab22451859de959fa9982bd6de48cb70e698b525ffcdf0c92f57366ef7c9e2b34fb92428d494aeb15186e1f458a92da48cf7106027da8b528c74098e +M = 70f7d3398839b5454ca1e926efa0cdb43df318f98b739b0e1759221dcfd3f0136854ef42cd7c4af811eda419f0050a93c6337e4cc73262937a605fe915788e11e718e4bff49de87f86fed37487a0202f5159e1be53dfd013ed05a657c610978f0ce2115de97bda0b84045d1f80a7245c28592ab68264e46b8b13c60a7c286381fcdc1f52eda6af5ac52d2aafea894fafee1297f7b7765bc0c39472f1 + +ModInv = 2a08fcb8fab3adb7948064358dabdfdab13ffb0b1c2639a2f766b20576164fa0cf3b4c92ac40f8ad2d77585366fd850954860aa2478c4b7e22ffb7372ed5f9bb94eea2257f3e949093d104952a97abf83b04b8f51a6bcfd4b5f97fbc78afc3aed2ebf5fa6cc7164cf9519df131dd8dd10cdea16890d47faf0689df70df2830aa10bda53f24edae29becf50cbcfe23b9c9fb1d35b4793918ad00a29 +A = b374117f9b3144a1f0a402f4eea62ed48753c852873ba0f42e6188c6f196d30b99fb3eb640b8c71fe0537ca930456346ab1c59d237b2e0c8cc433ca149bdc2c21a69f006dcc1c29429d770b180a42126ced2b88197ed48c4c7a8a663f96673e9e84e5d481589 +M = 7c3a4dc91fd622ca7b743492cf57aec55b4213e0db1979ef3b0f1f23a7197081bc1703e5f43a56919e27f23eaa6749b6a58d339c59b24ad4dc5da52a4db672bb3877168d8b0fea098236b0088f9558f794029b8312892b96f1ac3badc3d1b5138dca47a01d685690b61514ede6b87945b9a46d853761ae35c74b86ec09a621f2563f9d9838c9b21b004bea9468f6370a9c3f955a3b774dc31e0a4f + +ModInv = 2b268ddc660148481ac946e8bcb8e914a0c4d139da86efe4a0de68a06e8c0757aa96694744c9adc0531cc56dcd600693e6e2eeb230084326a3b9d313c70605dfe6ef357da8b2d7fce343b09559488dd181f0530b0dfb2f43e54d3f661401cc3104b34da49557fe11f281539ab2255351f47243ab38fa224424635d32845a348d6bc2be8020319643a9f9af514524980d1275a3366ba49a7cdd6edf +A = bdb979075d24e52c32578263fe5648f593cec87603ec71b1641e3bf32a1c115c8586ee8b6e466e84fa93a48e9346e1b8aa8534849fc243b25a7fe7f7fcb1a48fb627f19035b0d0f4dce92a79c1b90ac7235ae0cfc3c777a1008892d962a3defb4b63b6f28805 +M = 32a07a3b8777936748c8e76c3a2d1d084ad5fe7fd1a41d636daa05b86db0609dd59fa4f9cdd1517ac4f59ef09c23aeb71f85c9b903a8069160e1ded50c3d8626c14a423d1047d93e4839e067fef94b09c76a64cff21a3b113dfde2bf776d6843a174a09ef4ade339953f9da319e80fee144002783b7e8926436b220afe02c1c36748e6f6459fbd5c00696fff650daab4516edc6badffb5de05e7bf + +ModInv = 67c243b8ca3d4919a07d71efd74c1eb93c39433938017ccf8aff7737d7c6001e70f6f5944fcb5b9f292e3e574f970da75908f6c4a87b7394ca68bd76af8b9a718f9591d78b480b298fff6a144e410782e7e5479deb030350dcd118cd836b5aea06b3346a77429278bfed167c31b6cfa12b9723e4d9479425e853aec0717fb9a3dbe646dc237cdd9b2ce327b2452d56b11ae3a285326d28ff9ac9 +A = -52b0141ea572d1b8bf4f1ff3b558e6f66a716b90336569a7459969362bc2be60ae9478ea1480ac9aec27c347573c6df6c465cc313f04245f71a41eca6e983e4f7a9411e404a9f80c2f67d0170751507a87ec1769552778e41760c01b5f39489b851b692901a597 +M = b22443c522a4988aec4619d3fbcfaa3c72f36c9df821f537af68bc80a118d6e98a0c94231f977099dc28a89e23510344e37a5ef7f4aa49e7c7dc9a5eb3016fb2d42c9fa936e25d0fdf192ef33e1b886f5c96496c4350ee5859383b367fe55de9e3e4e587c71009450e9822f6b007ca7b4709ceadf3547ca0014353e9128a0a1ad6b89f0d109e271b400b6dc86d5dc133e810be6a42a72c47e2ff + +ModInv = 2ed29f323372fc87e8c3fe93647060c3c8c3061f829164fe5aacc011b42d256f6ced8083983e02fbbe246ef40e53cad485066f3f2469775c59d72b38edd88b36f566e6de0c5158b72dc4f9e86daede239da044f0aa68009d78e417909a2793b87d5bbf3067dc776521fd83bd429195497c42f7f4324372297b49fd53d9730f41e32db1c6d1cf26ac2382e168547f995c43f5f776d8a94664ad +A = -1b925a5bd9d35bf961265f8281a1848f210be5618bd71c29667cfc207560f6110b556625a33dd10a6ee0e533f65203757d5961ae578f8c43c34aec4ccd0e90952e806097d78a9fa92ca2b8402baa83304c0b0ed53e12df585a350f51fe682c9bc32bea20a54a5d +M = 240656fe31573e57a19cb9ad1a82851d73168bf72eee56516ab0685a35e497bbba38137a8179d1e85dd82a07a6cc338cea045a9ebd1b2d39b5124d0b466bc964b15e69df9ee0356ab8b11c1168a8ca76df208f40e29b67f62302f73247341fb127f5b38903715a1a982b428b6dc577214610c09a399ce5a1b50a6f79df176436cb4c126766117c1294b2ee58b587174edba6c3ea1ad689868ba + +ModInv = a1cfefe95c3a0c927cd9181f1bce9e74bf31ef89559c0569adffe46f9ef1931687aad697d9580bf4fbd352e237d1e81051c1340eb45a97f852c205b2e5c215654daf0d209e823a6cd5da56d64de13bdc8cccad6e83610d579556949ae2bbc914db3c487b78c8711eee7e7da685f9f2b4960ce7dee2d50863f7c680bd8f636e4cc392cd60e591fc2dcf499160ff4bbdf2c52ef1706cf03f8a0ea3 +A = 842c8b3c92ef1743f0e56c41dc00d504c081ddc5f2c8cc2e44d8a3fa435a8a6f659b39649e83a59349861c0aadf2dbd40c49ae777eecf5e17bc5b7e89af5af898d8963133e888ec4b25b07d09281d27c382874888ebed5ca3c5fe351cefeaa88e59fbe784bd02b +M = ce96645acf9b3dbd929cdf7f3be0699a0788876d96715d3e9ad19b4dfeeadfcb4882c28f467085453a2934a86924cafe7e677e1d4d0618a80f1396b5a46ee288feefad0eda89deacb76b60d1e9802e2c064a13fbba12d1e47915619da946f9377775b47005153f555f5f8e30f026c69a2680a9536d80f1126bd9aad86798422bdee6e129d9841c5de45ee38f54b3f030a06366275fb4c227aac3 + +ModInv = 498130661f68d9365fa45579d4bc3b3af9cec181329ddce8b1d1cc1b3392ec7209d85ee21b3d485a17eac2cf81be9f56890a460cb671c2dbe90bdf4c79b72c13bf904b971fb91ae1a8d48238784710ae233de3727d2f9e2e3b81d5970c1d4120a1e9ba230d9d351b794af75ec588fac381233916bd7a6b835987e8dd030749fbd7deca10b1558dc46cc331ea48039b1ed7f5a03d5e6cf964df +A = 9988b767c409afe441d5a7a31642593ce5e07408ad2a96ec3a15f0688bf4c3e23744c8ad10ebaf97033b5b26cd7fd646c2dce4c3d9e1e12bb1dae6b80c2ff821e5f7f00324fcfcb20aad8e7059b953eb8b9554dd25db1e90d0d8ece0c157fa68c30db0e1a515f04f +M = 6c2a815a4b6b0914b0b958bee39eef35cc8b9dce30ca879c0be29d2ed225bea7dd6af12070ffff31946392eeca3015dc913c2bbc5d8f3bbfbe997e9a514933064ee75e106ce397cbaaf026c7081a183ee9c52c663bc83e9c3e00741a96abc5e82d6b37a602b9512caf640840065868cd1341e4d085d3d86932112b128c69aeda398a91bca040189310457a7772d13d0d352c6f2393ca9db294 + +ModInv = 5474694a116b5282f89f771e0790054969910ab94a8817c682bc49823ee6f7a905c47d3df5280abef7d6b665e5e33f122da84c847981e4cda1fedd0a3e3283c72dbf25d41c41906ac968c3d6b3320c0c6449f949a1147878ea4a66cb93aa0d9b6ddee2ed6515e3388cd2b6c835fdc494f6efe5c7b11ffba4268d4bf004fa37a5beabca7d5e59a699f36b0e405d4c68614409f3e414071d340d +A = 42c45ad1c6f277225ffebab1967c176456415e6c96f73f481dfa5c3e085b1c44f049ca07cc4c2a8a31be04729942f824fb47a9f135587cc6bdc5af1ddf10ce7fa252cc5c1cfb68a2e4ce8393cc8c9fdb92355b434b2d7584bca0aab6fa20c54ba48473b0453ddf0f +M = c78549ddf1eba2fa4e91285e9934496a57267b02e3ce509edf47bd64d64f6736e558fc45ab164c885c313af6476d4c41f660cb75ab67cfe7484b82e65e038de723654a947b71077b2c062661a7837da7902b9a36274bed2560108b1c4035f4857b1e6f78e91189bb9cdb4d6fe787746b107edcb4fe420268f338b9e80cfe6ca5cf03db3f9f4c8260eae8bd9b86487d35f948f142ddadf8a251 + +ModInv = 2b42f8fa6131ab1328e5d80b8944cbd731081140cd97d42b631f9dc633265ec025446406e0eb4cbc029a182fccdcc6ce96566bbfb4a32d63e29f152d2f6b4f22d222a46e7adcc0884640e159744d963d8fb68dd666a159788705edf44c8a4defccf3eb7e3d7a1b7ab0c021479428732d8b3d4cdbc82208de8deb5d088825e544c26178f5ab75d7dcb70b72b499386c135d63363b7d051ccc37 +A = a77a429b200bcc4fd1e9d3bd23c698f7deea217e3bc1bc9052690a8740158255386f10bd2079c93bfe64b60696233137b3d583c3e141d5d6f8eb7c8a03e289769e25d2c63046064e241b265ae4648bc25af4f48d7a55aaf5402d1113a34f6118c92e5da38da55429 +M = 41b6f1eaf0f07b6488f24b43a90625a6a7424de7176eb7862867556d7e4c06e841c28f2dcb86b280969b393105803411ae79b8a94f70f68a0e84b8458f286af1493fa87c277d2bc27645623376cfd7398ad645cbd67bfbb6bcdc48da2de49e65b08c54eec42033a83ba6dcf45d36d3dcd3717819ee15f482e0dcc54af85710ebbe28cb9b78828f50d0541016d25d76ee595dde576386e0e64e + +ModInv = 46753a389cd79585d481c7bfe0510eb0a70ff19444b3b921b047f435f243a74bbfb51bb50ecbf2a089ba82b35ace79e79a8ba77fb2abaa75041076ddf38dea6d35e7c7409b37c6dfbc6b4a67a25f1be496b8ad919b3e60e54ac1be570b1a9d807103d2e53bf49b0192a8dfb51561b4c406a8ca5a56daaeb4fd1816bf72c24bfe5caeb9ba2a4d90215a07b20a1ff1bc1bb47891b3f459972e +A = 21daf6cfa18be121c66d7944a5f89625c282c89cd8d5d49a091fca4181551e359898f87739780a65e826d40f451f542e5dc5f9df40c6728b1ccaec3f6460febaed9b6e50c4624c343d3a6bc73be72163e49004885080c74b9d564e73238a9bfa29a7013ab8bb570509 +M = 8d333bf8ca53bfb90189113de62e66985380e3c362efb02efbd689e4b8239a1337fb74bf5c0cad3a0b3aca95128b0465ba8700a2a5163d3a0bf3b402941a6686fb7590033aa16e265b9c42e6698f7910eacd94a42edc911ee21ba870de764940d55bf41dcd6b78d28e7c3a72ee3c99ea9eef5d1f3854c6639cfed9e9d120c11d3e96f6b6538c28837b1d0e4e28e40edf1a196e9452d6e36d + +ModInv = 68f3a899c0a60e539a404b066a3be2481461923369b11294d819a0cbd50d3195ca694d6bfe1021952276d33f3f9ae727e742d5f37adc23574926a61c4af7a9ae4e8eeaa1323a13eda3a33ac857833bdb9b79e4ac80641f11ae0b3d0bbdc63020bb9d3a84ce2e56068b4a7aa6eb9165962bcf6faabfbeab4cc2d607e66bc3395dd525cebe0d44e970c9e3a7bbcea4f7ebe83429782f19fdb5 +A = -ceeb8ad10a090b9d72db30b72a4428ab634c0dab3bd44b3929ed39b4ab7d7220dfff95fb32fa8ae55df59cf7f4246c889b686662f5f1375624abf1f8f37fb859b17e86c7a9ee63cdecb95f20321bc1b3032b4d700493cabe7f5b4c3aac4a5568af9cf865b1912f0a53 +M = 758593ff102ccd182e426d0bcbe4a9023afd1d5335c9ee1ad3bf38047df5ac75f3231d7fee4bda37a68326f9b5251fa36e08176ace11202646d70833e668d4a6cd2a313f42dc01e62a542624d1984c9a0efa6634ce2e2d86dafa22581e6c673cdbc5f7af31f285728db85747d32cfded91f13ec9f208ff49b1127a8b9b32d03b291e8577f84be7b6caaf69bc01d2032e62735ab25f93b3c5 + +ModInv = 2a322de2d6f4df478912bf5f67dbcb7cb0eb50cf43171e63107035204dd706b67e1ebb003c35d1afda5bab657b981f6c7bb0da5bfa2c177e84013b03d1047c17a83e234636d902ee48fccb7e3736fdf6505200904b3aff0275442d550493b225fabf6210c3ef69e80410ac2e1e60abbf48d2df4cf9b8c1bfd9d9cd9e944b32a25dce71ea103a19db65be74612815aca1645ff4ea265316cf +A = -6fd7e6c03ee4debf2f7e1447c9ef025229ad64902b06ec17b3daac0b5d07f0804cc62235e4c9ca24fbd224330d4efd0f18b6a6a44dc0b95672ccc4fccef5b4d9041c70dd8df08f43058e25ad49fef8b9782edd7d2f9368abaf3943fe30322d384fe3ba94604b9f9031 +M = 3057ba53af349ea7815058bbc429001c1c5c149d316ef3bc99eb2f9d497183f0ad764ec1aa17cf2fbdc3518de2405031f02272e2147ad89b3a71bbd064b9ca0aa91b01728f139b29e8d58e86fd3c76aad17c8d6ba698e21b9809f6b962da09a3f59a30eb7a9dde76796b243c4c20ffd69a24cd8aafd74a47a4552b7e7efc4077779e84d8d411f17ffed4f7af670ce6023c86d27f9a561090 + +ModInv = 2b3b144c0236981d0b827d4eafc3d73fa12749aeee4eb457f53c0b28e01942f43516fe8c15bc222f1b8e3f65ccec47b86279eeca365d43b8762a744ea56b1c2b019a6c2931c666abfc3b5570d2c62ba7167d0ef517966b64bf0b02ef0ca3f3f0ae5cefc491b9a33f078423272f30783e742e5c6c2888d48eddc0f7931e7c0e443ebcd053001b00f9955948e4fd37e7d1bbee466d093cf +A = -2dc6571adb1b1332f7e37e31aaed06f441b41c2a5c37c60beaeb47544d5ac900899d7b0a5a2060bf6910e077517a8247e5a3ff4fc17fefff23361a9ba4fab7119dd5392fb95359830a7d75d638d875db2e04d92b67418d151d0f74f5010968aecc54e946874f35153715 +M = cec94b32fd386779548c7c73b941f2d4b6214a48e30ef62523815f1dc7203be09364559ec84f258f50e2ae7765345524c8516658e9cd320336a176118ad6eb5dec3739c743656701730dfdc2bc95f6e558a68822b34b14491638926b2db6319b2d7137d8b388df19ff6397a7d69648702edc6de4d7877f0cd19fbc8005b9a38777a68846c2129c1065a82896c6d706f837121bf7da00c + +ModInv = c4f2f5b9ed8c3bbc7f4e8a74fe126cc8b05ab66602b18a7af20c5839b0c45296424baf512584432054fa3cae5b5d3a024d36edf8dde29865ed1e1af3bd3598db10492a0d0524143e46ff5566970773c0da929e47efc91bdf3670198011b364c1c1c15ebdff785ff6aafbaf98096c6454f2e4d981ae30108f401330c511e5e59580d08dd72026a16b5a8204b2a26fff18dedb596e8c82f +A = df54d8182049a728e32594788e39854853c8ab631a3569627c307310894ba07cd6bca4ac526cac6d3e32fb16927fa1be4d8f61a1964af4f5a40386c3b642369d1519e9f161c2f7dd8b1f92ac9e3236f9bf91639d2392993ed10ee0169305b24e16c8a81c3a5793e32e22 +M = 28998073d8350c9ed0facee1e4993c110e59509f61e119c239f3d802933f8d009b502350818565f794bb47d56d79351cbfbf3ddd11550e13736830ffc80440430d22764ed3bfe26a46c268b941e6ae220bc728d7dcd9daf98089006b71928ae9a97049788a766a819e1ea41c6074bccc3e894483e2ea0aaa91b911a82069fad7e0c25bc2cab85b5233bb34b5296c78e0e2e7ed988281cd + +ModInv = 78e7293faf941d83c06e356018425b133d66173c32550d0073e4dde2481a61d4ef82a8ea7608533dab42727b337b1d7e2a1d8f1ea53e22042a5a9bb07ee9113bd90b7d502083ae36bf7686b4960d9acf606fe89e8d62e82147b2c2e958ac55d6889bee5922d95e9ac459d3ecaa65d147e9d74c4b500859b936c4bff3c29e1db5e42104a2fa7124ef945f6a50611fbcfbcb4cd8aae8 +A = 34c9879c37c6ad10f7266172932517bf53021c3ae936ad0389f33a174b790196934dd848b4e8f20638f53bf2760738b83df0a070b8c7a6f2f90b38a5f4374c16757aa2de7b5df7bf378a2f72abcd20d5d75aef79ca2d78766fbaad9bb1dd00bba8b3a8557b458ddaf6a8e403 +M = ab32a7eedb7a7632a70d1cbe7d53218cc575bc98b400177928991694d2d3d62ab3e474718386635610fd8b3dcee4c5529ecb0ea5e3aab57d9e6ec2f52470c1bf49ec1dab66282a4b48cf718d98397dc85eb43bfa2e530e0ed90494d3edf8e5e27be62f91da431cec81af78b50bdfa689fac17255a41a0d3982f1486bfa882055dde6361bf7ea63b90a439ac2feb08e56b5a44ac797 + +ModInv = 764eca51a55adbdec1d4b7a19428b20e48e673465c6b4b4c1a09a2788a09f69b772d9960160ccbf5be1f76b76a01be2288e2fbd47401355cbd67188d4f696eb744468a36ffe9e96fbe8a184e40933938f5fc483e1f379a8114ca38fe4facb10abd1abcc4bb381164646ca74a5990d2a6b30ddd6756c2ac0fa910a2fb877aadd35b46f47ded4bf0e90c5bf7e3e723894bbdf6127e95 +A = -5cf5dd2db3b995de619b9c317de9a3f4ab42990b2f9e8cc4a7d4a0ba65ff93eed91622869c94b22425d609983b74310e6b98bced232ab127780966912d00b90d7b9e792376994100285faf6eaed8539cde5514c86e98571328c2e63c58e4b7af16a2900b83970ef58778f85b +M = a87c30920213e72461b2af2cbc1320e9ce6e2cccd161bd2243deb23f57dbc53a3e3b4bc434ce154f6da61678e517069dca2545304df0a14be120e35a38262d6db97931d06d6992514c07b6cdca67db41b7ac6152a5d37f03c90ff1a645ad3a1f3765aeb6dc5a4f80836b151b2d55c1c9bbb27cdcf20ff154e95c34f5310ec366b9ecc70084245af8cacd969ace3f40e0daf4c2cad9 + +ModInv = 5b7c354adf438edb3621b4d120afe4c903780395277afe5161d8140814f5ac25b19e21a3321691ba9df99d9a2ae50e4ab450df4a433ff7ebb7e7d9aa5df22706d9ba467e8a219aeca6865832a941147df2c984c3b2b1e49678046f3dabf270593c59f5c59a171c530a2f2a19f1eba9f0f1204ceda80f6195974fa84fd857971f69f44367e800844e763ec6db14262e6bfd1a5b71 +A = ef32195bd648259c29d9ac97539ac8b04a15e7aabb2db2ded591dfe64463642e5e4984dd9745850ac3e187486fd52b52149b6c86ae586417c1215e7208017cf976169a5b8fa26fa16bc4b606bc265b1d9c32a043e9ae2228a859dc9ce90787d5bc7a0559adee1657db4e482e49 +M = 6e1fcdc1264b64bd5add6f2f52f0483e2445731111f63e9a2181adf4a6479eaba63a19fa9d906526ef16331dbcc1a77e393e2cd1200bf74fde0e15f2b7a753fd9452051f5a2f33a58226b3ef9fd0037446379c31839c29d8d0e3569aa29967f746b17a0b79b7362ed629bab75504b33a3f79087304d6b93a203dea87c0fd22b93666c1ec875946698cbb26f3b61d9573ecbc43c9 + +ModInv = 4ed300b034ef2481ffe69933036c8825cf453c75392a0ceaaa3127a9e3c483e70cbc9152a33e5842866f4511924543149d953bf526307428b22f5bd4397537e433a044015c84ce602c424ce235aef48a2243e164506a5b05425eb534a75ba193eb3cc7697822281b9e52888720257dd44c253258dd48ff690175624c5e3ded383df7548662e942ead25a4fe11186adf41fa06dc5 +A = f5795cc22fffb0e346331ed6ea5ae05bf4fab87550a5d3d8fe23a6e957933d50f7729151c4e5627110ff3ae23abf829d82040986f147c4755f0413f610d3b99335eb682ed3cbcef122f2f94f12a59d1391711055fb068deba8d387bbfdd4b35ad28e2a945c82d9beaa66746b65 +M = 53fc4860d6be5bb84efe3d810fd4c00e048fc2a990df361d6a3faf221351792489eba8b35989a0dfbc89f77182d4d9af119ce7429579b4e2d62243463f4362a277e8fb7220c566182babe3953a286555b3b1596dfe4254b146676375b5309b1d547cd2a6b4b0d70fc5b9b1d07b5ef1f6a521852e6bea4dfea84745903e4775d53b68bf97db22fe75b8a19b59c27b01e09554d7fb + +ModInv = 6f7da03ed918b6b18921d58851810e114b39b44caf4af171c931bc1fcefd52b8edc213adde4102e1278250dbfa6f8fa1deb0297eb64d0e2ea43a1d05cdf910e829d70f6e71e4db9f4d30c9b36028d8fb783ee7c6a3d2e2a2b33e2a0d11a9f81cab72a9106630fd3f63917c06322d5446d57df8b1dbf118e7354ffd841abf08c9abe2831fa5a5b6ea1777aa203d934d4adc125a30 +A = -a155081f80445cf26fa9f3a00375abc76baac76c685af1894ac231235eecc7bb8c6ff55261b1b1b945b03c35e030ff844bb23091bc107bf2bf39b112285ac7934118d3433e603cac7bd2b1116103834ed6e3fc788059bc2efa24df602104b8c36232b0a0261e27c870ec621156 +M = 95f0626880af2c577d00047e4106d0b7618594f26830f00e805c77170d45f1f75fee95d2da3753b7dd4a03d29cf25ca273dd93e66261692389e0da7db801805e23b80a19ecbc36f06195eb8f2e4f91de1f25e31f866bf1c222f7a1130c036340cd4276176bcfca3118f415c0650723470eeb6c04a35698e24e86f28ebf036012399b4e4a459063d7e5b49cdd4b31a3680414ea7d + +ModInv = 772e7bdbb3cf14b00eb9338a2b3f7a407d2a5a238b282a53327f51bd381e638e9b0cb130ca6df0fd8e1a9040b5277fd0536db1da2bfc56be1c7a77c762a745043b7e8b3032254c47c7a52da3343097c0a5605cd74d638bad19e20c5e6441f69abdfed0c7879eda74d5c7563ad74eee1ea935b22e64c50bf50b91d8afdfdea6b07e2e44c106ed6c3200a2ce1af0f75194d70e67 +A = -68be7ffe4d55104a2e08f4d87e72ef7c8c6a1ea23c26396023404587ec79a59b2d1990ad19da7c5ec7fbe7284aaeb31bd536d748b6aa00ad7ff23acd1f63a0d4ac7cc6b556cdf17a53609709fc91a96678df7cca5d4a6e1ad21162687b7021efd5277a1fb9ddcf56fd7d8c201571 +M = af212be75978169143c3fde9065aed88ff38bf94d5780703c08b973c1aa0a8bbeec5ab96125dfaa6c12c81dbc736b525432dd0fe2f31cb0457988de36a6a825e0bc2bbc30135ff78b9c955aad75c5e36ffd40363158f0fcc875d13dfa33d170dc8a031e4841951697727d18d67e8cd908c91ede0cf29d12c9c8bdf449a5a73f056cd749783ed44cbf1a56a28974006ac56e012 + +ModInv = 1f0cee4859d848b4176a5a9aea0875c4f2c34baaf41ba4fa265d31c02c633aa08b037309d56613d4b610eaa8f68e7d6bc6edfac73b376dbd5367221cd1bb66f35dd4fae8e752d54019336ebae3996da6a2f4804a33d9514efcf1b37d4f412e0d691433571485a4a7f7c075d2183e706c7f849c86f199e56f88adea187624d076d12d15f06d371d6157d60b4c9697773a13be4 +A = -1ef11903032afff23076ab06200187c9deaa04a75e70a70ce3007e4424db4549e8d7198ceffd92c19b7a664c77c7f992d848303afacb1a98090f81d466c6027cb11f547b041598405554165b5a77615ff35423135d4414d52cfc0599ecae5d8786425a979a762b347b5884f51ab1 +M = 590d14cde13c1efffad54e26d6f365d8db64fa1922e4950646dbde72a803640004d209d72f66fff3eadee322e79fc4df3d18b425c7e43afe8d5274728a7f82d7e3b8b26d96a19e97bad2d4a6826aef3e3b9ead65451de869c83244eff6113bbf1718304e1264f99a852e65c25f8b9d5ce76f535ad9b121984d41d85f033bce10f3760a95e2c29f43cb45d51585ac1078619cb + +ModInv = 48ff6470c7b9db96b259e84948f0cdc709cac7f2f1d9c2b670364f4da50b413f485084ce191b1184b2423d7cdd20019e41259df40071ca67a4b542d73a22548626df646794b074dcf862e7c5fc9ba8c52e26d092865b0efda9471b36697343e93b0c437b827ce3ad94a63847d5ca622b1e73dadd5145f91a75f9a570594880a6544fa583c3bf5d644993f416195969f206e5 +A = -654950e9610142c64515398f8ddd621573ebfb4ea51869a2827c15146194790a9ab23ff75d4cca99df2a364681e753618c5516f16775a42320c03ef90d65be92d228f0303890afcf5ce3219841a294aaa64d61f2fde8e0f83746f640f3ea45bbf167b317a108e51b358c24ff473e5c +M = ec48f221609c1fff3269e9775ecf60ccfba21bab54745e40f2c01ff346851d5b857b1e8d2bfd581a292817991708874f6695aa5e3e3af1a33f444a91cf5d2530472dfbcff1836133528a59f415aa5dcc771a7eec77f02e854f7a159813d5423f78fc4b0f025548453c6053e9d2ce1402e143ab4a4a1e99404188a2f9ef0b6458679fa438a13cc8c45af3a662fbefc6097bc7 + +ModInv = eae9999c8ba99acc2165b8780dab91e197d2f63c65a996ad83e6d61a61d403d4d160d0e8c51cb07fda707e498ca7b7984416d192072fd1ab108d65860cc4b2e82be3fbaeb76e87b34fba243016e35ccbf0923ac4b1ef379d4dc0c3f072f626020552592230eaa7f5f43a0235562d3fdea69ced04d6e5d242e0c2ce0c698eb0250031daef3ed4d5cc42ba4bfe490addc6fa1 +A = -294c6d52201589dc9f20e3093de8ef9ff2aed1878cdea0cafa2f0b4835c1e61c5da29034b16efe23a6524b012649814981bc58c8d1c6ca8e6215b86661dde2885a1c28abdcf5a6238d726eb84bc07dc0b4888be6f935aaa5c92c4272950c8cd24807502baee091525e6674ab63ae1f +M = 325a478e5477b0dcba11876f6d6350ada488d47662328a1fdbc969282958107423d3d231cea56e773478f6a98de8549c474eb079429b4544bdc9b04d90436b5aab5fa5e0669899d8b0e5085908995a173c56977fb51de342ce465723a6dca29cd8a91f4778940de49bd2490f96e5616f604641cc914141af617076cbf4b39df07dd485f36a7a0417d36c4cc74fb992da5258 + +ModInv = 314641770831f93be9e212dce2bb89d309575d59e00c4d1dd53f473e4517f0105a779999bfeb6148f8a4d381bc72063d628315385bce9ec22da90b70ab5ec7ea312a2831df22ebfc8d33c1d150b75d50b6777d44860ab2c03e5fe9040c7dd2a744906a05f67a5f6518363f5b9804013ebea88a5c73b003e00704e76461355d0318d3e6e16df08e1d3cfd763f47244b69ec57 +A = dc022a6b3b66236be3614796fdd48e33f067ce4c23dfb965cd5353274a31d7638137849f5349beea3493766d1b9622b33dde5c8277b9a57b2681bee81ed26f8968cd16a2aa36b1a04397cbd037a2fa22e5fcc551bd3242fdf3fc99da02ec27a43aeb8bb1f1974002fdebaaff3e47a7 +M = 6c66db84ff114e7f62300aad86b32bc03c2a70e384dd3b54f11c578396a080234eb843d750299397cb8836ffbea352154324940eba059bd187de6f486522d36f91016e8f6babf456e53646bfb03dfc64ac8caf130eb35f7c3d45710e2977a372866f8b7c66772ed1d62fba46a5fdfab7f4ce26d8292b3b7d53bb96889c5e0278c72def5301e44923f5a8dcbde6ee819da06c + +ModInv = 48f7581c24f5f29139b8f0b23227bad3ee9ab667c5c3a52f12c9f17d9a98db95df1bd93b0ea1101a6d56bc0d396cc5ca2c9dbd2eec34a39075a5dff69a585167c56d3c39f19ed574c28b9573544308485945456ee9d7cb2fa4e9a18ce9e95377b60cb01cca6e11295624e383aed026050f26cdae73a6dece530b1a9a394f35a049a202bf4723af2cb6a1e7605ca29e754d +A = dc96992802bfa5418a31aea56058236245ffbd69e8dca6666eabb990f70a11a4edef604ba372a8d6c0fb9eb660982118b70902ece43c4cb364a4fa04b432f9612c048b2a6b1584608a9aced35fede715a13f71be62ce2cef7f206cd4ea73e4e071f2494a957eab2d6e91beb41470bca7 +M = 84357dc580fe9b3be98ece1437c18e9b350aaf31b6b1eccf033a8b93a69b64d2cb331372093c76eed2755f39ecb3c78842d084ded8c6a433362a3972b5cabdf5d1a505da1d48fd714fe1184415f4a8f7584dd47ba2df2ba4a5f8573a059bc5c0411c8154be39ee529a435beb0650409326de2634313ddbd9b065bfeed15f46ca43d3714a81a33f2ce7876cdafe9493bd67 + +ModInv = c14e4c037c4fd0c8ece3abef33f37635adbbeacad751503de23d972578d420f78a03eb4031443996257bbaf655dfefde266c6b3e6d2e2012173bbfab21bc9ce4860101834a061db1681fbf12d20d33ac29b6ed2f8b6fb676192a07a0d7aafcc70121196df52e0b7d29eb482a97b3ca99130a51c80fbd76c29adc4d6e381bd7564b97c7bfdd83098d41e3fbbcb58e9ac125 +A = 10b30f188dcde4a5eff9bd9cb1371d487f15ee9df53776e49ad43a19f010356a5b04f90719947539da3ea669bda9f6f1288c7201192089f7976c29723c0f4a5a2e1dcbbb8b881e93c688438da940d6fa2dfe5ca916143c959c2087933bf39341bd20e995ccd5d98a988dc657a3816005 +M = cc03301721ea238f08e783ad1f74e6181b3f12c8b4573f614affc30dd5d7a7c20ad1aa42e9f5a17f03ff2725088b513641c1d3820524466e001285eb0981182691839c623efc48e458110a280867fc28d9766f89ffc7f71aa02c5ab1daab5d460c81e28ac7bda045ebc07edb2ed31ed3f4689f0adde591926605d9b02e117d353da4c7a822cc9f6e10bab07e5e1e0bc2c8 + +ModInv = 30d9faed303e14c13e14c8bd734630c993782954b4d261c810c782676e9a64d9dee7504aa8e565b833103912f7a3a7de48c228ebab5692ed388ff588fe954e845e40ab4b3f0c3f74e310121d86ce14e91ca803be57a8d810b870deedfbc46b9b0944996883bb925637b8740c478c31f0c85eaa5d2cf3486ee5baa5260e79f218d6c55671eb5e39c352033aa389d294eeaf +A = 4ae89869ad0105e65aa90eb7adacaac79b479b13d0b7dd8cc046b13925b9369e843bdf700f53eb847d45ed88d5e35047951dce475b8baf68503942ff1297375a6f6e7496026f5cabc4cbf00a86fc0fddbd2f7b78d377909b443e462be6a3dc26488a9fba4f3e271fdaa5874a0c6276a7 +M = 5dab6af89cc3872191246cc5583d230e259b42705d6c10305ae765ff04afd9cd2603d89861705800ec327c3805de9b1c0d2dfedbff6c732945cc56b8ee4a5d46ea148dd596d8309f3b4cbaef096a9ece71821c8797c0f53ce4de206f13d262ce09cab041ce1f9f277a708af37c70272380cad0125a448e64640373cd9d907bed107f1367c6cdfd1e691e2dcb4e90b41f56 + +ModInv = 410a55623f5fb3a925e29d3f71e26f95a6c50c0e6cc38ce866562aa0e5da6a857367d3e35b268d697e8a0144447043b1c9a18de48532cde720850923e57008bd0d8a2ac80aefb3c97a0cf9aeb3080e22c3573aa5f4e75c5bb7e79a8e7aa12b538cbb273517237fbe537337af1da7dd76b0a4c44cffb3917f42dd8b2aaded19ae596a2f1d010e10e79c1411da9bc8e0b +A = 2111a4b0a1d5516fe27dbba1e06e747460a59cc20b404332299bb815316b32f2cb43d8ef4612fb20f8d373e156d6a550ffe50ff99c41e077f2a52e711126dac912573bb4de15db47116352f795ddc3d6b4c94fa9ef465e9b21668fc05846f1c2aac053678e0f4ea4facaabe1320c3eff8e +M = b6be04ce8a9d0bc948f0aaba02b26cdda20d5cec47e2e12ec05003ba738333e4d13e1579734a9742ca32049eb84810a7837e9575be0bf1067574f125f6b1ad41fb89ac7c4848e399efd74c990e60361e405951c2384e064f0a092fb03ee6d7f8306deb7f8e7d565da23e99884bf1b63a3accee76b8f4e3516a8bec22deca6a110110a66a4c55941b968ebd2885face3 + +ModInv = 10b98e48ff771488ce87247ce738e067ceeb20c5bc1cd66bd8a6e4dd4195e0f2e5fed0d0d268dd9aafbc491d4100ae631bf80a9fb7a9a0558c9e20d43c8d065392f229fe5d095afcc5a84871de30e4c975e1c95730833d84751a367763dbe7b39ab8a0f792beb936ab583774c9c7154a2f100708b4993328a5daa8c62bc15f918bd555ea4d79c367af22e5108e9853fd +A = 3f53905216a1ff9a3be6d10b8c1d681c257e357477203a3f94c228fe665c5ba243d8d550f78ea63b994bc54ba1eb4f3b9c16d22591e0273239941bf2fe7e1773968bd74b97254a4c8e09c5b102396cc4657971115fb665b6d906743e7aeee390f251fe9d0f14c2578f20488b616b119045 +M = 172063536894d75506b83a0f3b5b671085d4a3c57ca57894ca4f71cabf38d2cd6f2c8f3ffd60ccb3c2bd9b5a4402d357cffa0b902eebff4a6d93224c2209c6aa560a88e41bbf0cba04128386df364402ed7c9f54c6c36e3d7a1d04fa5331ae69d918abeedf1137e55e9227cdf50d2f58f0d41c35e28ca3a73fd44271c16854c6bc635d40323d72560e7aa9a96240a7b8 + +ModInv = 36517f8b8f153da06a77680f6912e7dfce59a1f55b5cbf3ac0a3f0c6731e7adf4ba7e44d43f85a449c6e1a4ce4cde829d6308633ec933cf178bfec3c458c5d8f81197f455d8ec1edf6a3749857801c026e84a58b9910a94b7bc38efddd281e53685495b0693241603f21673bd416cfb191b7b84ecd42b0692406f1f14c94b920991d78e4906ec091df9af7aec60608 +A = 50f7210560e77aa92a0e062b6ee361455e1a153e8b617dfa27110aaf6dec82a4745fe7fbd04bf9ba403ac74bede07d4f6d78689055030df02ad0b92664c7d4090185b0499ed8fe2669a4e1b8ff18e72cc5f19a61931c6593eec78305061c48a0e4349a1a81f0e748284be7728c2fb6272181 +M = 47e966d0b03376932982b404be070392148f2eeee054d702bd198067b2ad981e4e0fff9a525e2b358da0160559c4880d457e2d0bf3ae1ca880c483b4f8cdead31c8077ce61620c135d338fc05b8660df5d0f403c4423fe9907f6ea9b749c52310c5a20091a839e418c6340f46cd3b0e60b88f148170923224d590c7a9146677c842425764cfde6c2928a5079d5f165 + +ModInv = 9d601fd745cb06af368484d8ad6cd942fc220c6f1e0dfa6d1ef9e4698081b8958ed624c3ee4c3bfc95a86c34292d8b3de8a1c7271c7d3f4f491f3d4d1a6f143eb9407f9b0199182a3074e7fba731c4dc604e3b32a4470dbe580df3fcf87b34085815e0db20b18fa303f8c192e69fe9c3d790536e46affeba732a24de55b16a88cf50f276dd902e52ddce1a993286a8 +A = 8638fe3094c9a7376fce1c2080d4db6995b39d4c929c9224f42118c562f0eb2dcd1c65f0aba15897d3ae643f5798e38e64008443c5a70a45e15896c5f6c5ee0288e0ab0eacf023b3efd2636cf03c22e0690705f0a6f29e70e73e7b49d0a889cef0ecd66d7c6158d67a5c58840115af1feaa3 +M = e80684f1e066649dbec5106d5988e4a8ccc9e7811705e347c7ef4650f77231cfa6dd3411aa8db8d08e9e84a010a92f1ce0945fbfa34e3aeee978b36a4cbc9f400fc4764cc6bc750ae6397b22688f35a2eb1e0ad14877033ed21c630ff23954edf034421e8adfa88e8cc16708f3784be4a6f116e9f499241e80b1ccc4ff1cd97428d212908d3aebefee41b5ff0c6b15 + +ModInv = 24351714fd4a98b4e9976869613e78fd21b1099f3c87b73af126125d34071d7fe1a3d9847d51f3925f06868447634aa64beaed49e6e22470b4c9e662b7bb5e0c1723f1c78a6320c31643120e77ffc00baf1e9a09b3ad8162c998ced1da147ef003b4a6eeb910d5f416e2b5aea82b3be896b5ae4ae84ed2fae0c965f3fee1e493a57ecab5806c44a8175371a91cf +A = -b9ee4a18821de4510c646a7c63508496d24155f3124c378b712bbdbd96234084e00a432f818398e527b30cff9486d9a00e88370c7fb9b2cc58106a09447cd806896f795a840ec38833a38b29344069a3c12ad369fc53f48f5ef056304e6cc74f84c81fee503d1ce3980608bdc567cc86bf3c3d +M = 1920d730655b0061d1ecb3d74be45edaf1becec7273e4649a2be2a957c0dd705bc80a0908d197e7245a6cc91ccbf1974dba609a9fe85ff864c2923e6ee2899b26ff8a444015a0f6ed349f02acda326f86debba6a195647f873a58c49bcb37699725be5824ad13e629514fcdd46a672bcb10881150568018f10af20672daa0a5979cce10ec7e6e138c229cfc6ecb4 + +ModInv = 5d07663b6a57d559de5f984e086253ad82aa6effa58db2026f82d86becae792bdd530491ff1cebe176648cfb50f15a71c8598a33b66db6a2a658dc62e873ee7be5c1fdaf3c7d54483d9e14e3c1835cb0c5c04df0c8a64a54b7e11a1e48f9616d0a08125f7228e072baaa1c8fbf4bdb167d55f4fe9eeb9828f361ad959d50826200583b1285b116e9c8ea243d1db +A = 834eec0a3de8c807fd2d316bbb2167ed030c13a9a8105fc2c16d57bd0f86b82dae2a354fb35d68be433e98d871968baf0a3a88347c3c0262ac601263fc181bef604f93f0ce8b16557d2554545299f2adcff1b696f3f361febe7ba6eeeee763be0aae90dd08b9c37a3cf8340422c923183606c1 +M = dc02561a37c73958066586bc7b4ea3a7137997e6821aa81b7cbdce895103276442a8d0b96e2b5c62ba1f078c4962f80224f55ccfbd6bb546cce0c95c8ad84640e111ab7515fb5cd7c963feaefcc803221ebdf6ab44e70bb611880377b33aeb9f942115d91b971bbfa39af83a0be27a32bd06cf01b30414ac97cc73de4fe8321288cd6e1df599be7fa3df9686c7df + +ModInv = 9b8a70ba495088c59d70c8a5ab8152d5539fc2e32669aab827aafa14250333612d8321a6acd09b2a41b2c352f87c537545565bf9fb2d2667bc40f36dbdd4bd160a28d195a47ad91bda5ab4fff24426c4593857ee623617b54300ec44cf1d6949b9e31287a3003086148da36922e5580802fef9a279238d02f373bb89a309797c40d0f9a8ff7297e4dda6bc4ca3b +A = -5536710542dbe76f4b3a079d4d4b155886a3a32e2fe759a8d3ee555d58da96adee6704d3de06a4aeaa2e798b85b28a5c2167e77c43205aa5ec79b6d1be25fc12f09d5b26eae19d5617e239f11379292dbc5e6c90e44eb5d26a477c13a04787bd950d23c8b94661cd8d37f94cdf16830ed44bfd +M = 18effbd5ff82ab34b82e738645c94c386356734d0f83edf1d95631c743ae82f6a16ec8d4b3e6fb9a3b52935ed3a2bdae3aca7b5ce8a8485efae9f09962c1577625cb7fb794f54200f3bc6c0d76f79f369be4b72ec7e64723d392aae22bd6f91bfdea94c5e36a40eb9873b6aed8a18a1480738046cff0eb819fec1be167f991e244a951957e9d09eb057d15c1d862 + +ModInv = 15b2cf6e1c0ff6d035762723c4da87b74f15ecc55384a4fa0e44f52ccb1c85425d1c70e110df2fe7aea18f7a7d273e8fb6338a765d471f94a4ea250ce29164afd2fc5644b11f5dbb8996e4c05e671a772e6d9f7116fa8189728510052d098cd05113ed9e62a4a71488f4320864d00b440da02299dfd694d4ea4fa5f29f4a3a877213964a606851f4230633daf9 +A = c5dced57c20764aeb6ecdbd1f8fe3653559de20cbff5b52597cdfeba9a7a9b4136e0557a6febc1709de1ab00fbb637d70b6af48f63ed7a37a5d083f42e992692c3c3fb49c823151ba80d45d43a69b3d503ac435e2d71b4e69aa9a6e0149dc90b67bba85959a36ddb58e65df8e8b47138fba07924 +M = adc9a88d85950c7b81a928108f501b00ecd495ca38e9227175f1fe3251aec44293abafb0eca842eb7937bb386059b88061770714a1a74c650f5c1caf04cd88a4f4db3ee84e8c70ef6bd05b516baefc913ef71004fa43b6c05f142df58dd53df88acade44e28542e18a1ee49f5119f120b016a667ac929171c916affaab6ab0b437a6335d816c8c6242b96c0beb + +ModInv = 855c90256062f142b8bc414ad20fb5138eff2af205b16479da1beaeadf7156dcacecd343e243e0fc38365e566a3ba55456196d53e38ff48c2e2a3af4e11103b90e6f4772c2f3017714ef65b342f30084939d0a81a599c810f2ea349c7433452f34dd71399daeb135b1c153323a281edb75bac4406ecf5cad62048905ba8bbfac5f89e34b4cc0709a191beed9e +A = -bd937f6adac6042bf1769e48386e047f51f926a848024769ee0e37faf565891020642bdf948afe2b1d908f725058dc49fb031f1b4bb447133db936f3b366eb1511a5a59ebcfc5dc934f29564e5af83e43218b3c3f5b5d7697d972356e0e248a0ec7ea6cfd135515aed4e278c81a0c0170cd8017f +M = 7620a084c44855e880941cfac568e2616fee7a5b8baf8975740dc6495b9c5ceb7ece4768d95b5918a2a0bc154d5399be5133fa255a683791b9331efc1cf5bac84026c4c330c236ce4a8e7f68a6e544e5fb428c067ec1e27d60bb81f6f8b0610fd0260d4470e11ea9dca17b123cb997d71e3a8970626ff0a2e325abb9eadcb6d7e7e1162c3e6ee18f7f51809b4d + +ModInv = 6dd565991bd46d366971a3407200041903ff9e836547b101e23bc419506817eae8078ba23c2760e7f7ca225ffc15611fc486998eae28773ca39d6f6ef47185839ae5a20a3419cf4531cd507246da7e58a39de525fb441b6cabdc7b776723e939add9711e5788c22270677309debbabc5e854655610727b0fd385483f987eaf7e9701dce925a1a10eacadbcd +A = 6e26a11cfe6ba07e6dd62f93009b5ad0b52e7b9df291671b912eb0753254265a21e49230598d74ac98440c21b3fb8220fd19b36e2334053d8c88442a859db92ed04b870eb1ad870e3a3ba64ebe7d07ad58f4da378bc5dcd521f1d27f38224746cac6d3a8b1241f88af89d6ebed6833d1474e39b605 +M = 2a673a3bf6f4ecabde84039e36c9ac458c3b185bcfafa6f0d7ac82b7e536ad54f42d57a40d83e7a5cce0ca9896471e849faf4338c271e9eff3c8047c43f8962ef2c81e0fa03ab88edca17a41c6171b7b8a2aaac2998d51a29697e30c0e5855fe6cdd545d84062ab1c4762246213a921c2a09779722d53295faa639aa48cd372dc681c26a04e01aecbb3aeefa + +ModInv = 5d45e45c5781969097d2e8d1edcbcb3f4ae0eef0e41f51e3c0ccb42b4d31d5df58b38495b6d40129ee50b59cfc670f3aa28df4f2ea92813182e9f6ac98f99d7d7c8e2c697238699a63ec305f1c65b6b369ee9937b1b0aad46eea52bafb04028ebcdacd714752510799628505b4fac2b5954064b3b6471ebe4b3142d3b18fb6d43a79aaf26b4b63c5b0d4447f +A = 8d5b127c7d67822328d6e2e77c363c738bfff7707b40da52b63cb5cdf95ed2987d97400d930850467e448d6fce4de7d0fb5a2a343ea0ee7beff992243a97294d787067d77ec609fead9a1dff6cf6c1aae51075ada6df4491cfe50fb4414aff787bc90c0b01d96a556a111e4a3b87dfc363317e2bef +M = e6c68d6470502ee192dd95707d6a72ac6ba8a144a48ab68864ffc87d25046d3be75f664a80aa6abb43bb3f2686326c2fd88d1ae545625c37050d20551273cbaaecd31f9ea3e2705b380649640b62677e12f53a00b4a22455ba2d7c971b48eb04e50bdf7025ae75400f4a6b70e328cd7c9b0d896127cd09a7e9d5e6d44820048f32579cf282b5e66bd9a6a810 + +ModInv = 24b1774f4b11bace2239be25f963b23a9d6bc08cbb79988d1ae4fc82327ab0a3df79d6aa6f630e80294259cb0e9e33146860b9bce2b80a933d76561abaaa89d78735116b044a9b9cb578dc994499c574e6d2ea8637a2f272ad7a0928ead158cbb64d1145468e43892c6678097b6042c57a21ffc42bcdcd1207834395276ae77ca6f1ca49e6bd197779e096b5 +A = 1e1a5271269477cd464c269dd0c7383573d93757657b59a7f7ff1de6a09cee1f7d6af2384eab0b67cc2bc6f327347f173df468fbb47ec422184271de16b278f1bf3a173fae7615473d8f57c48990ae5d5e44c90cab97f54f69c29d122746c0adc478b1febc162197bacc38a24b850cbc8ef39d302b +M = c7ada7e22468a8a528aa3be9e233b9adb8b148ea46387adc3beb2cf0674e727c65305a4d82c19181345d81fc27f26f5feedb75e6779a69aebb1ba196b9e0bdbba510a816cfd48c69ae9ccd7428aff232f92e69ef96c0246b5229fafb545a548152365c4142a14358378a9745c16e1f5918d6600a9d61a161e31341bab09bfc0f52ebc9ce4d2d6399e91178a2 + +ModInv = 1329f853037ad41a90ce5eefb10c81e61744d8c7dbd160e77c6b90c7cb676e58e972ab9c9ff1ecb116287b508e57dd7ee7b64a106b3b785d1633a1c3bbb5acdfa098e681f78f0481f811ebddcd25adba511afee9c6f9815fc34ed6e8ab7a9ea8327549f0e81597ab834b3d95a6a237245365b06495213f38d92a082ed3ff730a5849888abdd200c2dc7bd7 +A = -b53bff44272c43eb5d53d3c3ef34ab59573a32a362e2cd239322f7f17dcc5d12f8a35cdd2398a511fe9b6902569c76d14b09635dcccbcef28f5437bdd121975b1631b7411670d86d7d717a816e9a1f888373336ba0929f86c52a091004ad2e129e76ee9bc6fe6ce118aaefa0f17dfb7fb1ab27a03cf9 +M = 4b7987ca677adfa7792fa178f816e6791210cf3a407e7eb3185ac7a8115e1e45f5a881e31555cdfc6f3dbbdc932f0d308a3dfd9c4ee5dfa9c0a42b9b5c4bd3c24adb54e249ba135d7c2893d8f501dbe3d68bac97dfee5ba27e57e045a12c0a6d6b0797354a941e9fb714d84776aca84302150212803179e9aeb3f447804c12c4a8cb32d468f57235e6057a + +ModInv = 688830647a8437f70ea5c2707146cfc8f0e490f096819f9ac4754d2f4fc5bb5443217f2cec1099ba0d3aa9afe54f0de2d19e2b50052f591b23caa32855a43d0c3f875c0b79686336b1ed874c66afe5cf0811b405ea1b4c7a54370cd193f50e52d2c99ce5a34237ceb1997b4ae456516f58cef038f4973d0530d063171f3d62c5b7d471fb542482c3d91fd2 +A = a6b952597d5ea8950d0d58594bb524d4a1cbf2952a8ac0651bcaef278ec58e870a72f9a3e2451f21e81c1fd5ba6872b10eade25b354abc657478eb3ec312540496175575827ccc19a5f6e575a979bc74e664ef6a45e82c71cab7a02b75fa8d4983e7ae7a44cbe59492455ef338f97fd5bd0372f67285 +M = 8d5545468805acdc9bab659cf3c21db2abc633ce87d785fbba54c577d9967943eab65b8651c5f06d3c86b7a39688fa905f44cc83f6aaef83cbccb1df6ccd069dfcb4e6391d6cb91d305fb334dbb518f7bfc90d9ae2caa18e5de4703ddb95da24c3e75dad9044e623028dfa439af627742b2235e982fead0dccbbc2d06a2c9c1d6aa13eab7cc62fad5f03b3 + +ModInv = 234dd0af2e3cdb1a05c1b065aec7ed852bcccd8f2837d422fec4f22e82078c9d974f57685fe44bbf563cd55f83d2f728e6870122fcab483b7a1b36b4f90c52e0cdc1a369a2e2f760f07ec78897b56a13eb1a2a71f81d9ece1426baaa988c1e29d82fefb5f18e7512bc4303f6b234021dfd5743d136ea22c5784a8c8cbd0d0e363cea91f9bc63eb6a92bf +A = -3b516cb7e5c7d8c963b6d9435b2f3144903bbc5f6831d6d05ceb30e1600132d771306d380dce66712fb86537f799a3301aef3c0dcdd600f4d882d94e8428f99cfa0ea8e862551654c6ed5f815c9ce5b44a412f5993dbad8052b6b0ec7eeaa5c9b657689ca7610827fb925eb4ab1635021598403035a9f +M = ada5099501bcdeb6a4efb151560cb04a24df846a8a3eba372392e5721734d362d0aa68ac0c5aae8049e9758ef93a7245dc8e3b144d087d484273d8108a3a3965606296dd1dd7a0c1026728c106b8ba88a47f7d745eb7324e76aed298cf54ca967c58584c386060a650bd941c78284a71980d218a00826e6dd403310fc1f639603c0837d3ff53309474a6 + +ModInv = 26b04882bbc86addc8e61e64ca5f4846dc61270167ccbe7e75e177071795e1557d949a3a93a51493cac059fbb1ce098f6097bab9e5c1ec21c4ea424624b48a0aa847dc442599de0ad31e278b6c2362801019385e2b0d2e57448c8c768b683d09068a1646bbea030208a6b7d5ca9e3471272c693b7f1d51c0c29fac29d78d816c53482d3b28edcb56a24b +A = 9c9c5093a6bb013ed2513284e6e6e5743211980472203c5acd93e4764edd998a54410d6f2ea7a2c67185bc61135558135d52b84ba06f837faeca0492a104fd72cbf6547b01506f26dab9c2e944888d3325630b394eb7c9fc83e50fed9fa3aa31ca135fcbe7f6aba7260152b2a26d34566f80246f74350e +M = 420695a3b450d08f836b5bf625a6f50c110805083150550b373856003fd922d30fd8a99f0e32f3d2dba166496085281a32cd829a6d366fb65206c61a0649e01a85e42e0444e7f44056c52bfad0a5cba8d2225ebf37cd0a9eb6f536d557b980ce7adbb7e1f21224158e1648e73269900be4a3ddf2e47faa8ed0802890396818b6a002529f6a57aa8fcd4b + +ModInv = 51ac6c58e645870761187cf1494a12bf2cf9a1e924428962737ad217c67eb10a8f1ec49f0c9c994e4c3ef96a671402f882466b8da905bab06d24c9292c24809a1f31ef15b2d291fc46d41c56f543f86ac83ff49b35c41f0419e3c6981bd2663c0f6b63db8d93629e7b157016b7ade8475a460a6db381a40f4b6e192764c689bb353cc5ae07c30d06bcf3 +A = -9b33140246488806b377c5e2ad9dce2a055820f5cbc8d3ee727674498081d019786fe9167af381a234852339931b1d97adb8ce50946362a1cd0d042ecc67ec146696fcedc23283ded6a1cff632f53a2ee52c03572aaaae4816562e7d189eaa472b356cf94c139fc07c50f5a5f82747b63462ad089d27af +M = e607d7271d8937e7aa2f7bce654016a009c8889ea6af1fb709e9176eef5fa757e6a311d80389e8ef4338bb4301645d593c28afdfa038baedb619846db64e13275c71f31a01ac55e6f7ca632575b4f163a6435a99feff28fe5f3ea94a3530e6dfbb818129f9e1d071ff414caf7789723ed25337019f9ef2d4a5f7849ecabd95f7d2150e03e6590d66a44e + +ModInv = a41aad75c6be302ed6d7deae934fa4d8a832be4b919c9e307c28b3d0ffb6ab666b42d21593ccad6438b5f6fb3eabd65f55baed7b35ba8f3f0aa8f9249544e5f818f68fcf973f107140d21d5619860208950f19f347eb46c5bf08dcb23051f3a06c450a5960c2b4d0107e53fe19f1659359def7ebf62d46ac19889fa2ab515cefeca7b53da53aded15 +A = -f2d12a6db21499eec8a1bdc6ca9e66697c24388c438f87836b047a33081b9542766ad4c22018936f05e2007dff36ff6945dca9b41dcb325040cda53e0ba58774633127876f3fac8c0094383f7f6a2b8708d4207cbdd8111f0a8226492a658f4109098b7c306e1a3474cf98610c9aef52acae65101d4dfd15 +M = 79acf7f46f269aa06d8944229eae47d54a8c2287aa0a0525f916a873d02c8b5fa553ce6f171c34ec353af2500d0c9bc9e05fa29c314711048be5b67a96bbbb88a8dd9ddba36973aaa4d28e9dd4d386175cf7bb20f1ad2d56c7223c73d8f341c04816162b0e6e98a33de400f9d0a7bc5881b879913d4d58b179016756c2124a7cd17dcf4368fca2c26a + +ModInv = 3181c5ca960196836b9444582d8fa91eef7d9cf751e585fe143ebc00ac6dc170a3ccd8de34c58c4c48159baa084d6d550d93525416d118945e766987ad5161a574f3cb281b40c32e3d31c09dc36312cdb347f75c4071f0bcc46dfa64803ec050bfeb87c218ae8058e7398b24a597fd6c0f1e99c9e0aa3d7384471545bb4362fa16da345b388ae7f913 +A = c1dd5eb14f035981f36dba24e5ba24864823dc4b5240b845a9cf4be73b8287210960faf351f8db052d8678d64cb1ab4a166278b889c76c94a817b36161f6bd5e8c073547b003f8429dcf9b24e4c5e04b0d0425211172c4e53e9259566f0631d6b26c3bd3404ceb9eb2c6e31662db8f403b646cf0010a4049 +M = 3eedf8fb6b2cfe4db3c00fec4d13dcd4a67a6212a0b58f317bd01a2597c400eca77eb09627ca6c28a5ad722b39147a5093cbfc865f3502f1a08588685c4885350fb08a057f6bb521897e41624d5f11538309185cb71ef39a689451e177742f45ac68ef862f0a9612e8c860495a4bd2dcef9cbb88aed54680b9aedb3f24c6e35ff39f4c9083441ab1e2 + +ModInv = 8a2443647aba0ce5ecd2dfbdba9e5e66561f4aa0506117ecee978007a7b6c5b873f0d3fd3ffe4b8c0a4fc751649b5ff9ed979edc9ab1da9431047e2a9bde3ded68ba08553f4ba446339dae3d4acfbc4214aa023d21cb55172e526a2ad627ed86d97d03ca0f221250892cdd84628c6e717af84dc57d74ceefef6375d9550368c13ffa4aba57c2458d9 +A = -59d5f07fe883520f345a02601f9bdee8c25150961025e68c26d441538330dc6f5bec4ef10494168db13ef87a92fa9d2fd00db3a49a727fb849f0ae554b1945ceed450c3eb2347c09ed014120b65a6c36e615f3a48a95d56628187b7fb33bce04afc16957daa33e3ab9548d3e0db7b29392070fc82c44de3b +M = a6459d36b78e90e08f314f8ae54121ef7d78ec827d9c357d3b1b11696d1d24ebf82fe65aea69fae795e1f992577ec909aa74160ec2953e83d355138dc64e77d01f00e56c826e13a47aef55b9b2974929c7c932a428d1ab5d99516e533358d22909910fca76f3540aeb1505e86b157aaae35b36ee5308757cf5904cccad93039e6f38c8712047bb9d94 + +ModInv = 2872f62d898101afd595f8f17c399d487c4a4eca97fc7f882461cdd00f0c538c27a989faac1d4414a93337566c1ad0a7872b6fa5d756dd051ef4c2e7ea7fb4d085c61d1547a739c1419254e4d363bd6f703ca513c759a84f57c59b2f5ea14dd0640f5f828d11e28fdcc0fa4003e8d55dcbcbb3bb3d1e98e267848457b44e462537bd7920d43fb81a +A = 3a2af53073406b561eb3fc74b610eb0b49dcff799d9be68089596bfa8a4fc2ab16f6fda4fa8f36f3aef6909893f4d201137b08dc257a82146e4f23408bc2f7de7f612fdadbb731d91786a98ceed27c11ccc614bd9bd8379584ea9993144aad683d0b7879e1e3a2a932e7662d7e2c73b9ca8d26015663655b6f +M = aea76de49f17435840cc0b12b9834e77378f61582b40bd3d1c231ce6053078508d21d2d002bbe98dcf7a28ad91f331434e7756e77fa37179c5e243c8a1f4373f7874924b3eabcfb833805c1c982c955b254c4742346e4eb82749a433e74d9f70e594465da13e3e65353e80acee1f6e327b4b4df5bdd96f0b63b07675344c8c1a42bfd29fe1c954b5 + +ModInv = a8eea69dd99869652c6e6a06d94b2abb5d5f56c6dbf36f435c96cb0a1804b6149c1adecb165aade0f3cd2b886a9470732d99c531a3b1d2350cb88336364afefcc50a3034cb7f90abf99b1819950d56d5dae530cdea9171afb84017884583e5916a916014f2afa62f3dcd5eff6f6323cd2953b2cda7d5566b56493cae3a6389c6af05dc3cefec71 +A = 846719d54df05ff2b7fa35d4f47be73fd2fe44df4658f8d493241bb0735a6f8c6086858662f253ef0101034942f021f353e5ee5b6b9190ad980fec1b1be74a8ad36f49f7e01168633577a8c6b145e07ca50236bdbc0a0f09dcfba2d4bd98dc4267f69333b9d2fdeb6a0dc64792c949a2b537191fd8a5cdec7fea +M = cd13dc1904937d9aea3e1c8995f1f1b6e5895fd4e7c39ce22c76b822c00cc9e6257c7c38d13d9060deb47e380cef49df22c7de77233322fbe15a62f3982bc1f84386c8fd6a9d32ca19d0268c397d42e2eb8a6255a98f76332aa811aef78fba3eca27ec8d4b3e58a99e6dd518931788227c5fc8351ed603b846dea621f60bf118fc98d7b11013f9 + +ModInv = 2ba7c828010e6eb1b001dae6cbb7e9269722d9c2bcd5669b61315a0a8615304f07af4325c096d9555a09acb4134ec009732acda7afcc251c379c194cfb56fd3ab8ebe4d9218a65a62924a6a6c0d4c7eb573455b2857715716eb3a1e306af6fca43af9856ceb40eb0923909aae9671fe4f1bfb55dd843f5db5757d9643e0cf710e6f1fd7fccf8fb +A = -df5b408985b265cd6b212e0edb5fb584f8e39b49f32cd2fea6ca83e5481ffa7a2582970474f0fcb16c0ded1cb26d604137aedc1b2a946a153909f5c319648c9d312e3dccd72f0acf123666639b84aebb75f4162b6bf04bed26c2ead0719bc44f4841178cd8848c21ff9cff737bffa8f7a3c2ee4cbede60c16c9c +M = b148db02eac9c3cdab289f3282abe7d80d2acd5b6ca14f23a038174d11171bbe4ef13ad088bdd52054da413fac49170a76c2ff9258883e7f4e934e947e466f4110a664e1096c4f0bb40a813a888736cc2352616023131f309a3c8779e266ec8926c50efad1f1f8719f4123ca671ea7bc940c3b71907e8de13b2bf15600a56e1491e3aae5f34497 + +ModInv = c50e6b398e328961d654769d55a693fa07694a6e5c02c40a97d707de18ff8c634706d00e35e50488f5631a12381d0596f2af14303f5c20283c57fe0d7cc59cd4e761532560b6ca3c72641715f3e0c81d90d8d76a9c6ba726dd3926ff83bd983d12fc685494d175b667de537539acd551b41139fd707f3b7980216fe4cce2eec981866cef2df75 +A = f2b4aac90a29074e5b1d5c495242d36a68704de4c809f0acdf5468b827a439635d2be64a69f43242b65ec4f48496d76afd91a417a858e029c974ef658ba00841138b53934f52e171c6b30641875c3142175a22e8fec8da9cc3fb8f279a7ab2f2aea41891f830dac1ae1e1c5b925bb371c70449305740d4a6d72d +M = 223bbd942bee009f98c3d4d1b7ffdd1f90fc416df1c45c4b299e902c6f218e60aaadd4f3eaa154857b8c2ea6265b95f96d35d06c70e19ff6b06624a0bda768aa88a228a576354710397196a8e334ed919ca1f75785e2e24175d722251635de6c550ac4f34209d4110b6161f259cd0df7ba9bf9ba537a8afec9e2e28d3bfba39687c0f3f06a2450 + +ModInv = 5182a117db85ababd221cb00d0484c63adbd1bfc1b62560fb2fab83d47990691351bde9903afac7b8100e7b22c440c78141f2f57718bb14fcd1facbf720ea09bac606307fc7111339475e3b81bb1ed25a6aedfd8eedc68977507492e90ff8d0cf10c58301f3e5402ecd304bd10f259306602b7fe6700d518e6eb3e35e7881c7154a757f4adbb +A = 7a5b010c343445aeeada1a77db9c048414f8bca5b314d7adba8ac742b5bfaa0191eb01d96e2b2d9907f1dde94e72009bc33429e6e2c81c3e4daa1f540f16dce41d3979c3636ad0cb8181e77aed31f8963dc80f8c6321174a8c1e0e0db24e1fb704bba2d8263eba3068b0edaf3cc4abbd889e3054e56923d1c55663 +M = f5bdb50449fe036774d2aaff8c4b4020ebd0f342a7d2f2c67816e09ca34a515354ea5b973b00452921c762ace16ddb07168ec39a31ac076a94348b8c13c6b15ded79ad62d9c66c82a573648b67161dc0a18b31b54d1d89065d3056ce5737bb04fab380ccad5800b5c57d2798c7efc6154daf60854521cbba20e38f720cd4ee82ff04e028dad0 + +ModInv = 2867344a65c54af21dde32089c4455863dede9047f66077b95c635378a89e58921001cfbd1d2e9aae694d4d0fa9911d09e192cfa95b5ecb9bbb26214831d7eae4dbbd6356e847a6ecf21101baacf8d503205a526145dc63758619e628a011202cd5b058184d2e8898c2bcb84872cc8ee336b239f7a2f1fa5a44eafbf22b3222ca177b017917 +A = -6ba72837440ecece82777a40d0d76da8c85110b0f149975dede067914d2eb4a690c4c319c15e42335e346adb27391943ae007fee1ac7fdb31bf6099e3977bfa0f7e78a3c2597aebd0dbf9b088f6460eae6e4ef941630f1efe04080aa6c40985415bb8e4d599d9d89226fb5a4c3ccae0d02a470c5cd47f6a15ff3f0 +M = 12de8e1721c595b74d5578002154a93f8abca94549f288f38d6d334498513548b78d27469552ffdd847c65ef53e281a2333bda364a518d943471fbc6432f89a68f7392205395d16f5f20737a083e3ea74305ea26829047062fa2c0b53c02375703ab12139a9c7864ae9acfebf7925af88247c82cafa21e59c21a351f2c0032967412910003d9 + +ModInv = 6b3717e1c10a946bc482cab67f6e158f18a9cd498be01e0f37030518ff5dd5ab72bc39f39755a85ec2baa0574a5ec4dc2b03cd710de71bcd9a90f5854e10a82c3b04737a2724c66edb2bec3c4d796701b2e1468752c000dee203d0f95eb74f1ff0a02a939480679173d302b435d4ed65e607cdbc23d98854f0c7faa5781339847badec4bfaf7 +A = 5d17bc1999cb66437e7b7456feabc2e7ae577e9e463cd9300686d1aee594c5dce2a77d3326a72c122c842328ca866478dca859d7644e4c9bf3a46c57d1a9f5d3c9a2c23254d8f5ced5d498d0abec3f6f87ee7bf50553878883f3233bfaaa0ecd60d71c66d5623017cde702c201963727ad6c6a9745d348fcea7c43 +M = 8cc2facf4017c629e8a9ee03a9222efdb04f02b12ea1ed899127a70df6b54d9cfc965c897203663d1c5762cc6b0eba5ebf4543a700df09757c90e6241423858ea820cd6693bb3a78ade71b928b836360cda7acab5bf5db71d0e65ef6e29ed952778d80762278c0ee06bd39169a00f95a7c0e24863476ba91b078df359bc5d1ed9d2d3e3b3626 + +ModInv = 777b6c1976ce35a1958e9d36c0dc42f32282d18498460712cf0dae88de0076f83b5444427746aff152d8f99d89b5d3d1e20cedcb400e12544f1cc9747e078a79a172ddd404c8673ee074d18053892a728f15235eec3fc26c860a7221746a02db06d553d0b31f0cb73811bab8aa2dfe2bd9b01da1c0a3a791cc21b9f1203611427454d0b55b +A = -17abf35d5111539f035089bc3489109ffd7b5c4dd241fb4502ed3b51b731be45fcceedc550e03bf191cad5a9f7cb825464fd2689cb976cce29bb5adc3d7eadb671dee00bbfdaeabca1eb222acc7aa53c7c9d5d0678bd5461ce01685793a7633412e6ce612f52bf065caea2e11546f4d2e0a937ecf87561fc1eeef3b9 +M = 7b822ab4602b37f8dcae59fcfe61843fd8d760d840a03d8ff154baa79de4b697613b866d2921d0552b481b5368662c80705492019928e78fb519c2fce66ca8ee23f2edcae51672c85b726cb0fc94e60a7ecfd95262c079fae321673011c209bff98258fbb3bc994044d7864d44ef93abd9e8b45b2b353a2c9306cdf06047ffeb4a717be021 + +ModInv = 3fb165d0a06dea19eaa060e792d4dd5489d03bbb550145f27f892cee895833083d6da5641d1f6f333857431fe69df6f470c34cc9975b4cff2dfe37e2d3c7cd386858883ddd7510cbf9cece53fd9a08a5cfc0066043a2cd096f65c567961c05262a05a4353e86897155afbf9e1edeb51011fd0fa3734aee17ab46e00367a709cf0cb4e8bf +A = 74fadf846e5c9f317ea76313746d176bc0c518165e9f26922f55945fd5609bc3ad08772232447817e61f36c7f162b6c8586ee02e17572c8c5c1926985edcd89cb859affcaab7b527b9d3ca85909f6d7f37f9c7be0e4a03dbad53732f42bcc33922eb040f85032a93bcdc019b0bcc689aee5da01bdc32e5acb4f9e6d78f +M = 62bcca07b96ea1ecb09b7f5eb48db5a83e969fe9c9d8c8d8f2eac4dd60ae5d9c7d40fe8f952d415a5284d4693b259e23019dfbf9248bbd896118b559463499638721e6e387483370a53633ef17029d9984471aca0e67e0103f87b85453371e4fe15b9fd47f33ba2ceac0b07bb36d8c4e437f0a01c5798c4996fa2d2e71313217b6027696 + +ModInv = 7461c181b33672a74f0197cba22599782855caf46d59b8cb0201c332e348ddf990317065f0c142cf662241cded2e680180a0b60e27ffa68d1bec4587430b42c625112976066a32b41ce1c05ae8bbb9068b32a2bd6dd15fdd1f76c81d5ea55b1f0ef441ff687f59b73ff9ca138fb01e5d9fb17df0880eb7e9457801a4d3c5d8c3f54ed +A = adb40a6cc8782edc6fd57543afabcc5604a33a481fd25dd18982aa8bfa01ae54d49633f89baffb05a81d7d24563aade19b1a5d3e238b3d9ef14dabd69cb938c92c57215c58da6ffe6666fa72766dfa900d4688e108832a6f30c077c8cd55101cd4685a5c468964c38c4119613698c2a7af9eab79b0056dd177d2c700d84d +M = 17c5b049342bb129070b45408e57181bddf7cbb45697ceb2db1a99e6026f9d2d1a44aa8b65edcafbabae1237d9599af21248b3c55f009fcfbd2409b775537d77ef456c892a486ad560aaa5c3d6543d05f68f2f33756584e354bbe7b10827306a6d28ecb5d23309b6d2590dfd9f0e25762c5366248a141c7ccb3b72bfcb60e4f96b0e5c + +ModInv = 20acd0aeda594a12de0be7757360ab80a31f22569dd982247e9d0291a8a9a1328df7e0ae5270291bcb82fc0a4e1b68a4b5c984fa733627852606b0a6d983c0e5ea8c0f75785b36f2d62b541747496bc1c9bb39b47fe4c7ad66983752c3c9ce0222cc61caf5029b913f126d8debdeb6ce02df98a6ea0420fdb59cbcb4752a4dae0e988 +A = -bf30b55f5d1ff30765a8bcb1ccbe07d7ef810cfc3dc1e11502669b98537e32f6ffa49275dc84c7fb7f2c66a2ffa0c60f8fe0a62695279070962c5fdd707eb8d3af23681c2889290464c5c9307bec60973af4e709be9c8e3b7512175dbc22f1d5effedcda26fb32b27cadc29f12fbc2b9546e0f0220f3edb7f1d5cbf15150 +M = 1345b0e9c2b43197c59b7a6f3f382d40f8ce02e1c29267dcd91c8f19832774212c0feaafdd271c68193578e726fffca2e4103919dadcefe0b3027f905949f304dca1ab260db342ed25d1989c8d81a9e520ad2abbcbcddc80819e8de8bc71f23002c45aefe90ebcbcb30e039ce26b09a7e0b4cdb3d8c88ab7063e8d7e3c1131ec137e65 + +ModInv = 1aca5a462529cdc717d2ed10e12843a54f686912239ff0b4025dcf016503882139fbbadc1a399ef589269332742c6d925db185470cf6ca9953fdf4c8b671d5b7cebc8c043aee4ef5f123c28c0582558d03b2e3a5c4010f7914b46233fd83c657ddfb01b014e5f55d840b79d5bbdfa5b681d29923d1f80da37b8b1eed4f496da530d +A = 7c349d38e3ee614204439253ea771ede4a8f88ca7d4a778a0b60a502e9a47eab53372c58435c6a978053a01cd672c9fc66ce02975f8fb3ac9dd15cdf9d70f12444fb01d3bdc021b6214042a94cc30ef34de6440ce235401a3a8d85ecdb2606c447a6fbb54b9c5214b67b93571d9d6a71f2223ff559a0f9f65923cd85132c85 +M = 708b209042fee6851111c610bdec57590ad14cc53886731f2346b8e3de2a705f5f611a7f2c5bd44d67bbede7a3573ae22351e253ea7d3fa7e1e65f50ce9939527456c8a0cc5625c8585d188d89c0dde361941b824530598fd79f601618e03ae241c1fd0bdd721a7e73c8bc08990924ae05b837bfbe440a67f5e58956140e25927068 + +ModInv = a6c03079c70a5ba37f7cd6f4eaf2403881d08fe55b126720681e46e3aba92950114421af440df80de364ab414e8fcfdb0a314e6257b34ae8a3f49527d99918bd9a2f3908af5011c3d9ffc56f7ccdfc164f08ffcd16b3310e881dad7335f5298cc32fcc7c324eb2912cff46bbff3f6b1383f9b9d831dff603e8c4de42ffa3735fe756 +A = 19018bbf1acc8382b4ef4e292a463c7e0269edac79ca6e13f46772956fba87323d4226340b4be408177665168afbbf4661fdbb36cc93f53cf7a04ace50324fc41a0d5ad0e721c6c4ef664b80c29d6e2add81c2e051fbafdcfbbb5eeb6dbeda7a7c7ca485c6eecdbd37c64d13dd0cb9fecef7077cc3c602030c06ab2e21172d +M = e5445f7db1ff69ef7335372477b244926a424df37ea24cc8eb38754d6c2d741de2ef2bf4b077c98fb7e2040525d06dcbc86f376d37e8c6ef96d9dd56002675053087a3ee7d60b106728823e686672355aca2a0edf46df8790ba95a8e3ffc98782bf7dd69cf342265e6d6fc5d96cc82bdb47203d28c0976bb95db567433089217873d + +ModInv = 10f260e0570ca0b6ce265d1f2bd242a39bae5cb58007c98aef8a06619b4c460eab3d3fc1d272be03307c51194edd7983bde804ceef8476828a0a7b571eafa9472a2527ef438c7d20000aacded33b4942877d407964d8427b20fb34357a937cf8f1e1eb9e943d324912d889f061a64682cecd805f6350835a592e2c204048f3f090 +A = 448bce8f963095fd1a609df92e29017c7fd174cb938017452bdf6c649c220aa9653e09f78221d08196c394627a320165c301696ae878eea286a5bda877f3160c08f43bdf7e2b5b16e25acf77593a695d105c864ba75fa96aa8d0ad82a4aa10f42bc27e528f6dfd28bbf31fc4594437e38bb0203c63f4822ebac3a3265d65b94b +M = cf5a263d2f55ff21184ebe64b4231bb874835dfa91c3c6b49a5f3843a25876a0fa57a9a51694bd6cec42e7a5333bf25ba3340d9c892ef78b0f74941859a506583507c897a2be22c030478f66bdd008ceb8582a7a809d736c933dc4f8714ad7d0a459b39884551322a2d896febde135c5475ddf205d5c8eb1c256d01ad0533e0395 + +ModInv = 1b6411de5044d3f743418d4b94d31cbf17dc3de3522d494025033a2a45a1181af1e1f63b2efe10d962f159c0f03b27db1024a1a90fe02b6746129197cd88213339bac3e62f86fcce1891065b93befe01b964cb78d7c8e677e273c2d1859ce20d91aee0258efbcb2f6c7c306d962f4172b604de7a14052a424a57e4cf38e2b33f +A = -2768dd7cad1a2fb79863b7e6c6cc32d94a23e12368dfaab154beaf95ccb620d9a01894934cfb6e77edcb46d03f636e22c55e6b64bfb749bdeece9af45cb8c92a67ced7384bf4eac10f5dab7e5e834c0f2571f36ec219b61d4485106fdcded4b961cae9a673d45434de52be468a63b18a93d991a72b7bc694eb04e5f7cfcc0b926f +M = 2284e8bc2eb62ce74d035f4ded2fd4695eec1f7d00de9e7bdf3d3d2bf762e4455597b2acb07272715cafab7b1a367a2a15039697fc35550bc51c92fca2ed11a5156277cdf52869d00900ac8416996d5a9b9ec6e3e7716097fb3775e09dd574d258df6f5aebf7d37fd7db4b8b866255d2bc1a8608723b24877954d7616fab6422 + +ModInv = b7416b2cf877e87fb3dfb70646a587d637f72ee854116a23fc4fb6c452351224cf63b791cc9be03ee686d245a088795a7840589e238cb319844cdfe68a2ee12bce088af86c16df193d7b36ae3b0c4f5d4fca2b2771084fab05b23a8c8eb8a961f3052fd82932f4c4265ebf8b9d8f3df251dcf33540bfe98b168899c9318aff6d +A = b3c045741d4cc05ca9abdabadb9019f60ee621834e34ec27a5a7a736218fca397856aa510f19845dc5acba0d5d11cced3cb6d87cab4b3c8284bf53fef322bd45025bb41cb2e641cd1c7aa31bbd50e6fa74bc6e272562540ae83fe8a214ad461558a260a6273aac77fef2ad108f583e20b534897f600b5977440eabbbb235b850a5 +M = fca35c9a955ee20e65ea0c762d1654150907a5a7b3b1fdeda88822245461ca3cc2a91a9aa41ee090a9d2fbe83f09fafdb7b8399353c37f6568e07d07a936da9252036780c161ddcaaebee86e2ddb9d7057253a8f0fc674ea09976024c724a2c5451d77db97b8181901cb1516fd4f1f78845f43e8e0adb9241cfbc2751ff563b4 + +ModInv = 21f61fd242dad254309b7ee23ac2fb8386c8f63309c945e14d8145f621bb0403bfc4f74c09f40130cc4ab76488bb22a8e60d812bdfeea53e1fd34346953a544eb22eae938a59d97e8596015e4c70d7cba617c4857927463cb6819ebefa5f561128274c806b6937c95fb781d687bdf2598a86a856b256c7030363f9d8613f9cac +A = d1cb527368b873271845a11b96b5af58943df54639e7746c569d0be4b44b64eca25a1343b7a08283d17367ecc2199bec3d1c82ca698668859dbdfbf5e98a264ac7c660ee5751f0861d8a3de26ab8c15fe273ac65cd6a4596aad2074c79938264373888113d43be7167b197c2e9634cd5c14418ce6e79556a23f48e121e068c57e4 +M = 63319ae1311b6dcc4705c97a5562bf526e1d55e25222d25abc4e9808f50697d0ec1fb99d6444c49431245ebc59bb1a4c6092f09937a3f39f29a08bac26945c5b76ce1596b0c817302c447ff09b184890e11058325786866975c560579952dd3ddf84c801a9bd3a5dab06755fccc3be9b02cdb5cfeb4341810043e3604bb056c1 + +ModInv = a5e5e9e9a39819f145333fe5686279c17db9aad75ec569abf8cbb52f17c4f5e880bc203fccb31d4f63597405b6a3a5387ac801526b496cfa840937e1a74a4341e88bf03f8262c90f45f55ff924d0962336c4df06e477eef930d82584c961b5c66e5f00303946732302b4d465e5d2a5bb70547302a6fc49ea74e91d09e20bc1 +A = d085b28be5fb923a256b0992f6afdf63c554b8bd34a706b20fe584e16ebcf7bef3d84286fd2e5e2016968c33d20d213fc9276931b01161580cb74eb42ef130df2fd904481e665c574df8e341caab0e00f7043664ad01b7a2f1df488f7ebc7577e5ca369e91f7567d2a8a28cf3b2dc8111a9b6c8015448be9748fa637695b6300f7a1 +M = ef79818117b278758713f21bb161a2a5783fe1489fc4c3bc26de368ee615efd28bd2d9777067139498d14850fc3674d85dfca70a083e9b230529cef6e7759920bb982fe64d88c08c3df1b265bdfaad3a24d93a09b06916c8dd79b5d661dd0b6e0906100b302a985bcda7af125d19e84077a2a3a0e0638240671bb5439fccfd + +ModInv = 69ca3d80fc19af84ad2b8d865d143bba71e38d1f97c58efd7953610807f711e325622688e3d66eb3750877cb2631f2bad67d4a03439f12629b9f152fd44dbaed5bdc8df05791a7f2c1d4dc571ee4e4ce48d9ba4cc16b018248a45454fd60de906f5c89ceec95e1ab1f6edf95897fd3a71e72dc8f048ccefedec3e74801ad3d +A = 17ad6310b9a17a956cd22bd8626a0f122b7d65445496abd4487128344e4ad45e4a0f180d10552a0198cfd108f8dbcbe5a23d273bb07560009cc6ed308b2660e9fd14025e69ec3b36652da84529b2b48e3c21a894869e13879748a2dbfb96117fc2b4f9cfac4ce6e28ce97523bdee45c299d7ba2eecac359cc125a5319a80f565e22c +M = 883f5b05e2ab87b5ac6f2603e9df31469222fe0e057fdfe77ca750160c1dc006e3ea84ef2b30f44ad2ed8fbec6ad94761534b628a3846b8d453da2458da0ced9f9c88faecbfb4853db417414cee2b44f1d6b315faee6b0f3564c4ea3627ef564308424d34113660943c3c9bf76e32576d7cc6294cf4c4b7ffd984fa0c88d3f + +ModInv = a9095e620f2abedb7e04deb2f902c2422f676b2cece788c8b4610f40f4877203ef54766fa4d2e7c29ac5e5947f6dae38a8303963b13c56844bb06108de2407818dfbfb9827ee64358c43a2c6e23dfca9b4d58b63fedfe9929cb48eea63479c390a43681bdbe2dfc00cf808427639c8d05b6c113dc7d1c928604d8c668470f +A = 3d9c386cbf3f1dd65b52b153676420a0a9e7e2243e3476ab905d7b18f31e3b4ae376b839482775294419912e794348de1cf00f2718cc286f19060468aa665378565e5cca78262f7bebdf3b23c9d2fe9e3bbdc20501a1614517f7c221cc823bb5e8e71353dda962faa60f185cbfb41583c59317147019a1d0d0f509ac23a7d2b5e0c9 +M = c13114c8a5955a9b806a192e543bf99b60e98d32ad8a82d36cc71c68331b5402575321b5efb99a54723b6d3cdbfdd2dda14c6e42978e30fa3ef38dff612368aeb269c5a606841001da247b092a092f5abc98cca7719400ded293a6758fb7b1619674f4e4f086dc8f839060ee40cd87e133cc2ffb7dd88819a52fbfa64cc516 + +ModInv = 26e657da0b6073a2548e20fd528ba475b3eca9461d06eda2e3cfd5eacc614f66775543dfff005442c3fc170247e7f6b7ab4b142105f31b86df66f147dc5dd62b4f9430e3659a14354cbfaab0fa0614a6b5314ff4549ea2a6e548beefc3fbb53b12ed421866569f5e1a60734d5fc91375b60c769f1f9d67540d6539b0d7d9 +A = 1c105f86434b16adb9ba449a8684e0766c5bba169882693933f7067527e38774ec2cca271b13cccd2575c4369a6982f38a3ad5df8406df854df458fdace276d372cd51c03b1aebeb1017eca0d105b56350e284beda6f7413d4a1a0b9c8609e34f629eb16457ff5c5a80bde360ba61c02543ab161aeb3467401dfc029088dc571722c61 +M = 2eb8a9f4ec1866d8a3843e8c328eab8fb1db5c1c081dd33873998556ca1f79bdae6c87b93dee379f6a0763a7340cafb42cf646eb189f0d9fa5f5fcbd727ae349c1839555bb8e31e22abba315fee3a6fbbe9b900c63f9919fffc2a2ee8d10f484133423a93583b3531984a1421e90d35b4eee833f2e22f85a96266985a116 + +ModInv = 630e32fb13c20fd61965cd319bfe579149c04f8d4d691dc4b83d92ca8287221a5cff9302ac26396d8d8246946aa70938cf38abfa4c8807b8b0bbc005b2b74fe20d695037cf795e0e59bc7f6e100e8c28b22f22aaaff16cb5faf2f2784a2a82f054b5c4697e10bf44cb4bb60b202f9dae664ac4b9228163b6d2e0df53c27 +A = d9541a6d19c2cbc377f79c4181c14e5b84befe10a7dd62dfa9b6c005e638c247d7e1ed7c568415e1109301819a491bbcd399762bf5c7d5a04f0301518884af2be0c1337931db9d7b2836162b82a35fc263b4204b30bd90ff3fa312647b630f7d42a1324cae8e39e278c19b54aa01f9ef63cd2c0e1089135aebdcd9256ae9713fdfefe7 +M = bf3c14f3ccf065bf843cd6a9f626aafcff691220764ec94eb485601cefef880d484dceade622c9aceab189271ab8800858562dce7998b006bd39e9c3323f971f1fc51e8300d06ad001f246966f41ac3dcd873931d4e3404f1de349bbbcdc341df8e36d689ac84542a6d78165d63f14c32f494940765b6e43fe2fa43027a + +ModInv = 962785b5b56fe463392d4bf1961a2234a22a273e6b07cb357a2d9e8c98dbc1bf78803baf1368113925348f595bf3020a1bb87115e0d65473f279fb12f40550fcc0037aba7151d7963d032224464a00f0b5a5f69ccd5c1b0a6c8082514ada42e1dd717f520eca6bc4e4e7db0838b0a3f969a1b10a3d099ec2f85f64d65a +A = -d02af9e9f642d38ba0404d69acd4f50158c3a66405515bd13567b31def705dcc31d9247c1e32fa1c4ea93b21f0d156a91d363bb1173a076603d1b2290d0871192dcc7fb6944af6c342a528ff8cdd7af0e6873bf8558a9e557a70e3873cff71530ff4d40ee5039515cb2fea2573c3b6b7eb5264df95e73f67abb36654ae06e093ff957795 +M = f2f917ef8ea695a7dd68732befb37f690c5951e04956f29e55f97e4e8e9a91c3615f5d4e41e2c88a44baebd7f31c30c6ae369ffdc27cb584918cf362931b8f8f3b843ab6c9887d29ae5508acebde90c76c0bbae1bbc66f9fe9d61ad9a0aed9519193140df099ba1da29540c377cc2da60ca0282cb465370c69ddc39ee7 + +ModInv = a2efa7764db4999dafb5db27b90882494125f82d7d5ac03700f3bac69f8c75e6bcb404eae1521cce9cc6bd6fa35915d6c01f8a9f136103e137eb59404f18ab13fb6926852f02ef4caea5c9b40b10d2ff0a8da8d6c5167d8cae350cb60d433ece3fed4679fe3474eb5cee16a12df8b06d41d62cc70d596a057425cbaea +A = 729999a56d7c5418794e0c468caea238f56a39d0a5cc0d7218d19958a26bfca61415847a60e6df0299a11d905f100c06f2bf7a8d8c29c8446d485a106e38e734d1d14159081fd2f1c5dfaaa36b37d7972bce59ef0fe8d126e036d634178b18c7d3ac45c2f9a734b258d99ca3eb488d4372ffebae6b33c8779c463a27e350df17526fba27 +M = 115b546101fd78829794adf5b373ee695429b46fb9e268b650c9afd5b0fff5efec5838ec0ccca6ea025a6d77e44365337429bdf709f670235ae4e703cc7c733ea25b971f747aa5971f647d0f0b8faa93ce5189115832ee8f97fd6bb278d373490efe575720515c396d524d9560d078ee0e5e519bb5c44eb93a6a560253 + +ModInv = d3d7795a449526fa06e52b4f35f86a79be6545564e938f2e01dffe9da3b1e29d1cb927ed238ff50771114c627eb1b6771355b7aa36c9a90e510bf8ba8c575c856817c81372de6c7a5f6ce6f1c5d9cdbb251a4dbfbb4f814bb07640e15f07adec3d15e22561b491131961a117fa3f5bfef1ef5a8188e6bdb0b029a33d +A = b1765fd887acb0718f6995e692e5bf6de5e873badc380e8637b6fa2b079607da791a722f477a61583da8606c05fdde9145113ac22462dd0770eb80d50aba8f4c128275024cc40441a79a665c6d382140b4e936d7e89d4eea94e9f9beee7f752b185ae76e3632286f95f9e985f75e9ebb29caf1cd29d7860ef5ddbbbdd02ccab91b1c9eb04f +M = eae70b7b500ffb57371884690147ccda8b3f1af923ebbdf0fa60c10ed31b1f5c33325aef191d1725e3fd103478395c63245f49e92392b3eb2efd1171cf3c9e8b656a30b803029c213c5b590c03f9c510f8586e5c496a25f097385d3208e75defe789a5e1504c70e60ade71a9c8a9a6c708b4bf73844a13047b70a276 + +ModInv = 61ea3b54e0e8f2debfef34756b97f6c1700204f88a169dd9e4dd83c863008074bb845d799973befe96f4697fcccf76c9a808d4d7eb49892a0eafefb727318e730339a6233fcf8ba82971b00953153e552d5f7dd98b88ef0bf7d710fb797c3d9fabcc75525e80616adcadbbee181a16c9589845f72ac388018c63925c +A = -1b89bbd0e6c21ca40dfb5c88c2d4f8df3c791bc70c99df06530cea599963a2508ac60496e70f400ec74adb277705b0d3a75ce5e5fd418b066a04dec5e8ef5d821a9328e8798fa1ab597786d2025f89a64283329a6c6a0a5a9576c1c13aede0af38dcf5d2cd7d1f985b9f4d8e69103f30293986d38da9b0318f0c8599f7ca6402d6232575 +M = 7657e4967c27a82379f940520759f89df78ea6049d67a0e4c501e18e2380aaaac29227bddfc5dcf3ccdb04056d85b5b098ec0f30d9337056d66a33528939783bf53db3f9fec57980f9f7747a5492db8cb8f10618387dece0c9e697580a226ef81cd58c09b6fc4bd71163eb7c9b7ec24acb7a8627f4b55d2741cad61d + +ModInv = 4f47ed6de0ff19dd99a4a3b3dfc1c34f830f443512c915e201b7a0fcafae54a6889f8899368f5b7184d98741a7476ef408f68ad689763e376ef52f88dfe221457cc0fccd742af3de43ae21fa87f739f75ee3f0185f23aa4f819d4779afd22ee339ee790464dde583717ec4a65186d756375f94c3bae1c8bea764f3e7 +A = 44bd17c4f0bd9278f3761de976187965518f2f0729ddbc70472975f7f13114666477dd044b1315b707862927abcba652e387293f1a14a25e8010a0d5797a50a56df3e0a255e1635dc51ee23b041d447f4c11d45c3f0b49d40c33a2b473268d072a7f7ae781b7613e3c8d90974d1a332475dcf58e8e33914dc320c658ab934e5c044d346b0a +M = 4f88801fd2d60e728675b84f694ce1de93b3f74f2dcc406fbdf7a0874667304e46fde103f444e7c50291d5cc37364f6b298da941e90dc013b14baa623476f0ee8c73c325e2914bf79c5962354e50c2fa5a682aabeb044137712135e750a21b69800eae6388286a6a069ce17bcb4b713abdd2d1eb68229943e8affda7 + +ModInv = 245ebfce2406c53335678b002d94bcc10724a047e49c206d97552c82c4a547949395265dfe0b52d4c0bfeea73c2324a7f80083bfdbedb79536c238ac86ae8c65fc58f03605133f807ceb68d70dab3cfa9c5b826b92f2e749f669712b1d0a78c31188ab4af022d52e24afcba3d373be54e8b3f098411ef157c189b +A = a49cb987302ef54d5ee1f8142239c871a91f4923263024d6859bbd95f7208ab93625356354630ad4960bb7be7d86eebb94926384eeb3e56632e72a2e2b5c51c8a4f175f74c7c5f65ab26c3d1df6348f3fa23fe71651fb095901a108362c222ff58c8222856ae17e0c63d7b7febd535e6ec6c8fa07a955dfc40b10e71329d9fe55bb83f96e2eb +M = 1213a18e805099fe24488271b2d95983bc7c4b22619b56846bdd6d52b2700bbb664b17200d6d327118cef625c35a1eed672a538409f01a1d338a65e46a1be82fd193a9e8d1fbf715155c576c266e615f9d6e29b61695996df1a13809167b38de88e8e52e1895409a51bdad76f467239a18089baef558d9572c35af + +ModInv = 964668ff5acaa87a2f6fd8661adc416a5119ec30094c63bbfd74d7a32af2d65d83a2ac72a1f631dd2e5a4fe89550a46044a823306643716c9cc75d25e455eb0fd4a18384754863c8b1bfbcd83ff702db144ff550f0a136f874a44db5cbfcfa4115edf8b91ea9d9806b6ce294d1b0b81284a1116793f6cb74582b81 +A = -8f89c94003132592c984494cc51728ef76f03c3c4277d645b2bec1d4a4ce7304039020b27abb42d41301adbb714a501609e52fe193ce22f8992a7895aa892ee4dce7d0ec21dce4c1ee739618d88d7f868b77f0c27f912d621b2f106f67699e059e6532a4515ce7798c2d5e914c5fed2c0d9ed5102c80de0e89ef1f8a1c6fb1bb4187e4b5100f +M = f145001724f1a146c1115e48cefe33d1ec97851d7345171fe5349814d04b19f8145c9793cfcec67975f88e2186b2b8d5cae62883d1d4ed5fc444fe4ad4551673a1d0bfcf35f005f7dd5697526acc09975ff659460c8dbbceb54be0e768be571775396f91f340080e4a5a85e7b6cdbc43944d70d3edefc6c63c8af2 + +ModInv = 559533076e5b4b9b72b3169318f04d29eb862b96a03f3d1745a93c8e86ceb3532cabba231448f5c63a58b3c1a3c712a9c322a3ee42cd3f638348f6e2a66e134907598ba3e99499bea020ecc14c6887eb31e29176e30e83ad24f06b8110f5678849ea4bfdab6b1c67f754d5e4cf88007d302b01658f027bba5ad7a5 +A = bf2b0eeba2612f368044b63393d3bc997b6c68899beb5a6989288325153049c4bea778c6471b8c0c1f9fb6c9f360a96274d16743b24f0d0aa22625bc10f7976398c1ea79a468cfc6a9788f2d7ec4adb6df0df39658a14a6ea70f8b189bf0f505343c82eae9e2ab0fe5ab6430c1a291738c237545c978b96c59a186c99fca729f9a87e364d2c9 +M = 62c8ce3133dd30530c23b7e92f005bcd3f5cf421689f30c6a3dc73bb1579caece9206de39c509f7e85e9e286d69ea114fb51672b12b3bac14ed4f027a609986a92b4b909e10cbb5a0ac178005f8b795d1809a00aba71acf1bc9903de8c42ae0339ddc4fbba4a14b8c32125b88e71cab7bd7db9b8af6dde3ac20ff4 + +ModInv = 25b38ba97f47c7488d8e78230e3739b680773da11e3519f12f41a9c2acbbd26b321e103e0d035f521a98f9dfc95eb0151e8d72e25b1b46b65366d23739f19c5a59b5eac545c1ab27c45c1c24413f77a21a9435a3d973b5703062bfe2c2953b63389c320e2063b56bf6b5bbbfb11552ee229c0e97d1e4cf4af9ce +A = fb75177118dab2ef14a6e541af4fbe50ed0ad0253b9003bc0c863ad9b07f9a73cf7c6d9d772f407e0fec1f9e0eccf7b9e854aa99d88943ae3792c36c14950adee9ada211b28dc9ef4b8525295e1a4473303ca0176016fdc0ed00c9351d772d451577c8675c053ba440e9bb9997506405bfe1c563c4f025fcdf41237e9965e3de2a6917d0a2524b +M = 7cf0c2aa601e3c71fca768b0e3ff1131f06bd2fac8e19ef7a7c8ac75954813c72137d346670be5d2b26c515730aa3fc8b38632834244ae4e0b96fac92d357c9cb995e406c3bcf65939a99056108f7099235e7d283fbbe7faa014de8fca29a7cdf8eb59d99970603fd9e6c27979ae750cda5e3b3232c8fa3b1bf7 + +ModInv = 1844a66a945ae469bc2e7f7a9a53c435a6f6b05144770c986f0174b5d3f1cbcf1943c1d73846742f2838276c31979edb9afbf564378ea32a0e08ac98e0f0c24ed0c7a203449559baeee2e4b5305204340813e5e8a819e4148537d9411054c54fffbe987cc4b98584a14815cae532e495817d976d05d631cd5032 +A = -da14a60f68ea8f35177e5f2421c0a55137dd2612aca90f4d4c776b1d9b75d704a4c936bbd3f3fa2dd6666d3754fb2edab11c15db48b6f16bc37168783f1f6508318063f3948cbcd41888f7da14a4cbfa1c0ab1f4f79d8ed8b64e6af64c7e9592e33b8b8b0e42aa1240e23aa3c7d35796744a36ddf2717a5d89d43600d42328b31cf80b5235401a +M = 89b9cef1b5ce788c888932bdec502ddd4506fe706d58d579de1ee7048d3a0d6e13c197af98cc4bc86d657198a2c53a44a7e4d5b581bb6236d4f604acbb262c56839be88e368f5fbf9f1c44f969a3d71db0cf3d774f97976d8fa5a51fe3ff1a7347405e86974224f1bae0a21c13a64cfe711502b7c474c084693f + +ModInv = 803a4f73f5b7ce0a3874cfa544805aafd5a55bee4e7af8c5e4a9f25327b972396549a925071775e8d0d3070a5f292caf8f815f7db457a5195806b6832303e651e940aafc701767d5789955ab8febdf3c0912db5dda8abd6f8cd7330f8301348abe6b06baf491e20d3185bbde6371a3a5053e45d64fb7886f237b +A = -f93624a50c55e958163e12dd24d59f6e961061be4a960b67f71590fc77346b298f79a5a57b5776625152e9feb0b0f174f8c4c82f44356dc910e25c7a714d9277d7d9041aed50529b1004f8b5c0fae3a1fe69bb79d330c912a062a823951deab8c41341baf23393ddc9706b0c40c81df579c7162f71584d512e81f861ac8581a39b9155cf426ad9 +M = c79c98458978736f1761845669642cdfd405745130c21f519fcd3f105adc9dbc16f5d301368ed43360f3d54271c276c6e2ecf3c060ad53560f559e2807733141529e0a54384a9a9f9a3591ddbf4ed3001ba271efa3b92b61ebb0db5ebc65d6585198ef3b86e7f0e2ac57195fb3055095d69e7a254313c3bfd992 + +ModInv = 2de650b05439dcc5488883f3c290c9353d7587490859571e7943c5f9064d721711c0591c4cba87ceaf31913a66a77ebe263313bf0a9cc9a3dc70cefa074e81a363b2e55f21ef2f3880bfb60364f19df6c0028d4746cfa03573b26dde44a760ff09c60ce0990e9c4992866ac5910b5423d58c6343981e52cd45 +A = -6add916a8014a3df65b15f38e3f5e16cf6607cb6cc01061d357f01546e6a1635dad8292898d7dc088b0520d4dd8696b504577a93eeda7f0f3dc804bf9e2e232228212861869fa43503922465e827eabe76566c150af38896339ce9e3203dc8561661c4f23a9c8261183ccc945944f59f7a20c69e11e98bd8e4d0718cee490c27e1612d0cbc27c73 +M = 63cd6f3b557fa8aff4e13c1c4f57f16613072d7862274154ce5428523a821f845db581a30cbfda06ae18b4788d83a962acdd0cbe2be07d0a4b30fa789f13d91aceae89e4f5896e1ce08b0c9faa8f199eea9d74ce4c9b1df1e0394db58dbc8bf4e5b2fd2db2f95774a4851b1b5593d7550d4800fca20b394918 + +ModInv = 42901886b3e7c40d71acf8526abfe6a70c13511d43e3aa253339ae781653408d53717db27f30f92253a6c824b7233819fccdb120009d012218519ec5e96b13c7a37cef618f0020c900aeffaac96cb6b6e7b0ab1ad10d08222b3e5e76c3640213145c8a8032230ab722448734b28be2ab342ae87fae03067aa7 +A = -23ea23334e2267024bee63b2c0b2d8a7a103244c3b41b0da9958ac8ec6af14fd6da9d5459e790fa7e96335a8fcad3f43f90d6616080478dce98e54a1cfb7492c5763d8e52b888d113c47c4c1eb2b5e6058f3a309553da63db6a48b93e99a16f77ce008f63303022293a618161119d8a99b4312bd805473ccf2a092af4c6d9257cda74548797e1d2f +M = e08e2b79b5a4d8a2fe9b09ccba4d73cb64d6ad1c864ac218045dccac90a0fc540640faa32546b654ff1267c544f4c2f8fcf679b99a0192c0331ac86259d700b84e52810c96df71f62f081de79743e5491fcbf39470fde8a2834f97b9ed9205506c6aa916893d02526aac666831f05c5b17885ab0cb60bb2536 + +ModInv = 1a08ad3ba11ff328caba64ba96016774002d90d211d5e622bb1ea15264f1310313b335bc53eafbe9c9f1f65882118862b081c3d50f13e3fb9d663ac9143a81a43072a25f229be1b46e8a6095fed58418233a28d549681e32b0b48ea0e1777f5ea9d61bcdd5cba5a603112a48d8284f7f110ae76e395efb6f6d +A = -1daacc81168e78f6589ab0cf42b7dd4770bf9a5fafbdbabc155da7e4e2ee83ae803c7cf6b5fa24947d48a07d297c4d8ff3a5486b0155a215e7198c5f22c96787e2d7c67576b3d74cfbc705abc09b8e7014668da4de82618e0c07e95345f9c1c7bd7197b04734603b77402618b6d0e1690b83d4bd898328938a46bcd6d7b3e080dd9edc0d30a16875 +M = 7740afc4176ad5f5fa2f5eed211572168508a335411bcb17ae610024933a65bc42ef307f39090d67efc987c37dda26ca81ffac9db89237a8654ccfe1eac2749c5f96e29427327cc7fca5a139670a5ec300f6af1357c836f59f536c5f4ed306969a45cf5ddd58d913fb409233b49e25ea132f24a969a8f0162a + +ModInv = 297205eb42c2ad84df7b460e059724fef0f22d479bbc10572741a3a9af6f0485cb8b17acd1e6fd5ad60157f75e4911eda985a4c3feb23972f836a4f9d1d161ebb7a0667f6f3a7f2422a70b2f5f0add98b18b216c2c9fd40509064d330993642534b9904122e9083e8108f07285cdde5239c597f8178a4f05 +A = -ff1f33b2702db2d2e1f3c266e0ce705768b5dc98ba7067bc8b28236092f2f04f08713fb3fb45957b3beb97bde0ac43dc38b96d4e90e65517411ec2764e6d840960b1ff6feb7c329dd135b7f5addc6db7013180457edc1865dcd91705a0d5efe0322965b1b578d6fac7254720cff5942c764c869bd9b803c9484a97a7276366021f8c2ce4f5005f7d8 +M = cfd08ed390febb8aaa650a771c966f8eb03717cb0761ffd78610b4e987825b71c2c47a43686ca24c396229072efc87dc0e2147380f9f9184febe222b1c29a3b87fce52813e95e566c5525df3087a1890cc949607afb680b9ef54ebe71cb01687ac2ddc8b622e3648ad3595a93a8d296df5e298e7e4aceab5 + +ModInv = 4670b22a9901918da55d4801fc058a85fb7853e6df2e3854cb1ae3af42cbb6cd49dd22bfc67bbcd42147bf202405911ce5ac2fcbef07aa8c650e757d96eaf7b28d59602419e77e1495ef1d5b7f568c465a9dcccf328a6161c61f717f695cdeac82ba67ee8dec42faa16de2b7b57e25caa5fd0fde86af5b67 +A = 9be304ee21323122f8b77c366850511abb958c60f69d0807b6e2d8cd84868849d78bac318c7619b053cd3eaab91ca2c0cd9f10cfead74d7669b2cd000b4edf529af21281ddae5f123d4eb4253758526cee99f031570807e1677e08413c17fd467c99ef540bbad4a86c11c04870efea9aab38f50442aecea45b5ccd01d4647a4f5e2658868b73f091a7 +M = f55f0e5feaae067bac50f569e5f9c2777257b810b3932be4ce7697277828ee814da61526627a7aceb5181af180832ce526cf03241f16f14a17296edbdf903bbb5ce10d6c94b757c0b6d0520bcad2f1e5497c0b53f015249f17a72ddefcd02c69c32a8501b794662c06db5c4147037b532bbcb116580d336c + +ModInv = 5bccff021223b106c2f6baa05cbfefe9706ee6e4759fca09ada0108355b2bd8b52a138c09966606c3e8eea75111bd22490bb1930b163c08178994b67577e008bfd9172c3e64d525c65ccc48041fa1286b1e0af5d2335dd9225f0269f10481560c8b92d7426eed90fa218e354b2aed0a7b9f5e5955f8931 +A = a30059024aaa7f36f8898643c7d1a784e9144b438311814956936acf04470a0fa0b33c88399f57ae84e76f8882816e6d8351d743b4eaf69c7d734b70e63e64dc6a6bb70799d80a89180626c91f427b5091d88d786c96845c53d006c6c4d45239bce4db05f201557bf3a8d002c0c7a07e4846adc65391f0c40f3e4fa03cbeca267326d30d841a210f2c1 +M = f3497bec3fad4dc0dd4191d0b649c9acdab642d2fcff9d5e3ba965be75a7612b6f19644a8e55b535d366947467815ae93658e4cf15a283c69a2dba7e8442773f8bd0b0912f15f0f74745a57e2d7b8cb5f45e75b9326b20d167cd5b1f93ad9a51e477724ad11c09a69ae379e254d94d8a8f80a547f05fe8 + +ModInv = 1ddedcac7b37ba742af956d8f0aee4d193d223fa0e2c5beb3e880d23a00167f3f93d3b8d916cac7966a3ed69f064be9f3256936fc7edb0913737005ea6c9eb3598d37fef825435591264b64c508be1180f5a87be04deea61d1ca91191ea1910b24559c4fdad8aa38f7dcc666bb632886527f8fa09c4351 +A = -c65a9dd349da1d6e5569544fa6311ed35e6d8bb942192051c30124be979b329ca3dfdb81ae787c6b2c5364b8aa7741ecb1928ec6aca47aa44b44fd8949d934486838fb5cee81c40f20a988b468798d8d05bbd3a18022587f5dd095c0f2578bfd9cd8d22cebce7e6084cae93bbf0f9dd675176e669065df7de2f5cd31480105ac6c7619a248c186afaff8 +M = 8a60076da6fead07baaf8d8dd93d80f58b346ecb7bb4b41e5e55dc31408bf76634332a2185fe99bda8c5e241ee0f4b65f27385ecfa3b007020f12d520b7d2cde2afdbc12e9ff6856b857ddd2954a6327cb375a94bda73da2af0d1f175106ad3e26059ef682371366213dc209831e82bb8c2e7a89bc909f + +ModInv = 9e7815935e768d84fd0ac7d63c58944a1216d8350c16753dcc3828c7194e258df781a943c9d4ac6fd5cd1d33ccb9f116a0482b0ea221b850d688ceaa5704cbfacc976cbcf29fa6434d5d14d058906c25586bf9856ace232a77231e38c8ed4c1d1f060da4f8b615ad5160bda081422795861631df1c +A = -60e77c1ecc99de5e06269b8b33d42cf4f93f2eace5bbbe7fb00ae059f267ed890b8372ab22644cd81232b757ac0d7725eef95dfbbb69cb20d24658c11926593f83f1a4f55fb60a472a6e3e52c1cff12ce69d74dc551e19779050626afc0f1f5fb9f753ac116f6cefd376775f6e05c8290813ec6f86a32aeac055d71ed0b3f8a94121d8451290fd51480c1ad3 +M = b6dd75ef01c57e4c517e62d9ff85f0f95dc1e11322a7b15bc8144e27bc7ce113753cef876f85ef6a8d7c73c1bd04d82ea0727159448b522846b97c599a026ad25c326a75e6b5566a852be2ff9d24b9c93ce7bfe9367301fbc2b9c843a8fc8164fb46f6b2347048e96849661f5cb1fa87603385fb7d + +ModInv = b70f9519c4ec15fa78e84a0c8cc5603fea604aeaa172886f3f0617fae2e7085bb94f42acf33babd58ae42b509bdb9516271f96e591409dff6f13e7ae5b943a4096a0d929c80377f381592f5d27e6ab1c50a630edcaeb48bce434058d002509b698127e3ce36bb512fbb0006bf16487a0eb844f5fc8 +A = 8fb15bb7165b48ebe0b5f7eb1035f42c19a0b7278f887afc0c1a8f989ba16a95ad326dcd68b6c820c450f08b9ae8cbee1534c0cf81c9a07fe3a6b411eb4d14489020e18aaef7a5990f861705881be7b590d36718c812371c1d7348abec79e810f382f42c2958b54b0481e0d8c25b8b051da33c30a7dbc54ad63724361193205e342fcf830f8f0f4b071ce204 +M = bf56ce2f973f71ca99ab1b89377714f0e23f19dd37d11a83011c0b3975a49c2acf01909fac26227f4003b0e7595dea8eb10b6ba9d6c84be50f22e2fa0e4954514c5548365651f570f6582e4eb2d0d8a6892facedc8446a0650d7160e69211bff47072958e8bddf2cd3a28aa42e43db32321c642123 + +ModInv = 17cf7db0b802f52a2098f765381dfcb72b52cb0636c0337cd0ee45addb477c14a8d1786823ce71eeb1d3e718afc355b076d348bb3fbeb1216abae478b584aa66be4431b79630fde3f2593ebc65001679043e83b498ab1da36b7dcb8bca284023cc41f429a23ef5caa78dce924a1a44bd460a19fd +A = 9e3aec3a5c5bdf39a3fe5124f62000f7d0d1ba907298b41e557b8bb1688a77334c4f286d4c002303aef5f1ef69ddfb35a0c30513ed417f66e9a0eafb46ed194b5d7befe38f6eff9d6130e0fa4733704edf722288bb2c7749d27d10270728c90ee99e80289cc58f1f914bbbcc0c96dde2f42d00787102865bec0727562471eab1091f8feed9b421371698bbbde1 +M = 4ac8a14d865fa60cf72929aae29abcd3953434b959fae3c13cd1921cd97577b5aaedb8163dd1502d8e20c22c4bffd5fbad3aa51acf4a6a140c44a1611bf24a260c465535bc6588549b15d77916cf6e7628d4170f300e9a6824c90082295756ef9668f5dc8b8495daa7115e8be1cba6cd1084e094 + +ModInv = e4b53a7d20ff9dc98bbaea49a38c5f4cbe10132780759642f128d893e7dd4061c4ee1203234af185caa7a1aeb67e39cec342af1e09fba33550754777db8780164072f1675717a545955e87b21da1ad4de230a516366037e2cec7625a4ad3e5c45767dacb7441af5f44ba1978db0889fb7ccdcf +A = -2a31ddf4b26fcd69d7af45dab636f020d3589aaa84ebd38670c4e9812f3d1e6cd8a28e359ac2b7b306cd2f92e2ddb5ed2b19fd9f45109613522f135732b636dc3b6b69b44b3524c12d24119b74d8111ed5fa284c68d17f3f839288eafb9f6410e3f58eed7c99aa2965dc6fee88515549bd43cd4ea8a3f0b302f7f93e3309d784059ae400d4df1ed7bb76d27719 +M = 31cab02d36036a2695879f6290580956b5075e0c9c05c781335933eec9e7de1a3a20154cc608af0950ea0802e7963f610c525d19726b61611dca4d9103f055df21d19adb48ebed29aab07b187836bc39e2df679318c58d4b86274d3676df262369748c1df33faf76a4a3eb13318dc6f7c4c017c8 + +ModInv = be67b1686031a08497389e74639a680cf56c9e64e6c2ca8b152794f4b5195c72b13690e5103f9f262042f40efe3c3350c9c1e121b28b2edc62c1d3342614f4dfd2ee30ab292a924db86d966f5d04f61b819a3d9018097677a3ea8ce9669e4bacb117245538573026d9d01d31f1567ba4a4045 +A = -b6940661e057586cfd13821c35f404cfa1795c928b4ee2c81578533c96066fddf52d007c2a6f8ec52fe0c18fa6227a5b2aed55359cf94b83e940025c6b19a665af65c7c57d934d98c5753c3029c46c2b74d65b19e3989e28e392956b6e2c41a33ba36361d7bf4ff737ab1de3fbb56fdefb50952fce72dafc72e11dbd27326d464d3d20d9a77e84f96377132ba0d0 +M = 340d9d4b205263e708ba1e9600b7d034d772404f9f28f493a4ed28044ec837a64a2ff971dc924877cfb9a3842726e2ebdb7b1c44560a52e79d4beb389586e744ba9fd370c9974b555ccdbecc29b1bd040fc5173098c897562b980ebf0c4035832211b3f95eb0b9d03c3817a95ac01d952a8b65 + +ModInv = 804deda2c85acc8fbc18503873e17a509ea04682826ab2baf9b8bc90fbf45168a78109576d711ac0d7292465c50a5f9a43a1ae290af33413a87185a41473289c29d4cde2965c14166c6db310fdbc647ad6f6af2fbb5357002cba03eb6512c1c4cd1b5a5af0a87f054e1f3b7438890604fda10 +A = 57d9d52035084a5b2e90c5b9ac5a36bd350cafe302ad9fbf3c2d6ed33b49acbed2589a2f64fd1004b0dc2327baccf00fb85aee2c32b6a05a5376face8bf520945838a26edf8c6f2a3cc432fdb6e2981802d0223be518b5f762b1516824c13fbb44fe0c4c99efb4726b48fc46f6c3d3a2696a9f6ef938317474b2df651d5b4fd581657cbfe1a6b89e3d95e2563940 +M = e65e40001ce41c3ec6cb7e77610301ffa86f0eeec6e14262a097ef19f5cd1001f025529ac3a2463c99c4f1b71d52127e3acae2f3168059ea914fbaf0551cd541211950f5932389f22104f385370454df7eb098de7fd1d1705fed56874521bd37eb29e5223f0f203b9a807b84ddedef972352f + +ModInv = 2eed0eebc2a25fe91202fb062c7173423cf6c1ebffef600558c909d30ee778853665ad7064cd74d0424864c3e680d59e0fa3034deaa20bfb26ba1abc90ebc161f30a46caa4d21e68fb5f1ff66bc69b77fb3948a8233ba1c6c5f82fa4453d4e589b2910a47c73d517128ee59c1ca3f8f4e8244 +A = 323410b76e91238b1bf16bb0134a326ca7c43306773c1f1f08e58ee66981d7c5f5aea69619bebf9be0f73009c5dcd90c07332958e53cfcf393c8fc1e4a1a3949ab07f8a4ac802f89d2bcc81832516461cb8cc48e6ed3b0150d9d51c7c6be04013dce5b8536c06ec4f0ddd7ede4f865bcfe484f45f4f44c8a25077a99fc1890aedb73baff48995e6996ce8add1e25 +M = 7cdff7e4745b88a85581f040ab30136d597c2de60de9a15db0eb3af98318fd791cf94179516be86870d7a2921a35a84d6ee6531cb16f839041690f5913f586da0a84bb20b71e4efb8f18f9d4a47d628b48cd3e72e719605f0c3bed62d8f9fb9e59b0f2eea81b5d91767b2dca9c225e1f97267 + +ModInv = b0b1241a7019978432c7919214ffcb7255be7a3db29ee50127e0a0a009a4eab38a503c4e445db1437c6553c92015a52510e509db4f00f2796657dec0baa8da2bfdcebc0ff419d3512b4669a40862d9eaacdaf0cf64f9bd6bc0d419f073bb0ec1c9cb7c20d9c84165cc973707b61e5ff9f780 +A = -4e0d1cbe1397663aa13b774ae82a04b88e36ee6827c2cb80f70eb8fa89c54e54a73e64d3f34ff6436332e310fa2ff1aba89855df6cca8abe7633625fb9ed0e088f6e26810decbb7fea593be9632757ffc9a55ec27fe5c2fcfcae5b2a6a6ea69938e1c31cdf477c8d3f84c31b48e919520394b95133a4a950b4c10deee39eda58604130496a72820b9400d308732cb2 +M = d58353e746c2883e82d158b602261b8ccfa2d52115183072ea83ea66bed2fff43a94e6b85b3af103dc62b29986d5dacbe8831dc0049f84ff9e04a6be8f6d585d44590bb015cf305f9dd004c15be1bc7210e59f93abf1ae81c7b51f0cf2445402602a6700c17ff08ef16347d3987d8e11e163 + +ModInv = 1a2e510b30911dff8199f8d819fbec05f4f3264cc21e6c967b9cea9ca09c495ca463eb482889c3598a436aef215670278e362aae1a367e3eb366dc4404a3d3a46dda7a97e3af64e21a03e52d5db356e54912fc6d37f2e8a202a53da49ce325ad7bdc6dbbbb10c268458d318cdec9bd4b3d21 +A = 505b9ffa26a5ff989b9f91111c89a2cc3ea4c4c775be0b23cc4cb328715e439265ea84e35ddc5dd2fb524c57bb58a2d08383909e70b66223801037a7fa999e8374f4b3394c2d880b38defcc3aace9e125b17309062e9118bb8ec2701a363ee6140c622e9a585b5cea22559ea4bd6a6b5584f3e3235707b77b18a49af00d44d4074160f35b3e79493836e646628a325 +M = 3f3073bc102b101817ce1348800200f7e1f5f93a3e5083c0d89eea6e482f5c443449cc33195a4d0c61fbdec2141535543667f1db4df7ff868b70a846e1e562824fa733c11771fe078088d1dbc9157c370682a55ce89df8eead90d591dfdb0424ec334698eb1b6dc86142c247d940f4d01306 + +ModInv = 3741d571a28131b5c2031bd30e6cd1f1bf06eb6d39b1c3121dd72ca018fa20e358172ae1c5624dac8ca0a6981ed2bd9f71069554734d719bd495d1abd3e85a87f33f2104a58b9c9c0e47cbf20cab2407fb055519945f414219136b5a34f720a1f488f00cc29940516adfa41c0aef8cc22ea3 +A = -a8a3e675b96eca375a0310c19830c925c537631d5f16c1eb248847a0542fdcb028aeca010635798c456e41054c7ca3860ea22076d9564238e4e609e95f20a5d9996b3a1b1143a5c731dce65fc7aa265f68e886cb379bd26a384df4493e8f003cf16d8a725b26ef7085a149a865e14f715aab822065e88768aaffbb4d476c8e8ee2ffbc8b4ff15bc5fa971249ea5f91 +M = 78aafc028e2ed3a5c04ae307bf2003aa5d7b8ed77d16930df27b345d7fd59e9d7b54cf37cd61e62e95d3c941aae632dd0574fad7fc705836cb431578f101fe99977874cb0135bb0c560aca8fd931cf3b4cd5e41d0d5d9863ed4b2132b06a5d4d173311f350c5964b11028c85f28a614bdbac + +ModInv = 324e46e955320127e35dbb1fe2d9a8a264c9438761fd8a59d9635762ee8e0927aa939e0b649924201e204a5f821c2dd962dd8d4a7ba45bbeeef5db79b741e46318aa814ad0ed358bbf0aef012a7b83489e73657365f4890f98f46b0497c22c5803c2d85b6deb712fce3cdf755354cd3008 +A = -117bcc9b132f34b497de715d758126d499e1c889985d8ddba8429dcacafed210f9b61250efa99f1fddae6f32ba6b2000f748301d13f0e93065867e275fc2ee67ed2d2cb53978af6329acec045644546ce90b54cf01613f3ce2c9053170f9009e0b1c1cdd0bd2c0d621d38d1b8eb16c1b2ce4d00d7cb9ab37ff1921d9de2fa4217dcac0497b391421dce31b1782ada391 +M = 330a65e2a44072b266dfbdb300569cb25e75c153889aaa7ecd27abe1885d457e04a7168e3b526227db1bde59efacab07e44fc5256a8db5bcfdaf1918a576be4ae6605f83ae16ed77334aa8a852b5ee5fa97e6e7c01b3502d5bbc35aa6947981b30cfe810b48990512eb899b014d40267d3 + +ModInv = 7f55d45ad5dd9609585b2f0395892b02a30902c5f01ef809ed55b326d157261db15e48f2be17f6c8143abe9765ccfff7f516565f043449ea5297daf0b07e4362abb3f59432469c698d4b9f9833fc03f294098ded8b149b6461933b9bb8a0bbea4d9032226869f61b7be125b092354630eb +A = 7b3308f21322da8d8cce9527d7af308b7669fbb7aeb9281921b4f7a575d2a359332629d1cc684397a3c00f0c9ef9d4e35768645293657d4dc0aca7d343bd0355073fa6c989bf545ad4e147e2dea3d2740fbab52e8c29cb202bbe9055b7728824ad8676e848bdab1b57d40393b994f9b32f3037f6e631a952fb0d9eac56e1324d9771eaac4da60f889740d4d432007303 +M = e7afb92a2cb534d4958dc45d3665c97c96a43fe3451a5925f96b5a5740ba3bb290fc310e4cbfd6f924b1bcf541278fc4fb275d7b941c7014fb18430dba55a09384483fc200c22358ebc10dfb4ca42b8c6f847bcde88622a6c010e3491f4bb2cea7d5f9f9dffbe48ca9d7def8a75515cd90 + +ModInv = 4cfa6c5bc889da4142e89ae17e30daeb7fb4a674d71c1aa108edade8e4f58f4fde2557d093050f1ddfe1dceadf5e69d41d8535f6e39056c3adc405a3559da8715362719be628b006a2f70121cbc9877c1f990c3616d27f136d44be00686077bef5cb17f418b49ce27a83bccea8c477225 +A = fdd009a11f187e72ec6d045256560ec6101f35532f632974c4f8d78e7e1694b7d9773ac7404038f4a64704fd48f0d40ab59bcbf66541c4e2099a38d67723e252ffcf104053a407134a29d77e792f97eee4809fb86b2e1796e899f907078280d7a9ffb764614473d2cd845cc6685b79af586f2e57d17a9475140f4782b8005be07f0b1ed8b38010ee71d4064ab720754a +M = f04f8b5a8bf0db4647c748b8b5a27ee400a7c829d6884f15d181ce6eca9e2538fb0e3ec1c262ca7a3c21b7250fd9abbb6d7b5879ff1c9b5c461a7db20ea94878d0145c86fab0e5daf770ae9fdc11b48bf35ff16deea8d385f0e114bb4f0dc7ee0c4d0de2ef776413bc26fb4a9f940d3d1 + +ModInv = 9bc90044ff9e3f7c3a7e3222fe3118d370af884da7921af1678aad63af341ce46653d3effd732949f770b9a8e93d265bde32a0fa23cd0e861ad7c5f07abf9331bd9cf03d328fdfe9749b8f0e4137c36816febed6d7c41a16d4df55779cb1e3ceec1287f4f382af7667c81e79ed5307b5 +A = -fdf8d861e3b86ea54843134ef274e2ce2e217654e83263e26aca470dff526f1096f979547ef68672d4936eb62d51c2fa6137a786cc5a40e75e014c1c5417164a6288b82bf5bb3fe49a9de655bacc0e42601146e412892629ac7bcb42ea3ad9f316e40cd920d27c77c8e5427909da41970cbbfeb22fd9136f1c6ab0f20adf5464a89ed3a8bdb1d336246aebffcf105e16f3 +M = ebd18a305a8074e4076fe7efd42e91b7ddabfdc7c8388c129e91e7bd5c83eedca8a9f970aa8a0c51440fe606b5818ee649a1461668cee72d534fc9c08b7c14799362e3e319bf15c2500272b013ab1c67af5e2434aacb8b70c449e9b6a2e6e420f28d28ba4bb0833dfa813d4a8e39c8e2 + +ModInv = 97df128cd9b7f1883db70fe33938e1891239097fafd0e65e6107e35bca147509e1efbc573cd8d8a22c9f455eec5084a895616d6a9ccd098950ce31773029473c16be7c39a756a6f7bc811a1500ccbb1803582e58dcebfe9f4b060e58c08c2f98564ddd0304049f627519f45da1a29e95 +A = -10703fff736ef0cb646cd9cce041daf353cfea7b7026389b528aeb0ef413c6a24d98227ffb9b3f93baca214f77a4ed6827a278e07fa11b173ff9c1d02025b91bbc3f7051f76efb51a341b6f6ba9173ac70e02f7c44063a36d69f6cabaca601922ddb96458b842120f0681f03a6a65764d4ee429acad687b6531b11ff7206be9195cc473f4289ff2b13ec8223dcf8c36413 +M = b87615581ac0e31457dd75ab362955d406cbb5f08ebdaffceaee1b91092d5b187709e2b9bad6683e75c91a7f7465aa9dcbc8273b6d9ec7818a1296c0c5f87f2e8c2274468dd6f8aacd8bb12f596bda422050cf49a04442f084065cfd799da89939193edfc50215a8a37ec59bec177350 + +ModInv = 1d0b6689849811c48abee66ea38bc65b45ca550b4d934c879f600cb516d7b14a58b441d13fdb0b2e5782c81e753e19546baca4c06829257f50d5076b138a73b124a56b4e208f8ef751a9ee5b5a8e5b3bb90e6c556dfb32b1c4b5ec18abc24296ee1b753eadb93ae784ae1b8227b94b +A = -2a4772ef409db1a0b145d5a970d79f6b2c4546e29b312b0d6509dcf794b64e6f1a1b0e84ea5ec1f2414e35761b22f3ef894d4930e7786d5284a322fbd0f930188126cec5f11f94439c92ed230af18360ba9995850f0a2f8a286f82fa6e1bd5c6f956f6b7e6294aa67a316182e62e35290f8c1407df80db99425c49fc1cbc054f6623f1ff87e30924f1c0e7e888fe78ef89dd +M = 47bf69925f95e366a53753cb3944a0c840f731c62894f5cc1db24432e314df7ef62d722dff0531fd777b5c904d5e963df8166bdadf45226cd124e83e2eb9118be905974dbad5dc38648cfffdec152afbea23aaa69c6159750cd76b1595ab9140a8939c923608299975573361c71b50 + +ModInv = 22c5c7e28fe82ad820c8c727cd364c7fd4e9f8b2de1daa1fe466d576e7f0d509afeab34deff32f1dde12021463dcedbb9bdce576492387e311b96a7bfb76cd76d75f71fd7ac038de6e135b3f20c3137d6059d278b849d761b90578a211ecad919b6c3ea830d1106f339adda84f93 +A = 71cf823f9d11f2c0a6abfaf1e963c5e8dd3910fca87cb58289db521d54b61f00ecea13e4dab728a1602445b8f1e2f2584b857dbdf574dbebf6551c80a5dc2c46ec7676a54eb0314031684302efcf7c92192e8291978c203da71bef96064a69c65baf15aa973e52ad4ab9ebed3a0b5b9b40d46ed7b65cc4b8e4376b8e11e2ac18c88959ddfc8d8e9ddb3c88f8b2b97a9baada6b +M = 3080655569d0cbd312c3c05ad87121f109aefe50383882bff37716d696e11c309a3d30bc395885d918decd1e2a35a416e3ee8bec201dc66a9d7f1dd32c0750a4236d2fa375fd2edb103806759c55ca8d1ba01cca321554874bbf16d06f41232e80e7056369814b88c97c2ccfa904 + +ModInv = 17ad29d04d86dfdf41bcfde7312cdaf351fc200a27d8caae4e53f0dffe4a75c1d18c51959a696ce60a06160ff324c1f0aad8247cebcc88ff67d4b1111e9b532718c0927e6e20822b6ff9dc70b577b80eb8021e7aeda32b927ef5c6b51fc811dc0946d27d68421945c382503c2b53 +A = -2158ae1503cd18510febacd27b922b84af1b1fd71a3c8bb87a893d4f7b73670c1b8ef28d4b90ff204de9d5b56eb5537880c7c9469def8c79c498c73bf582414898f276f92df0c44911c87b19429c42d8e0f2a10d3cc4ea8d352c305ab07c76abd3f40d5879395e8a78ed5dd90f47ff30c1352ab390ee41d58904cf586436df1ba9e382f7761aa1834d150104728f08d930ab35 +M = 18a0274d7a6bc0bf9717236845a8a4ede9b56236857790b91ace2cd6713a51f3360aac0802660b246bc39a5756699c3939b7cb02f1d8d82a8a541748c07f21b5e46f9e13f1f3659ddf85b4ce12fa7c2016e8d152d133082e0450c79826962df9e93e89d433a3249be5b637085d28 + +ModInv = 1dc02b8a166e966ef97d466eac65641099cc4565beaf0a96592ac5e04b1aa954938b6df81366c4cd57f98844de962ce8a0209145a77c2028fe75c997547793dc03dfd81813a52d4010cab35de1008422df411e930604e158c3b5acc937ce4da3fcab857e1c574bd8b0c19bf02f +A = 9812753454902987b77515e82092948d800d77a47504bb91750d3e5f7eb921de69504b0cb24a62cf2ff92f454dc0a833b0fbd6971c1cdf22943895b9932a75cdace9ae94f3ee59c29f9406f74fd5dc0bc35853ea68707680c89c197661684bda4c4358b636e42f245a1edb97fe69cfaa24b4b5e0c889900715c4b0cf17f2832ca7b42d41218165833ad02ded911d1cbac849b34b +M = 7d92240061e627a01a068d38fb156ae3e884c797599a85b1eaedda6e2480e9814e7ecaa5c61ec887f1747b70913158633878a85fefff6a4d98970685e78203f151d6094f5cb2aebc5b30f04067dd68333dffd144cbe28e8282add1d61fe1a428083fa009cda6e2e1997b6a6984 + +ModInv = 2c5cb3348710cd5d357440844ed01f7c83662960b155393b382f0725ed5b048733422cca3f46f8e0ce344cb011dd2d6a982f8c304d94170f8008843954800bd53d225b9f657a14e5eb6cc49f7965264c828c57612dc8bdc559b91a8554164f2539ce3a3e564d3b7e5e2ee05ff7 +A = -364ee6c23329163a62e16abe0605e4f1b32a93e57fe46517ae3fb142a11a5772d06761d00d8e9bc55329a3cd998079caa18192a40e2ff84a077e3857d233e846dd14237e7763e55b219d06990f679b01365f1976a56791e7dedcd9e4a62814e32d1c83e66bf1f7b8dfd5606d6dacf6a0ac83adba3ee1dda5e65bcd3203312c907ee36cf5b41c83978ca7957746f8cf256485c155 +M = 4752dd2307b3397953aed1541e4e48429b1a76078e7f16ae3aafac22d1d09a4a6dbad65cedfae2565a140d0e9c6c4451d0d0ad63336f3e0e0522487d69be4cefc3c2314414e73faf89e753bd89e87539b0e5cd95ff397aadee0cf93478593a9703a975977182b8c7d34805105d + +ModInv = 5b14be09ff2b4ad2f0a2020f5584da11c3b685f43b899048bab4ba32dbb1c868d695aa5aa0a18751afebe815cbda87d14747a9615069dfcfa7974176271c637ce3178f6b7141b43de66820510c0979705d090740b0f931d3fff3add2f3ed126d176489e43735e58117797372dd +A = -26654f26b52fdd6f1ca00f2bd63e3fbf66d374e47160ed743be2b9dbbe8bcffa924f68200ff62dae3bd89b0663b94162ec6ddb4b71ef5a5b4204c91d4c55e587d8af10500d9ec2fa1743e2c8f82cb2da319af84b23cc13ab6d6914867bd081e42179a8cfe0ea95a4cd80756e237152a4e8c1fcd5aee1ea5073471b2f428c565946ab7d41c4632f9855f7d3a97e48944b982a0053 +M = 8be79c85d05ce6f4b4d05887c9480d1d1b93e0e50280fac4be8076a2133552250ca30a28333d88c1f09d8227e7a9a0ae1b1c2870339dafd4c97e4a724ab4a681765e273500509631c13264a4778af319266156296eb572d0da55101b95e718f5f3b65b49c4a9520ef35505a293 + +ModInv = b474f38b5addb061672b18dfb86ae44db6101ad57b9253d341456dc91be5b0ae1de3499cce1777fe8f2c278d9dd5ea94cf889992b502e70f45cb77ba9649f34ec90fe38d1ea23dc23d483ba5c397c49acda18a79264dee1a7f3a08ce7110d5bf05e1ced2a571464fd139cd0b +A = 47dd53248c665b269ca897696aabd17cba2300eaaedbca13b2611d344cce5ef40cb8d246e1b7d1b772687485161cbfe3060437b48275c03899c098acf4d6073ee85a52b324a9a8a0de3f3d3ff8c137d0213d6d2edf1ab760103e373ed02feb61abd1c88717d93e1a38d0fd10bcca3ad84487dcd20648067c6fa7c49a11910a42a97e82ad5dc5ce59b81ab8872d0f808ea741c70e42 +M = f1931bc05be1b0f455bcc6939e73a7508d235fa2e9ac13c2aa633a572c1d3649fa7164fe3e6e11c57e6d82b0f7ae3de00fd4f784d9689ade9011891530deaa0889f4c4d099e603bff15e1544d26d28365187c9ee97bab45ae18861701f52e36bc026588a8ab8e890f27b2747 + +ModInv = 25282df867ea2c40326b794d331fb856edd232cd6d51bdc7e09b5946c819d0d3d70dd7caf56ba05c2c50d28e2dead7b68f4c726f946fc39373b778f8a46c7cb493f5d4de10ec84a63baca882dd8a704051159ffc25c17708f2ab8ee74ca945e606dc210d8d2b5606ebf87946 +A = c5ecba5c69e82042f106713d9bc922eb06656fe0c347477b325c9f6d9a430f9e9e8c25f50cbfafdaad33348c037f59ccfb76f5dd44fea5f232d27f05161ad3160c82554be9d33ab293ba069304daa0e884fb85a7392a6674bdd3979381d271c630f5c00644a36f4c96934844ee2af0c7786f1e5004849397e219410008e0b84381ac488f641026a222a752696d44e4ac44437f8d6e +M = 25ba32e26789113615feec5f7116feeedb0f9dff34a249d57a34d49227b86dbc5c315dec36327e2e11632b816c321070a63bf256b1c4767c61f300732505a774d41600044134b6822a798ddd7b3edadd07f63ca5c6d18afc1609d0760629a3d357b35a0543cbf9fb4dbff81d + +ModInv = 9a156f693709e6960ed5f258c14bae86796ac5ce68abd882496305f8b459f9e8b601262182aa9503da4695e5b18030fae7ecee67ddf49da72b62f9f6819ef69cb747711d30acad1df7d8505d5861390974947559ce81cbd87ca7e10856769aa8fd653bd909e47171d30755 +A = ced9f6fcfd63cacec32fb74f7a6d4b1e25a09924a6b41578882346c724773ffb7abc8020bef8d11297947e8ea874208d1d71cead888221f0b207b492e3453cef8b5f5db427029987371a7dfbff350cb577703a72db157ab90719af586571cc69f68d6fd7ce0b3d1d293a5bc8650b99c70b29a84d3b1d86614c66802ba1b5670031766565971af3e7da2e9ee34d099c40902f4ee8ec03 +M = da6fd994d50a83717a870be216aae7915ac1e14fc481a7bd861b5545a78f141bbbe0b121de26cef143b947630910bd731ce6ca98d793d7da4dafb5a0a9905c566be7b3df3d25eaf6ba903def768057ce6aac17ccd79ad7dc0d7e2a22f8532c5c2c66cc5ff89398e1ff39de + +ModInv = 18605fdd4fb7039c8779254fed691e47be4b80a001c8e935e16e542971f2b6b8a1ccb6ce69bfffd8a8ddff3a1297704d28c0530f48dc96d49615bf1dc2b366c89a771896189e997c4d7f972248316639ec24eba3f37456b93e8d8f056d51c24626e49ac4a6ecfd67b8e265 +A = -af70b4a233235948f3cb724a5c39f5fad70d51e25e0d19c1adacfd325d986099afed28ca0c28bbd656099d634b3b37d1cf7d2c4a34383e4783a4f2a57204339263a4474734cf4f1020bdc76e8d22a4fd61fe1e1853b5e4e15b3544d40c9b2f54abe60f609adc462c660c27c8aae1feeff07320fbb5e0045eecb5ffb716ed3db2b5ac0a2ad7f91dce8ef58b6590fa518436cca032d392 +M = 6cd83380b359c822c6a1bb44a92b17a1b4165be3a12eb9a03cceb5fd9634914533c74ca66135a06edc62b19e8a086bb6415030e74d36853a3a96d8b0fba2ce4c21dd2c82c2964efa1b8ecf6adf58465d9753c08c9f4b79079f68d236761d612ba9f21453f3f9c9d98a5b35 + +ModInv = 9786cfd0861d3ef284f211af5b4ae072cb052469a2c92b628e928a8bc326403624439a3cc4f7385777a197256420677f29df5c2bfc6ee50128f9909da047567697a9d23c7fd23b24c861c29b6e069ad1ba402a9c79e47e33e3b8df856b2245ec04b24a1c2ec3a628476 +A = -a3df107924da76e0a3e48b004b072f33525697edaaac2184ac9c867429162e8bb1b4d841e8849a020c19ef734f4c633e3697149b9c80299cebc0f433b790e2cfe3b73a234039f873f462ee7c67f8e1d6a40d58e23c3876fb73013ceb77710f0ae6e90840e7c15ab94e175d3278f39f13c93418a5cdd876a8601f13c0e22a97f8b7b0a8192862a051c51f1c9e10c2d74ea6046cf446659d +M = 659d207d2828ac380f81e9110fd10976f4d3953a0abdd509258df1d2594a1ee369647b0e13bd08e27e20f63904e760eb9fa0357b5df2c36a73753e50fe6c5549b54cdd79d06098c324c5311253142c4c82b72c45fb53a9e4f5406fd2fa990fb78f51c0287e89313398f5 + +ModInv = 7bab468cdc9fdb86d070b16f1bb67ab8a40107d003d1706cb3325ecc1d2d87d7de6ccb558c0638584f466740c4dcc16990e5f6e49c85007b9f32112e581e54971fc5aebedc4c765c2c23e73613e44bcb7fbf0d6a84327bcee1e631e0f6ae7c804ead40d3ad0f158bdfb +A = ffb84c959d948154df91ac42bc2ba3e8075bddfcd313d607a5ae7a97b590fd94a57d73756a9a0a6206bf4cda955d9f4f39aecb546b0abbbd790f852a900ee84836c75699a9acc924e235efb6e62dcb4168cd07dee017b14709d7fd31f80a706f4de07bf8bda3d24cbfa0ab1d4d5299090c6526eef26cc569e88b790ac2d42672ed494d63663a98223995325e1efc672f273edf319e70c3 +M = da5081ed759ddc795229642f939cdf0c448d3babf7bdd2df05b199094646d03f933765788685cb4a8a46c166b97eb39b06e31741d0bc08919a19f540c9362e1c2d2918870ae41d613dd36214eb03dc1e0aa59589071942c2f56356051663aaa7108db6bb06608e84c31 + +ModInv = 2f5b57c0826ac78bec79f64e7d3398da3f7698798619d713a30ff52387831ce4f14082fa7c8bdd9b4e54b4f52843ca2ac81f963686129eea5e6aa4eda75e6402a73d3b2dc780434fbe54e1a36b455f3069e01a465e9806de171820c83370597e2ddb0d4fb18518c371 +A = -8fc12c68f410267a37a6ac967c809125a2b33b2c35833151f8466546c7d82a413fb29cdef0f1957a6a213edef87712f18b8079cecef67fdb5d5e756a09f2e74fe5eaf67c533bde27b9b897bec7de4c7d6aa90ce3e1a883372d41c65cf21d862c8309764b798ae66f795a9045eee8cc7aa1385739f1ef7f5b476a594f63d98cba7c07e710d3af9219638f0bbfa6f365e811362a470742298f +M = bff50952efa073d6020ac6dceedb68a6a421581fb3ed910b8428b874087f885bc1483bab3a048c6e481e053f33d6b180ac8c57fed6ccfa5a18bbf9faf406cc63210c2d5d77a909400f026d4da2cebfd483053fd5b540d8909a98ecd3cc591a87d557b184b7eb9718d0 + +ModInv = ac0926cd638ef0575b8220e168d3539abffa04aa3aba973fd52adab709237849384ef70874707da1c67a89bba60b7e034d599d54aa84eb91280cda8ff6bead88a34b765e555f718ca13abe53ac8b9fa6bdaf0dcbd9189a3325266d65d45f59c20995e29944dec3002 +A = 50dad16bd62671d8aa86c7f8ee7815f290bbb75bf1a1e48655ed8857a6f3b3f9574536a120da73b4c28f9b731a72ebac94ed7da235ee2884c6ac5fb062111efcc872e3319787f19886aeddc8274a204f931aa503fe6db29012c066f0c239b70c327376ff5e6ca8cf6098bb5a5a6212a30a30109b806dd264202bf37d525ff90076e9bbd5540c7b064ec4eace046279da8a0fc281d40025ed +M = 1165bdc6f1284c12eeccd8be4897e71d4d84ed009ab64f45c835b1f32ac9b826cf9127c49770a85a637aed7d01899df6433fafc410fee44ba9880b78074da5541510b18d6039cef54450bcf4d45e6501243065e3838ea7edc67080395239f9b4bbeaf092fab1c46053 + +ModInv = b48b3c1a27896716da0bf84e2b4d4a835e78d5f441de716b63615ca49e738af52aa12735c9c053fc489b9b193e066b88597e9b828bbdbbde63e7340bf5ae58a4bfa9691188d503a1eed4b7e17028a459abf5787e747780c7900b3b62473d969adb8f9da1a2a193e1f +A = -ad60947c22b67920107fa92fa87d4a0a8e01baeb28b129a3a20e6e4636c518c8a49aa0cc39e2ab43ee8364124c72a0a01f1aa54a56742e6445d2391596b9329bafa2903c91a39773b25b227e5f4c885598921961c253599d5d86bf29a8e2a0c82e9c3e6314f4d872c2d3fe5bd2d5e46c11f65763d075a2f66def407707011e21eb5c24e20fb8eb18950657847a3fdda38081b21812ce4a55 +M = 205a5a7ab347fc15bac38df8fe81e6b0258997f96ca29f0943256e647fc4376a3a763b09862a6d420e6f89e30a750783769b4e09a4a520377039db8bdc562d17c8235fd11812c1641d53d07006bd6a08ed43d1e58dc36fe74417a4b7b2bef5cc0116e32e0e97fd27ad + +ModInv = 1e9114f3d8566e3fe927c260f0b2cac2d855cbb2206a438a4d59bc99abd8ef69b142f17c4fcfd1afe58555f05e2002d2bf5f8b6837f6ca1a2cf3824005919d24b7f44de96e4c86e4c52ba5c165e1865b5b8d3149a18859bc68f007079586ae528e156c9599a86f9f +A = -85b7eab123856d30a1bc712ee195db011148aad754f49e619453fc896e6ee1b0a6d570d830434f700b11f5dbfb5ea7a5c892dce0a66369e9363d0c50fc39c89ab09be97ca772fb4404da97a96fd0afac0ec42680d295b8494dd8ec7927a5d11e65308c471fe773474515d5ccc0334cdf29dc19e8c00d3ecd48199299f98f6613be6e39b6fb10809b953110f3180cafeff91fb648dc8800c895 +M = 46987f58804fa7fa98a50eb921ab73c3ad3468542222329fc2d912d02fd3ef17e6baddc407af35782687a9e9cf442c69fad4cc0dd177b9b282c29c0062e250a2549fc6773f8a49ae118c78c3e67ed85dbfad384e5cfaf55cfc2c7776d93adabeaeafb14e5063695c + +ModInv = 49ba75836d2ef18816473c519eb302d48ceaad5c4c27a09c2ca12b6e076547e8a80d18ab3767c16b56a11670357671db655414141bf502c440c2c6ad4d68aa09bd06efb8c144926dcef2c5bd97e69ecae6b799ca5cea3a9f2d4ed20f88662c1e66cdcbac84716217 +A = 827f4c9a467e29de989919bbdfa1892bc39a548dada683949833a95aa8259443446519ceba7a0cf8524379eb4d023bd041a7d73e7ff078e0ab64b148ea9664c4acc2ce2aac951c41830c21f3a702365f682d211ac3da507c379732ad2a64a7df317ae44976633ca0dc27e6c7853167f2100ddc4f50a80a3249823981fc115ae3495fc99a3c030f588e800cd51b1c1f64a4243e821a8b0172a6 +M = bdb7322e9cb8d4d111aac75cea2450d0080aaad6aa6e5d1acb4bcc00c1a1603e8e092a97b2beec04a906579d07e3f70d8106788a30102fccaed1d2cb38b91f16226af8549cd1523b2ba15e2bce7e9c19f2a4b22b70b77e0e833c57def9e52c666595a0f9b15ff775 + +ModInv = 9e7730ad992ecec71ce959e4c74fbcadd1b6d13f5e6b162691da217a264f175e7ca4bc89bb1c29a30adfac0236be0d5e85b987fbbc4e32a767d885af11402417b26b48f289e4e57ac8e3fa3fe374de960b3081b154dd3b6e7f275801e0dcd18f31b6dfd0ab597 +A = -97e3b2994de7a80634b69aea351dcbfcce544963817eb34d4342a1dc9490b1a458cc7c7daaf3e1e3f0591532a0c6107791e4c6cfcb7297a58a639a3c09536a0453986269390ca2568acd960fd6504f4d62b57918cbc5662c8ed41c86fdda51aaa4102102c53e2083efedf2d100cd00f98bfd08014bf454c43b697d3534938f293ca2b4fd7922ebd9af1bbd0e01d152ec58f7a6a271de60401138 +M = e986b4eab0958e9e820fe55849eab4f51e993864aff5f37e51a8534430dac66c73b94bf962866dc01f693c8f4e0bef1ab82ee38a1a5a55c212d047cdd4f057005a026426127b70242b6fc2e2270c87123d4994c05a5730cd4971817cfb09ec66b9198420c95a1 + +ModInv = 40c4be0945ff99b8b57ce39e6d05a66763ca9757ee2fb755e2a25efcd6dc4c710cf73e52dd098bdf6805dfe85b953ed93af5971904f10bc0ff684ff81a9b5ffbae34d9b47f7f6efebd9e003854dcb2d7d7832fa13d0f4a48fd7649af18c555991558e6dbf13280 +A = 8275ffcacfbe0a11fb21750e0a6f5b1f034d31640fae20af4612158e44966f44aac7fa225d1aaa07e7b944f0c301bd8ca046beda8dfce196fe94dff661230151d478a823acaca46a892442040bd484c3c42acfd35ef550a313c82b6d47dbabe2ec1f881824e943360be683684b2091f0575ea55e97517ba0fd2774f54911836e5a026dc4fc564835119c4a2c894c35ad89f7c03380ad74ef1e88 +M = 4860e65fd32eb947368b26b4421246a90de29487194279b54f89036b4ce343f88156cda8646622cf03a31be57ebe8878e6be1ad54b4c5322d0836cec33268db838efa4c0c5b59ca8e83a1dae253af900f46d4caef334c1a73b8eef93d1f667e8957420a31941df + +ModInv = 34cd636023529b9cdd26ba7d5b312b8984056d595ac3561f43bdf1ebcae795503103f50475e7bee9f291bc754debf0b61fab78977280d940220c71ffc687b3c281a183c0a8aabaca8d22c39a16690ced0e797e231f738842d5b0112d1fabb6593735a4039c35 +A = a8cda02b4bdcbe211e88884aa1750d16b4b56e65b5a7d5af419b0ba794ed5db7206564cc6902b796a33a794b057bada277e6fa9f2741acc7db85d50653df399e98b901b375205922d71a55cfd5645203397b2abdd06108198c18d68d0a9de081b8761c4cc698c2baa08027ed31f64ff3f02fe9f6afdf36088060a5cd798e89245d7cf5663b50ede87a7cba4b5d9a01b38a89a72001c0e993cfb946 +M = 3f9cedaea471b258b141886fec7e3516634cd7fd136d65a92aa5f58c9c92baa4d20e69c643bc3a35b042b444960d57abf09fc0567f8ca1bf84e725e40dd22fd07e9f6e3c88b9168b472553dee227bca16020bfbeb5c64b38287c58490bb5133e5eec89ee1225 + +ModInv = 812d28a9042c56d6f4a518366cf225577fa946730a33f6c6a2640cfd20be51e066a6adea1a53bd20ec63792a933aebff364f4520dbe86cbd1dd2cea131f7bbf6ea1a9b526f6d6b56ccbd21df0cfda950f4a8371baa24fd5b92a95e6488c7dc47ab0e1266f046 +A = -de122a36f6e26eadf40673b5194b9b5f5c1cf3b308320eb192dfc577969a0a1c1645e9556e3e1e67f5f073277a1c3bbab4c88bbe3d5aabf3f1318e45a26416f3d5538219e337f284f784e3763b8bb461b49558a7bfc47fc8005ffd4058e38940c9cc8b41c1ea6d1d9f0b596b79c9f2b8c523c6063b2551ab83b226a8597d0948328049a6e2b3f02f40c4d14d52e98f825e19514d1101a85070cf1a +M = ef91203634fd739c2228beaf0b6ddd5d24fb265f3a41cb2e0f2f5a975cc30ef8091df62f32c56d4c1e89e57f8cdd5af97e46195865719711a7cd7db4f64c0457d626ac70cb08614414ad23f47c80dea1b1e42669381915a658ef504bcc3ffe2f3add4e549443 + +ModInv = 1b07aa030a994a92653112bdb89d1aa78bb282eef81d82b3d2476ad391ed1e1c9207a26560350bed93a2308bcf5c3c7311e698997163a53707cd3c3078e234e31ed86167a7597d94d4a86251c624fd6345549e4ddcc154414b5594f0546b3b6a615f5ba046d0 +A = -7c9bbf80ca17b703be0e66d868c2cf1d4a2b12b6a20bb02edf0743175e99412607ad5f76ab14759da618fd7bf78a4d9f8f5ffba5f80a0a58994953040e1e30c9ed0248fc9799a707e36d6004762a223c9f90c95ac96628c438183619322fed157cf9c6b16e2d5cabeb959208f0ebd4950cddd9ce97b5bdf073eed1f149f542e935b87017346b4501eaf6141de9ea6670d3da1fc735df5ef7697fb9 +M = 3fc8443658625af0f3e0d9a54a0d7b25331f4d6bfd8fa506bfc51025dbe58e725d57d30aad4b45038e220bc4621b9439852083d9fca716c40a33acd51e6699f9823c118dc10e774520d7e98d7c358a84c15caad14268108727563ff4bb8cf703c9ffe1668271 + +ModInv = 10cc328c8d9260f3da4e4e71875f945a9ad1ffd19026fc18598572582ef4d1034f3dbb6ac637b8f9f37e5b07a0b1da57d14ca36a5b53af20b232e12433199c5fc57c60bdb59d76ee91f73cd2892b59b7ced9b1cbc5b83d5ded9462bdd905e2fd360d0de9df +A = -1332e84d0706e9a925f879f4a75a8ff00ade38a17564a836ada7144c0432dbfbf441921d213a179e4490fbe060a133ee629f1db37ed53b5be62bc27ae8106d3431f394b1f9a61cf67a23ab7374e8cebb0d7676c07b7062504895d564b58754f086c95a983635819fbca07a708d5e643d7da7b158b64ec24131f660b9ee899c7840ca384b482d3a373627fddfc3ba40ec7ef5df2f9a72818c9a0ee699 +M = 70b5d0aa945abbcb5fe26bc9622bb7311aacd975966ab9a98c6a10edbdcd0b5faa81daf4f1acf78103d0028c8193ab696711b46866011f1b9be0f444c3513821aeb402c416bd1ac575ba2a2f37427be3aa9d824e8682e71a6b7fa8a22e7e409fa381758328 + +ModInv = 85cff4e51e6511c40b3dd739c56a66f1b239187cbfca86fb19c6fbcdb3e680c639aa86dca49ea3160d0dd0b14cd2af43cb426b37fd4f583a2b7da8f0263b570849fd4275ac9344eba2e0848c6f9240186f5b813de551d34538a9c7a9884e90c4028d45965 +A = -6dc986a827d549adb4425f023bb8c2275f7d6dff5881ee94832a530600c345935dafc17063bc3bbdc77d93f9db334ad1258e4c917da3fa0d76777c0028613bee9676f718099c62dbaeacceb853a2a8618ea0213829e53855cbf14b0ed30f1a1a2a3544937da3c0a791768de9cd43c204a2570d6d04f714a56d03c0d895b734cd1e53aed9602e277ad4d0421ce31dc15a524a72128912dbce14440113 +M = 104954379bf8c18c60c8ad50a36dd77442abd2ae90e5f6f12c20dfc858ecf6d847579eb77b3f71bc7dd9a8fab57f39d14a51a5e39e07cf66485850632f80e7a3d5b50f023968e9534ed00216fe81c3684adfb7cd6c45f8ce6eaa5eb8d7c99d53ae5d0a4ea6 + +ModInv = 4ba36af8d80c0046b9c0d2837eccab813d2ef13fa69360ee448cc0ad79005a27ac0d30ebe1d3459ab27b4d166ccc54848c24048fd4d2840255bdc917f0970a9964360f487c44763e86b170820045810ca9b54ef552e7966c1d689f49504b46d2f05ce05 +A = a07db958f263dc7643c405467745d0f56f7e2a24b155974efe7bce2eea18e8a69f906dcd8be6b06fb4283ff81489f9638b4e9b8c1f4fc9940fd410ea4bed18925ef45a658c531238bf1409fce4bd03f56798eb9153afe5119c596990515f4734cfcb048a6465650e9bc23881d9b5d7380ac6315dc1cb4fa738560e7a4e3dd9004785ca44e381ae5e1afedaaa9efaacf910ef1443d9a994a649916389ce +M = f13eba18a5530695e3327efac7afc4bb8405d61980e8b0d5b4f20e37a88b038d29566caad3c128340f16cf4a35674165a72e9d8797835c220f4a08265a46d2bd2ccbc8bd924c51ae8c9de355bd6f9f780f2c718c75379f15dc4f8c08ae74b39a9a3ddc1 + +ModInv = 67b24a145f560daa32b3095ffa613c681ed8ace4f904c5605d2a2d4b817f000e62156cde1cf8125aeac397ce7244e672999fc358b699dd925457659b9ead63d02d3b2dfe609405b56c4ccf3eeb5bf68ef8c303c116f165af822cb0ffc4be3d051fe75ee +A = -2650a28be6f86fb289313ac20c8196a98a4769b7067644133c56502e67cfb39d19e7a7e0779aa8e946ff522f58c23c73ae89bd8f32287bec788f4d08beec830c8c441e4fde49488d3028792674df2d835322f777c3b3b46fe296b84fa2a93508630096024441ac1b3fee29570c736ad646fc06301bfd5ff9ec44af2f5e6b5354c4630e8b08ea730cea2cc55d932885e597a98903993aee12198094f694 +M = b4e63a0933b134790087addbcf7db9da18241e895959479635c46059c4a1858f7687bac6be584a2473a5f10c538280cc64f6a0cafae6e4b9b638af1c7c21df6135a3cc33b38475745e9463a50505db7d7949b6aa1514ded3d6b980cba093fc3ac8009065 + +ModInv = 30335f101c72b74751ebebecb8e612d6a41d0fce5c641381faf12c9d9e20c777d1180cccc5e9854a80384bb91a47d0a399e7e3a29071b1d1125cada7e08509b92b230b559a7b354d990fa12621d9f46012df04859a8df890852bab97e5f4413f561ebc6d +A = eee11b641e430ec035efa8b6e46bd90bc0263201de4936716018b5b8670566fdf35270c91b42badb4ea7f3ba72697c2110972ec3147639c247d55abfd904f8303e9f8c4e8a17fb6e96230e058d8b663a7de66c584506df3d87d36918ca7813825ba2020822f021253b428e1de4cbae57fbc0497cf3e72cdee8cac63a7b4cf8f7345280c02ff359197646ec0804288197efa003245964ce737525660d47 +M = 4fc33c4be740c5f5d2886ca697eca423e929c11dc95d10bfac812d9c31d5808ad55c676bf090350917f9016c5cea6d977f7b6c7d7d6f63a6436b745ab4cc6e04af18086758ae34ddb70d1f057962eeb7e6ee9da5031ad42c538d71675168aea632933502 + +ModInv = 115d66031332a8613008ecbc753d61b2fa534e166563198bd8d0ae2a0362dc89bd1c846954655bd9814e45231f1c6400a9f4db79970ec363cd4ace3ca4bbc1920e5bd8baed753962fdaf4a5788238caca193cfc40e2203163a81a3e1669aafa008b436 +A = -463258f229aa62828288f667d9f0a167cd331d8308f856506751ae2a5670f53d0e0018df1cd6da962faa1d43a3f5b7e58d674afe1e08d8226752d4a79d46b3a74b99e2a0e67a19000f71e32d4721f7e30009b431f209d61b9d52a038cca14fc82225106aea199398e19d5bc60ef6cba82e5c46cd05aff8da29abbd3233de6dad0667eae2f2b4b57caea670a06a908b03294c1cfab2ee1e2987968c091c94 +M = 2235efe68ccf7a28c5072b3ae63cae8cdf43f822663c629669f72fdd2cad852c720885d2642d6ede2517dc2a2269def0e8880ba4277bd21d08757baa6aed5db38524387ba89d80b7e947c87671ef6b0285128c3f3b166d0650d3eb6d1ebb0639ba1151 + +ModInv = 3d399490b062f00183bde7bd6d3099cc4d5adf3f94624aaf62cdb21f12f1dbf417def67d212418cfcc790e128c5b231301da1888013577870412c09bcf2427dab5ed07089bfca50bd92b378b7a2bebf49f6a64fef8c62f9ef404791ba4082ae5529300 +A = -beff684caf40d29d4a9d0a00208bb2f4712a5e62966205d7675359c1aa831440a438b2f0d7b293b838af3363dc3d3980cc03a1763c43a4fe60b7304a4afb349ad7ebc496847067eefc437489dad4a85a1752dd2a61c7162fc657a63cc21fa144eefedeb5c9887a7897d24eda147ef95dafbaadb59d305fc802df9f2ef45be5e55715dbf3e2827a4c77c63fc8c1e6592b681433d47399656679ac82910f90 +M = d0b48832e22925b20e870f245b632fd19d9263403cb89df1a53ffe7d135ed80c2ee249254cbf18361629f41ec4cb1dfd4f4ca55f28edbe564720f8139dddadf87c7301fddaaf2407b3997f8a10c58ed7cfc70f5ae01b34876ae3663fb12b94732a4cb3 + +ModInv = 9efde918c86d544bc6a865e65e077766ac39b4482de9394916defa69bdb749c41d220214aecbe07526ed0001879f6ab398e5d337258c30528e340fc6290d28edab05077b9d25895aeef01ef200e6a02bb59db2f16bd53f623699dadc0b4a9b597ad61 +A = -310e99113360110cf5f308afb94d65f8e3fad683ffcec61828f2998c33af56e4a001b5b81b1a01b49ee04c10170ba3bc195e9c5926cc7e2f60cfe4b5af4306eaeb66348d12dff0f5e052b5b37e8175932da313b7209283e2728c68389be45c8e288355eaeb609038cb5595fe35f9842d3ac9f0df568a983f378f29d95ba9bdb1255ecfd4317354418d3c7706f2c45ffc7ac6f2812afce07b1c4d231e619f +M = 13fa7a5822c73bf8cd92f63fd6b759896cd44758cdc278b60562d1798debc8f7eee02113c52703913d2aa25ab57a4584a56e00117fa2811c1bb2dbb57dfa26d69e2e98b6dc164aa5c77bebc53eed6a83d398cd4512f508416b95845e908bc436c27f8c + +ModInv = 135e0099c64fd6bc46d3b0e919435edd9493911f0141f1920f4f787fd4da6e3ca9cd69c3a4d7ebc02f166ace104c4fbbd8577fb186b499ac6d29319f15fb786a1d31b25dc0343b703f76297d8df9ee38c256642c9090dc595ca902e095f07645b896 +A = -303fc7ec5d503eceb2371a8a4770d29b68b79c0f49ddb2df01a1dc619e55e9885890ef49f7fdc6667ffa424d57d38c7adc454dd0c9ffb530b1ca6f04d63ca0692362061794759acd125a8dc7b9d2b3602c3887b01176b058d78c92f06a86f9e35c1ef841ed8d550f4189d71c25b0672e39bd6516565696aa39158ebc78e5ce4c2c718beeb9f0336951cacc729f6df97f405c7b6411b3247a1fa8eb1f7c449e +M = 72909ebfcf64c4c761c6fa7beaa6de7f20ba7227a23efd14d96a3355894a262d411b94e4a3b36b09a6dc106014c3a530fcd8833bfa7392d438167e17a0c0a6052b359ff0e016a8f8efb38377f8ef78291f65bf14782630915d58bc07b5f874d1d897 + +ModInv = 165c07619c6e6891dece14c3823f19fd44db289401c23462e89790022ca4b7bc3acc0ab54bc30aab9b51058f51dc302507c36ea2ebc385b3bf53f2ca5a6f8dd9d869f85e3abb256cbf87c4582d28834a75c546bea81f5f3eee82be80c4fe9ef94ff5 +A = 3180c09504edb280b13053eb3da2314be6f542ef5c520e39154510be170c65fe54e678dd02557117e7853b833686ad610035a34539ba93c854f4cf0786e2f1dd64ed54a34d05247260d6f6d30355ff28880e779bda36829b4dcb29d6cf4de3da0ce9a86e85893a1476055487712671d8552bba0c1dc67fbe0f31416eebf677572ffba6cba008785f38ece4b3e755fbea8c16899677e7e21cb8fb0d01908445 +M = 50ba386cea95576502b590e1fdcabfa77623bda01b9f5c3f78f51642a7c4564739f18d3c03075d10663d73d611bcf3670e4d07a6b8f2ab82843767dfd002bd047bbb9950eee143e23c7cf00d46d38cf990b40e345aea8b4cf5b633aa2d277a4a1bf8 + +ModInv = 1032b4c01738432ba292b14217f8eebe4c690d96d6fcb18b8835094f0b10dc552b7a905bac24d51e74de5019687ca714fdd437bbb9ac71632ef65420a569e82fa970ec319bcc7004a3e2f27956d7ee1c5ae87a0ccb2e0140f37f040c1f421a8c39 +A = -225692e0576246b0dd7720e4fd7845162f59e29e1a47dd9ae958c649336ee4e112f151b30704a88064ea90791217973cdb724e5ec9d290d7c8fc7908d1bdbce8fee432c80f853ded6139ba7ea2f555e744e262efa6e80eb7f830556e377c746325426ee4ec6a01947617d562002297ebb605427c04a6108a6e2882c2ef3ced053b0c9f2c60a2853b69106725955980f62ca9f1950360645b849e761739fff0d4 +M = b96532e75589fb8a41957cc08fc6ef32685353fdac06116d2e60148b011632cc4afc64598bddcab2b80f504398f70e1be7d7cf0fdd7e12280ca79fe9faa454398268d3d2aa05bda3899019793fb63d1f1a1549cef161c0064aa05d34f18b7ef0d9 + +ModInv = d7ea03e213b057f64536b58739d027d4b1ec559663668ba649713052c9d3f3bc4fa01a35797dbfd4134ea8f2719a117a4d55a0f5655b8a6fb67f8043602e7fd36c61c567b89b0dbb300c266a4445378e8edf2efe6200764fc4ee9e67d46ae9711 +A = 352509cc61a528deab33d1a593a3bb950d990a25763c7a9f89f0af59f97399553b1b46f905175c6e54e3c48a172c876dfc2ce10c2f14d2aa2209519ca1b988013674e9d95078cce83bf393fd77f4287ac5fffeff4601fc1f1f758592e5e52e6e0476e809e08054540b9b2628d01d5abe380b0bbb822d94bbaaeece7583370e6ebd5fe3cb7532a720056960828cbeb8deb213d0c48853f968a8cb83eeddd50f88 +M = 2d966307d4ad07bb50604698098b9e804b5c62eb041b21d7338914b0ec8b56220e10c35386f0360b76d2b78d4ab58654754737b3815da7a22f6b31f493d5db0dc0c4888f1d8bf4eb0432ef07a0c74011853ac62899750ba44f9729e8080332ba47 + +ModInv = 3efdfcd68d9a37e0df881dedb187a1d55eb3964b1045f7c54943383ddcb0ef64194e00467a168ca538cf24b5404bfbfb135ea34051f1f5e78e346840c2b97b89aea238e553fe92826a46a98d2f084b7b0cf9d4385a3fae9ea4b54016b901f957e3 +A = -78398376bf990ec20b64cb8dfd15d8c0adc324a44f2efaa62b537ae3d5866c1c6b555d84f3d82d25d0535b2f4d844639c4390d7ab98d20e5b51304ef52ffd163b951a3eae08f395ad31f7681d29d242b8640c3359501b436326dcce9d13b8520e7adf1a6062933924d23c0fdcb8ad285d7b349f2a89afb97ee357ab101fb975ad804ee94945e3dbe2213634ca4e96c91763a2cff52e40788b9d5a5ba1e3c0831 +M = dca2c9cf1fc45ddc85948c3168faedcf31de93a9adc57ad03ef50de935c8f628b702b71002aedfbf757f533ec4e9840cfd7207df64bcbca134c884b0005c727350479c16e1f02297a870adfabff5d96f0b15fe42728be988006714d02c8ba27d1c + +ModInv = 8b173d5d042a2ef104a38504a764b70bec1f867eca4313fc2714dfbd0813270db74d3b59d070bd177a447838b7666c1e070b36aaa59fd1ca2092286db3d85877e8daf50059580805aa4bd451552183adfe76b1cee85d4b71875979152b8ccf60 +A = 966b51b13aed14d0871ee7c927426940d11b182f25a504ed61bd1df91da53fa3b5f18999066911657b3d41655d29932ce25cd30520c23e8034939837c8edd54dd807453ab115e2d750f1d063087ef6930f7d93de646ae8adc12f2d91021dd413524ff0c2c466b51f615ffd295969eaf5bbf406582beb1cb31f999c17fc56c37b4d6b1755e007cb05ab73d65fd555c6e07ac5b042015c286e87bd1958eee398d5e4 +M = cd8b1c337de059bfbd10e2496299d64467f1ed64f34aae0d2315663052b91f8b015d19347be0aa76ea6ea62ec71fe8bc00eebac592dbdc038a5945d96ae2b78e469fb8291dac7cad537a3dc0f57c086a0d966086e9025e50282cbca70a11aa0b + +ModInv = 67e978b423748f18f8c0f6ef07a630da107d354188a5a937ac65dd885e1713b4413572d4a9d4cb790cd683df5c4cdcb57c1e99d8d579629ab0925b9e9875503d02a380926d5812d4b23ff81ff89a6ae9782d78106a0c3ce094975d71bedff9ed +A = -dc51d1853dba24499f4699e1af5f0492e3874051ca5b8673c4207f55b2e2f0d04c3b2808b975f9f082501c6285a08c9beaa22fc625187ca51bf661765a1869ec0255b21213d27aff727927cf1d34d98c87fcfa8852572db39ee4d18091718e6ea0a0b410a4464d7184a71c2c4ec39d0f31f59b4f76bc8b754deffe5ce34c148396f289972f3b509edd2fb70d837fbd86b0ac326e0ff5fe746428c3c8b13848c57b +M = d1d147da6b6a8a9d479ebc5d6ef5e2489f56ced23fff4f4f49da5ed222ed6ec3ba5e0d995d9b310025e114f38f675e5e5f49cdf1297900466ffb09dc2b554e4c877538c89049849b5f97e84bc9857c9b8533f03f1c8bb8afe408db881a510b90 + +ModInv = 3d3edcf1c5d05db972f6fe48c73cfd0cd3df3eb53e102d8421cdcc858d6354ff12745722b3b7e903b22c6a8c0923100f95aff31c2c5480323abb25847a76f78e4ab8a14a3db8ea75795a2c8480bbbdeb7398fceb7f989f4f665dc6a7ac949e21 +A = -27bcf856621013a30191f3de6b92969812a5ebfe8e7229677114eb3fad5bc9fb32c661e788381c4b05d7ce268190806607d81dd477d62c8ec378bbdbf73c52ec84553d7167e78c01861a5be8f95f802910d0d60fe40df5e00e7f5af57a9ead2a18aed7cce8bd8fa4ba769d215296bf6a443831fa5a5390a29b034acd18b940c1b227344a0175a48c0a34d8fe4ae7cac10ec8d74c9d3287a275260b61690de20877 +M = 80f76b6a0cdd16c39f1ebd269edb9a87a56d7e24519a7cd0533462ae3d3b7cce4914f8ac813730e1bbba4ee2d97affe257486870bdd3f65b028a6ff96715beb6b255d37dfd8692cb5f0b837596f9d39622f699d7f7d8470f480c297328569d68 + +ModInv = 23cdf29e65abd0270611afa0b66f3e45849794d51ca3788561f5ac3db576c7dffdeca544d533c5da61ec7ec9af2790b4843452ebc95eafda96735fd0efd5b1177c302ce875004f72b64ca2ac7ae56d50b97e3675ca268786bac9abc59896e3 +A = -c1fad642a24d4276deef383251371486878c36fa34deafa6a78cfebea0f1ab1ec4a026862ed1c94a43bde949266e31f701aa832dfc037e4073834577b6bc35af51a5f963538fac9209a54b07b65a3b7ebcc87cb7ce56fa6b92fd55cbbfe038216ae531bb6f5a4d3b3b758467bb852f8418a612bf25f71d9cc2d59a39c0b5f170bb9f039d0ca7bbe73f4c2d0776e0b19e669fb6a6b5ea2ee6da2adf35ee0d97a7bbb +M = 4ded9a792aaf7a6b4ab36293c233dd85cb49ff3909cf08a83244b33d8243c7eab869bd57f8a8439241886aee8d44d55010408dbec4678a1b2f362ff0242794b9dfa0ea4d8f09a7065da66b702be17974f00144270d91b30eaca170b0d68f22 + +ModInv = 33bdca298f2f4e64a46e916c9c1f7d2ed3f30a22506ba2a4140f3bedce0fa5897bf57c3c234397ca00793bf2fc5889a4373f2fe28db51afe2796883347a75103f8ac0a166335ac8f5d61a8f64875c26ce9a0d0e22fbb395fefc2fe55b4d31d +A = -b27fcd47e9ad1cd63a9c889bf71a2fc3e2884ec0bce3cf2f65b462ea40f1df7c5a372104bca7b0bd2b73444ebd42592f461eb3bbd432e65a60afbab1de4b218ee73f856f6cf560f8800203e45dffcc26e554786d40a4dcba4159bcce67be5fc6fc61cd3a67317a2019ba20ed5c00afcc5a0e267d3f466373422ff230acee2a2feab3e6e3d63b063f1b8a5b823fa3654de6f83060b587a8d504677884244c932141b0 +M = b5c4f4dbf3ef2bb6bf1644f7ec84db5e7e055fa1420ba28a4db414f7a00f26cac0cb142ae27127d13906bd683ecb298d6e2169442267e4fcc77384bcc3ee1b9480ceb795455b85b2d8bf5edba77b4071556cd6873f1492cae9d1472564228b + +ModInv = 36b0044b7624a7c65332335e539c851d9a781d40ba1cf1c586e09a0a13ddec1695305fa88d5ceed4860558e3604e8f1b60f3af95af7ad80d911c674151c44177655809dbf7f92f6b1eeff09a9e361ef92ce434d1bf997eaccdc8fb1d38463b +A = -d5297a35045cb0c07d2938dde1628fd5dfa5438212bd9b561e04308877b3f25e56358207d22ce18e0b3b7ca8769575f83427a089cb3aa87df0bb6455910f8141a23b69d229f4d6f39dbea2fb62d1bd4c05c29f563642a9ea4cdf61a87b8cc63319dd80aa3d46602b14b33172dede85fa8dc8aebbed089c67e11f71ba2fee49b49e599502138c44df256c6e24e2bc3fe3ba384b1072b9fec9f1685b70c94bd9ef4071 +M = 8b8f3073461d5c2b409397ee416fafadde83c76aaf90df04f19e439585a4d192323f5cfca1d235b3b133697685941950afc1f82db316d8ce91ec6d955a036181957d9ccccf7681062742425b4d603dc83eab603cf586c5b5ff2762a8e9bfac + +ModInv = 79a078f49f8b2da5e5e0d14d174200aa797257e79eb562f06cf3bc334dcc9443b71bda117e71e55d3f86cd4eabda0f7fb4bbf5cbb35433a4b4df7f74f2f9cc8dd066758718f1f2f1f9a53012b9d98b2c2df9c689ef0a95440d99df04b199 +A = -62d33dd4a361bc7f91b6e2a0e281178ae93d7d96df23a64ca10f92e78bd0fea236655308393501829ffcc6d4f0e8afebd2fb92da593731816fd0c04fab55f604399ac25e93d0b477162c267ffe1bf424c6461aac2ecd19c8555550c71807f41af2588a86b97f03e24b0c6d1662fe3da5025f17c5dfa7d46286c2ecd06dae63713c9df896754e08b1e22b230abbc5f60a5e1c29dc8add455c467689cf42c04379873fcf +M = d149645db955ab171f1a285634b636fb734d4453da48c73704ebe49489b20dec0cec3418edf933a30cec32282f27bd6196a38d81c1678577b9af15f0beb1c1f58050650077174e3f73cb3c07bb545261ff0a3ca021ec1eaf928f43437d9c + +ModInv = 175c6afc97879fde0b54b9aaaf2fc7d9bc7b992e2274978e047da22426719f758d42bc834e365e3f441306a2daaef612bd7676d956bd3fb11c7d42be9c9a6e5d06d463f32bab1497f2bcefdd460859407ddf513b1d1c3a2e419f0d856ced +A = 33b033bf3195660aaaca7eaed8749c77f92376e82e1317f4ffe4f46c3e793062cbcf6b9fd1c8a29a170ed452f46491f10946e9b181f385bf5ece12aef6aa1fa5c80781c88a94cd6639721c8f66d6ab0d9a1de66ce27caddfab55be20534c6877620005c5186b6e7eef1815701e7792cd7a6ed11ee46607b227db612434302a66c3222db7a2d798f4427158273edd2c6bedc6ada1beb31fe5601abe4d63280a706be6e9 +M = 18653f8c6adbe766141099df1011078fa4cfff350cfee299f533e4c6f6e95d8afac74e29366f61f1029fd0ae20f5f301b2da7913fceb17ece9d9d89f30362ea285e2128197f4bb5ddd49fc715f1d9b12fb3dab6f880f79e1202a004e8aa6 + +ModInv = 60d79f3b5cba1b6062d5d505b2fecab6fd59b9619383996ac940658db7184be5d1e98b82d8e5d51d17a2955ff141edf3695a613c8a255ea27cf9213fe91f4afd99f370843a1fa926336b0578e653595fc0567b04cb7ed823d1089adf5609 +A = c17964b68e43065bf0c8775036c3620a2cc945268c80c101f3806e808a21dd621adc3e0d62243268b5dde15341241b816ca6ae159154243dc79c5b4e9ee59d93c78df177852fb2690bf767f590fb366620e2d653a181fd91c94a31303ce43e0d0c423eec138e5729e32079d4f2fd5f53e1523690476559ca714e0a3b23e5c5f445e35bd1176f8f6003a82ac16c267da9acca3b46fb688131b20cb6ec876ea0f4277384 +M = 7eafcd2afa5173aea648b29f6d7aa1583479e9473e0a754f6e2af4ad845b170bba204af63ef3b9041d5d19107db8a3766cb1c2a22b5ac613388eaee3e6ee61617f864f5a4827ec21f701c3a6f835eeac28bf3a69e4d9de07d33516f27737 + +ModInv = f20e6ab26bd40d7d71f8b8e5f69b8c22931066de9be4dca61a5a9209840d2d51eca6bc0f09ad63428b4b5a9e9fe92efbd74ede8ab343efbd09e3d6408a185e5b32de746aac7b5ec95ec2f132779f28d07bd1ee66d1e3548ee1f9bef94 +A = -e59124f1c4a9e37d9a62ef84873761393b6f8505b67d791c0e01d63f91b6955c311041902fe019079669f99cd09a18a09d21fa0599a52bd5ae092e27db0c0647f0f441524ffed6e7c5cf8e87b88bf7a75bb0c85df00bf546fc8307487487a98ab56fc9e1b4b6c54e4eb311c40d8d6a2443e8d50ac3bd25ad4b97991ab655446f76f0920f014c07daf6a4fe76e57076cc9e6e902fe0209332d965a9f147230041659b443b +M = 2431aff7b61744fd557e970201e854f33c3766c5f55a9c75669991d7fee82d62ebc4335b2d0b6b9de3dc9311c3ed32ef8f532b0beed7155bc76d7be7886e019e5d215a6dfb07df8da808edfbaac2b6ec535e3d1fd6f14ee2576c19a40b + +ModInv = 6887d2e47fb8e43698f50461eda7f1581ff12dbfd97f40e519f4c8c2ca3cd2c7f278f608a901d571aaa331242978ab80c1225481dd7a47f208dc19b65efd5df24da81bee71b24501715a4a3e1f876489aba8a8181fd8775b7d324b5cd +A = bf521384466e2fcdc0a60d03884e3a09733e1344e6635e9e68321257d4e18b8504f94e8dcf05fa3fa20ec607c709d2969cb649568d1ae423f5bf22afdb3f83edbcfc253790b4273190149f17bf91b8cd22b2c50020c8a4a323909c2c453b9f99168e9bd0c556f1631a955160eb7d09265ac7f403667a65e0de6ef6cbc134c4a896f1e30679f422676be5ceead071ec3240ff1932ed4b500d6544c9c3784d9dd32bb0fc4d +M = 76788c6db5df49719b54dbac48e54b56f253ee742680a0516c83c8dd0ef38953082a87394f9776c8bda989c6cf0f551ec7d3a751f4e3b352c65b8dd04664db63da965800d4fcfe6f7d936c517b470d3517753af939573302a95154850a + +ModInv = 2ca859d535c24f2ab5042c867cf1a9d357cc01e9bd91993355280c15de595a2597a972bfdfd6c90e606c01ad54b76c1a1c00a17071adf4161ea9287ae9125db04de432b4dda60a72c19d1695d3d93c9ffd42a558879de9cbd4bd8835 +A = -14fa37d79c6d1d0efc6907b5ea65791207c7e19ebb98b28d76a208c13ce01494be81c7b615305648dade6a64e81863730f96de44d4195c6655c1f586fc76fc99495629dc82564cc4d207b5107d91e986d8a682f39aad650d2d75ba365b8602cd26af559a5a11f4e219df1263eb8fd414233a8e3e2bebd49faabb263d57151bbf1dc39f66d33096e52169d4d047b76c6303d349b2488e7ae23a6bff93380c7e81a764b48455 +M = 501a4072beb2963b7cf761610a657f94e0c83a7f1ae3cdf35fa816e01e9bd34bbed798998db749a6b811fe75fec0358cab6100fe7b02421673575f7125f8c84d03dcc8d975a15b3a907cb4a62bdd306ff362134011bfac45d0ab954e + +ModInv = 59fa16855cf03a66dc37b70cd65f89c93897f1f82a9ad70909021b3ea42f220c8a11b4a32ef308f4c03dfa394faf4da446920571eb6ee80809a47678f060cf200de38909618f3382e72095e353034f504dca94351acc0caa474fe5 +A = -af1242a8ef41f76b5efc6a3096bedc439a1d6520813ef808ab7493deaeb7a2ff4b2e68ec3b78bd4f26c5bb59bad656b4436b0d95b1fdc93d04ba2cfe6942f040548933c4c5816eb6b005cd5f07bc62ba7f3c0be2ccfeff252dc5880cd363fd2a3fef612c34c6bde304ed0e75d8d6ae9a87e203f69179f4f3f9c2317e64e3b687262104c15b8e6d7fb6beb3207991b20c9646c928e70822f2846e8bd81ab8273096df256c41b7 +M = 74976222a8f366a32c7b2cdd1c63b30112874d8edf711633355c13d54975272c917f59685dfee20457d2f746d39be5e2a57eaa2c5a62f45e483ea4dc1e966611d59fd56a962bc7a98be2a9c81267b7592f5758fba7b0d6678b58a1 + +ModInv = ef2c7cd93e06f8bcb550e528d6218c3eb9f3b1700050f2d8fff3826c98f24a2c5d17c823f48ab8d6b79f2768d40957e39582169d7356d04b889b07cd4383b641cbde60e3adff4be5c1bd3123e9e12409d29c024787a6b44cb19010 +A = -4c67825dad8ab3d4276381ab174fcd0464cfaee134be6d7837c070d6065d69567e215f98df1b565abbe4d62a80c776ea450d54c997856ac65e1df77385d10e4e6598044f33abdf66f0b5e0457c59a7568d6fef6140f6a64373eae43656d7e79898ecab5c07ca8a390fe5afe88712d3a77ce6af4bd359779081bd337179946ea87788cd4ff2bf24351ed04b3d24a9a28f15e43b662a393944176e719f744df816b8d188a6fe56 +M = f2ebad265f1a4b07dbd248672f14bfaf408dcfae6ad71f6facfcf0a2cd4cfd0a667ac7ca0d25a3d8a333e5eea149838036f91e1b38c566e47e9ddd1dd77cce211fb6c49abac1f1dc82b67f5dce7cd4772d3ccc036112153495207b + +ModInv = 935d51cfec539c9046257962adebf78089b19b7ba3e616a7cd1611cd11f5dc6e5a84420bbf1301629d6f868ec4e1a6136463971ccb426bf8dd4574b3f0ccb73a36d39c884d01b3e1dcbbd1148e1205e3847c0d26d91f6aedf6005 +A = b6968200e02d18181ad79475cb9acf9c95916e21e70a168f50470d0f7307c6aa8828efa52e79efc03f4058d06fff0d6fd5e615a2fc62c7a0c03784ffe1080154f6ca40d52a76f7db423e794ad3f696b6797101d92ce812451c6bb80518766f4828bef8bd24603db64353ce6d8ebd3d33ecfd8c1eb276de04458bd933b58bd8d297e01353e530f394eff1532e56e3249dacee5490b4d2de047c2e4ad07c0ecd2d62f16923caad +M = d803bad7c9b41c978a48df664f3d6339f57865a5d502cee2161818b8cf60e50522f8e829a7c303b7759e29f043aabdbdf169c03b9e499ba9d14762ce9c8f858a4099ba2123f5341fee3568e412e98d672cd110e8b6cd4822577a0 + +ModInv = 72dbc7dd37b6cd991159529e6e420e2ef8f396631adc16f3130ac93d27f370d07acccfb829cd79d6b5bb2016a78df7a6eec100a9f8da357e8380d3f757b5b5e41746354dab47d34c313f5324fa53360f806c77db6597286fc84 +A = -22d38edbb6a54f535669bee24fecd262724057128e39479ba12cb97c28ea01c854397db40ef938722481350268e277453cfb50695981c14049abdde2c892c15f4289265413c3ee6da0d72e5742310c66f7f776708c2386b93329d9d11235154ac84265eb2cf2d32820a29b3f26d0eafe1fc28c6e3196bc4de5743fdd1f2a8aa67223a6bd3e7794d50ad0189fa1bbd676c3cd2355dc450b731b972c83ed12d6a0e7bf7f24147d93 +M = 3e7ffdbb4777db7c039d82f4f9af5c815263daab1f08053a677483a33c25e0b8c45a5f98dd46970aabbc79af7e63adacc4a4cabc914be82dd17670c5e0d2933e9b7dcde79cc78193ef782e45b3b778262bd3395caadfbd86ca9b + +ModInv = 3955abbe339cb2492e37e5fb2a4581b84f3830a705c95345656a2ae65036458edf14bb21d7a549f7d578c1deab256c20eb986f1b15839a0974c215209bf245382cf1cd1b402d17b6191a8ea058301349241a5c4f3251a2cbbe15 +A = -e4aaadc77c0c826274625cc916010234c5e88de19c62ecb9a01cde0f41a337f9110565b680f43ac18daf924ba95d7f6883766fc7b3ba2a0e2f7da3a86a3092a92126714b7cad7305842e6eb3a4effc682482120081f4bded4a1413ca733914db6148b2507935ef6a692965dc0f51ffd5174f8714af66c2e5d0d10fbdf0bd7284492598c74daefbfc16fd9cd3c65dc1d8eb2cdc6916a52e9af26f53274f92197c474cc666e000bb +M = 8b231be4d8a1c9a2d60c22e192b2c70a8853ddb722c231aa3b98c7bacc9c55bb8abe7d72c6807ba3614fa611d6672a5962be0873e34e062f7171213c21107c80f17f5d9092a23653996cfc7ba107a1e9d2b3320d32eb6eb5dd17 + +ModInv = 19b8f82f1957972eda1cd9568a675aac9f6a02e9176abf2dedbe0e07f3622399f0c7b8a6e43123c1e7889dfd9f3c327c9948bc2481cc682518b090b7a8ea7b6c30714bd264e9be9130f3a834dbe9f2bc0cd6993f46dd4568e36b +A = 9978a1586adf1eaeab280a84927e0eb06c5c283d08465c252ec66372c7a3fc12524915ce485c5e67ee1002cc512891029065e48189f0e6b4dff64cd5291a1341ff79e88058b71ab32c8eb88cdf851d16febdb0be192459f8441490fade339a3d138556815ebe4cda25e16a468cc4703849278e27c3be31eda1256bf9c5b684c92ca51f6aef048eee54594cca9645cd6dfb74f87c0e59ef1d1c22f3299c5d993f09afee5956384d +M = 1be308a2de01881e92ca7a462a2818bd8486ebc656ddd6d4731151dc03915350bb57edee9b8ab58b310d9df4d439c49ebdd8a5c07b00fb2e8c95723d2cf5ea5bf29251cda2f193ee4b3bbbd64918389566e7b147383bcc76eb5a + +ModInv = 106f4c5f6d4aee56f7e7d335c8ebb818beb0890d1bfd9a532d4cb92d492a11e021b8f10c3fe17d5a1f2bec6cb240e79675e2f3d16eaa323314704ba9e8df079e60c6ea62537be793c0a696f30a24be93bb6187d4e82041d9db +A = -fedddcdc943538e7c0de1fe1cba95be4ab03252be33475f173e1ecdb2fac60b092a15c55028817d2114b11ef58f92fb49dcd46ad9077478474a22d2c5ffd5cea8b76c70971c97e1c285bbc489c2f21eadf7ff0083391888d18798a45815cc2e71dff78a48370603d9a1e42d1225b9015c1b7eb02a7a04fdab73e08ca194693b99014decf81788d3428c3a252c05fa5dacaf16199ead4255c4468ecf91ad2a9dad66b2ddd828e919f +M = 2bab270fdb67205920fa3a00a2c31772937671d79d05bc59f2334419f2f3487cda08faedf475a8d7019626bda57b5e924675dffe9a5b30d1259263ffceabb132ad31c8b1268a2af79d9b39ce3dbc4fc62846466fd41e9b9d29 + +ModInv = 113be25e41b5ca5c1a00fd4441da37da38d3e76e6c364c2d57bdf26787b32508ad23df6c715559464acf81a5682ca5c97dd525f937630842a62719cd207725d9f8eb8aa03c00a726765736f086f94b59e11fdb15cfb2f69d0 +A = 67433a8667518339e369ab3d591d3569ab0a0d83b2ff51348161701f10ba53d8e66eb1186613c33da29c4db3d20833556cecc2581bfa530d5d685155e98cd7d9dd23f7b6a801cf8bc2f40b3034775758b2767375fe03e76f643cb56d4ec10fc6fee29f53ebf644bb5c1ed35fca2410fda28718e5623a7a755531ae6dd30a286ec6737b8b2a6a7b5fbb5d75b895f628f2922badb05da83cffb5bab1cd888417a5ecefe37b9e250d03 +M = 759ac68d26ea43fe43ebf96c57b0c751a5ade42791505078bada1298c4cbb452ae2bd4e7abf522dfdc3f12cc0c75ffbff51e5876bf982e524e5a695365d51f25e60490392aa9eb72624f93de30ccd1118fbccfb637cd367ad1 + +ModInv = 12e8fda24c2c0a63a335421e679489b94e89d69b82ed5f72a1505cee0917cb63fda3a8a939b9503d95137658f8bfc2c5d199f415e70b8f0c47a0ab08532208955b5371345eecd666df7505cfb6d665e2346106a46d2dc0b +A = c7967a6626af30b9dbfb3bc80a4818ee86537b2b0bf2530eecd99f5730fa36e992a43524532525ab1b26306e1122298eb1541970ad431b1823609a20e8ca049202bf268b2febed2c7d82affc80bcd823b25437eb9f685df8fb26f29e629c4d01b03160ee5b327b2b31b76fc7ec94b79e82b7fb40fbe1ea46f9cf1f6e353c6a02606f9ff96533fd4828244227229639b7d7e112ae90380c7f80e35fcde2625e03ea7ca299c46ab7318f +M = 2b657633e3804254f59de86bc71a4bfbffd88310b6b5b83a700297cbcbf1cc8a42c1e7ba4d64203ded9eaea7d030c4b5be471f4a9b9fc4cb80a79b1d2261e5e006b44c7cbf8d0dda3b447dc3bf8961cbd1fbd4aec940ac66 + +ModInv = c125f23ea171c6411c0afdf799bd85e4ee986b2db95f9fa3df05723af3329c6240c417a403b466efbd1cbd6196fdc768f2b6595bffda3245c7e011cab2d23783f21b21a79f0e8407ee25cf7d1de3216032a799f8fe34d4e5 +A = 3c521c821b11c9329e312fe31dcc24fe416c33c74ee951d817b6aaae51e021c6e926206c312490e7e54d116de31042b7f181daf2c29cb743f358a2ffd093433c8f506050d98f14bbb6d54a3c87514e89c499385938a1701c9f90748206b7c3b59986f5defd2f2a0efa187811477a5f41f8ad5722455eccb3ac1be7483f5558f439b6bb65f437dd908d8d5dd8489fdd47b585b264cb721bff16a32fc9bff4c5a5a9f83164d119676f68 +M = d1889eac4ed8ef0e45399cb0c5a020533a8f97e821ee76315bcf8cdd26a186484ae1f2bcab0ce670e5786c724fe9cdffd8d703507d89546a148fbe6e838ffd53d7264a6aa746b3e7784332ca182c566421fab3dfacc4c47f + +ModInv = 6f5e78145cef9e527149e5bcfee3439f8fc465bcde658acd5ecb8cc3531cf26a7d95d661497f53984057703241ef6aaf5dea30d441eeb90039d7a62fee0840406e8d693c46470f8c9eb1922f23bfda05e92698e9ce408205 +A = -86355bbb6d9de9b6a3a7c7a3d9179d5e2908760a0b512e2c9b558993d62340a31dcc69852d4280b62b5d6dbc1d8338c778e09063405e730244347461d1094bcca7abb2c99199d442829e968fe66a69fcbbaa0be77e731f494187184d8f5296faee8dee4dc835f34878f191c780bcaa9ae6bd31dbc6433aab095f8ccf4865e53e8fcf8c00b242e920f11e197bbd11f492a5cc3815fab0bc9b4723dfe08cac7762ffb3672bbc4c9274db +M = a7f0227a7cc986a3c4170b14aabcc0fd1b25cf63ebc7807bc229d1904f10aec3b414b3622bbfaabc24097747b9672ec1ab3342d23f6946057e4bac5b6ce71932f03afb865b6f98a99fe300b63df04b2054ef73c03702c9bc + +ModInv = 34ae1a342591f11b93ad5f911310b620d0f50c868aa87b8b63b482da44e8fe628c7811d2f90a6dba1b71e3d61ffede2d8ec642ca8eef8731acad2ea95b85df859e85a057300cd0897322ebebf687dd8e4cd26cbab8e84f +A = 9f7d77e209c050d1ed47a49a6e67276ad31471c7f4c17d59cafc16757f083e757d88864bb41e59d45576772dc58dd7bdd82e60bd7c16c24843c79e1da8d38e3d2c06b6d4c6d44b05ad620dfff8da15fb82d9d3e1d6035975bd2997630a5ba6dc3dff30c1f811daee0d2c51b1ef423f8146d0bb46629e3cfdd5982976dde9c2e530c18235f54f987702bf0a015c2dc24f04e8822d5f6d8c6c80209d1c31be36fdfee710ab7894c563383 +M = 3cb87c22d997789c2faa60d89f7d6e3dfdcc861f0b3520031c1e514fff27844fa7a7f07af3e6afe32888228cfb77b82fe4d272c3c15695d1638e2db77669d8e17d85a1c4eb56a17c2d8656fd38afa43bee6251480fd2dd + +ModInv = 39422a01ec5ae2c44b9bfac0a4d0cd186dc385108c2ab11cb2468a678f67dc7252b64ad2c5e3622e343c6d639849ee7777c9ba698544361c8fa392ef76c589743245e06d6facadffc908bd77cb9b3797c3814bb50d8461 +A = -13ac951a6d7bce14fb6ee73f0988fd2421a62671dfd95a2fa0d50161f9ae5f29b20dbeb92cefb75808419663322622254beabb89d6353768e48156274472d688cdb964b559b8d5f8d77782e95ec22dd31ec26e18d926cbf38782b45870ba3da2286e886596e5f6a275299c29f5c1a897c3534dce49ff11d9c028f84071cc62e404f168ef09c635b4206380cb97fe7a2b30a8ee6471a8afee5115f32e2fc29ae23956e3c0a2f43419f41b +M = 4810605945f84f4ff34dda56f5598dd67e88fa7b80bd0bc9f6955b08cba2d64410c81e1dd4948c246b5da86281298e73465304cd838566e486edc806170e931352c7aeadcffd4f9e5c730bf1ca6962126657bb99b6f096 + +ModInv = 2ffc80d0b7d22c4eea310bb33e04ad98d6bfc3f7aabf9017bd2f6945a71a99f3275a33c57f2dc4f20ff4b1de80171d9248a2a25abdc91c0f47227e7519a7ef6bb070ae875da877e4ed25c2ebd192345c16719617d05879 +A = -3a6e7b42a557f3fd41bb11632ff912c839f677bb22c16064d1b4671c3071249a19db08577958de873271cca0028e125b36f0d4353ce53a656eb9ca35b77b4fe43949d29ccaf2b8fa08bd70dab85277248eaaccc06ef6bf5f9a262ef7e3fb3eb2125c0a7955a07429ae1f97b4f44b23a4d7339cc5960588347cab7d78b369976fdd3179855ea524ff023b50f5f4633504d33136c0af55f8406ff1367327031ef3025de085514989bb2931 +M = f98f98c95bdec1842df3f798019f619a78daf551784340fd9dd5230d3967a0d3466798ae8d6d76b07b805d583004ca64ab873b338dc051230f3e73fc71a91680c8baa510b0ad55bf5fab47927a3ea209e8cdc436880f7e + +ModInv = 84c03e480372506cff8bfdb5e83f53663abfdfd836818309093718430b8d1fb402ce8d6adc4ea8b44a6bc3ba0eba0d39212aec0f2ef2c639cfaa209b18c5bf0471a9125b8de6aa5f415f389d98f984ba1276b066aae +A = -890c95d9c88f9ab5cac9a624b4d8d0ee114b443bd6483a8326e75befb44bed0e0f1c39a7526e0e40e5eea27efd6c01f916821cdee0cadcd3b833b342b22d4a55c8bcd82f09d24bbb3729a2f138a776bc571a986d9edfa2c4f0f4a05aad2cf8b3e41580b94c6d8af32e3d425f8bc5e34e5f2e5e420e6e641013b3d997d44540b0ff0fc40e9f336011df88ad4096d63a3bbd4a9bac166bd6769ee031376b38ced1f2dc14a2e8ae3ecd012210 +M = 992a760e66920ac08fca51ecd93079cf17fe4e7589536506d70e847ab852b1750a1c4a79e8fdc25390a77fa308d5dab83f211994cee88036a22da0338375f3d3eee97d58d2c0a0d0a8f860e6252d90ccb14115e93ed + +ModInv = 7a5afb195e6c9bf09c461f1209ea6384e7c20d945f4ecca6eb3788a03907560357517adb36e6fa01d7852bff997556aea3fb09edae89f53c9e1490e01f5dce6e25fd59e98cb2dd501f14d848aa80cab73eaef91d35e9 +A = 50a80427d3a7ebda161f48e8085bfefcb2e796df4470e455cf34d555b13925f66d32e87dfe5b28b6982a1faf664960a5d010307be743256274a58da3a8a8faefb35833c4eff9f02372ae58e96854f88cf0de184e03f928d43ff14cca4a36532ad1d73240b5c5495cdcb66393beacafe9fec7bff1ad3398773a122386173bb8a5684e3e1edb4c79e8f16fd06e6dc2b8cde1b935afbbdbe942417d3c74ac5e6257f7433b41ad5cb31d5e1acb +M = e2348ae708d5522ea50cd296ea70145687ddabf772a0d784545a169ca0f0e6593fc44ced550f0c86051cc4d5a5fb76105b9c670f90bad2c4b823ca825fc3f20ba8d29979551686b3831027b03bb773c194c021943fab + +ModInv = 17cdd16de30a802f719a2088b02fd1ffea71e8053c7f23387ea7bbfc9ddcb5e047e48a0fa0d4deb2fd6142b72b81932abbf2ba0bbff0b71f09c07b47720c1756194250aab356cd12e6dae6ccc7fb78598c72c424370d +A = 73c61ece48eb164dd409f7842c595cd2eb027b43ac2085b8b9d2991d07d0e4f9fe2019944fb97a5476e67aa41aeb8822c50a5603e1662913b61d622fa668e7d069a426863981b0bde3b85b8953add9a84da95aed202044fb2910980756f5bfc254899bbdbf2a209f3fe178fd53167ceaedc942e09fb706d67cee1f85aa718c12327a55827bdd99434d15822f1b697f3b06761c9e7b642cd7295f40c36f0dcab6bbb9270d2e225cd121ffe3 +M = 27f0184b649bf196b445d9f1975a99db8bbf071054d1822836a11179274438b2244c3c37562b332a986aca2136e2ae689e1101afdbb3d2ec72fdcaaaa5034bc5db1b8f3762d76a98b251a5a9ec831b05e4aa0aa33f0a + +ModInv = 338f1585cda9f5488402407051bc047f08265c5cbe7b26d043636b1d284433a875dd1e00b2e90bb98dedf9d76a42d8f5017e05bd4d089418f15049a62b680a176a741c1a8463b01447217449e12cdf741c63437ffe +A = df5803ac1713df14cb377aec78d51edf2d7d0f4efc473ed19c3df22e43743ca1703be26712fb409ea033e5bf7946e0c01ffbb8365f44081600d8925d8aaab1de82f9586c938ca256079c8fc3b6bcd387cb99bf173d086a854dc7bd29b6f20fbf6766ef6f286e8e0b11a3053b425b3ca667d93d9fedefd6bf743356629536a47e8e5fdbb0cb57343a8b6ae43baa4d913bb895494e375ecc3eef14d3cb3e85de6597278c9833d94cf637bf55a9 +M = 4bc8dd464673a001f28b47f0a3fd987310fcde5fd6d15cf5b993cc57fec568682de79deb1e3a3fa7e81b5a0f8152f1765c9e657133f77df51f45ec880f62c11eaac8ff2b0956b8e287841629cfdb80d203e2180327 + +ModInv = 336114c3c44235959ab2a715b01f2157de66c37a2537ed7fb3c07199b1d65a24ce59d965b640a7f0838d2ab484551144b001aad62d614085a11f9f999ca6bea90abc98ffb91a85af5fbf5cc86292ac52d626be3646 +A = -6b56b45c66b3e98c4b699a0b253c320e69f82528b0362e915d3120a7114cc60d8ced0eab55be38a50e988b481edaeb50be123d63c1c62ea18312e5ad65c97b4ea78e1b4066d5f269b605b5275a9fc5e727aa741023c3e5f319b49c75be076569e052bd9a8d7126bc030563164cb2c8febf9fca14ab2595cfc7dd66b5cb1eb623029ea68171ee2d1fc0afc51e478b578419bcdc64c42447624c343592d604cb974abcb438b2225b9196b1f193 +M = 6540a8978c80a402053a80c6b3bb7b43d1f51d9b42d3b59430c5b448d3a58fd0af823e3b39da74d2f64b863b9c4b30c59e7c4fd0f03a807b6e813a703253d49724977068b4509a4c07bd545668b6c873047305aad7 + +ModInv = 3ceecb459c2f7ce69db01a68a310a01e2792f958ce1a5547ee0d5f4c52341c937f3814349a41c64538b2af6e90b462fe00a813136b4c231bc0443b87bd18ee269ade5d68c585c48a3a419f787de22acf200d62322a +A = dbd11254605a16951446926fd53d5a7df65399a04d2a424b8d24317ae1acdd201d72a9cda6ea2263c7bffda4061aa8574958df19c1f1dc750c42d949991646f44437b819204e22aab63c0f47842a67cb9437a80a65df1cf8792841a5d514c2b5523680d6191ec419ca57e1199e8f4c1f0fc2fb8eb0786a512084ed567ee09181c2efb2ca187be883abf01bbf5542fd78b6073899637238ec19482c7ef972d8a7426141d69d9368cea5033ec3 +M = fda31363f9ca75d6d5826c204514af1722894b775056a7532940da9b25d2e297525e26147ed0d0fcf5657623be9238d77f2293271a1c3199ee5006c2dc106dcde843e3bec6549a755d1fd1215fbb0cf58b752f3a7d + +ModInv = c512d8e1813e1f488222b6473e57839f087386e9875ed0ea41138b265305fb8d60ddaf30bbaa5b4945348cde169439e1a5add404a941b0c4a5c5b920aed8b8c86a7bf2f03941a463bb19fa2ec920ec6db45a45ef +A = -5ab8de6af11b9595a0a6425eb082cd252039f5af6ec1ca0dc7d676d12552868da13a1508d50ab352f46ee4b5572375f5bdd5a1a301b3dfb1e84422532b848de9ead24f65c11bd2f6a9195fbcdfff47463f85d36b9bb8caf0db7e8102a7a842f4839005a812498d0b85f6ab23c6e270066d41d1f61d060c7aa116ac419e328592dbcf38e080c0d5e36f7ec6fa29e3e43aad5325e19e5a97c2b3b68282aa7b95cb7e4552d5a5752203e677d39653 +M = fb3b472630654c8068addc73bd50a563b530543424036d136155f5b046746f2c4fdece85b1fd404e16eb580ae9c83f7ee9cac04df89c88267c0d69f09c306084e0569321197d120bb7f348c21e4a1d6a6d3dd322 + +ModInv = 124fea9b4e6a9627f4352690e0d6cd753a3256a61fceff79484d307d5a5882276cce1e5f0c8e1d43aedbafd1bc3891261607897ba992c3d0b7652abc63544b60f6a5e0ef8c49996be0ce4b2d4d36a1a71943c4fe +A = 1bde12b2a76bf53fc7ccf7a3262141bb3091979414d57ed1292f43d8e02bb4706cd5925eee27a40507e7bd7f188f23cfbeff789e4567026cc98d1742a021c27e01cff65fc07e48c120e2dc7e09d4c08f1d9a3df29415e994fbf08d78a2858f8a4479dfabcb19c75c8edd52199f7a6705d56fccca1225477287bf286ec63549535e6fc1fca7d9eb4a017e9e93a5c25a63c9b9b7f00bcdc011e31a8117a77aa3a058008868e0b75e779325d4b344 +M = bcbf7b0db055189b2e580690ffbfbb4e585d0df04e7b972840550f8ddc874c9f76fa7a7d5615bbeec866e475e1cb453d45d4b255da6641091b92f8cd75d694b8bc78c7f48f270b2ae588d18347f5c8d2b0ac1727 + +ModInv = 6c99f44e356dd2cdf32cd7ed547061b6a2927e1616c23da872a55e549378b23c2520c3f6e45b92de10c5956b603d30a6fe8454e4847c177a4e656b3f97b23316deec5a65ffc59538302815736a6a6cce979778b9 +A = -6590ef5e2029418c23215b3894aa5d28c457667f5e17ccfc7d4addd2f13ac5f78084399fe9189f7e83748e525fc917f358218845613bcd2db2da834c16323645b1faa34bd660877f00f977e4c06bf5e80a86364b402325b2f77367a3bbb8332c5d6c11e7ee8881b0750b01cac04aaf96efa06c51a4f9d6df82e59fc01456ac92bc1200e127d44d7b96d3a8ad0e371147bc250cfafdcd5aa75164f5d10d70cd24f1298bc67cdd4b1187036eaf57 +M = ba121d0915dff8ec7d6b057806a07f7c739132416fded7779fb68fa05b0ee04a814bf22f90ec0d506ad58d07954d72308bf45ebec7fa7511effe780faf6c97deb6963e4f5eddbfb2f209f9e0c93dd8d1aeb25454 + +ModInv = 8ae5ee6d64966189a67e8e52e2ea05b2dd1c190f0abe9f8e7ec305143fa4ed1261be59ed7dd150c44f2de6d287264036ce6b9b945d4310c01e94f4f58294ef29c751f4140a68342977780e4b990d61423132fe +A = 4772df060c653119d09b8cf9ca22c516e05884beca5d38229d163228a0e62c4ed561e7155de11a9b3ecce1497295a496fb0f163b34af657dc72b037dd4f960f9d875596887ea35f31d9f3f4ad012a2e2095bc52c1571a0b0d73cf548d93c4c97345baea4f88ec32717c690ebc9284719283165f4bd3baf998eb5a4bae0672ba9e124d1f45fffc1bfb9c71b8ecca52358d7d01c3c22f07dbf526dbc008fae0c67cba54faf8a79d8678df0f4e4cc0f +M = 9adf5c015a88377cea66973af857eb14cef80272ce7b95c7a97a9f1e88fe5f77c9c23c0e3193598954958070b31d7f2dfab346bdd935057537cfa457ab357ab6b5a55b4182e4d6a1be33c5d175253e53f1bfb1 + +ModInv = 9f803f14be20a5559386fa41d794901c72d0bed0f4de16c5c48b7093e17d6a2e268680a31370c53880293b3e3afd6b062262d387cd7dc3e41579512991ff1ffbaf368762e9abc7e4d7d0119a06c2fe6c15a89 +A = 143e101c3c0b82f6df38ff173222af4ec1477a9619e472ca0fd6ee03b25b92d9f0dc25ba12d2c2461641e57bd8904ba24d40ed6d07171df89afc23cf81003ffef9e629bfcd232be40d99e1ae27c74806ccb1caef6b8ccc32ac0f7b8ef8f4ff6460bf70deea483f5f7127102c2f3c97ba29f7396bf939b67c9d312efe94f8dcc3ab3b11d3d4abcd3907395a8d5b007e94ddc3a9ee3c5b9815f0d0903a51bd2ab733b33690cb9c03b44bef273ba34a +M = 2ecffa691b7208c71c3124e908cba00bd1ec4f21be175d27021b2b7e9357a5ba9caf7fdd3001bc3e160bbad32c867467097a08f6333411ebea885b7a65f114db654df8aab8492ed7aa11fc71df5c8c6b557f35 + +ModInv = dbe28b8b37959b415254ec9963bbfa1fc8ca46ee351c16550b9a0e5669807dec00418a315dd160fd58b8fba0b6d881c340938c3c5184195f437d223385868d4c1f0138b0f5f63b5520e00e3578f36efd88581a +A = 416a1502d66c69e5fcfb796015f8789fb9acf92c15748de226685dab71530a834e6244ab2393a3b6d6faf4abee13ae8dc5dbd5636854b3069d0e261f13332d38c853ca1f647a06d58dbb2a6b5a280ef0d6eb3c0749e70732a2a8fb83e0b680729fc75c0700c41f25041e08d49ccb0d6f2366a5aee9aa7cd330d71d6cfa233a54aa42dd76a89db7995889f8ca4e43b26d13ba4d6ed99b0ce4e8c59b775706541aa6492e3bb57a943488b5df022f6a +M = e6608f57403e3764ea9c612bdbdc23d2f6ca794b4ced1d074710da6a154adb80fc2c5f65b3790ab6dd2c4f1aff84c070a5acdbea67d314a5377f0d1230fe5ed19cec4062079c7c5cc9d53b0a26a26f14b37761 + +ModInv = 71fbc1efd0577efc9a342033597d56582c71e663ee4f49d647498c7f03a469cb6ed6c6147dc2687ad145bab0ec559fa5ccc935bc404838c7872d50e516972400414ed91e966e78096a619d0701a9656d216b +A = a731ac4afc740d3afc966e0c4666f96b5bb1b80c3df73385eac6ff5548a81340697b3ede23e5cbaf4f6979f82e3bb21941c1db31c324eb951fd01b98210413dc5a94c33e7f6fee3c6f7652acd77a23b847ad61918825eeb91a9dcfc8bc6db87f90e1eed93da923698462706a6f54bb7e68f1fe7dd26ef65bf8fca7ffb820e8c6e176ad05ce1c84c3cf17652d197307293b1655f56cba2374568d761ed68a4d71c8e9bedf3eaf4fe634650242d730a9 +M = eee990a08345f542f2158f81e6b928b168e3ff3ac4fc67ec0bfd92fe320d35a0d1cb1e7687f8161e4661ce748f43a04f860fa24fab85243879ef7b315c63d3b9760373b3a70fdb45243a0923db02698a9f22 + +ModInv = 505609ad7579006ac777a72c62ffd2acb0597a147ea8a817b30fe8415d3f23ad7e8807329d59093f795fd795b9f8145b6e341c8580fd10dd05261c524991073314b5f8871f2f26d267d372648fe88763ef25 +A = a5669da86d9d833a85ee3cd6bb2c399e9d45dca7f4d568d91584aa8a294740c8f167a758db4cfdba7b4a99a0bba70a391f03e993c73e639046f32ced9cd8aa91d3ba0a1d4a6a647a3b0f987ac09f62555294e206f839c77ba33be93811dea6e37c07bb6a28d365072904f9c760a3fabf4fccf0b055db9b12ae678b630b6b57f66b4e3f0fb1c419566897df288767f0a6ccac0714ee27dd2178bd3e4fa73506fb8aa80658b5a7ebc10c233160679941 +M = ac5bc62c5d1b14783daf5772c717d0ece79da4a2716ca7b6c972d15cb6c88bcf8fdd72d44276c6018a7f323efb892b77587b9698ca2d47762c7afc06a0e21fc53f7bf0e64c6de6213f072d80122dd5352f3b + +ModInv = 164563d8e74ce68840b2c17b1c8b49ebe03cf404d914a63e6dd8ce99ae12b8c13d57902d794c5f1db41aa74afff41db579bb99c91a405e2ca31372770bed20b5976792cc23ec446379d6fa26f2516fc2c5 +A = -9c337123b7e633c002f1c3d7af0e18b03603e08a2438259ca445fb51fdeecbc46c8d476e7b271e691d4a6fd43384dbd6082c56183b4b4dba53f7707768a8e35e0365f9c297be527482e38bfa3d7a54b7c9f061fba3eea2506281b07410e38c608a5545639fe2883d61c021ce6c288a17a920fa4995faf1aabbe2602ac30a35feee6f3c08c7a66a5c9b1639c03c242d7c5ba29803d6a4ad1150b30e08d84820aee0e2fc418dd49416ac2c0fa52a5d4015 +M = 1bd8a6e3838b2dc2efb3b49ce5cc62d51971d9debacb62a8807e8477874ad83b3072a95bc3fd57a63bcd6e181042cb174c8547125f0cc433de45412a1df9c94c0ad76a48a34e8da3b3975b50f491053dc2 + +ModInv = 14cffcfb4241dcc3e2a25f463137a6973f889ef2e7f72f72a90ea1a21c9be4bae2785d3079f2a0af9b6e514b904e39a955c0974d9dc92485a995951c8c3ca65a5de00f7dc12cda08b30bc4733f0717901d +A = 55f400fa254400c67636749dc31301b4fa6c6efb6e860090b536448aa59d2f4bea5acb6b8710c408d1bc866dc5cccd316b26daf73b6ef28c57cc68f61919ebd787f64b6adc13bfcfe3b3fd84d564ba12a6a245ae47178cb8c67a90555cbb14f9d0333d0fe388fbb8747433777cbbeee4fa6a6572474572ffcba87e092bb4c7bafc617dc091df48f9cd7a0e126c89650a7f6b6a2428f5eb57b81245440b312ee4e57f07e3712476dfe3283e5abb4b30c7 +M = 6c13caad0a6760aebcc9476c3b1a044d8a863a971275129fdaba71f1035bdf576fc40952448a0ae7726954813e6d135923c305e44b1611c04ac69b0763ac3073af85becc9f11bcc81e7220d3f55f679ffa + +ModInv = 2064a64416f41cc776182cb5518b22035813d116143e6216f959bf76396594eddfb376d8eccc1aa8045733690b7f492300661bab3d183879c1a0238e47447174254af5d5c60a96b1a5d45bd9e3082ff2bf +A = -28d3f1b2a139ddb1dac23a992fcf69e1a6ca16ad2af20b846e17eae87501deb328fd96b2a27b1db8817b52befee41149568759816ac619ed887f8012dc2a5d8b36378783d6cfb20495e3086931099f7506046cf129ee58b2a16510e91e3fac5e0c373f61ac3fd5b2faa119e995a1ff783f452015416815e17f96d9d34323ff120fde3897d941bf3094272dadc53e348be865b2515a6949e1fa1a46a40abee6508142789005c85261a62f752e9e2788d1 +M = 26fbb5229a141ba16ff2faf3889b5bb21253af8fcc1080f3c83a9eaca08979e757604af4462dbc4d1e9863761c600f72db6a896298004ed00fedbaeb74d42554e2150b8221639d3c27dcc0e019957b6d0c + +ModInv = 17d9d79f8e07ade97dbd6f270f9b6bf1276e6c66802c1cdd51238dc76b4add539de710001167b8a1aecced9939ea710abd36fb5a6d3015626baa8088b66897c9de2fe8f5dff69fc8b3b3a9ebee0d0a45 +A = 30e8b043a9ecbeb5fce1be3fd59884c3bed211ddfde0d335b5d07b5423b9a095647c7854a2c8f30db3077b6cb2bb0e7a6a9473332b4dfc8c8e0b80eaa5ce1d409740871fd4910d9800ba03c13a56d42b7af6d74f910483d2cba702bcfd535c96ea1d84fd1ef2555b9a38ddf043b703ea84e9c7be5935baac864cf4949d316d50d09413793e87d92c77a91437bea3054720573dc3331c366f7e82c0edf155eba13b1ed234321cc91b494645e9b17c1c59e1 +M = 736e7269bed55bc330fabc12a32d4ecd4e0824e3989608f7a3c3859efb34dbd6eab9b942b46d9fbf3b28cf83819ebf971da622866f1da80df841dfa2b2956545e4195ab00027c5c42885cb2f51cae1ae + +ModInv = 14c69b3310fefb31aa6a42fc6dc7ef23dfd14d2f6c9b4c9a2c208de6e4855376b8d628de3bcf201f5c7c555dc51a1b7dbae347466b2a341aa83db2b5f09ef593b00b07bee8719903b2752166c24f65a +A = a6760d8ecbdd64b1744da83d8bc5c3bd48b857ab34fee3a3de5b8e84bc1681456f4d55f2bbdb1cceb7af5b52cf53ad4aba9e819356dae4a9863122132d13624c33194b27ef7c995c44eacc4103639e2106de4f84c5c06468e023772b6a4cd0eecdd5b242ea1f987ee6eb917c116cd10873a07e790bce171ca22de96dcdc3c132a64492370733afb73a2b36e08bba63bc932afc67758c6fbdecc7668606cfb64d0162b771965a291abfea2067744bce48a1 +M = 807d103d85b36fae1bad61f40ef4dd65301d5d7be90625296debf4095389f8311dc16185cb663580175af7e8dd5400f47e0a4894c5ed13c22f751c3c564d7f2c2cac605066acb91b61061ebe3149115 + +ModInv = 18f6de3081a737cb3efedfcfbef88519e733ddea74efcd42c8d22720d8cef4a980fcbe6ef224a25ef468915976be8f3b47ceb6a1ce4e2da50079a71a3dcb6349cc76f77f211cac7b61a95798b68ec4 +A = 2825332854a30ceba96ed3ae4a2d7562c0ae394427a1311ed6a9c2b56a73cfb416aab27237ec29da8a4f1671d5040dc72cf2ec86613c2ebbd9fbbcc3c3381b8f4ed5c091fe24a0d8d88db0e804eaf5a4d1a2921f42c56b434d0fdf04705ffe9c0a19d4826bd80c232dae62cfda2ec7bae835c62e5723139a6b0183128aa8980536fe63ad451461832b317c02c39a994243601b1a152aedb26271dd03c6fb71f112b7de4cfe9db6a84540a45c24d218173962 +M = bd2ca0d67c8f42b9bb54d131fdb627d4342687be31984bf0cade1c105c3bb7863721cc083741a27d8f61a21eff09bb20b049ad1ab6a3375a51aa78d332ac695682f46dd812dd811229ace098aee7d5 + +ModInv = 1207207ace5509a117249889dbae281fa2d0b3d60b16f9c2045bac8d672f9a300bbdfa8e74037a368d66f01005c020727098544de8e23e1af7edd6277bc25721de8114c3983760c9981d3acbc1bc32 +A = -f8b130b53c0102a18d31dae4756c5ab20f437a341b361b16adfbd0b8ae1cf3f19a11b1cd7ea2c361172ce8059c7c4f2fc32a87839286753fb502be653faf3e34646b8d57b7ecb9269fffea1d6238283f805428b5fc97ed3f30dd647fce4fd9a6eab3c6033ffcda5e11166a8e23bd1576f6c168523dde2c482ee969e5e86e5d6a6035583cc6a7d224b7d08a8f9c25ebba23d57877de60b087c98fdd7ca6d7a30f7e42427747710479c02af7e60240c7bdf738 +M = 314deea3cc58a5e15e948ba3800f2edb66a308ef52c8d860cf6c0c9fb6b1c25310d27ee528316dad51b3bc672648bbc94690f7579ab23c2836083a9d67a0671c99036b01144299c61f3e9bc3276ab7 + +ModInv = 22e6c4e62db5fa1c497f01a07c3d3b61cd20a3377480e5986049f001c81a04b68f2a49a17ea4a4625afda78f06063aab30ef745532ac8d35057594c902084751ebf3ad4c13f6b943c1b01cf263b8 +A = 680b751f3df638f50fc4cc9e89eb9ee0977caeb003fcc26d9b03e0c2d7a84db49c5c48f0c6a56a98e2b6b5d3621b5f8ff4e6f577f7d3816e4b868d83ec4386456620a0899150574c7190c13ae498bc78a5114698c632e77fae733527fbc0f077f9e5bc8c3ba3437ac4237d479ff3fb86d77ddc3fb5f4401bb0e57abd92d14fd3ce40cab0913fadf7ce538855d5070a5a7d8d70869196c99f8c210e1ffd111dae6a98e843392d0480110ac37db9125a0c0bcd0b +M = 90d7529d886ab5149b84ee118900ba620b693288b11995ab5a5a6690c616018cc0a049cac7eb517746bfbc6acf5e2efa46e88b31017f7312abe3ddbec7fc909a1f43882609b08f30429ff63e204b + +ModInv = 6215a0340c6ba21588cd0f16fe2447674a7b7594e64826a410196a88a0a4f7c4f54d9d9ce74e51c196e91c519f88a3c31753c136375588ca1464b40d04e92edefe9e0ba663acf7c70dcb10e76a59 +A = -50cdc3ec954aec65aa088c9c776ef8d597e7c60387491ccd697cf5d65d80d215dfd456995b6e7b209fa2abc69f9a35a3e1505ba7ef3f15732d10a3ebf7fd80618a672e2ca600e369f7a6e0b87b86272a7cb8af46f51307b7c4aa55f8727ddf912381733dc62950e25da32001223fc250d73e754553db1e68a9872dbed94c64f1b0b1b9fa5f7f9c9d9289d21f6787ef313334ad2eec480245b3af4302563c2f922bd8ee605a3f60a19ced00cb0ad653b34097 +M = 822ad361e829cd4ccf813e7b13ff6a4db1f5cde2035cbb990aed934e125dde858eabd581594ed4d48d7228624ce3c3f38746aadfb509c82880343011b96bbcbbe525ce4c13e39c4e802c5af0ab10 + +ModInv = 2b1ff1f6e3fb7bf9d7a55fe23c404840b1c9dc91533b898b1bc21ef0825963b936a031d890af6b7672fc3a36928337bb89dc0f5b91a59adceecdb998a95e29c37789abcebad02de7797657387a0e +A = -422fc104340cd00883b8f718aef270d1dbf3b60c44ba047dc19c1de5bd0d910b39524f66117f4873aaec57ba67d218720eb54363d9d539783aa81799b8176041b540724553606c464b41da1c05b072198aca2503557c14c6cb4b0c0dc7576c98e923ea89e45118a71a530a51be9e4d47455dd503421a303a7e34cf5568fd5a8b095e509c209118c7ed7df60362be5c18ce776737ab9092f413cace80552829a01f1067daa80ca8fa941b4f14d4c805feb2993f +M = 9125b2857ccf60cf6d96946269aadf8c1c0f1d0dd0a0394b9b59d0c3a39ca6343ed4f095f849200bdc7749a0802714fbaa8ba8a642984fd701a3131fc16d523e88ad2b87408f7f3eeaf8c4c7bf81 + +ModInv = e4a9c631d83c044ac6fb88a0495773c6ca00d4427a270062227b68fb76079e8dc9a9da1730c4146f9c64d43d908882f3da87ac6e2171e469c23ad7448b59c89c45cc8ba1c248369a2d4864283 +A = -199bb030083c49e91030c1612ce4ecfc30b5a4e5e3b232e2fe73d597a563c44c3658a7a6d23486cc14fc0e887af71182a06ec7c2741b2aaaeb5be04f2172fe3209314bf03b86936e149c89aa7ab19d21c344e631cc10f53b09bd5f029880669f4df450df5f6aa341d78b51b6bdc91a323a469b545a23445e5275dd465523d540a655c73bf0e89d89e19181d2ab6f54425b78313a317f115561a58c44a46a45826664eec4e045311ff3bce1811790bea7a77621a +M = 3affab60864f7139266b488c4db5e604f8b3887fd1f3b444779ba80c37e7129bfa2cbfeae901a29e71eb38c3e2e19afe85c7b8220f4b4472329a9d6cf7053573f08373e07a295290af70dc7eaf + +ModInv = e90900ee376a40eda36c59634d0064fe4de7f61ebf97bb3c88fd9a9ac5c11e02a637e67081211b44e742d701dca392d86d72d99ff6b4c684a3eff8b2b3f3f40625f3a017bdbbbae10ebf7578a +A = 4e217a0d2bdda68c468a542b9878be1ed8fd20a7f00290de197f3e97990b92b33472110c0a14a1a0bee30ca39f48a597fb8305a5f98f9c2ed76944ec3bf05e7c884c530a5869f100112d7fd9af23f12675e9969a18ef70389f12ea457a7002a3e797ceca23cb749a74edec90ed2951a910db7b393de4749e61dc3fb29836f9e61212e73b1219897d0949b82bc59601005ea858064702688e3a91c7720340aa5959ea9f8b1ad4d60ef19f8377ee749a09ba8ad087 +M = 4dc617d7b0a9b974b5e6aaf737b497b65d8e94f52e836b287d23502d85cdeb71c9743d2902d068c6d2fabf44a03ca33924f073aa5f58b54209a92fb3242dac22afd75d70b36cefbea97ebf6749 + +ModInv = fb291ef1030650231fdde5d1714d9061ffb9d23cf8db994ac5b400576d56937457130a866b38455e21dc28fd70660a733b169f000166a33c3eb4772842e0b1e0b7c4a4dcb24cc45aef58914e7 +A = dde34febb1482677877561d52dc944939637efa7df6c67ce220e756864eddb48a125573fe3f6b9cf61c5c82ac5f72a9b33e7a5b411d691b089f37f3e109fad641b572bcc10c42bc52baea1a73f4780efa5ec2e716724ca87fed21cc41bdfc1de768cfaa52da7ee46fb781fad75d715a309b3a352af5a34ddf9f9a80a5dcfd503bc0907a57e9e4acdd29c4d2104b876d12b0e5d5af45c6481ac5b3b79708353798d68d3cdd3321a47201edea378a69cce0078c003 +M = 13e88477d2390325ffd54066f62b842c477e391dceacbc8a1a8c29abfd15f802f339aef5f2f69b86c29b38da1bb60b39d2cb9290ed7be4d59feeb56bed725c2bb6678aa9be33d46a56f2be1486 + +ModInv = 50eef03de39065968e28c59da9d03e27f38b01d612e08fb2e107f6d69a7fa8105cd2101558e40f09178a0cb1ff57303a9d4760931cedb1e09a7f006ea30bd3b82ec516a01becaef03d3e910d +A = 31a88c600477efe6221e3d59345a2a5153f20eb4b1fd93928c4cb679fe5b68d3ce1e5ce49236eb149e9d52fe571b841d113a984dec0cfa8d147a409bd5ed09bcd0805d900d78b8a90840f4b4ac6e6cd7e62b0d9b3edb24ee019bbca4598a16c23e5cf5d488dbb7696d00a67cf7c2035a66197e2999b569663acd515d2a4adc330c9e4bd777181ebea30c93d3c44af7c63127a908a7a3ef67f7f7f32aca76dc8a49e48f62cdbb921947469c17dd9473462fcc9b4b0d +M = 613281203d70499a6950f4316a4a2fe2ac5559f10e13e256085d7cbb0ffad875dde0aefd30fca1aa40d75bb8cbe0bb907da589179b184b04d3ae9d7fe70d6a6fdd3c23a3b352bfbe4c9429bf + +ModInv = 3641e4c8a8c11f8e2650331f49d5e7e1b589af687bec57e1f8ac980a188784cbea04a360b45369bd4af0c29e2d37df669fc4bc9173117e42bae52cdb72530c55ad7833098b5cf5e5e7eee86b +A = -bc71d97df0d65923a120bc606fa33f70bdce80c994327eef6ad2c9ddb7d04e82113f36f9e5b901743d4a165cc2e023ca454c6877df87f992b344c0a6a6199e21eba16c023c893b41dc90a22f8a79df355e352b5ea49fc6abc97b68e8a2777ae4f4e7ae84f424b2e80ca766924b0327ee5696bd0dcb7b2d60ae1f02058069f74100aa37a6e63af9ab6b378eebef1a40130b4c380b6bf9c8ccafc47c16f6a5b6e78787c241bc05226db4e5519de5d079eab7b8462e37 +M = 98f8e10cc823ee561c470e0354ee2fdccb8e07a3c5c3844da3ca531909eb616cb2fb12684e4e1dba3367d259eb9604844c97f882d52cbe783dba1f86d4a5808e725d1e9f722278ae9fa3590d + +ModInv = 8a58bb08e978a7e67c2d120825fba76db1407f78812d767ffe1eca759af2eba0b6aaf40c7d286c052e565456a5d3254c5484441ed18595d2f89337345d66b6555e09e3b9ce375d9ccc459f +A = -1c956b53e7c7cdc1610d60d76c6b4bcaeb9c09f70b30c9b71a76c171c298681905c58f0c79003777cc8fc54710d52a49540ff7b0874376589d4839f825271294187e48f6844b464aef6b9ae0029dcef2f8d51cb6a33ba0f13633a3e5d95cfcc200b6fdca81066c976a9531b97a78d49a3e8189c1d6f198ee4a51a5b3508f6ea8d8775682fb5ed66b6c2d190871ea91468919f28de2fe84310d6168514e0965c1a35231b6f4518d770cbc20303c2ac1cc402195317d7 +M = a831a0fa44c0b20699c049c9e7ee910d2df2aee1f7b377eac8d74454ac981e3633005fdcf6766b8042a9c74fa783a7f7b25034221e691b56f2a0096912dceeaa3bb6950e4e45192ddec729 + +ModInv = 273e8892aa27d5cd13288353d1e37fbe74716c93942e41c0675572620c73dabdcdcdfe87b9d84a457909214ffbe95e733aba95442fd3394d44135531ea2fa830717db8df8a9cd94d37ee33 +A = 6b0f486a9f22e182b8fd5f6063da92b59f941a3317c0f50a2e7d87da3a14947b9027e293cdae0df5cf4b4aff29f133b1aa513ea4a3de7343123c0c58c5115a354d32f4c26530f68c82a088414ff4ad3a3c446092c61969a9acb4f30022a5b8d49dea9422fdde9a97b6f8938a131237085fa8f9efb4afa4dadc14b437ac9cbc1c4c1b1f65654a8936ac7c555790ae76a924204d37e2027f50f180783edbd3e70439c88cf86b813bb1c39726d135256bc31bd98cb99d42 +M = 890561657768777362690c69d0b22184f6d1ec2828f7e42fb2f982e8c2a0a51fbbac854bbf9b8aa4cfa0ac041f7eac0bf68362273daa7a29a27dab158645575733ab5dd8c9edf79d8329e1 + +ModInv = f2c2fb82fdd34d9c1d3668772532b884fc4cd1bf0413470e53baac9d2fb25cca25cf60f612412a1b9e32dba4fe858bc0ffbb449260ad4864be1c3c0aa509c50492d7ea9798e9e51d1c7 +A = -4b3b4ca2aedec38ea627b48c0b7c0c51e0f3612a53ae4d4f0e803b992d4e990255e0479c60bedd12a8129897fd9004dfcd826f9b5262ca1e51bd1291923ab6adb6632af0253e080939cb99621df26532524110294b840c34d7c66a7cd69b596ba47afcf3795df2599c3f16c701771fe2452c4d5ee1721d76d336f23f0ce73907b20f76dc3c11949a963c089582e3792e4dbc344b8551151b31160d28a73d286afa2d1602debb29aa1e0fba26636d5af8dc7cf576d7d859 +M = 22f877eb94d0767151a589f1f1493f1e66e1427a90d96ffb4bd9f675d70b0ff9a29fac3c29c936ab1b99b8a2e044ff4cf1f1cfdebcee1567c8b76f70cf65c2bc164c24d0e38997a19dfe + +ModInv = a675d3e5a50213291b443c7b26eedcf95c3891e7012f9713e18b31f021e2e5c473f470113b87f6f235c17779dfa925d894144108fd78afc8cc6344b6ff07cdca1051d287a397e5cb059 +A = 2cc8985633738dfc0c8cbd88f30407f04eae7be2e884f065e02ae0b424863926668b442eceaa2a1814824afc1fef643472468b26ab94adf83682363b5804391847d6d0f9ecc3edc025e5027c0faa5cf409c125a65e7881b80e9a05e1605bd4608cee2a6741600f3b813abde79b527a9c46679cc731e01b08fbc86bb60ba31717aa9b5de757e7cbebe0ec1edb22586fa2f167f76fe4742c82f6b98a204738403175f2f7a61af30bd1c055b08107e4180a932cec5745d14d +M = 20bf51b002eae54c1670444e4b1f3d0442696a0f591286937e6e453ab5482af6d5a3b81244a1554d9870235fd75125ab349e7beacd8d9355f22956c50cfa235634f0aa776f4f41f5c35c + +ModInv = 5d3d4243b271051c68b4d0360a1eaf3606f63de4961624e8ace3f580583332e5487cd3997d46e79d232118091b560e8cf42e851b3e0e8728bae7601f3ec0dde2cc4fbaa78ad189968eb2 +A = e6a60bdd947805a044549e6049f8b620e01a7aecca2a5e4e9d55b4f202363cb47f4420080cf661668fdbf16a5715255c8a1925214c254bed72ab18942c46fc7166d4659055f93c60d25bf60b3787d4f16a684825dcca5bc839368adf9a8942154f96f526355acd5a99e70d5840e05724c72f8b6b72b45d073beda0b0775cd797b8011cd0a0f1656bc46d0ae704b94bff4691f96c4a1e26ff9ff1dbe0dc87337b9b5db4aff62ce3bc937e98a3b0654c280a002c2087ffc0 +M = 61302b153b0901b734f21f87728560ff102ded9efa69223a2d0c3e69eba09e45a66e5c4c13d93e6e92b83171dbf6c34ccca316d4a47d91e7f047466bcb678ddd8e70afce464d9a0b5e81 + +ModInv = 397a339c57dc5a7f59a56408fc583be546ee7c6311c394965f9ece2a423ee9b086afbd0b5155a7591d2526fa808a7c4ca1be0e974ebd41190de62c7656b3b4880068a63fa6b87179d1 +A = 5aa9bfb8289661874fbd96adc2a78e0fb201f2fa4a9b15773ac68bf8af9aea916f37051906a30486d5997a435b2e0055c389707dcbc8401a115796ef555c284f14608a35520e147212b413f59b36e48a5ea8cc3443ce93df84055902a7d9582a7e78c754e4a37766f17f237b54a8de6b08a3e1c9fc35b5eeae086e2070f9d19c4e7dc5b3d890dd1e7fa7fed723933aea4db15e1bbc65f21fd2fe4f1cce3fe75c68deece3fe898c72e5720b74ff83d79f74c290d551d4674b +M = 5a5c30d0cc703266432a43044f558934e6b16b4ac282c1e94706eab660a5572cb5e3d09e397c32a6863485224bd1a165967b56f8e530cbdf1d228f473bf886b57a24f24143fae30a59 + +ModInv = a4c98827a9d8d22f194bdc254363592b5ac670ff34d6656dc4cb0fbced31ffa0950ce9dacc2998e7b6809249d829c0b8359ec12615d438103b78a7b63d8bc4086b7436c4b217990a7d +A = -6dff31472f3c1a50e60d09bdefbe6eba29225e57b497d628c43520ecfebf8c77b24a303d0135d47fd1c3b3d197d74ea17084c26b746179c3362f759b0bc9865aa9d485a095557d1f01679b2c89b31365f84778ef93f65a51b246f9378577df30a5c56e14d4506bc87a93230ca3465ae97d0b2300d370da9234e2ca58f5bea67186a921d50c48dac583ebbcff30539c156eef65479a58fbadd016827ff0aa13387080016f6ae67318fa73fd628588ed3426bde73d3db075d8 +M = e31c3252a2891ed5dfbd336960880b2a449f4c371b016dba8eef37b7f0814cc3e6f54952eaf63c60aa1c4fef3b37c285b1533942b52461ef587aab23b26af1fb8272aa16f41b6a251b + +ModInv = 3c7cc10e8d8138942664798151cb3900359c744f561a26d31de7e3ca7c7027bdf0a34b7605d2146c0c2d6e13beaadc87a5919bd13c85545decc5c8d82b4d0f0357626d1988d8830bb4 +A = b5952e05de7e0c2b8b843fe93450372e0caf5fe742400134c9b57d6277c637d5437b047a51bf9f1969da282150379e63aa11c5951251cd5d7759b3aaefe89a911fcbd588ed2e09ad9fb2b37655df56850b33cb187afaa6ed7c9fa6d1de04915b9bfea02030da933e474cf324a5d2c27f58085e24d2841c926c406fcd225e6ebc8b5683076a5a97ab3cf404af45577dd675cbcb6396ebbd132f8096cfb70b183c98f3deca11e633e2f71c2c0a5ec7b59a5cb449e09d9dc464 +M = 5230fafd3823aea7d3f3805854b584137be0f782c4369d714eb373e72db472ee679ab8dae46fa65cb55766038d1f74ff08e206b2d2a14c5a1799a88c2bf170124767b213ddb2ebcf0b + +ModInv = e5c9e69be76852fa99c5cf7251ba0bff17b0c2bfcba6a5f2755ba5a7758d011ad78ed7d31c806a84f13a6c85f2d2b6375f104570961ffff7458db1b096d1518a308032232e0800db +A = -16b3eed7468c40fdda984d01f07c3784f59e0be56c37aea892885c03a0199d2beff834916b0a1f73a3bada54bc14b0c5390493b58a5e27dd829bd8cb1875326b248ebc4ef7e1bf6655363fabf7a9f176153149671ad56b1ae6f015f184b2ac9d268f68b44017f43c0c34d4c3c8adc4ae299a162483fd782671f60d1fd65d1edc5d02dc2776681fd6cdae2d78e106167da10b87b586f46fa3815b1eaff9b44f1b8e1afedead83447b7db6767249972ce94519ce28e738d2b835 +M = f37899e289b6029cb2bdec841d1174f9cb7b2dbd7a19ea26402df2afb03839772cdb3f032ea6577f12f7ac29ef51ebae5e4d6f29abf093039793400dc04b873d76025324f98ca768 + +ModInv = 177525aded6cdaa93ae191d45b6a9f5902acaa052cd361d37999c68a269dd951ad873f0a6604bac4463d961cc183c86460404dc088bd6a77b8b80815cd2a2d0f9d1e5caf00874863 +A = -2de76e52e33daf592efcd0876dad3031bb035f983956d6fd345b7d5f5ed96ceac564a308cded9524e67571f9aca3ee5b0dab78cdae14a535f77946a785ada6e3dffce1efb4782631ae7bb10c1c0dbfb0abf6d0ac61006d1bba3437041049d8f9943a7fb2c49760e3fe06897548c334c9aab946ced026ac68086671f4d03b9a027db020e3ddad48735d69abdbec6d58875a3e22b5c85b656cf8d18ff9f41489a91ced9a4b778c4dbf5eb5767013ebe83eb6a76c87ca18f0fd9d +M = 3bcca77f7d05c6ff7415d2100addb4ff54edf270bf9e12dac65f28f85e64220edde56490237f3f8940822942ba56b064f6fac656e9425b3db97a3d1f10e6f00c0a2a2deaedd88906 + +ModInv = e9843d3f3869f6ae8456f61cd3526ff1e48872239e05af0ae6feb12db3f2690d420b1be4bac23935d081b6ac96e15de2997dbc4f5bbb4b3409653ddf3fe76bc5d4438d925bbb4a3 +A = -15e8b47bc0a5fff647d50a50f50a27c6c63764a794c97f6417bb34c3a795cad573aca37e2bbbe7356b14b2e5c0b93d17698b56daa7176130454ef5aa7a1834e89f87b58a05b0d556c42e64838ba662ef9d319de49fff874e8ed3625883ea807633f604c92ba3994b9664ab337fb6e04aa4810ac87bc2084b9e031f3104758be562db9b76f8ce096314fd6cc9b8434f92bfe8cfc42baef1c02ef6a0efc34919cf5bd235ebd66c9eb292826e7060c00ca395731f36050e0d1017 +M = c55b45402c1c65925439045b893c8500fbd295a27754d085810fd0541440f9495cfca432de56878c19dda551f9ee915fa776f8f9b68b698f0a41a270828374cda10206cc477f2777 + +ModInv = 2dd04d3f49224ed7c4701352423bcb3e96642a88bbe3afe304bde523393512f14ada4d17cdf6823c2864e8af718055842945dbbc8c3562060a008b767e40429f5092b0359fe947 +A = 5f4b44759afcbf5547604a863593901274672ff299065b9442732a80590843c6a915a3f1573cf3b8ac8a1f68d472c650cbe22b5bb97b0aa330a934661e11fdfe7fdf778472d3dbe5b5e1212d412ff91aafe6077b5cd7c6a2f3500367e699e59954b24f889ddb41176156389aca30f81e760086b6bea14d9768da7012ea946f0af80204339f1ba98f12043a0dbfb16ad90f0c69955db8fac705de8333bdba413d450f18ccf666b16741b0aefdfcb4ea09c38cb409a299ff5c0d03 +M = 51ba04b65fe9564a60455517020cfa6e2e87ce9e30beae7875d7e09aa28daeb08f3766d501ed0b2eb898ab852fbaefe53210ebb7b439c72eaeef746be68b86e5413370ba52c602 + +ModInv = 2db8bc142392c2d5cb9ca5cad1fa5722ddc6655706605f241191222752acd5ccbc1a57ebc2ceb4d4b942aba43ac69af1d7b201a7309ca050525177c1e2bd6d0dc0fbe95b60b3 +A = -c76a867c388ff135bcb80ba752741acf589a965a1d6c4933ce7eb6bd0f2d1e36d285acec1d59addf43f0a11d380a283913ac962f488d097e3749a5275b5c6296fa3784af7769e4e00a5c7987a8eb79e62b201077b626eb403a6209f554d23f34b50e4c576621727dc404118ab3b1b7bf98d4263b9da1d450f5022a93b3e24d41284147405d715d7a267f8a48c7bd87ef13189cc2821ba84b3d418a8ab1a5fd7948a6648c91b9293583bdf82158e22324c0af94a12c5be0466780b9 +M = 7ffb7052fee9fe5c2d939efd7855f44460e53d8429a638f49bf38ab49529051084195457529feaa279b9d4b359b466367e1ece9cfa9e2b656d10147c9c123253e2a7fd26d334 + +ModInv = 3a735085fe751747801b2cde0dd6436cf182e37a7bc5a39e093a28e41c09e51f77f97b3b415a367abf6ca3dbf3493e53ab20811471d158040d9fd8283715dc4e68853b1fae69 +A = -d2c484c2511751aca940581920dc566fad1bc5fa3eee2c89d7cffd0b17b6b5a263a754bc03a7eb52304dd9870017944f2a67b9aa6254293554a7828af207493ff8d4ccd15488b6f6353ec17d28ba8c7097bec70f52ab4e30a6dc5bf5901032554c02301cbff3189a1cc52a1e538899108575cfe244900026ed0e624f63af0721a04308f1fb248a0aef93e0a35ff7b251d671c7db85e57c1e877c867d403c712809edec156f0eb9a64c305755e638b803cf84047413dd456c442c0f +M = 76b37c8f440ce9d970479f1ab36ab780894344b52c17b55b5fcc93f28c62adeaef202ce2fa85dc34244d9504f0ca8dc9cc2f94330dd832c32b2cc7c649be96a707468f5750c8 + +ModInv = 8545dea4d8ffbfdd9cfd628af75a6699c6882400ca565441ed035046f7ada92363c144041e597358275e85d512fc9d6a1606f0088a582edfe856cca4b02606da98780f72acef +A = 44cfd8f1ab69f71f4dd75a89e1fdc0fb20c68b4e5aadeaba414f511d06146da68154df41b989a38ffd5b01d15fd55c971805663745bbe59e6c87890eed8b8af72569034082d10ba03afe46b59d5ff404777b5e9fafce3b545c3590ee0590855a1214adffaad76f3cccfe177bfc057f05f1851baa200b912d1f6dc1c8e6fbf027537a92125a6575f0f67376128c3770fda5d9ef58a256fa992fbd5d1ec84c9da189de98ff684558d45031a11e1fe3e6fbc1ce236d52978b8591f8e7 +M = 9676780e7367c7e66a11f344f27a36c18827e401a5a61b17d65ee62f57ccc4054ac5b864837fdb391dad5e0e3c9954b3ff5c5165d584fa207d1c5df4e51c2c3b454a41ee7318 + +ModInv = a9a28a346878a80151ab4b3d86c544d80f69dae4c8b0ac53d6f0c8c4e5c0eede591af3bb596dd9acaff57612348926fd155a26629f23c7529e64b7d5e3309ea94597db84b +A = f91b88f6f9b782759aebcc9fe60b220a262d17fde019de080ac980f8f70a8b5b64a4dc4639c96504c5d9ee6a3b05906919a22186e704ed0345a080b15c63cea38ce68d0e96c291e32f4f89c0315b1aa7fb1cc33efa12358ce11ff72e58e4f5d781d172de97e8a66d8cc72dc069508cde7b63d9cb010bba6bcfc4135acc344a22dd7436f09b322eaf80940d66ce7ffc1d662ddecd2193f7c247961cfbbfc7f589e1657d02eeffd8e87561c385003e518513c1862dfe943b05d0de0d43 +M = c568afc17651278b005b39dec87315f1d99d793fdb5909cacdd8668be8131cab52e9bd46f932fe76a6bd344409b3baeba32b987ab4dfe51a4f2cf2ee53bdd5cefc9b86e32 + +ModInv = 363a200f49c61f4a1191683acfcbde178f8102bcc99cad77037c27d70d4c21f4ca88deea41ae4b9e81fd6acc8f8ec2b3ca26ed1ba9d825f958e5b0ffb922b79b23b45a8954 +A = -c54457da1662c72f75bc89d2e9c801f93a75124a97226b4c63862a6f8f21456cd4a8f35d5858044a9c3f969ef2faf46fc6bd30c7e60c6e3c278ec98838e2146d5b8199e4bbfa958d866153d259df5cd6707b1502059c906dfb1dfe376b3a0d3ba22b0f1bc2b460d5a6cf8fdba3cff65cac42c063547f60ca5f0d65a15e110b1f969f29c2caa93ed9533487c3e8a469437508ce38b3e858c6823f7daa48f0a23d76ea5d6738f42b7222017dd64fe85cf2f76fdacf1f3199381511fa36 +M = 3b41b54eefec5a37360b7f184a1514cef0a304649a4f53b430632b9ee6d8936d42d824e4a661ff0c6809cc3c62519404b9ea6c060d96b1dc66999357c9c4410cfe5622e25f + +ModInv = eb14cff4110d21bfe0cfb1335d2be8acf1c1cce6902e5e2ad7fa095c3a52808bba06ba89953fbecbed0643ddbdcf98f1abbed87ff04dd305e880e9ea1fd2154998cd242b +A = -18bd81b9b0512555dcdb895bfaf73a03d74b6caa1c2cf25b474d5d579ac0fdcc5f82ad1429dbaf8a40e179c0c9eafb1469e143e01cc2b82edff67e7a1e8b36c5749e80cd11baf6ab12bc988300fd220ecc7cfbb8b72decbe409cc792be6259255aa49db60bf7c232d9d380831c967947247090dee97b794420c0adfb2379634b7dd3a70bc4bef4edb940602b4d0e112f10423b4fcda3983167468dd170d96c1c965a1c2355c3673a47ebf7e7abb180521cd88fe273c6f912260ff157 +M = 4308fd9618a40fe08ac427c84cfd0b889be04b569483968c2a0a85fad397b291d411fc7fd724a68528f1be422b657e5c587cfaa1ee2ce68a67ee6488845557e0b69d16342 + +ModInv = 1b06ae994cdfd62f9c1a9cebc955025a4a2f1455eb8d5603aa0f6c07ae393bec2089bba581517c48027e8592c3d4544005ad1551e6085c1323a35e60d785a2b2a02ba82 +A = -a32ee7e954d6f2bdea90d6b8571619e2ae9d1fedd3b52bb8d420960815ac8fb7470635a53a6f9fef34dd4407b6a88ef96aed5e29a76228db7566ab41a2bbdd798321716fe165637eef71dad7363cbd2e7f138a1251d121c3bb561b6f3500cb981f6619dd91bcf99e01fbeea7062d3eb15c037ef4708503f34ac67cef6b22236bb2619c69295753910e26c0334fab61cd7fb71c6aa8fdd334d45cc5b1360ad39d4f7fad55819717900a940727f9f0fd5032140c369da18d1e6e1ea8c55e +M = 453d7a8a9393799693919f96688635f5708c7f6b54de6b12d1ed5757391befcd122e01cd1206984f380b623e33628ba7882025b194ff1e3e7e06ec4236ee724604284521 + +ModInv = 1ad0bc33b0b659f398dca6c26b4f34fd5e256bbaba823c865ef33ed826b94cb4c528fb0679fecf76c5036b6f4bd22984a29cda068bd6bba31fea5ccec01e5026d01d48b5 +A = 65e17f114e2ff93b246f0e3622e76f06b991779fddb8c16a888ed21d0dad23daae1c19893ec87654f5c14e5e48accb2786875a6a5f4eea599e04cb2a7ce1fc8bd65de7162854ff9d4eb4592f1df8a66c7d68c3e548d058f1f2c596929044b8863dc356a7a0a8e23375dc95fe4b5f56def70bdba53a56711a78832e7b0607f89c1a676b6202b48e51859e40ba2d5f3fb715cd74e06d92681fc2dc6860ed304b88401b95a87c0ff819c9ef547c45d023c43793ef52157aedf76f2e3d72a1 +M = 9b04e0fb0fd996e15165d178826c6c549a1163702d5d5652f13a9fbeffe981befd479266b8a50b156e923a5710b7bc34bbe7ac950989676c417ceb4c1e715c0a68ec7313 + +ModInv = 480e19d6abb7932ab378e18f3b8d0cd3274875b2a2b259fcf0806cc51029f5050aa05674f29211f2d3372cfff5e4e3e8126a2164a440e3b32b48ad1c5b792bb7efa2e5 +A = -4bb995245675fe0b754e9c8e1eb20921114e483140eb0aaa1f025001cfa911f2cdae74ddbe43351ba5518144e19c437d76644ca04d1e74c4f3fa6b991703e8021ad0f56e2dc06beea774879548d29074771c5a02fcf6b0cee56836164d3435ab811d6a05ebd23d919be4f652727386ecda47b43e2e9f4b87ec608037ad2747fe34662244ec6592937bee9ca9cc50c2f4eba2c0c13ff61581d58855c3e3fbfecbca952b28b4c37d49d1bf9c368d4131395b8327230b79943c47277929085b +M = ffbae711febed47a740d266186a1a26a3eb167f8a1e228fe17b258eec3bba631f23508a4b3eddd3c721defbde1a3a30bcfa22a3f8606eba2b5e73c19680f97c8aa631c + +ModInv = 72dbf1d41ff642124c8dbfd62b0bb7ec09d2f09744bc0622ee4475e13439ddc52f4cad1a0ad3870d930f7ffcd035b9ba23ef26d626cfe006f72f885b344eaa1a07bbb +A = 89de6d4d9dfd2253cb0f791096d485959a706acbf65780dc6afaf6ea69c4d2b5a66b6aff9444b7cd20bd4204f8adf0e8ee56eb61f698e87385b6151e24883aceedf04581b9b282b123765650f81b08b7107a9ee7f05d6d1addd7575f517a12bc93e88a4489e3a120b568cfcfa594f1231615b9487aa3cf871ed8a6e075d5e9a4c6c1d29109db9d62170c627a5c3edb8e71f9c22b160f986d3e2b8ea10c252ca24d2e55860ef8333dd5cb1a491da1fb5300be4c6a8897b7bf79db8bb1bb6b +M = 248a8830c03b8e5ef78e522e76c9c425602316a272a08fcf43df025c70c9c86f6ffcc2cd76301b1b346e5ab1119bcb823309cfc5f9b4b74705e8968854e90c688fe156 + +ModInv = 2b27f2e23156f1aefbfbee976e143a13cc7d039cf61ba10cbebe33cf901200f2cdaab9b23ea4e7d26d1a91edd8679e7ffc6aa1b84ef66de810583dd3d5a1d5057fd +A = 94841496fc537ea509bded093bd5a6b74dda50712ee1f54885fbfbabfbe9b016681e9c02cf9707f93422498033b655b9dacc2e4c9f8dfe7f9d7adf672afbcd0625a6a1fa2ff47fd1f937162926bfe3839d103cf37f62df179fe8e39d5fdd093a764e50afe39b812f38b0e579a1de6e8011f86159ddc026ede5d8734ff4854409f41da71d70e11ab3f7d2282c602168586fb213160082c679e97d1de061814d180661e379ffd071224991f03d393a939c2e1a1a4ab04de15bb7c82201c7c142 +M = 7ff0581718e5e5a428a2a3c39b8fb2cadb7550a17bacb72a7aac95a713a6ff95b8dfc69fc3d0a04e6f7d5e88f19355a430b20be3b4a9c4354036edf0e6de4cb249a7 + +ModInv = 2ce4288e2457ba8153a9fa07188b6736afb6c506c15bb0e73f34b90803c4570e66ac2353d8386b48d1650fb9f44dc7e11fdd3ddaf50d738741b5719b59549985d93d +A = -62a4c77626de98b32dbfbc6b415c89eb1a9ffc952c18b54a57663e91010797e5cebd40e5a893b5ba84798c573b76480ee57fd7001d9a2f45048acf615b2906a66b3c715b8bcf1cc4437b85a0cc7c4588668d346f7bace7b44ace0871fe53331276d9a39c79acfe9440061279b0c7489a4074271af8eb850e08d3e2084646e9b93d0d8ebdb59da196e2f49e160ce96dd1d1f987079bcf39086c56a5454d1bd63d049a6fc22844ed771e6715656148d92ff0a1e0965fbc172c330b3499e163fb +M = a9cfd8da346d7ebdcd49c1f6aa2df06fb251400a8098c645e7785ac83a04cbc63d6b56067116f6f97caefc98477010ba565ec13a7a0524fce3030910ca53b7b2f694 + +ModInv = 4ab729cc079dee8ecbfc2d5186a0b092bc058350f7b0b48f21b76cea13835aac3913018fc5a87d77c3ade25df323b2d5eb9db7be1fa9e712d9c3c6f5d5a5367717 +A = 6bd7114b08148019368bbc13661c4996eef0267c385a4820b2e285854de3e2e0dc3870ef91248a5e9213ac3096b83bd5bcce80dec8e3580ec565c5081e3a5bcbe76f221aa750ce11cb3f534f04cd0d7a31b4a37bdf6c36af9f65c26dae5f5adec6d75632ed4692d25566445691bdeec073a81d5b2472423720c73419852da51d2986e866e90097a5b911768a7256381e75f6b82cc0ce57ad84057ec75f86ba3d2519e26049750a24fc71489f99781b0d6ca4e92f3cae4c257bf73db75a24bf27 +M = c5ce4637b4348763d58c9c1ddcaee2e58c4d5dc800102798a7d56abf5ba7b6a973c671e462fd176700a11aa2dd898aa0bc7b6d5c8a8fcdc67e19ddf4840d17f930 + +ModInv = 90bd6465d3f2b2c457c32d908b76bde31f69bb20337f92b55470d6bc50979517683609879ae21582993de3d6d4127012418529568f9e7f6feb9227305a202be12d +A = -405ac2777d2c6af46999df6bc058ab82165a56117d0e5975ec0e7ddfb28488486910e16bbb3aa91b34a4d695ef2dccaeea1f35be6d337a91b21e6a76129f260928ad5342d602e1de7b8dd23964dcbc44b83f16ba24cf35f263e4b7a632b4cd76e70568fb1f02ed7997a06d2867199e09f070b3f2b9d087ae479435e7480d514749c3d81a90d8a042c48d0049722c396680293174a0a39b46435edda56f75b46ccdd01692f336e62e717e15475877309125ba3f538c1287551d954b54553abfdb +M = c03d0e4ed45160235845dca5391d46c6fa20827f093d33c52f717998ed4bd41d64de7c545006370caf8111558e6a8cc0e7d482a0bb527c719885dc5d4292f4b2e0 + +ModInv = 4da67f0f6d0fc04c1dc9dc80202600b65e4dde217bd02db16958dbc9fe19a8217dba5a1c7459196c14957370cef0a45d92f4867a150ef878fbd7633dd41d1ecf9a +A = bf378bb8ebc41ce6bcbd4b5255b061f3d466c3865928a193c3ecf03cc8fb384e157f9aab65fdbdd77bea4c84b7520056766068b6d60acde56d41925113405f2c9bc448587c5690e0fb525f5f0ec2037a4221fc9c62ba4c3e73bf33b27a4a1f6a79a1196a7856c4ca4a9f0dc5b18555a77967bc08ea303f4fb45d0e78e1f25e1d587652f76defe109588e9d09002a51f4b218c1b5bf5e6751a74b08122d8b6fdfc71aa70756c32d871e3c4626f0ddfbca44937e544512bcda7759be3509341a4d +M = e4c8d25247fee0f2eb4226e0a7135ce5c2f0fad26cc91a39620d6e306439d9917bd78459da4c5399dfffcd846859985f356b1e994cfed0d734dba9d38a66974c9d + +ModInv = 8476c202f4171864fb8c57227cae473f7bd8aa8ba868f07002771c8605f1abd4ea7eae5e32bf3d9bed42a7681cf83cd017521bf5992b8cdb9f0b3da2d9cec284 +A = 63c47d52079859ff0b22eab6c5cc0a7e70a0833c94bce56077cadad6901543a091e11f079a53cb33348dc4352946cf2f4c9d7a4f098a876896b686e51e7e3e455e51dcce0b4d71826bc8b74ebbbabeaad9de5b2907a73a5a1a728dad4b014a394c2c58f0f001fd7ef87ac8ac56e3ba532c75dae00f2679742b379d76256568c49bcc406a43fe69fb30ba5a236007c541ca043f7f53cc42e009ce17507ffc5ef20c2f6d77099bf86899c983866e8e86cefd1c793ec9a2594a29c5525458471155c4 +M = b817c9fe972a98d92a833e98097f6f572423cc0ae6fa076bb3b97216500f007d48b0c6f7ba0c6b603d546a940d981892a25f6ab0247c3247bfb4fcc0dbd62e61 + +ModInv = 1cf24b0c299617eaf6694960eaaefa36a2ae00594f948f85156678e6b301b0a23e816ce16a9b836a05c9ce1aeba9b105b712cf69a6b86c2661bfe9f5318bb4 +A = 30daa726f4c74f9c5fb2cc7d0aea030ddfc3bc1d1f5924b7a7234dca973b2c79c06f951b75e1b21dff311fc6f789d17d08965bd524f3a65876c698c558555573becc23be69dd5d834147c28f77ea704a10355ecc46953b6f9f7ff19800d1966f86915fc76b87eda9e7b6f90baa495a977ccb44bb347d53f7691f6c5225bb3cab3ccb891ce8713f07d328c5951d19760f62ef19d1ab59a7884784f31d7e65c874a2e00071672728949eeb920e5bcdf6df5b89b33d5533e71cfacfb17d08a4317053ae +M = 5006cc99030c4756520500e189451cf52ed302226dbb780ef5c515a928a59df3c28b6ab0ba13dfb35181ca2c200f7fca7af8eaf7529c229e0c82e0b512c5dd + +ModInv = 516b95dae63e6cc97d7c697d2736a3dda1eee05c095ff4b3fc1c1738a6e56908f1e7b23d77680484ab894f4fa33a72a14f237c040b5addaf97eb9a864011ff +A = -3ce3a93068fff988ebf71d5b2f102caa25a6e83c747b4e1800de8e6c302908486f2c15eb4cbb4f9d8b383eaedddac72c5c87c872866f4f7d59b260d7590966adb9edfc5b7d8bd3db7e03fa297e7b9a028096c3d07bd6cad5434b5bc05a0f4a69e70346e13eea66e8e9f306f8ee10276a614f9bde1e40985dab3af25a3db889eb01920b46097b11a897bd4c1fd552dc03a81d3b33b7ffdfee084556d20b1a65d6e3ea7394e483cd5f09170188f8102f53ac1727353c063dc5efeb572a1c6032c5b3f1 +M = c82f43d34a3d935b5db890808aca6f765b8f81c8a97d7ab0e5919596d2844da72b0b48a7b80d7ac4a7047498bc0d2026986d04d7139cdd33127d216467d488 + +ModInv = a3a77ddb6cb59132835d913f1ce728210ef95f21164931747604123f62101838fadfed0a1d6ab55b9f820fb860b449521f76807ac740739c8a026ad4abef4 +A = -2f5c7d2d0e8494b7aa8138a4529c5391fc7f0398feb0c4f5d050e2b3cd8a9f19e44a4e9e2d41f0120d21233d93ff538a10a97ed9a89fd09cc0d31ab202d00d0244f5ca9c0ddea61b910c58ffb1489b60fd7734623190f55192d0d9641179659c28f2886ae880e7ad4a0efe234ee467c0c7bcfeadfeb47009b1a8e8be250ecbdc6707e60a0159353eb7af8d0c2d8036c7d726426b591c7c4286a33a308b362e52cbd987518ebdb842e94e6cc015e4eb7e84016c9c913d5e7ba9506df735d7226d8096 +M = 65c365675b851bfba38377f397362a9a44d9977852af5f99fa6bb9b011016343bd2a2959559a0dd14d6c672e2b21710a06226cab20d2a24062a94937e10aef + +ModInv = 728312d66712222d8e5b505699f93554c131ea01a06e0d56d767b254495af6ad0025ec73ce588375802eccf628edb1d403d9e80ff550bf65dd2145ce5781 +A = -2f63997d3cfde3cf8a6b8e2bf4642fb53b14ad957f4ddf0cc65fe40f1fe3948b3f6c943a3bc117549a9bd606cd5cbb6432e6e7c6015f5eb1ec8a723f463f9a012476371763e4051d0edadcc7d6809275a156f2b60bd219cbb6a7edeb18b45f51c9532b075118458da428c25ac819fceeae5f8eb2adcdd4ed78c518086638da1f05b5b063e172c5ee560644f2e34721de33df0de019d76ac82d62fe3ea03f702e9d177b19507258917eb562df53386eafc8a6fe423a187d0072e8d366f21a932bd4f49a +M = 81c3c5bab8ee92d49bf6c16b148fadbcdde025b9b8f373bb6b35e3f2bb56af65aa90e85a5606ce6c3a6ac00a51c6625d4ae515c96e7cc4d8d1052b1bc131 + +ModInv = 4d305f409f4b3705d9ddc4795d981313e72b28f47c1a5fbe4dbfd44881dfea0497baf1b4d3d8eaa9dbfb008adfad9cc3ff096925d53244d014d103518f06 +A = 219492aa41a21886d2ba6f831d89b3c7f0629924134507e8553251f413f32bd1a8c50afd9ea9d88eaad1b7e8947b57ad64205abfe0f279841162741f4f211ae1270eaea8786c860d8bd08e1dc2577ddbae52a1d1aa7edfd48267aca8261120ff53c04d6293086e2d8bb19cc192acf98f59c84851fa3045c9d091e9363b15dc221ddb80106ea547de73d701448cbdad4b9491826af665012371c3e220b2fb8f978218d017041bd6bec4d290e05ad3df15c855b411ee9579d7bf4406f4cd77ff6bc35f43 +M = ddaba338bdaecb6e8d4c9602c83775a416b194fd73266230811827978f88068281f0e0a9ad9d95d9c403e53639f93da0ef974abf4df31899637b58933bf3 + +ModInv = a49054bad5c9c45b00128590a132ebca128bf2e7632044f87cf035d7632daa1bc69bd32311be08847dca61664af009df81e42bc2a91e1b52028f47560f +A = -fbd0dacf1cdd1af72ee40da33fd7a29401f275872306689a952fcc2f8db7965f3e028b45043787d51d4abe7109473753793352e4ce48e13abd123a0abd397ff7a35daedade7bbe1fe8cf8cd22f16b7e99597f5b059e94f0ce0a60f45e05529734a65c70ac1c0c6233c94779683980f6fc97c35fbbf3c614f5ae6b3b4a085039f523b8958314b64aec2cc2102950e284df0715a3f6d5f7d8205d5dd0dba11243e308b6ca2afe75cb927312152fbccf3a9ad62fbb7f66f07fb759c064eb89c7542efe67b75 +M = d59bdf0799847f2b7847a3d6d41fac65bde584a5ae285890055d946a9343befde01ae8c5d54737927a82d627de62fb8f2d6a32aaccdee73b0f1061ff67 + +ModInv = 17f1fc470b80f45c93a5b309463d9f46af1cc8d29b0fee76ea7330dadf3357205072914e8527a2005c3a5742011d425052c4f4032cfe63e2dc6979721f +A = -d4380318e4979625de8ee8e1dbfcf3af06ea830f8989464637421c10a45eeaede28334a7467955df1d47bcb5ddd6d1cc654d34d88259623b332d2df856942ca9934148ae7629bd0032e35edaae1f1cbd0686b65712d69eefb8f835e585e89da56c504b04413a65b938909423e5bd8e9da84c88b6c72d8b6f1ac5cfdf1c2e3497a7beb351a289f74b983e57c42a5bd8083841d274d2a9490522dd524d25c1a8158efbd484bfac557dcbdc1caf0406fffb954729ac340f235464a2d06b4ae2458b5876e75d +M = 58fa10d06826d83b2aafd5c6779a8a37a010a2552350b17620e61144ae708cdd575a827afeb0fcb334bf5d9a5be9fac480122a1e7c991c4b09fa583994 + +ModInv = 17c56feb25c059b5a74c9e6bf96b2137fd199943ae610e88cb95492f4b9d6ed3f04e3afdc8cee71e565d7fa3ce27d864beed38f5bbc61866f8b26f39 +A = f5647a765b9b7cf5592a12bd9e1c2937b71cdc4deeebea0f0c51187806cf5d1f072fbb3e3d051b361d15ab2c254a416f9a79657ae9c69e5d30d284f04ba8ac51f95f837fded9d6cb2fb1657c3059633940027fcba36f6146236b566427a9b6114d6eba71b53ebcadf7a058894efc90a80d7d43aa9199db2d81bacfcbc6c74af3e63d4239ac8b4d4c87e0bc150ffd3ac9491cee1dbc8ad8d88b4b54d6428bdfa4608985b39833ccca887d67fa4c0c83beaeac31866bfa0af28791392ea744ea2f2e6337585 +M = 425a1e8334b23ba27968654d6eb7bc7978ec5d093222321a50652a57e144b6e72a3e7cdf3dd5bdcbd92e7f98321f6ba24c5bfb5a069420200d6053ee + +ModInv = 7678f982f3c68dfcdd9d2155f07f6729f7a396d33806ef579f3671b36684a4a35afb2b9ba0c9e599fbabeef04c0ca11a1b1571ca69b3af5b701b6ada +A = 16835acd2b7a28e0ae12dc8f8792239371a7b4e85125a5e88f00f10c3bbb5426b43f6faa44e55ca6a47ba3e63adcdc6123260b9e65a88c3d4abd0596493581e4d5dd087046c82daa2fa3a9e49c9d1b361d226c3a3ff612b2ab68b29b23f965e8babcc01c1444d502c54e873f8753b65a5ee63d0e2075e51b5f50010bff7579ed48cc63e83ac00242372fc605ef1a01103e08074811499eaed7c96f3180942587a631153a98a6b1f4140b4eb2286b587641539317293074ce01641329f363db1079b68190cb +M = 8c5470390ad125ede30eaeb64d9fa8dfec9434f8e1119a22e566b828ae77befb69c8ceec2a3c20054f5924232f8e4703cf640f2000fba50bf76878e1 + +ModInv = 1637d18384a24aef645270d26353a3714d014e723d40729532fb1fbdfbde531f412b288c062a0fd2e4be9aa9483fdad2830c178e4b88dc788b2ae5bf +A = 90b0fe371344c2d17593028b7fb01191c4a9a1baa3444afa4c9816b12705c4ab3db1f6341149ea4fe12d8ae12cebfe883edc1ab0e3ed388373651281b5fc4be3774cdbe422636a14e1b79b838407b0f062aa0334b0ef9167e2636290135e598ae7687927a10704d213d6656d3fcf477e1dde1a88bc9a78c0574cc44590cb5b881c28ce333385d5888da56fa3b707aa6a8980558dcbcaa5d954000d96cee7b641dfb4f2cbb7c1f63f1ffc36967859b694b93f2cddf5b36f136b8e5927520eecba3213f95789 +M = 1682b41f016ec4c10977e06d5c1358f5ebf8eba447186ea8fb4fdc34c0ec000266f16fa0faa6ada5ad75ee68454f44b9a2cd5bcc4a46c50e33d45796 + +ModInv = e02ae7d074da147e821568d3790b0973b90267ac78059a4716be93d4d99353224090ca9288f0b9bb29565348b8371297e7db0a8340874b6077f6a +A = e037615a5c242e7b73f479e55600672e15a51c3451a44e6e86ef3b0636ad5699ebe6bb73d90c11dad9d92caa6234ba0f3e4a903a6401e56aafa05ddfd366b3cda3cd0f1af00d48b777b93a1407d720a2bc40f08500b374bf44e528d1c1b83a1fb20fc50cb45d369c780c081763e062bc00a5234e58d0ad066f4d0f079d9b3316cabec8bb9d74f8b60bc80e7aa3acda93ec8074f66e2cc5e1699c541a185c5a4dc1f981fb0d6d5b2995c357886458547875e0908364d157b0a136d0aaa6a14f0405a8b247d62c +M = 28410dc475930620256ee8db3b1daf93e721336aa23f9196331e4163fc178f04326f2d752608db04eb9ea6dafebb0bd85544249549de5653075159 + +ModInv = 23d17494fe87398c61dd9d8584a95af48595d1babdcd6c59a0567cd6a84394ea2ad72bb73b68de6e55709269a902a3ef36cea30ae3f26a59e1909a +A = 372c23281e654f7b1e52f3a39ea6ef4254e5767e54cb42700b25d41e6c53c1df9ad3246b9111a61c299b76e7c8d282f630b96e60232016b8ef3098d5c602dbb27ee68600e6452c43cbae51fc295ee8e0ab72d3af093d5bd54e5dd1a46bab3b93240022254940a9eeaae855d0a45eabc4eef45ae41db37d751863ec1e4f358a39dccdb9c5c9baab8a1c12a25d56a588ae797512eb253c88795168c4abd82d22f7b70a158ee185f901eb787a905d052155fd852caf20a25e92b04a85b8884c4aa9d161c86da52d +M = 5736707c5019f0a107813f7c69e3b3b56c8ef47cb42e834b17d16e8ae8dbc6ad20649098752a569ee2dd572da122e2ed7681de481b942b6bee0801 + +ModInv = 16c28a3573eb1ee4d2ffa1612a9071272f47bff03524fd713f2e12184b187b4c54b99f6315ff17f4aa006931f9a8449fd444349ce434d582a6c25b +A = -b0905b55270b94bb4018082c2118b1cac4195b93a3f1b417cdc9e3ad8e3c30d63caeca47e3d3d0dffd96efe92fd65af0d35d01c7902baba66da7bde742a5afeb1e2787eeb573f008cc9b2fe311616c7b4bbbef1b4feb856c1a84bc6825fd9f4ef8e952c34ac280f2bbd03d233d309e782f7b129cbec2c7f18ccbcfbc703cf124d4b1df70a7ca4d30ecc0dc207f0c0e0ab16059723c1e5994cf44d8f739e911a2eab45a5e844457a770417032bdaa7867e9bca18242e7cafef771db095d575d142c3772ef91dd +M = 3e85c0156d96e13c0732bd2dab69c46eab2fdd6fbda76b7739a49d41e669ec76656435ab217ef9e990e155d6460a6e734ebe258b736d53f45b2482 + +ModInv = 794f7aa343d733e02b76eda6727324dec51889a988344cae096673e0a381a657720c22c351b3f4c9acc2b71eb2fee82ee95e2a3c7e65b610888e +A = -c5c3be1246f323875bc421d0b76e82da665ec21cd4a02e3a5a3e6bd3e43244b39ba9139d22e1cd2b44604976c2d331d18a1e942358a9ae2c6a5d2a4a2ff3d6a11c95521472b5075e1025edb0d046152f9c9f8feffa24d9453773579e1c6e8592b6f8c625a0ea07701edc42e0151cb14ca82082828f8e3cabb317638c8dab91b38d37782a552eab3d1f2f23d5da9fe41422c78c1082db3eef5e2f97841aa6b99af25cc1c36b8ef09a59d3661bb340329873bfa7b66d34844b9ef4cf55b7b811ec5e6573d0007b32 +M = 911a2b86b53a0cf24566239e37479860c84510f302e5b3c407962fa81c06370096b98135821b69134b7e6e374507a852dd33fb7ad74a190ca177 + +ModInv = 98d8035c8c7646f12d66b767a740681d92f5a81023d6cded0425beb8d25328a11384ec8c3596fda3702794e896ba70c3690fac6f638d041da37 +A = -53611e61f4aca2538f16608d465677747880890563de5c491cb01483301f1fac98d7f9d140bbf55162f30f4f78525a7df109f7aa7302e13418c338017034f13d097276b2657531eac2e07b680da9021e07b8aeba28e0c311e06ec8ecb632abccd1ea16802e71da43687b56b3c775da60c4c404ae2a62f70e6fcf27647465d5ac692094470fd4aac53a00b0878c5ab4bec5d1fdfe2724b4d863ef60d961c3002d6ea8d444d5d3b678b909517c0218b60538aa35ef8a4eb1a8ab2a0bdb680073511d2f42997e44f4 +M = af6c6880ba43fa8a59bab7dde03c321a7fe8cc2d14d23496198e1a1e605ce034854d90abc5da210e0dbc73ea2a2b9812ba20b2b5765e7ec31d0f + +ModInv = ac4ba2464d5032ea9a29931e8ce50b8f0cf658e722564c7f483f42d8372edd15dadba1f14ffd0e74801f0067914e1e03546858012e09daf42083 +A = ce59217dd708b9e3ec44bbf3e225bd16b6ebcc8a1f54c01a0701f78f0763b2f8bee02f93244624191ef0efa6168457e9341fa76d3363a2add46442bd5b837d5f27574b1741b523345c100998eb43952ad958663ef852cb97e95f11b3b971e7363e443b270c86e51a0fc5045f6c25cae9eda3fd450a2eb78c0552de014c9ef1ec4cc937ef77e499b5a164d2c9db146c8d08e5b921cc7e029eb931797e4b363b1914fb4639c2df4e7110cae4231a0bfb6385a26f59849e69118d118c22316943d0c7429e5f2668eb +M = e172cfac990d42b51c92078cd0e14020a1510f7f72a9e6ea8c62c72f74e234cf87a4921ffd31cc1fdf5854626f9d457b25092ef42f42f950fda8 + +ModInv = 9a2692cd68ce8f37ea53638a2c6bad3545a4a2dc75c353e9011832ab6b22a721e76cfaf8fa04a485da9317f169865a10ec19aab2057278f0b +A = -82e79fe07947983e0784e09f7564248dfa97557cc9d92b8f59f151ce2ff1d0e1075ab284d26c908f261573182f1256b9689863b56e43a5b0b4730cc29a7c37b8f2978d4b4fa389ae05d2b453117c1954cff11cab6374841a52e54f541de7bc546b95bfa9770eb15208368e61482e8a07dac153219188d5b3c7660073427309f08e0a2ddf3309817ffdeff98e775e700074758fbc2114d1079eeeb79f7a4d9e5a9d7feb6595abd57318828fd85914c47706b1abe43fddcd01bd93022133ae5897d14c2a8c5f025115 +M = 475cdb4cfbc7b0f83ebf3716949b9ffbd114fd4b431748686cf87c677584d8c605a35a24a2bb3ce0bc1953b4546f90d485aa85d37bc4466cbe + +ModInv = 71c4258e4fd55ad36713bbab4a78f14d758263cdaa85d7449f31a97029094d6625eac296cd8016a102e7ab98343252f6cd5b66037c5fdb12b4 +A = -7f69b13848931e63c7c5bac64a74de424e894a53c92017514b16a9ce44a054e2b821ac8d7152cbdab4191cd7e48aa95c71972ed7447ebb7120a1e5fc56a32b5ec11d50c21f50968ccd9be1e3241f538ea74b40f9f648968db9130f49c2cfcb1a15f396d2f768f284336f5c97a83f57b350f5c9a172abf8541b10924316cf43441a3b47407c8da7471154888d283b134ac9da76c67125d7506e81fef5a742738310a7ba34675be7467e39e4ab178ad146c698e5265063275eaf8a3b9aa8fad86a1b2b2a676e0c26fa +M = 96988ae6251226d62340f31640c094d96ac524422e5216220797823c8a07686b402f38cb475736f708c00498091ea91850c0c343ce6e7818f5 + +ModInv = 1cf417d205d553ecf1b0375bf823c1b65a6bdb22adba7f094cd5e278b9a14bfa8ec8b3b9379920962e23156a45dc4e4b0814455a5b4c67a0ff +A = c3791aedfcc84bf440680b0a2da405110401412287c0fbe70396f02b3aaf607befe9db64911248b9d0a3e4da29c72c417f3a671690f06679c85ce5f82e1a5f6c9ab731b901f5971f183b37857657520da428cad85a504fdff3aeeed8dbacd06ceb6cf9ab0434b0a2b22f912ff3c1b783ae4a32c56fe6fa82d18862ab8b5fd6090d4440d77262927eb6b0a059176f97df3867764ea016391348d7849a48cd9acaa19c94c2edba265f7fd9fdb71376940109e118a5293e841dd1f89572e722fd888b91e19be1df01af +M = 9d96f84a6f545ace2391bdfebfdaa783abf0cf07977387838fd5da00fa94699ad882c90061caedc6f3ceea78360b3c782fd7ac7e489ffd4dfa + +ModInv = 86aa0a1b939f613e323b1ad1abdde2fec234d2e774b0e65c8461853e558c8bd3cc8cad715e846c8b9e342a231205bd3c6bacb72b9f89ad43 +A = b77d4a33714ddcea8fe0ba8cb8841bcf2362c834745982d13b87d9547935e4cd672006b010e0eab8bcdce25e10c7a912284fd31e960e0a2b2818621d07ef6e9f414e4347ea78af47c222d23d3c47d8b0b174145bbc5539aa3750df73c264d6130c44833666f545ce81ff62131b58963bd68e0ac236360dce3f5153e62987151dfccf7c390c84ab54d85668d940c8cd0044c9b262e2b16efe24fde78f809d4e7bfe9baa8734689b0a6b649bd8150c4062573d2c553ba77a079a7a24ba584f08b20044ce6c08cecf8807 +M = ca3a8762aaa5d3c3599f746987c31c85e5be8bc02772ffea21e199931141c1d8d6ecf81da68ba9f34d48931c8d02d5cd07f432e162f79c82 + +ModInv = 6d643b9578748aaad9c59877eff363d3ecfbb87ca3c919699543b4072615c182e5634a542f152f1d15c86c3f50a5f059920d13b19388aa +A = -c612199710ccf0caaa187b8cf5269401461e189f9528d2c959d5c7abe52bbce8c6da7e3053c5f55cd6a5360ea305dac22376d84d6d70262f03346b5575461976d077b7e5f880552073d45d26001f098c461e6d697bd40b629ebbd767b7c0b92571a24a1fd7949eb6e603e075b1dfd69aab4cb93de5b05f601bebe51d89d9089f912d7da7e8d3ec4871b6333c58c238104d2d6f5f775f6d930679e26776efbf3decc4163644f4529457e5162bbd5b2fabb0495eb4d0c28d1e252a5df0862899f0ee89e46c216d2e032975 +M = a7477cedb8a4755a9b488c6f07b2e66a82479aa0ee75eebbcdf1b1b8e2980ac9e9b2424a9a1e30e9560543e4ed35d11cdbc29de61a60f1 + +ModInv = 2d269f12a2e663a307592e9706a7227627f68cafeded174d44ad6ce5de3b722f7db20398dec61c7e14b9690e42d4b85fd8e2a6dac6cd7f +A = -d9ed971303eed0b85175f2114f963bce2f2e0689059abc0e7f2675a6a95e085b54e85a2289c3ef5c6a053e57db59305cac84e6997b385fe5619a287427a8357143ac8d4e51140b8007a8018e586a293e6c43fc7a8e249b50964aa3bde2d9da9fb35aaed7351c9e0be7142a5a0f1cdacd808457e96ca11170dce0f3343aba7ffa6287b9988523a3ec53b13374749beddddc398293cd199892d1247df02fbfcb9a3fbab9924e868a4b0c49e0267d572cf541b7177839393fe3467bb16f7aaa6f7b8a83e3e64e3df881cf91 +M = 9e9d1cfeacb1a1c13021219f974a8f5d7b6f476b52930831c27e861b01a12531817b6c6493509789c1f753204b19b1418915e04059b110 + +ModInv = 440a0d12c58d62513262e335900aa50d890a536abdf915105cb3549cffd782541c6a11c95550a22cba5d5c6b73982362a621df96a76f0 +A = 296f1c7af42ae7fb4aa636aed224b6990e57c9f57459b9cfb865673401cf89ee571e8df5e56671cf4f091bfe36c7c4c64ea1b5e1734394d6fae40ec7c91bdb383f63665c7ad544dec22348ab7b79b2ddb262680eea0fb02ed0b95ebeb9bdaf2a58200f1676483aeb8aa97a1091794bcd48644b26d1ea797115af460ad2e890e5033b9296b3e7513c2d7b2d0ed44dff518f92e2ad78ae04ceef547581752e0e418883c5548f8ca493027a89ab678def34ee9254e099ca209700b1675e466fa2ce3c51f5221d914af7a6a8 +M = 44b7945b3b280d86eaa4772f7581fc0fa83319d20bb5779ed7922c072261a1461d35a9d77a609e21fb2b79968094c86b2e4d0c7f26577d + +ModInv = 14088de6af6c14fe133152e6128efd6e9c077cb9d09641b72e8b806f23e20bedc38fd73ad347f59b65a6de28666c411549389cbfe3f +A = 3b5db1efd267bd215cbaa046bd6235812a4f6022e8a60bc3415d9df837d0db6a8de724318bae2d4fbea8a2eccaddfeb5b5388d19ded6f73a08f44a89e5287397289a1184a17143f9cdb29b28eaffe2af65dc7c89ed9a268e271e6dfd82d796949181cc29d49d78787722c39908685763248e86b845c14c758e2540a1762c093024e6a8bf6e93c6edb5acbc5b94aa86b6859794b098ce7b74d9cbe55d21c5fd53fdf7db24b1243c50c49277dc465a1a29a976b14b965b90926116034839921422ef519f5d7a1208900fce69 +M = 194c6c8a7d260d093dda10b3d2f1031ae9dc0ac0c840a7b18273e855ad908805e4913bbdb546889f0f0c79f97664efc811841085781 + +ModInv = 663dc9c1aaf679d9860dd01f2902f5325c9f82dcf9291b537c968a8268711aacbe359cb6874c3c9b3b263296af56039eeec34b76badd +A = d19d0f90022442556013f63674055571a4b89ecd69173e4cb118cc97aa77747ea2edd76f34c91937974b48e3b900a68be7fb76890ebf3b5176e0836f649100473fa5c5f80db1272e22d7ae7d0a12ee4c3cc8578210b9e18532a9a1c11235f889329bcbb935e02adef0dea0306205472969578af7ff6745ee6b642ddfeb900daad26cb0e7af07d2b931d6a756b5418133d9bc3ce2875df4e245847add96fb99a8d77b5fade58dec3eefb9734530b0d8cc6fdb75f1e471c93ef981a8a85850c1adcbcd3b7de9b89dd7793eae +M = b620c37149474f01fea7db192023bee4196a7c586732920e44ddb021ab1772497f9a0c3f0b14e3ba09bd3af558328eea20578fb19df9 + +ModInv = 37eb0c51bd72e1e24ae66b036d44135cf04baaf82d8449c021e21df0e76e955770623ea35dd2d2c09cb8a9be64bb40fb98510340c8b1 +A = 90e6ed87a45b88de3f1cd2cfb07df8ff16073dd68ee01a535a42668a224f17b0de09b97cdd4350e69a7dc8ae1071b128fd4e6a140dfe5f5d27ce3a6dcc272e1ab2693847a5f71dd70d8129ea3fdebbac984ead7a0096f5a45ee906d7de99957b4c2c7d38af330e913efc6ef77c84645998f0e694c8b682b54ff58be11712bfc64a010a975f01722bfb201f78342b3abf9a8e1e5b0a81cbb7f2b317120ae44c5f4582615f7269a11bef7c25672dc75c90705d99eb9552ecefa012814d5195531494d45def45305db10cdb08 +M = 3b39d34dcfd5bb88d52ab361240b63db8af81e588c957df2a569e26bcfeb7d16b7add73219408b7accef93f958b8f62975bc97a7fd7d + +ModInv = 13c2804b085f11cd9687e8fa22bfe6425513b0c7680bda568bef1e4ca2be1dc17c15b9190722cf02672e7f09dfc5813975c0d4fbf +A = cc08f11da9916ec1385ee45783a6b9e6ed81d2e13358127015a4949f67d163e6216a1ae3453332867432bea7ca10e0c426fa791c35c9a53f59398084790fbe63016a2b017cf32c318aba8bf0c508e973445540f5c5734fbaedca592991278bb2859647f9323e5c04da2321f24cf9dd3f7de0c2ac14add6ca178ed5029912ffa54ae777a11d08b86720aca521d0db82374d876864f6c09538c9b1a81b3e4cbc4f5cf8e7d88084cee8518067b6818a695b89e826ef3262f8514c90733d7bca5cc902900f33f8ef52e83f46c84d +M = 6e1821b140f07963234d9556ab1c1aea4c659da31421bd224c041d59996a6bfad8f36286ab6b31de18e3a9df45aa129bb7b8d5defa + +ModInv = 79ddce7af1ff805c8f191caf34eecc9669c450b3c725786bed6f82d6223fe8a3be22727d63601bf9b9cb7f29a7dda562a077531351 +A = b7525ecf33d77ebc6669188beb22ed5e278682cbb9fa164017a92509e8c2ebfd8a0a42f424f2678eff4ca721e04b71506d0af94b7007e26e5a084ba42e4f806a84e7cdc584251b2ff395fa977ef67f9dea6560abe0f77f95a4a82887e1cc7a8423a8ea2f151a04b2bdf7c4ca103cb11f0574c1414b4e6dea464769f4890669b080cfeb98ec49eebf309b8f1ab156706e64257f74bae5ca1cf5d8b6df5f97b3d026930aa835ac8cbe752212fff21f719e4ddcc28faad192c4527d59558cfb2687c6f640f84087b62f53b85d61 +M = b3602c086f5cee6e359c78353fa47cbc79f62b35e852f9f94f715875e52eb69fb956e29cd3491a57e9c7bddc3dbe6fbb7bfb80ca10 + +ModInv = 19570b41d4ae19acd0adbf67d08a8ae4201940c8be8e0e3b0f9b457aec4e50ab00b523cd5b333a09ae99ef9c47ca9adc4128719919 +A = eb30131004d9178c4c0fe78394e678b2104d2cadec7512efd127730b095d6978d8dc8f760f6e716071d71f38cdd2ec97f67713cddaf812a1cacb74f34d3163dd6422936a5ba959933ee2ea8ce3a967b98b8a2e004dca32dc7d589c249068def49ee9b67ce11dc378785ef914e7a0fce31148c758a9095b0830e18ec7a57d66ade35cbb61cb8eec62ed167e6f760bc9d1787a6011c6bc9cebe3f7d81b8cb4bc0b00a8ee235fc392f9ed9387b61e7026df4e3aa8b88267c471a99e1d27204b1806219f4b822a4a067251397fa1 +M = 9fe710096634633ee52b5a16bae8966ddcb5968fb57321c26cad6fec523a797855d5312b3f786cb7e50e3b78b7ed3def03a4085bae + +ModInv = 11c25c08e65de46270f30ba6c3770bdb657fa0249a06c6ac886dd1d9a4424b83bffeaa1864d9d79746b00477f77338493522c159 +A = -b0ef5e4684fbff7fc0e2259d150383ffcfff4f2c3bc54e80580c11f90c361191ad1a75c0b1a495d752abf0daaf4028d17ea54166906bef8007fb2c74b3046c9830796ebdf77956dc753397f93f2f590e370900e6a4bb12795114231e9247dd20dcf08acd3ea8ed72ddc7eec50255239f25c181f3212bb0b668845a271c9d0d066c52c03891601896b2b0fea977fd1ba2744dcb4f047c568455544807ebfa53550b5a4e5b1fb8eda67efb11b04e6d68b86e2d2eb7e2058b0b8ad5f8b7ac216bf1319ee72b44f467e44132fcb577 +M = aabbe60e7da6d7b9ac478fc2a23b2de3a92cc168e194f0a86fd63afaed7bbe42a6f7575bd83926a5cd36fcba44a4d0b2e755b6ca + +ModInv = 6bdf650525156016ab4784af2c6c82ebb7df0c311fe2f7658262525ea95ff46f01175eaf266912d27c6cbeca88364c2880a0986f +A = -a89d61c89261c42839ba2a5f46003f5c17038925a8b0d4d0c1eebfc4a91e3be4c4ec7ef67b9593eed84ed679e5fcefe96daa5a802f481add3ca3b1f6fb38af05ea3a2635265d9327c729e2b7831df1034f52e611c1cf3713ad61fbc09b9fad9f3ec0b2eb8f5bba0e5d0c458b6e0f401a4926118b8426ff1842fd59e88b9c2a917dd6765d78a229752da46e43d271a37449814acffa71fe1a2b1c9794955e601d404d0ee8f684cf5c65a23d086b9c50d8a6e2756e9afb5f6506df43edfc7b6e7283b31c8efb654f07a08af59c91 +M = 943d1cc6bf47045d0500ba9fe478e70c7001d3498e18331891034d0ec054107ad46c11ccda2021828ea2e13291497b8829cd7760 + +ModInv = 38a1b0c2b9611d7992bfc995d600f36424861355e3e461da7c05ef20c7a3843af8f6fde924b3be27ab738e9dc4c6cca02999e45 +A = 3fc143134bc33bf9abf3f659f59d81c4f1948a8b46793813fd99d1092859de8ef5b93cdce8b6f5630cf86ba2f84c9dacd95c8e536bc89cf635563cf6c8c72b3a7ea91d223b3f66a72e0c1b7c8c1519a9d5211cac2d978989c67adcd267873c3f53e02f09c279cfcb5f0003bfc34887c9ebc4d0d34d183af1e8a5e7b546e5c0c467cd3e0fb57fe4785ca5364ccdc50dbe0e0a30586072b1a7dd36426699efab0b3e5289724808f8dd2fc04b99775ca0c0a1cd906db14fb68349c02bc0030131b5e46adb1eae198c7377c1ff2ac7 +M = 89fb8161f0979fa2479899c28034952d4c50bf55c8bd5962ed11b6d703fdc3e8110ccd7014e6bd85a83e5c4a28676b84020e7142 + +ModInv = 3b966271b38ba74adde6bedc7656472ef2979457f1537a0a217650508c95daec9a2442adc05b4d2db8719050c106b9d5f2b847 +A = edb7bf613bb79d06bc6ca3d13d1b986d8f8592eee88d50c19d7046817c07b2076783822ab002f46ab3f2ea12b008095f045ae0a884b62613639390912c9a9d35f78f1677a901e4a25fa27904bcb0b3f106599490fdb4d5e751f9c33cecd3a54deccc1255f4e9215c39070f8d84803f5e77689ceedc8ff2c23f3048dd82025a17010822fc72ca61ae8895b03c9fd6810e31c99c73bd7f85a85a3c7733594b94c889df9a2596ea73514cb4bf37613b0491da8d723eddcccdb9d7e6c445bd2fb95b35fc6288031a5f658833cb20f9e7 +M = e954a8fcf0dc768708365a14b9406bae4538949ab2ab66f88e28cddc3fb5ba871eefe8ba811b962b0f769b00d18a594590e030 + +ModInv = 7f4c23247c5990700182703f99dc415471421c3130434ff594768d875978470fbf3924f40a1caf45c495f40c6e9f50f4eb2891 +A = -e7a3d621d6ea258004ec907584837b37be2baa39ac3a73aacd1624553011aa13886a6228aa4a78c21d21e494c670887c2a2df25b9bfaae9eeee6083d6ec54b6768c1c457351a4be35c122189f5ce964b7c1b13111fbc087f1de41fb8668a21563e94450617a268174b40c0c932b6259d72faf4c3cc199194f3042801dbde2a1dcafbddb9a28a8458a9e42648c73aa695f519913574db0a1bfaf7a25457757912df2d9bf24797d044a03a78289980dea6007a0cfbc0ad6f1dae102519656d3ad71c5f6710fae5b8dcf703f15722b5 +M = cc493ebf1105b55510922aba3550da4267229f36806809288aff32a3eec0f94bfe61581b5dba88bf32f81beef86b384e43c946 + +ModInv = 965b0e580dd3f389a5953a87af7fb9185b1d07178d1a9fdc05be4c5fd464bbbecd041c3d3b892767472462f596964272577 +A = cafa18857bd75183136ab8cdbeb189e3089b9e96c7f2dd957fc8d9ec34b711e012c1c8be8a3fb9818e5939acea932adf8a2851ee3f22cb8cc81b3bd3ab88f10cf326ea7a8a5b89980bc3f7e2cbdab10f3d6c2dc53dd6cf7422140249dead5937fc3a8433d8fc34dcfe2d010000f5b753e098ad81fa243679406547d5193d49b697cdb7206cad649557b3868426be9909f24fccc94f420846c152990125038a99675e9393e431911781b7a31e154c48cd8b1dcea033734be9f75e39886cd7a06f4bd1d1784578bac6dab05b03d73187 +M = bd85143372679151b415c9ec742f37e0984cbf24942c9a3f2b9012a25af0272243e30aa0349c7a3cd49d58592ce49e115a4 + +ModInv = bb64c5b63e86e4a7565ca2b7b31b70bebf4795f57b52ae275a87151a669982395a32415f84cc7d82ad01a2dd238edd092c05 +A = d1c14eda607c8d5301b154b3c917047478b899e469954fb5d7de81dc3e8eb23dcf56032ad1f9fae63910eff578f24c86806baa7ca7f67d5b8a7701bc82a8339206ada0601d5966a6a3a0ad530727ffcfd04124a02845d4777cf0afcc9fa2bbda34f81283786c5795a63142840219275941a7c643bd63320e0398214ad10fa1dbe78738bc57643c1adcab1c5cb16a4f5f8008c93fb163b9fcb89aa505d5a7684cdad7d9e41206bc263394d0f570ab4983b47c9cbbf901b55cbe968de588e60f60da25b1590cf83d0ffcff597adfd36d +M = dc00f82280ebc6b84b841b7b69ae9668415593491c1eaaec19bf1af710ccbc07cf282381a95bec951045ea7bf808a99ab7ae + +ModInv = 99a543302c9772b098e02931ce86a18e80e656c77d1ddc280e2eae1313ee9ccf5ceb4afd91f5ead91be7a71e92a53ef1e9 +A = 1325825fe645b22333f1abd16dbd59dadc471a4d732e3f9ca2fe1e72cc2d0e2cb94b480645aa7b049791a7edb3eb25103d1661c51ee04aa0f2cf51f0966039b7dacf7bf27422089f6145fb0f4715788e1cbc25f8d35f67cfd77e90168d6bacf677818e5a2817a7e879b5cdfe881ab208d4722db098eb0e0bf654817ba733495a795262659aca1810b30e541a0a7efbcfc4a6a16e66845295c509aea23e9b7b7ca3161bb3e2c426bc3cefc0b9d567f11185f9a04c9a5eb6278201316c7c89602de37ac17dcc7a33ffba9761f1f7fbada7 +M = c23917daa34cea02e73557fc44d8394b92c3a2d265344ee02988a5cb3de84b49c9d2135010499e8eb1eba6ad174b10dd12 + +ModInv = 5f7398a90bd096837d5116021a9983fa535fc18e45e487d2ef1bd49bd312492d8c78b635b2096a66dff64931f0af2acf73 +A = -f907b4f1e622345a61936329591a8b56762d86d89babe531e2c8e8ffd2ef1493b181bfc28b282461ab8257f39a12899684b93086430f76478fda6884bc7b4dfa309210b43d360e470b0245dcb53956cbfa6efdaa14515b64bab6a02f68d1e7d8334f16b35edf25b732fa9c4e3d0508427f95af5c449c07996c9d489639576a0b27c8d700469bcfcaacabd1655ff75a84860e9e0ebcc2870d44b6a77a5450dbd92008f4a59db0d9302d3d0ed868e388c3565595d5c0bfa87b5b4f646ddbefa5f6fc969a3373797831b5a617ffce26c5bd +M = 7102aeac44ec6827e1bda2629d9b0959bdf53cbe90ca31c6499d71ec076bd54a98541ad3d649c1f087cb2431f996f63ad6 + +ModInv = 1fbe4fdd51aba4d6622075a9f0980e6c87d5a9a15743e8963a7c94f637ac6523e01803c13422d3a2d512bf0baf175e8b +A = -538d5eb68d8a960e15b549c2e53c1e4cf45c7a5b602c3d13f890c140983195a7d8e327012dd5ab9329fa14ccca474b84e7139a71c44f7c359eab863b22420ddede0178e5f05264083d370d62c044f77542331b1bfb80d7af682f9147feb8eeb77c3ae74ddf8c2c39814a06c0917b12ab15531876c3ce64f47e5d3b7d2d847ea4a9906536aee1ad0f6f52ec60f1722c3c12d868481418d360a76375137fa416d6d2c00f965a16e2932a04e214c0a02ed0110683437f98cfcd2245733fcb15328e31b23fa5d30f7f53d3735ae5ca89b1c6fd +M = 40f353a3047ae8a4a859fe80d322c1f24c6c32a76f845e9c73c2204a3219a1a021cd94f1a1bbdc34774bb62f36953860 + +ModInv = 2ef2cb54bd96448e8ca4b8a433c80ac4a8c1b1decef0390205d301b572db014b89b41dbaffc7633c06051af50fd1fc5 +A = 56ea6c8bd6337616bb388bc9e25def7b190426860c4662d4073b47a54c89ec6473e3f3a02b54de3a7c8bf8fb1379b294a9a8ff2453fb87a9e8da2fbd86aa2ab0978a24cefcdbb95908f3c646ced9d7394de62268a83d79309a99f9f35a79386abb1585db372ded647cc52f63df25070ded9f8c38435926a304e416e70e4161d80e7849be48a942d2dde09f7f31a4ab86a558a18b748ea489503d655a945a61342f32db0faeffd864fb00f35205c500df48a2ec066072a13733a59b87a8aec0296ad9a1044c1df4cefdc5fe7928e02b249 +M = 246a66515ed76dd216f19edf1a9dc595c45607a66c64dc2d72bf22ea88337db140de400bf16ed3a474cfe0377b7f35bc + +ModInv = 1d34950c704cdb9e2b03276ffad760ac2ed52fe109b62878b4105eeb50c3c73b649b65dd92bbd5790d746f245fa3d9 +A = 4401681e4988faa1b41e31323c6e51254ddc0404cd522f8afc785b5aa5f197d1e52f485f8a17856ec0a350dba6f7b49ea9a532e5881b9b4c795bfea7f304fea01b78b1bbad1fa84c249eabac907d3bd2e1307af8848a67f2098d8d11f6bb582089e615927077af7d0983e674c95434d3fd077adbf9cd1659ef444ed1c61c6d0c07a553676945b3f89ae6aa3c07bbf2976f46e4dc49e8b333ea969d0aed9112f38a01577a2d7df41de5a114c4707a8492c62d04875d5b0850c1f3c098e0748817b4a981f60a4c34bd1dc8483082f889a01129 +M = 4fcaf1ebc474b55d8e183eaaa9ab4d7ec12108e909a16fad1e56f50e1443732637d1afc91e9b1a57eaef5f43aecbe2 + +ModInv = 833710a57d907afa63e61713167daa02d3d6c249bd404b52e1dc6c1bdb577268a98105501cf8b0bf1c870b8c44b157 +A = 2792fd1f8dae7e870b6e751eb7b9b82c9bd945da4467afabd7501ea07e1f045d3532bd84a32aa48c422ade679d566ff8801a3ee38c53ae67c74b26a4a0d6404c7a7140c9572626007a4dc933063fe36fc0b2f3234388157681e22818daaa88e80865adf207753024aa61f9bc125caaa6220c4a49ac4cc5572c4794111cc4aca1e83aaba7c97d3d77a386957497f48218165ebf3e40bf6e945622dc6d30f27a8f275bac2c75cb232d77cb263ee5ba64d1c6afbc0fe8d921103ecfb46bf40ba60e8f3dd37311825d24b7c514e4246e4db73e0f +M = c9adfd441473011f923e1de8a4408bbe463887133db5d4e5cd290b80e0a0a003337e1af07b248bdcde680c2048cb28 + +ModInv = 19e9b329b15a433379ffbd0c6222580ec2eb3c1b5b7ed731618c4d8b67b8fb2c84a6bc6b11da4cae127177bb575025 +A = 54cd2eb2e97193cb5a9175b97442571cf6a6b353de8bf24f736438a78031e06a4e83b6c95c12a9fe6c8a246f32a069d69618010900fee09ad8ca58594ec7a0643109114aafa891fc515b4891417580032027b4d719d840284268b1547099f2d26a70af9eeacb37d7dccbb1b86169370a8d8c46b37ad87570cd627398b4a0a3692f62b4793306f52e896ac920c347bddcac694f40d2df093851631aa51be46777ee49a491b7437a2a961a2652c226eccb93f32cc710eb5f91d2a92b1ca916a4bddd081eb6a3e858b6d3f5d30a5586d4135a0d +M = 64d457275ce0dbf2bacbe5c8dccb29ffbaf937a3fff941eaa34d7fb5c8e2245bc2b16ff8639f82f7693c2c2841a1e0 + +ModInv = 4f919efae42ebc93cb4b59cd2499a12dd86f21f2de66c15516de27f0f1a064b9e5c34599954f6ff640c974f123f5 +A = -433df0bd804efab712271aac3ac4a320e421fea41555cf72f77a7c77494c52ab9fe4ebcac85ce8c57a8574c4f308afe5eeb01c91c0ca75ec6985f0df5cbadfdba714daa8713f951ed754c1385f38cf7f0afa53f168b0da2e30fc72e464d9071101c5b910ee606e33cdb7a4ca839eb009e676a9f3ac3ce1d11246fca468080fd2b70236611f31fa6709fcda9a8ae9112932eb91cee5e0cc41b3d2dddad87655e2a556e123335c67d485a3381cca8a7cbc3650eaf6c3b2f59aa26d6125a226640c24540d9e882ba8d6ed7c29eb8c403c452c3813 +M = 6013ab765ce5f02967d58f13664f938bb53960f99c9f481e4d9fb24119d66411b5952ec922a9d1a55985e2dfd138 + +ModInv = 6064b042ed73d084170a2bdeba3eb4c44960e72214a24f86233b376158f6b6aa6141c52c098a8359e4f26e8f1e0b +A = a640af8399962114dcb3732c880f23fc06a298fcdbb8ba62d2d565d90ec81c89c8a3837e5fccca6643cab2afc81c1db35527dd8257562059a6a5a2f5aa8b64337df08a0979ae27854cd68d7ab3ee96d4f1cb5dbd6f46e1e95ad0ef3bc51b71b1864dd24159bee5bca6616a9b990f1f2fdd316c657f09953056e9f594a68e1dd33c82fc41ba910b85c81f8ed690d8a4f048d38fbd3ade976338b383ef1cad3d8bd68adcceda4342f2f24dacb8f14a3d57d89e84de8572fda1a517cc3a7802a347fe2bb8d0ff9a8ee298b2cfcbae55315b752b87 +M = 75e7422d2398433da0070832ff78f198a93069bd6b0f1b96b98f570cc7369920aabe7462b4c5f2e162de19e7f12c + +ModInv = 24ae43a70776c9175a5c8eec402d14dec0d1b9ab351140246b456ae0afa4f5d52b2d73442ddd7c3087996cb289 +A = -f04c3795e044faf1d054ed40132bc559a6c09856b6a1f001ffca9ba88e7078d4f1f621b54e7ad003b403d16f71980fec3578d1d2488eab3962bb59dfccc7258b4f44230be4e6de11e3e748d9ca824d2e121544a88de4f8a4ff8c7ed0706f610da77b0f3a25c84aa1d84ef2274f32aa21fda320ccae8971f5e8e5d7140c1dd3fb75831b7b2c6c3796965a00e2921a286e5622908db6e96464f6968d1780eb54929167ab9ea8d37b242b3496ed0ce48bab0a32eb8a788ee25f8ad609fb8657455ed67bf832e1ad3a3c250e6e754c76457dba885c1c +M = 6421c28b78fa1cd8766e4c20502e989bda78a69f22e86aab558335ab6f4d0cb10510b86e43d01ce8df171799c5 + +ModInv = 109b43fc8e1c8887c831953dcd2e4c81c94b935cd8cd2d8c20ce514cb62b05618314445d7522f58499c599a0de +A = c549733ebf7a12b5df904c43068b98df7235e01e8a462372be1ab22faaa55c0e1a848c52ec7c166a47b28434826630f58d96b09f71b9fce8d84afb15b0392a21b0a904a94238e1747dceff2bded60ffd43d1d7e366c3b8ee01510b9634a3a85ded28268d3f430d551b33f8bce2da36186eff67dd62dd7d59bf8165e8f984989f2accc1fd3289a2c13c07c7377a599458f91bcf0dba372230eb8f6564c6e37aecce44d2388b0597a29c68db4cbc3ea90b7ca3dfc4fa4cfd5b002e7c25902cd8879bee42c4eda2a0d472cc14d78094dd6c1185a56d +M = d6b8f351aeb211764d8646096628de4d20f467930ad0e73ed9e5633c8e944a7b07be5dc1215d71ef2be9285e2b + +ModInv = 9ee4d2940b0561e09359a8b89fab1077de915c50e994cbf0f3fb531d496e848771da6cd8c01739777b7eaa1 +A = e6f9b545a51d2edad26ad9bd60538f14af420ae4d328775f52b1b2a27aa4a21149eb8436ce11d082e95a1e6507a9a887f54588e27a8dffb36a67c18ad8c77c02009a644ef8f99814141cd18b7b0c5330b5a3892626673f4ff9aeafdee41622ba531d41ca5818d2efd3a4272b5bc682225d00326445562c897626bec50cce9ed4df5be1c003dadd074065cdf7861ea3c91fc7a2038b4f70ddee198f3d23a2ed40a1606d881b785c7288cd75cd6a38f7b98ff10fb1bc890c3d7d955c04db01c0a310337f5f18666aa1df30108de7aeafd829075f75c3 +M = f61312a0ad8264b535618fa5bd997689a460a49bdcaaa89ed4e0bedd07c63b5797ec0149af7f0cdd55fef82 + +ModInv = d7867f419e784a7aa54eb192950f179fe7428ec968718c23bfcb264867fdad2aa1bb29ddb36d5622afc86ef +A = -a3eea815d91a570f0f304684097825699346b200d562d4075b1a78c46aae9d81161fc783b21f569930574891d5c847f81a9a022d044faa4c5bce8b4f9f721ce19e77713f7f8ed9396cc849bddb8fc645ef6b7bc1a6fe703257d27d92eaec52805b39e6e23c41f7d783986f845c1b866eb348e5b3883a15cb2b27362db33920bb4e8fa7aa02ef092a5dd3ba4d6977b40f92649dcd320879c4f5bd40ff5e1673532942166e708cb69663d5f56ed31d5bd669cb5ccc2c690379a710f194c2fa5c6d4cd56129613415e49bc6c412e428fd93dc6ab36bf3 +M = 13d8af82053a7764eed260e29a74ad6e900e9f38b6aa53e4b877244ab8f70b4584ee8eb8fc3727bf28a3974a + +ModInv = 157882339e675c22290d0b5b424a24c60be2a9b00f4458b53a97b390ba176e61eb1f352bcb6c7ee1e13353 +A = 3f3effc0d52c74ddca51dfe79af5b09dd226c87a79a487f1ddd685e953609dfeb8087eca206bbacca8b99cbacf55ad2c684f586a9f6779a8b5c37a1cb58b24a10bd28a9d6706d8a077ff6a1a2fef1b39a6f2d6c3829ff08e2c1a309f4337a039ec1f10b71d7319670c8973b622b995431b6808f592a61742781b498fecba9075d15de57db80f93913ed8e11e450f8d4c23e0ebe9f8aa1c2d35303be72fb629bf66e5ff2fc40f21d67ab3695ecc6cb1ada9079e3a88cac2a09206fac44eb8c61041661afd69959a1ce27b3a34a103a918db18869425a1 +M = 3cc865669985d694313f5ed49c74e4dd2680fa9449f6416a3139b417658643bca1175b9dfd318ac94ad4ba + +ModInv = b0b1b22cdd66bb7fecfa4388d2e583b394ba6c1c78b7e06829723eb5544301cc211708a772939720120eb3 +A = a7849b8f6ff8549b93b138e1bc2e486fbd0cf01db60f3219447526050b9c515b54dcc7a6d6e16d4a27b8592fc889ff339fd3145cb011133184e00ef7958dcf08d0206a106c247ea109ed5973d33dbb718fc8eb72ff587c1401491cf4161f921b5648956da99902925adfba555e7a967b50f2aa79100dfecd038b204c29a0af773f58115432305c40d713f08ab25dc03f98b48e9fadade20c14ae6e601b78e7340bee6d4f5663e0dd6f3472e4f43677f6d5cbbdbe482052728c034c5ad3cbcd4f4528013bfebcbbf2cc2b78eebd7996bb7e27737576eb +M = c1deb34c479181c5b7d34fc9c70d5688d9d87bf8de6029583e698dc7e4381589679224ee8692d0430b0fae + +ModInv = 5c4a55bb179360d557ad1493e5b6e8b13faf30f96e9cf4facd95f7fe4035e4477ee3e9eac7517417dcd +A = -94cd4bd33e3f621e2cc8b0aff31c786fa0317937bd64344a803c0557a7eeaa5c32132b64257ae3fffa3c11a258359d293da77c8ec5246a2f91bf6305cd523c3c6f78372e3ac77cb6fd8dde398494e7caed53cae7a2b80d0178dd07c8377e6b5bca9ab46a138ea76e3a11f8e4647f5b5c4e1af0e63894801db7902fe89d2a0f717eaf539c6d751ba063030a74aa2ae9286063a5869bd435e08dd9f655136b0e47accde2b99dbd6317505653c30a925e32be5ca90d60ff579b9b5c0a80053188e2216d3c22dbed572c6f4b577eccabd684b4230bbb65da1b +M = 38b0b5830fdcb9e70acf13a8860e71516a65e5d23c63f4b3074b8437ea64542d9e9754d74a91b6dda708 + +ModInv = 297b98cfce8600f144815d65f239df6d51816db067b0b37d6f584e9888943b6dc8f72bb71c632702c38b +A = e32cc98de33af808f2072436acb6f87e49f0c0422bfea69eb59c0e6ba36ee9a974f62124b0f29c802dcbcd6fefb5a2f328343a9080960093aa44544f2305974a25b0c742283b340c68eeb4aee0e410828f7d4aa59314e25a38c9914ebfb556b476ffc6fc1ca85e20a990bf41dede52b20f94f315d0f6b039f28f088e442ea4831c6042c39ee8a226aa97becff14f87b54cf8a9ced5c32486c9e4d53be4c0faf71996724e9181b40ff7b00d5029873e7bbea94dc645e9b6c40339e0db6cdba3768bd9c35552ef1e18679c95c8de987daf65f2ab4bd28ab +M = 378d56641e9cb6e14d6e08788897562134a6b6cc2ef566882a94d8af16b761237bd9f231f177b470c2bc + +ModInv = e9ce206fbd8cac14e4bb409e5d9d79b4c860d1b419c36c426a8b1e1ac0dbfd85a6627da32e3e08ff0be7 +A = 42d59b0d0676690f96b9d0d22e6f185c8fc1053a406799bc949921aa324ae382437e3b7bbc4d802ce03c1842bf63db15886ab9972dd4ead0bded05ae20b8565af338d5228d733a6d9f6a91aeb1d7d90ccbf7f467797027fcec62d6850aec3eb0c4e3d2566275fce35c733034fca5e5380d01d91a194a0c3ea9bdc885d730eea6ff2d86bf1e06e3724230914444947b07c813f26ed453df5e64680f1f38b474de1e0c5823896eda5d13aef01397ee68727d865957431e20cd70a1ae5905724944827c31892823430438164fded168e76ab0f4f7e1c21ce9 +M = f51c35cf9ad8f3f1c5e0801296e8c65bc39407f93c6e801d0707cbcae7e4ec130984f21da944ba2c5596 + +ModInv = 5246ee5bb9208328138f7cfd7c59a5bce1d7d358693656147d5cd3c02415507566a4da72a5d6a94dd5 +A = 8388b1e2284b6ec914f1f0d7e0b455cf5c09f46fdc4d720ad5b560bd79ed0e54f97705e37ba24cff9355a6b271c40db0467665f30bf8eac5ed239e247e2699594ef465676f4baac7ed91c9ab69924fae5b434e09a57a739d4262e71aca9368c530afb8e7faff96f31dd57475c23b6d971c4fffad5187659d8a37030138be50ff082d047accae109341207cee1985add20e70028c508a565647e693e9f53f2d69146c00d15abed4b14465cba0203e88ed704853f48cc55484b1a9790dca7a153b55ddb5739f186a0df5e5e6d896cfaf327755c0164dd604e9 +M = dbe0da44fc2e2b8dd0192cbb81758e50408910c8c2a2e59c2fff6bf7ca2447b1bf4c2a1f1c66cf319d + +ModInv = 48c3415252bc88e5d47a6746b8c78201f2b15ea5054fe4bb8351be85c3d176ac928eb7f54582779d1 +A = 6f593c5ba79bbf7febcf72c5064888ef4743c7e251b196543af34670f9657d2478cc7b5c3ed2b895031b481e2c0c5df2c1751d8c1b139923cb53105b4fb7f618d3fece490c7e1f94340a5b28994e77235fe5288f35bcf135513d67a8024b43794bff3d7dc241405d924478c290050224c1d38b081ac594a8870a76654c4d9ed1b41ab262f81facb4cbe23b3c3ada6b616c4b6eb46cf363df933063e4f7358ad1aa2562dffa2c7a3a35153ee0ce517c19c9ad9b24df6e62744adbcdcaf9a3f02ffb85cccb4e0cd47d8d64b06c677f492c7ab381ffdf21accd +M = 167d0110067be8a6853444846420614f83425d60144e7e92b02ec3c0a612adaeb322bc87f35c3f0345 + +ModInv = 29743efb6bc20020e5b4a175dfb51dbaff4fac829b92297b67ce20af77408c267ab91b8ed924941e +A = -fa8aadfd1df0f1f9b018f8da8f9b05cb6eb4e5de7ae37d8901d5b072f00d6dd5ec9330771c0e6ed5e8d1df8d6566ebc5283916e9558c79de125a2924909f38afee691cf4fac2e9b677b7b6ba51afee9709bd55a7235ad0c9f7656872f05ed1beca74ff17469d03b22b0178d8907fee0b3d8c726ea7bb15ddffd98a5a5427f1879ae73e8c96d439009befb953313528a32f4945ba70ddfd4745dfb32d3f5cf3ae85851877094acc09f7de35a5bd2eb992870ee492c1aacfdfc62b6eade5752d1ac0805570a9692a15090b834ff6e28391e6a75bb258ff124298 +M = f70709b4ca82f7adf229af7191e824ed9b89d575b9ffdd20e522dae26094a978ec081526d563e8bb + +ModInv = 22debec7e4a6a4c2b8eeccb2235458eeb8f60a17ded110999a5a9093bc4c94420d7e002b13cc63 +A = 461c92a2a4f0fe8589c0748882670f4853665d2a03beb9dfa5f213e7d13c011d1dc9d353215665168800d0e66b631cfa5a36586def5277b193ea5eb2231cf775a1d79c6206d3e16e483c7ce8436261ba04b7411941da9060fea1e80ff943a0d8e8e887e109b196055aa49a399ec5f98f4f7ff7e404658121ed16f7c0341d7ec36f6194decec2ce162283f1f162012fb16006509d0718a84478772f61d6c4d741fb2176a416c6b3ce0df2ab3ea15c19ad01f180ee045904def3a82d17a5de8d870b163008dcee44129642ee301730f0484ff7b19814480463a801 +M = 2c73e2444694a7ed86a1ee2f4fc272e5030621184dfe4b69ba185fd365272876cb47929b2869d2 + +ModInv = 777f5d2881c1a108a244dbd98e96d2cdc48862ee42c5ed9a67adb3caf157f6051b2f21bbe0b3 +A = -9e87f2abba83dc973d7ab98a2797934c4e65ff62fe3b238bee58379a7b5b39c3b56101f3d012c6359ceb42a49a76d7255127d39fa08e68d2e81b702ebfbefadbfe36a70a7ac970eccfe7ff6931fd1f832394b999844edbfab842e58239658aebfd407087718b36bc9a2c5c6af4f027758ff16992b8c9f4675fb746c4a27909e1c8983139554f6ca7cefdf5c8b9494361c5ff495eff77bd4f49f3d16796f679fce6eca48b3c7793ca16c5cf9cece70c35bc18eba9fa2ea2ee75b76bb10e494fbf06aa6b2a753f1f34db377b40454faee88a0fe1e40a9a2864f659 +M = 12bad673cd1a38b4b3c4e1138f6116753d152214fa318d4e03b60a7ae922bfe3c6694f1cf675bd + +ModInv = 1042dd23987247ef0d8b25ae19222366f71bf9d153a3f39afc0884626a5b1620d7914d02f8e7 +A = d1a369b7fe69a59c3250c7e692bdb1a566ab8befd51f9b8cb8907a14240984903d1546fbea11c15a4159671c10622f438a600618334171460688d839cfaf4e70f3a1fff7f447271d05630efcf6045d0345b30e97bd96c8bf9ea1db12b55ab2b2513ed36e0dfba02bc2dfa5ee878d9b4bb282cb7a0b2a365f2ecf3dc4a695aa15897b829a5be475dc4b6c684fa3b443f7d12423b97c675e86b6c4e9ec03d690a63e6f37c2fd8afe9637714a2a963f5fa5010911315ebb8a4ee06f6340272e1e9084d8643263311887618073363fd65a9d5667f871d023304fffe445 +M = 1a370eefc42e10de8da6b025e711d379f72a1a4f0eb6d3400cc93a90d979e16a21a35267e1a5 + +ModInv = 42aabd9378d5c07ab07360be1ad9ad21b84417140e6a449905132aac298d93eb22ce5beec03d +A = -e9bd3e10b0a4edacbfa9f4abdf9b9c3e9aac25ccc9a741fc2b35b0e2e0beb0be6dca6044c875cc2fb7b7e9f004c42050c2d58b97c2c3921e4007f008506610c52bee575f7ece5bbed6b5d24d204d74090680944cf802589999e3ca18e14a3a144ea7d58a344e961e82da2c5d957b1291a65ca433eb425a0aa72c4db6bda5cc6d9ae7f04031c73f9e5adb3b639f19f3f5abcb7dc99976ffccfa660fb41cdcc6b9cfdbbc6db44433f531c1cf6afe9f59fcae0b87983fc809aee740d08fd703d73f90f23bf39a2a094d133635afd65af15d31b2724c644296fc9178af +M = ff3e71ccfe778d4f8ac84dbdbc400338bbf504558474de3a781711963062dc2232c0256393ac + +ModInv = 3103c1f6e3e318e5a8c956cf562643b1e0b688d2b70ef1eb67d3bb273f8d8d1e91fc6dc6213e +A = db09c96676a55b9610a7777e14492b0d601e1afeca90e84e410700b6f2d38cfdde6d5b01fcedee8ba2851672a777606d9e2c5ef5d8d217773dcd15934d3ee4fc7ea57f4c70febf405d8263a6a7b4c59ea1ce6b55ceee4f974130cd0c02c19e9d82403dd38bd71ca5d68c559d9ecc8cd5dd21afe270fd2bab954cb8f3fa41e2cbe3d6bfdde159592c89c7339669d2ce3ee1157cd592247976ea2f873b28bbbbac296be5b64e0c78bf11049d977e6d683c882a46f64fdb2b38314f1bbdede58ee9380e73638028a03209f4f1e96317ca6203ad0934b54ca03ab62ce9 +M = 6230264578e21d3c8de2bd39b381bfbfd8936f98e54849201a6e933a84b6d6135f1b4b023041 + +ModInv = 225e46d1f63a59cb69c26ac7cf45fc245cd514cdff825e28c18988e06331eac896e4a326db +A = ac897bd3da19bbf6fb939198857707c5fb6b312166ea0bfd9f5e83bae22de3b1f33036508e24548a02c2410ffc5ca577df7ca1d41e377fe73739806c1eebe7f792af9dd4ec9ac1efccc0cd3a9a9432f154f6fd3c1b50137429909bc29340774bf3263df545c8ab1110f2ba96a338ffb8c2ecb12f3b74b034fef3107dc2430e233b512ee35f95c7abe9e865717358b010434b6f0f069290ddf476157528e00409a9508a16d4858099e9251be4135af5ff90fdeca38d8bd9368446c02c212d6512c001b8a942300e9d19569ae2c66a70daf92a0e4a0a26c09a37636409 +M = 59d74d2c14b859d95c77f01932053e7bcfd438c7881dbd539fe2a196a5ed3e2fffa7ca1fbe + +ModInv = 31a171200f51fa71ba35c1c37f1dd315cd52e13d85d517443dc7eacc9380206e14742aff56 +A = 63bf5007a79b2c44b6c4943a477acbe5b4c216fb388c21c24b1869c88eeaa4a36866bf282766295f9978ce08cf3e459fb16de927332e3d35453c276a33c74c488ef4505178812ae784e54cda9df6ffc8544216ca64d7a9c7ebc3edd3994d0c91e4471b5f3fdfcfc7cbfe66ccf3a9a72b78ec2505f9655cf47f93fee90b7b6cef7d0d632a218fa28674eecb3dbf30c57cbfee04fb3952843d160ab1646c0262df9858a548a64a0e2b8b4680e5523295d4749eb8198047d3a74b49c07faf5b019f065161ae7e7b07a275325156c16fee112719d5a1ae07af603050b540 +M = b23d9ea84c17843aeb36d41f5499bfb002af08bf3e65be630ca04f09ac908b9aeacfcfbb21 + +ModInv = 8caf586feeb3b015d4aafda5bd9ab30159f63490cdaf769a8c218122acc19f5b836443 +A = -16387d9e32fbd50b5e6cf907211d5c59e06291dfe9aeb2cafd9289e5e001f3a1de5dd1dd2872e25b7a4fb4fda439da37cef8fefe6e49f3afe549ba72a642eb07ffafd93a78c916a5bad655ea63f857d4cb67be968c28645d35677955c32f6d4e881250d0bcd1fd13501b101d760d26e62ee5d9ff6034960681dacbd7fb7d4e5ae62e7458de469227dee82d080760389a48fb4156c86b9f18a47aa00b64ad77ae57a4a8912abbaf75a8156b9d7cdb44aef56db7758022ae5d6b8d4db18e3b16887d79331f980754c3ad2eabc7cec17ebd9488a67dcedfaacb8a81d2d815 +M = 2534932b25e60fd087a82d42bebd4a53de2a6a011e543b23d994542a281874b5b1068148 + +ModInv = 1d299e01fa466a76e0624491b08a81b636590cb17e53ff04cdb0c4188ac683649333746 +A = e32926c3f39caaaa0979b2d09918aea7e764925f694de6575b37e139f2e2eecca3a4691ca8ce6c04a2408f039790f00ad965578073fe8b6c58d3d5c7184c580e9259bc0aff54df5f40dab952a6d75d1bd3a9a736bedf8266375c68021813fff09afb61f1145dffd6e11730f4d9d2374422096a2ed6517d8b8da6fea32a3c02ac3d62fa7619dbb26555320f2a87d340eaeedff4516fca5ab69499adc3819c5eece14d38c8bfcd3de701026eda11514088071472c5d1922f453eac8a52aaa2550d6d5df1a963d5481164b593661198ebcdf26c297a6ec96a8c1516c48fc5 +M = 41617805aee80a7ff7c78fe85f50badef3489bc44b5245ad135f7593074e42c4c053c9e3 + +ModInv = 757e17f467671a05e764238481510d6bc30886f0fdba9adc00b9a6a2309e49f2b661c4d +A = 9a87299750d4947fae59bd14ab494aa003226549383500909c25014050748b9d6145b8892db84d63a095228472780c4f454c28219f22017d3dd57c3375da0042dec005fd74da88b221900551e192726eb1b00fc5f984e7abae15a21b74350914d55192b7f76fe3946c18ff3de3bfe64333f5f24104740b524865409d2985b94d7a249d55287a610c07f6b825b3dee732fce04921592e1b0ee34335e20266809dc2055792f0fd964828a1d8353945721849b1af79df167e0ef4aef12491d4c156b509e429000096e79122a95c3e23685bd0cd1921298cfdcb46417163c5 +M = b3ea028d87d27184bbd8220f65b14df7d99897171ab791e8d26887703fe51e195010a7f + +ModInv = 922186ce5458db999c21d9647294d32d959186940db989292384a9a3c14f14bb978017 +A = dddd316a58037e7e670c07f19c80fbcac6d6717d08ffb001fb5a58770432915682b0a35b03bc9a21d0ea8635ff269595ddcf8671bff53f67b6c4ce65dc375ec8aa955b5a00946f57f0b270406e02b6f88a9ed942e665fac72e016241865a1d44d9c39c17fb20e056eee992f75acadba4b5a79a3a0a73c64df7217fd74f32b0c139acf454232fed908eff023ca6033be4223ee504d0929f00338c7624e092677ed66995d4936fe9eb44d1cffdb12646d62736e00fe38c15af5e752a8c3a2ad9e8656fc17f4671841548ad4c75445cff62f9be6010f61013240046d36452e3 +M = be9e0f99532025f65e46c2a1bcd6b4d24a712e6c289d44bd636f79ca4c341cdef65a95 + +ModInv = 4608314c64c01d599730dbb697d16090ba95f07de1868c25740a5a79dcd5f112087e99 +A = -a00ae6635872afd737e3ce94aab9a4910e1fd9ca42f841a077c137a2bd6696f657a0c556e9a69182c585ff91cec5dd97ad5371cd27a6bcee242e8a66762ab482b35c37d89132cbf11cdbfbd198daad5267191a2d3f36333e9845a6ea1df91c9a2d82fa024e6a338d2a54374c63c80bac20d2b5dcd648392b5c020cc09d478e6959baddc54e1312c05c974c81133592ab11e7228b51f036764b1bdc25f2eeb3d065d54e34548b04eae1ca69b6bfc346d0ab0ea53f60f2b811cb68c44c8676f61ea95fb6fe65528fa23f0ee3b9b609cb2cf37973a1d796cc13c27570b57d9 +M = 49250c13c11e80bf5fbef673e21321dd3cd5d410abccc838f8c747b5de7ad6671f3b1a + +ModInv = 20b5593a6c45c89c086b3a522a84d8f6633c7cfce56bc897875ae28d1d76b7aadf57 +A = -3e930fcbeeb22a7a09f78edf7f6f543f2f4c11fe96a2377fba3ffc23b8195cccf835bcfca6a5e8d115c145e312506cb3ffb91ab680e99059457f587029071932898acc5692f1157b6d19164b731a3721a2a2b6ce8402e50bb6564c82bdc9f6b96c925b275a789386a976595ce56da97d590005a6c8554fb3645b8438d335834170163bb63fbbfc86921971a43903225fa96e21bd9ded4fff92915bdff29326a568c7d921bd4930ea279312d51d75527715ea7cbfa830476b32d62029c15953f4abb3ed5a0fbbfbccbef169ed9bd35cd777c0461b4a6355954fe9f79ea0ca1a +M = 25621e45a96ce450f981adb21381224ba53abb2cd209d67c7f5edd06fbc41ae093df + +ModInv = 1b7f2b4df8e2d2b9b26e4777dd1ec39083a39b3e5f0749e62e286ff48f39ea4830b1 +A = 56c9b585493a957353f7d37d41946916e03fbe3dfb08010b4a2734f498937d740fee12feaedf527161ceec6d4a583d374dd17286c761e1924a93369b739b6d5b2eaa0d7611334e70562b0f3d37170b9484c3f6b4201ebf3ea3665a08c66e2f868133721ab41bc7c5626d560d45ecbeb8a882d7d1260f6d41c92d7df2a5512e5857cfa835e951647d56447a49d8618311b1483389a14628a9366068c40c2b7c401f160e842a4615ddb4475f74a9d4700a1a8e263ece631e1bc822a1060da0cec2a9d0f3deb659e73eec5a9bc2982542fe4fd25dc0f296405c497c9c969650ed +M = 2e9bb17138cd5e6e2f74a7862264ec160c874914384071f986853934f4027b4a954c + +ModInv = 41980b8a7c84f68cdc701961f0fe51750707cbe2b66fa9edc686911d018d39d3a0ed +A = -f29b92f84fd8c68a0adb1ab1b8f3d059c55271efa67a0e6b3863844130894a7e9db9bfdfad8a7fefaefa01181424aa19f218579bcd8a9bcd62fd76af24a0cbd30efb53a9634beb37efee65324c44774ffb268841abf5efe880be6586033b519863bbbde90a489369092b241bfeee60c8b6d12b236f76087fc24a9fb3ac32c7f9bfae4fe825473a303f8acf87b794b81abacd826a4f31029acf0bee3c80dc3058d3f596dd4a090cb3c76462c4480b3928ea105d308e2e08b89ea96231022696013777c8dde48f4ed26d2e692428e389b1662041215cb91a0e4b4581d78ae0d5 +M = 59a5d58b811ebe4b73f6d7bee44dd7718421a2ed8381b70449cfd38d8686efef7a5e + +ModInv = 336a19ac08891b0bcc1b1ffba1f2f4e0d1555f2d70d7b6496e67dcdfc40bd39bb +A = -c8f5aedad5cf26103654b03f4239468802e5a3864c0d5b9df2dd6a77fe42a978f4a73760736334aca964be115f5787fe05657425907fbdfd640cc0eb259f61a06dfc00e17eac18e92bc5d267c9aaa3f4c495543f74f73e8393fa7c3a8aa55b20db515f81302329a384e6b519ae960d4674047f9147eab1ee04b75334ad011d753ec5953e087cb0edda844877d0ba67204f8ab6698a1b15749a467abed6f4fba0be60298447bede75e4be8057855f3afa9fbe185cef3c7b49f795ccbacf7e665b0701e31f06665f935cb8686289569f1661939e90e1e512710a02a4f30d1bd591 +M = 4dcb06907b44fca56bab076c76ec965610a9aaec83937a71a57cf94399aa050fb1 + +ModInv = c68c44f31f7475daeb21543317297fa08ed1828125c0ab7e1620a0562dac017825 +A = 99d0488b959cd1b03f42d0dfc2c84d16bf88b3691eaa090c3cac6127d7449542b3f85dc0e03a1af598122141f09a83be3c0e76285eda6bd5438ae0f6483afb5a804d7b62c66c512af30d0d008d168ba75f1b22e4747d51451fba086558866ad064ac119bf1ea098cad0144d5f81c1b8315d41e4c95b6208f46bde5e4400820a69d3566c26de59e0f2468bd93d8694a9e0c3cd442fe59c00b7c27c612d6ef4c9b0ad24908eb79959c65355cd24f86a62d9051c4c918e8ad50572479e0319b7fc2cbc8a4d1de321df7584b7a821cc918c02d0729092f3b0f6b941afc78caedb0cd +M = e3b58d031c8dc2a14e6a19a8a7eaf42aa01c53835d073cd495852b0516339bf34e + +ModInv = 24ce38aca668d349e047fd81422b95ab887d2ea1f16e6ae2ff1f918500800b14d0 +A = -1992d0047308ca24eccd522b1ea3d4455b959322cc8ac0d0ca1237a5a6b0026eec14db7a8ebc38a2ab4732a3966a3e302fd793ab0223f31af3438dd8a10acff6c749b9ad075fc0b63fdeb366d594eda5ecd4c917a7a5a293588b680603eefa6040600a37d6ffaf6daa7f7ea89bef7374f0028d4aa1b5bf90559c199bac24795f2f7e69cf06c1910ea259165655007ed1306227574c0ab57140bcdf19e1dc92526eb2be5335821c73753432d04a69c05fd4237ee29979814f262771e9a3e7ce4c401310d354b553aa719b264708c83aec97808e0925c1c9e7c6f4cad7859e5456 +M = 2b3862afacae116db871139033dfeae9203be0bbfef7c0dfadf22843882d17ad3d + +ModInv = a1db3fdf86707ee44c2e5938e1413cc4cb39c140c39d07ac672d414af0d09563 +A = f5ed652326ec8e5aa80d657fbd54f4004f99194c1cb7aae33fbc7e5a06bb08912d5184fe4c7f57d951656540cb99a89b6409b04aae51fe60b69f3f9891a1898d555c8c897b717586c904c9897cecc8b22af2c8dbaec90ce7615fc845db337aec9050d96005bbb82cd822658e1ab71cc99ad029b7c4da5f9fd2d6c08b5949cc30003f348d0acdfe09e86107c42c141e306310e074ba70f8367989c98bbac3761d46bc0a216b03f2b18bbca7eb97f96ecfec4031ef4c4950a7b8f222c6925303873ae1de5765e211bdf76bab1c0ec5664595d98226964c73d557643a725bc6a5c4b +M = c9c651278849bffad65c5b55b97a0fbd2c000b1d18e259d8e374726650130800 + +ModInv = b403412364af50ffe0478f8fa08874b7a55033537f3c51c140dd4db08e4f43d +A = -6338e696d2484897473f9d6a9fb1a59db1f05c85b3f56140bd2ea1e8b3867130b92a68d740aa75174e21f8faeeca12149634fb37116bc541979ccff0a8c1c7805444bc5bc36c63299e8e40926e1eaf941176a39a27cdd338320cb47644da9087578717bd38aa9feaed82e8d49cf7e00942bb73af79649209db5533a31a5c049b71fb3070f0e81ef4f588b3d88b3bd725a910fbf18072b3ce2aaadb20f17ff7824b5ac703f431f62ebdb1f8b08e4433454ec659b0140727ee1b7d85f792daa1c013a02f0270ea06fee5419ff7eec8f73e7e0af4126039280e8667f2607050c07077 +M = 35b45c789739a9cc1a23e78ed92e65803d355cc4b8351fb25347d21338ba151c + +ModInv = 1b85d9b14644cbd70de3f5f72168056f4cf26a1cec1759a335ff055f165df6 +A = -9773b9bdb44f31b868a07a34fa5da6435aafcf8d9690c1863b1fc7a187b0cb27e61bc86672276ef761bed1d2765c0041fccd5e5fe48b9aac7db3703ec1152874af419aadfb4118aeb0dcd273d0dc2e005a2beb13bd5e19d165781fcc210ab82e7700c56045c955ee32cd39f158fca66c0077bffd355bb17c3626bb3dc494ff6df623555d4fcff9ecf172e119a6206d35f01cc24373ed859f26cd1eaf0662f0b326590ab4554483b4ca6e15d6593dcad66dd33a2575f5b1a845e9b82e8528dbca0d8a134943013ce4c92659eb20549e0ef0705c9d57247e9022aa76b080d1ba47ab1 +M = 1e5401616ea6752b36d5608653b301471e683e47a1d3608bc50eb006906753 + +ModInv = 425e97452bc499d9279b1e4d96ed8e82a9777b9aa93a7717a766e4345048 +A = -ed7947f17e0c8a863f6ad193c12009739654b20ec355d7b1d99022db36ac82b462f3a537baba0eecdc6bd05079d31005515698bff6071c0045429d7600da1d286e29adfc7e598c33c0de913cfd1f4126b8ac2ca6f96461f0521e6541f79de43ab1752e5f947371c1a962d8a8fb83abf825b506847d05a90caacb8298718ccbbfcf79827f5722789d8beed2f525c44812347c20d12fb141ca2aab97f8ffcb86bd05f70174edec1068a148a4e770e77ccfb0d89a9ba3897358fee800c496fb7f726768855d3c9559958191bc5069367120cdb58ac65eb025beee445c0ec3c600020b6bd4 +M = 50c72dbadbd6ec5412b6acf2f17671d3d509ce95b6f3345e127bef7f34cf + +ModInv = 104f1df0fa553b49df4ca7c3f828314faa7a8983e2fba5c412fe3535825d +A = -2c6cd5fa45bf5cfcf1beff964a528a3c0db2d454496be51963a3c46dc80614d2922f337b48d2435128e85f175b58e596b7e5073e98627425a6595ad08e74503beeb3501806a29b3f85f48f42a23720651b4f50b1f870703ed30e65c3ed4e1f9d54373894ae76e94344981485d9a0d337dce3fa86fef1e22fe4fd9b5af0634a91fa2fc6dd04ba5bd566a8eb840011a0f934c1d353d7c49d8c4a842be2fc10d4b8f6ffacf47393e42fd1cfc2d70a8c60e3f7a6c6fbae555f52fb09da2f6a2c731cb13a0b967c4f22f421fdb9d204cad08c5f83584b422d9afa92b510c01620f7c11ba9d1 +M = 3ba47ebf948a4a1685cfcd52d7efdaff93cbd193f24414685e560034322e + +ModInv = 3633dfc40d19f47a19e6eeec68fa835dee84f50f11f0f9c9f5eb1f74e37 +A = -d8f376fb3f68f49640cea5ff4ee97747a69c25372b17b887596d7aeeae8444877f7a9bc95598fdbeb72ab751d69c58c23e2ba200614d6e005dab91458433f9e8c74b5c280f5c1bfca2c46ce6db02bc78274bd8c026d81aca53c42861835c3e27e4b552b043365f78b2e808d008200687b4871fdf7effd9705cc1dae612016a3547d7a0ba22f3d6a7cb0356c0d7f3e93c73606d87012b45b77933baa6e1d032098a91d075febfe99bdd7a424ec867b08513cb805a15cc6257d2fdd5a1f31aca200a1fe1bd5ba56b3c70c7ae25746695274a474500ac3f5da5c57545b468315813e32659 +M = 5bb246a077b4db73c628277011b68414218c97a7d4553c887c530d804b60 + +ModInv = 26c1a8c4ecd4e3128e707b423c565f39b1b369d1d528e08af3a045ee41 +A = -6340e7eca3afaffa440b544ea03550b52b88236020e3c3f870d21c169c52e505fed6530df6006aeb6c729e89c96b921b027649468c94481d986bb6adcef79ad7173da6c355af3770096c657cf9273185c4f5ebfd28f4c7c5b626829d959147869aa01ed6060ea9b092f3f8c02347cc73ef068aa43c783fb046f2291e2725ac55df44d8713d9a6498e91dc2bb27f9694ee9654ae5e993a96c53392a3d41cd97444916ccca12702b520fb1c21e58800b9bc49ef9e09a31231b0e122e8d05ccd65c9fecdbf14023abbbc3dea687b406138ae205660090b1306dd77687f327cef5bb4aef0a7d +M = d97e3645f0c9d66b8728a200ad501ccd029bf83d426ffad95b80db93ae + +ModInv = 50e93a5677c87f47b1237e89bf00febdd429b451e2dc0364b51cbf8a6b +A = c5401601a71f992ab78df3c5c4bd2b0c04f4a7ce13590ca563be49721f32760146dfecebdb703a9ac3547c7582d658eabeb56adb4809a5d6346f6db9c22b4f086f311a0bb2a4a5fb9bfa911568633d904a7edd5711500a69001e9d57964f84b7aa6c130cfc25ed085a8c647b713dd4a30e5a9ea1b497e4e722138839a4566374d7a9404f811b62b610232b92ee520bbb58cb705522648acb96d1937ed83a42ccc58cefd19d634209bb724d44abc2e8b8d8b85d1eea8d310e8142e26922d60ff7f7ccb23010e62655842012d99a5febe790411479e4ce9c4dc8ee0f39e37b2288a186049 +M = 9bd21f1a88a2073047775ab0ed3f288163cfe2169eea8da9d6355a875a + +ModInv = 14205409ae3cbd01de25b99d9df6d69744850c5f316e2b6187171d5b +A = -4921d410f1c143516fbf4e711eff4cd54950315207bd2aebfd31e936fe81e67ed22f17cd5d3d91901314570360714aca63c6b1ac85c26dbd92b5d72333da03e34d5a68ace1b01f566872b670bee262cd45f99927542828ad0a534dfca13ebb4bc3bd7ea7f3d5c694dcd1924464af346b4ef29cda4ba765439164335f6f91ea70b6edcb9be12d7005a74310c78c2319907907f16f7dbe408a4990f2c5ecce59b61e1148214487eca6d1de0e050b522c20378c5d99d586d3760208310d56fdfea29c080976c6a8ab99ffbc80470c80834791df3797e9690bcd9707c37a94f73fa10a3a85c031 +M = bcee476a53a97962cf3910744d371974f9777ddf539fa0f88dec868c + +ModInv = 49f9d014569205d35108cf0a5a45f37de62e177513ee19c5c781ed75 +A = 96d1d504357094af5d151276e3e97bd4373416769023e407284e01ea6e94946a949d391d0b8cfe48d41c112b464915a140aefcaea83895cd9949c1def9d1de449f1fa082211990ed533a4adaf6596175314b9945d08d8d7733d317a61dc12a3a1d7af4ed4f21a51a5e1aba905a98078861cfe750647f9f33aa2ff65c89e0d7b020d8a0b24e0c89972e5c96d976394519c98e8fb8b8fd2d38c7de2c6be80a788f2928f280d22811ce11d83971ca0100f96502b98fd94161c3baeb9457fb8afa29d36ac614591432ecd01033facbf77af1342a0d0a9c48bafbc3928674de07580b45de3e6988 +M = 8efe1d8072fa05697ee437718e1919773c3a991f307eda7ab3bc3129 + +ModInv = 1c7dfd775f7290bd204cdc0efb00f768a569b18ad35365ab304e85a4 +A = 140999684a16f54b9e810513fb883f81db158dc7d0e43ecbd00bcee805e2eea4b6e2106867fff6c1d671a9bb6fa1dc19a50d191dcae8396fc9f7b2c37b53cd2a3ff6a85208c11f15f92966570cd21514adebf63aa15e86a1b5562994532d4ef5f32a7f63f3da25bb7d97d1dd3bcb6c5f4ef8eaf0fad4e33f73cbca6351555d99bb49ae73fac23e4670f18b97103c058928af646f3ffc56ac574fc1482c93b2901eb18cc28b6995d7d32a73609e1545625f05a7198d81bd3a7a7f1d16a78a127612483f445a7c4c221c936703e2a197bb3b79ef2ae227a37706b42e219ec96ef963c2d56fe6 +M = b717fd823ef165965a2ea07a3ae1d4df86266fa9f4775e3187a82f4b + +ModInv = 7e7918bc35fb8403652ebbfa3fd6c2f469675c227abf8de00e08d +A = -50538cfb778b159da1734e8b4bc04b95d64109450170d5e468f69ddf4345b23104fdc8ffc7dec6913368ff4b3a2dce47ca608469b68b00ef0df7ae9a1810ff03872dd83320614396a1526c92892af758b67620d676c383354b04296bc6eb53ba556c38b74232d0390cc2300cec0a2460d74a68c97e037395dd5ed2303ab81c510946fc90f0443c866ae3787a94cf18b48be8d1f5634b8a1f1fb654a3cdca4ba97084e38fd314800feeda0dbfc9598311d3cb015d762e757ffaed8b72fd6c65dd5f6068004d6bb4bdcbe529e4b9414c3e1bd2c2168ed09180da3242f4826598bd09bcdbb10398 +M = 100ddd4868ee5e5c8a246976eb195dcbcfe65cad2812d07b61683f + +ModInv = 528f303c32481f39f6729a297842e3bf0901da321b350649b424 +A = -d796984fc9c0526bdd04245cda244cb9714b2873f09fd69220f643f4b33149a5c1249b228afa0f19534b3ca0e6a10524a4137c09908cd70fe6cecff56073bb6af4c8c2ba1a3e5c294d8c82328b66c2502cd6a08c6613092c2da95e282ce89402917fdbf4db29d70f9af2d084aed3d61fac781e00d107df99a280eb36bc9c3f8b6f89870f44cbe0968b9fed76d40be50113c25cf0059b7c5195c6d6f6276cc36884891ba9880be639d3f147fe1dca69f69bcebe813d8ce586cbc47b86ce2aea956326e8142980ba345cc18c94dc0613a44d499b69e8dfc40c6b3dd4e7a444987778b390cea2e316 +M = fe8ff8802a4a29c1bdf325ab4b7b6be2513f4ca03e9ca1b48c55 + +ModInv = aeeebd1179ce38478f7d3fcf6feb8b67b55c8143160d7169ade9 +A = a27d080a2d82a06a4132dd7c1aafa827621a04c3a87d4e10c8cbe7e1e5bf4b245a051c25b031650c1ec124b56ccef903761380c41edbd74227fb70458659e22845501ddccb5aab347b2bc9f86ff9460788e795314b352a7c32d6260f124acc40cf16f6ed8c9c9baebb563603e6f5c6237617139bceb745c28db48e5496f4fbaa6ab687c9e6d81710f1b9d0ff2d31a1256218551caaa9e0f657734b05b86d8169d0a1508da88564c35f25a569037493459a950eb38cf866cdd7cf892b672685f592e010e5c2461fe216875a39f4598c3f8d249add014f78386da70e28b36a3ae03bf731a48a2603 +M = b082706a2fc2d66f253ed3c49d5a43921aa91fcbe9dd8d61e819 + +ModInv = 27b1ae32a8e172437e4a32a69ef597144bc56ef23b335d42e64b +A = bb66fae58dc8e0f87072ae46fe792676dc3fff38438b6e4ad91ee56daafb64e1ecad59603f33212b30ac900a9282c3477e2eb19249e26acb6edb3ea18e8b46b40163b39fd0dce030367701bae92fe39aea314fdc968f55ed8a3e95b26357335e0795003fb71c1f587a2737f0c8e5b121e17a471f1e2b227efe4a47361f98feaa710e635ae4c7c8bd9ab0148433a2c7ecf9c3e4ad2d123e2d63bb24b656e9b9baef0e403bcb23e0ee1951aa0d497858ad47a82e08dd38cd3f2fbc38e1ee0d88564c07c70ee097cb6f63da6e7f81fe3021ed7bb4d2e126cc83137e3feab7e7cd2187fab02ad0210b +M = 53fd483ad89d71aeb0c3a1c09d7294d17acde8c8d3a298dd9eca + +ModInv = 1f52595bf05e1fb1a1206ce23413640000a1e84737aec1d1b +A = -e6082e1c71fa2afe9a17edeaebef2092ffced0c399dbeb189d1b4be8ba1266ec4f3ca5ce09a687358f45ddae2bb738f5d7701c919cca6ea9f857486aed479c127a0d9b1a2c0d3910f1243472d561139fead1e3ec1461b86861ac5a842246a4b41c811e996b3dd69001713ca9fc649f31a3d70867e63ea86291c6450d5341db654b5ddeaeaafce8f207ac867d3f1ceaf9febbea94a4b97ca5550ead6601e20dd48ede7aa7ccee63d3b56f442b9832b4ee9c3fa8fdcaf430148deb6373b0cd2f515f3784dcf154faeb86d067e432bb62b905a2a91583484186e1fb5b1dc052ffcfe15c87c4b89bc01b +M = 55d938f998406b8be405771ea994263164743b62350bc3bbba + +ModInv = 589aadfa12b0b7ba7b414b2acf66bddf6673e26b62f25603 +A = 7ef1bcdc11e3591a84181ea34645f562c30139d32ff602bc6d105280053cec54f587c35c51146813eb849f376fb2ea3b6fa8548972eb66082deed642e5ab97e948ff2ba68f54b2bf12149f61ac16c1644992609d9ebdd1cf9e66e7fd237fb3a56889af2d2d22158d5c6e549738cc461e52148a243f943e0f8fbd407c0efa6162584f54d07dad3a7d478a6f20ca45f54ff7e35f0c5815c6016d780c30a5ac73ad4e0309faef5b4d89b0b9d756176dd762b76e659027b1942adf6c7342523ba5476df43333e4e73318a9a7733f9c3526376bf03799dff97133a6456cf2af7e4e7683ad319296eb3b7269 +M = 89ed56dbc50dba4c235d7387c0e28104ee544ee4f46cd4c3 + +ModInv = 8f79935e164c3532574ebbb87bc975264d4a753e3c2f5f9b +A = -ec7d063b8f14285d4410d674f9d61baac6ff886c4f75d84720bdd354b2cb26f8d821df7a25bae9af2e8632cbb099d67777682d7ca8f72ba2d444858801e9a9c13a5afdf7d265df05ed405d6834d3e066c63e3cb7462411af728a5ef333bb24a26aed9919169fcb5e871b854371e57d4d83f3ac52a3327843a6719c294d8668060af89aa2aac97d3a0ba8d520ea0c26623591823fa449477f1ee222508d03e2ce13cfaa33a10534b470c864372a269b67ebf7357fa4b101c22716c2933cdfbb613ad10924368e97cc8cd3ecf91873180b2a66e5ef41b9d5296c70942fd4bdc4522f8f6f92ce9237a015 +M = faee4ce12d0c19b4353e93dc83c01a520a2375b8626b9d36 + +ModInv = 55b397829f4704db100eb4e7105810c3b56ff861a7e84a +A = -1c88da8bbe91b961b7ccffeb3efa0661cc662206d20fefced9e7cacae2251141318704c68428272b646458639f9301ee758c36ff58b65e2d96e14e8450121a5e7429b548cf22d40bab5e94cca97c9a4d15b8cf5f8f15af2f490c78cd8a530b5e8e1265bd32a22a737e979b3a85eeb165254ff71849212cee69b5228167c51ca06818a45c5515ff60b085500b7debaefec1cddf82f3ead5d7687c40b0bc5920aaa54aabba195bd6873a6241338ee04898f7801eeb6a1499103e17a9dea3968c7599a480b58951c588b9748ee5ffbb4d328d730bf03e9eea7010d3c39255c34b869bb7ab83363a109bd374 +M = a49511d862ca0cd169dbc5a52b4f50cdc60f658b8c128b + +ModInv = 23869111e0437bd21999a2ee41f4c9b1d1833a03bc3159 +A = 775ab1bfa4ea03b6cde2357acadb83b4961ce9a1cfc7e14500c0034825e7882b11fe1615d6f4613a20ea55991011db3e6f552f24702dbfd242dd9ebb29763c7183867c90d3231c26e1d04932158afe3191055c0a6b40c522d2eddefef7735cc20e9921c97aa900cd3d1bdc3f7f83c059c03f0d4a46373863b9ed2f6a626b3360dfed6d4cd4b6f18e8aa6e5d090cd67ceab2e85737340b2bc482999eb711852f6c7326b2da7e58034e766162603254ccdbce0c47993ad042fa7b033d442b4c54996200aa5ddd8cf3215fb56d86c7ac542ac3907e33fe0a5ceb540686bf4ce2afc2fd3b0be1d02ee080945 +M = f486844b9f256967df3ef9c315c8c9daa0c38b280c43d4 + +ModInv = 1a155bcde8f486086d31e0b148938f9d2bf505f55734c4 +A = 4858a709b3efbd9c34f09cbf8ca283430dd5a6529e2d3de7a6380400d77be4bb438c335b09f7627500da9caa8b86a6ad7e3383c2c474df76f81e0e6331f0cf3d6717fd0710bf3d673ebc88ff3c6a20b30dfc16388feb7c559ecb86b48fec28f409b5109ff18395501d6162218c57820f5287f1b8ec279f56ee2340b341cd85d435a6fbebdd07463ca79e17ec0e4f1f8d1b7bb36e4d1b764d0e2801e3fd7fe97693a2068b72e0318d266325728dfaa4a90707b14e3e222776d2ee7e2fd8f4523aa8cf529b4c68b2de3a1a308dc2819cf22072ff887fa56b480f1a55a2aaf302a44b22789042e4958c97a4 +M = f3c000731f35f4ea0cb9dcdb85cf23f2031edcb12b663b + +ModInv = 125122a56eb3a779bf0e30d50632a9f43e70799831c5 +A = -c233a7085a7e4a6f3392184156f456ffcd73cff0b50168630658f4932f2531c10715f61157629c7c9de1bfcda730448b19b01b8ad840a97a463d416142a9afd43b958e6fbc20652296288de906ba67bec393b7d0cd06c80e832b085fb1d2ebc24e44d40ce6224fac82c29fd2eb53b3a166821a4bedd53fa837f9595bff35c7bd4c8724c3f17bebf48680db6d8da2ac10f501e3c24cd6ef36c6595a7d30e095ea8f91786d6ec4d94e188e035774a749b40191528c4e65d5186618280eb6bcaf55be47a288c331e0d78492694c7d2e767a0027c4ee7e85c7e7be0328c78e5abc494bd7364c7dc080459fa4f5 +M = d6f4f6e0d09f5fbee3a4a7911a42d0387b45befe20f3 + +ModInv = ea1aa46e6612ecb304bba6a872046682341534e94d +A = 9afb77e48279d60e03853104ecf907ea1cdb9ec1ff78665da071ad639513e0a38ba71bb694a55e99ba7f74cc7ba88a7fbf45f537bf2175ec272a24020cfa40827e51b7783b1e139039afa43703534b737529c23534682d4d7ca8bbd385f8cf54fada4fd9516351bf5271efab18051849cacfbf524886e0743a22cd709b9a7e87bbeaef8a09bc1677032099d82a39c7ca3359c8e698e28c5472579832abc8d2fb6adc73f0c80f6d9ca6a1dba21ee80f69eb2417a166cb1f76962c0b015be8310df3e598c62ce877a3360629039b7112af284091cce3d30798cb3c78ff05fbc3b4af259acf70f37ec8987140 +M = 2e6b643fddcfd8c62184b87ce8f774892505c2aa4853 + +ModInv = 185be5ebff799478aba1b6cd0382a9ffedcffb70f7 +A = 1ac6dd7a10d19b4f2a243f4d93a8a4c6840d2805c7ef4edaa23f4397a2d17664d19379a7d1f4d4409a51cbbc0a937832c6636f24f5b3c8f48490b5467f852702d34ee1cbe509cbbb9a1ba6b8c310bcc934f369854324bb4a176500bbf879ae46583928a05e0d8312f8da3d63c2bfc85142a0c0bc248484dd6abf686790f36c2ff11fc3290091218e045a1ddcb0bacba569701a33a24bfd798e37b9031ec1e00849d80bd64cc125a2908d06553d70b1ce01f11b02c58684911a5c5dd955debc8d348f16623875881ae93daaf5ef5bba738908acb97ff9f7b961306934e68a9a72fee167945c70cd1b4ec1692b +M = 93296171faadbd44ce6fd6f29f778d1d5d0f0d8df6 + +ModInv = 1d8a507c4c2a0909d8622371e814c9faf716a82033 +A = -9847453683d1bbaea8d6576b1b0a8b1aba4b67c2b2e3e62979bc57fe869da7edb6f049e743d82553d21b1c1e05a17bea5e67abec465f16368f9c0136f156328c377a769c0cf3e80d57b3be2c9ea3835aec275799b2fd9a8612cb9576fb86ba4c45f32cbb0c8ab555f54c6c64ecd965307749aee406b3d55d6097bd8c1b84de6d7853d5f2c2ed0238f3a4d14e5bd52f477a371998b7ab2eb853246ae5dd9af26d39be86739d99925223cd17c9af75e472260bc1200d4c9d9fabac52cdcb3debb68c8b93dd18a7b0d66b30cea2a35061fb08afbe66c5927f29ac398368f78a9d69edfd1250c4fbebd4701ce699 +M = dfb9f9824b7107aaf13cb64e2c8b4146f5c6c3b41a + +ModInv = 47bdf7c0628885403abcb756c9c7baa26e5457 +A = -bda782a27d540ae3b3f474a6b9b3ce6dfae201c3d976b67c18c8244f6a1d25dd58d9494e725518478d67280674fc5af0d29576f530a9782f71736529f916dfca6523c8ca8f06882aaff4be4e8b3aa76e23ce512e90f037e1b7e58fc113823853bc5521a751ad85dd6978dadcd9ea84bd3b8be0278f18fb72c9da3ce64f183d92a953dbffdfb33c3bf38f94ef8563d029b2abd2d8ead0cad0a350c92b6b4dac32122da65d652ec7dd2680dcf4459fafd79e0d9ad27a7f1a3d152b444f84bed29e7176405945a4143a3aefa226f9174b59452f7b7a0032d9ff5754c8aaf7fa33e7c33304551ec1a38a0fcae70cf11 +M = 4f09659158a16be06dc34f46074fe3a3bcc244 + +ModInv = 1201759d53f93566cb80add8028ca991efd881 +A = -8415dd9003fd8fd20db397c4cdf62d80215c0fe0cc638313585065597eb13ed2a68d34ece36c590bbf62e28f624ecad231f3a925d39880a3ff513528846acba28a03645932c29bcc881b1530474aa2675bd02a12ecef363862ab5c79e42ad81e47bbd0cf34b73ba468575ab6accc22cc5c6b553ddaf80274b555f6a2fa3ca7f97e838d972c4f45d29c5797e961b403f19386748d644c43d403b35ecc4f642482a26fa9015e0dd1f68b484e1ae89392250ff37ab00071f34dd098d6d70b9482e407ecb957293ec5cd01eb1cf02aa0f45327327e0fbaaacf522af3f02ee6f537bd5a46505cd8677e29ba7de75bcddb +M = 147b0c814484206431bc7555f5f97f0f5bcdcd + +ModInv = c515ba744bcde15bc75e13fd798f50606be767 +A = dfd6dd7061a2d72993df4c77e0ad545c46f5921ba6fe40fc94c18a7bb8f42d69eb8a3cf7d067cb4419edfb3d072342ef22c7dd1d6d3acf6707ddf3dad071f3676db7092dcaa39539ef39744caffa267fc0d0f24eed3fc83648a08ef6513f17780dd0214564087cff19baace31900493679891bc64203887f44e4883932e3fac78bb38a5ef6d79389c1edb4984a953514b336f9beba7f4fb99428b09c203dc76ee29e3b9d358b7663c36e31bb999c1b5efafd4d8a7d881db01862c1f4ce33151df755add0aa65be631f99dbb89e86dfb4fdeb563bbd1fcd096dd66f276baea7423e3ba664b7caf53592c44efd432f +M = eb365fe4c7551a0acc792bca7f33ab213933d4 + +ModInv = 37f7ef5c7f39234cc53c05c57567f278ac78 +A = fc905e52ec9384821b2032501168fee357dcead6c2eca55ce3434b89f949fc9a5f432952e8bf385bcf886188d58e12e025b372c46cbded2d9c9b6783792ccec9bfd6d89afc7a435cf556ff4ebf17e1de5ec4ca72c5adfe1bcd207fb698901f426af40502b9b8d16c6a4e5c285ccd5d62c2cfee10609ebdeb00f6226dee008f0124ae2c0c08d73c158f8a448ce72a712cba2802a23a43e99fef7befba845db0c7ccbcfbfcdc6c6fa0181130b6a71910939968d6e9654e5d09929ecc21a70efbcacb1f27f52e048cd8d81f864de4d43dac68db2d29cd1361a876486aa51eac3cde295c612169aa716c4b0e587b8e9e09 +M = 73c35e124aab3402cb58abb8efb2d9216ea9 + +ModInv = 5f7dcd019c6aa08e906c80e0e03a0d0abd0 +A = dc4ec10befc026073150f0afeec7628a6b7dcdfda92075b9ad3c302eada130e88595d8817bb9a2e2c25403826eccb22dbdac48618d52253350aa869b0a54d2c6e1c43ef78f3b3dc8f64ec306eab8f2134305c246171026b0846efa46ffdefc1bc337544a06fdf7b8cc992181d7e6a72a03b3eafdfc01fe02b5ea3166b4bf0d23cbe9564f6478b0304882dc0c03768bc5f3472a50da78a319fca22b312f666adf53a14b849036c959051f2b54b95aeb827ef834cf62285f11936fabbd878f95849c2ef4f9b1331273ee5e070acf07f13678be90cf4b0e9f017c15f2008332f9acfe35f6adb025f8c87449d41aca374f +M = f0b0ec979610077b73bd6b94ffdf2073043 + +ModInv = 8cd0929f077faf96e2c2e8052d96f65edf9f +A = a13259d168e0c3cef8a3473c4539151292d3c803ffd09a45c8921ec7dbf66f9b69529ff6b02e252b54572a96e31bc76f50975d74a862025580d56ee4f5de7bc17a0940c7c38e0e8628948d55db4e0e34d8b51d77696936f1c14622d46eba2d51f67dad3a9c738efef75b8dadf0987304caf0fd17c0575157b100269d86fb9735fdcb904bd28cb80b388c680c7c6adb7cf1840a481d4842c2ba51342b937599b3d391acda2ab8a42a05c38d3be175f65eb7a06f4870859783dc0016d04990b79eab4b1e9256680e4b88da10d3308d074ad9d06ad4fec87c1f7683265358096630485bbfe7fbf07b6a3fe459373d5a49 +M = a30b227793efd27ceee7ce35514f3e7cc146 + +ModInv = c4664bfdbae39f91f29373221727c3c33 +A = -3623fb82cb875af57aec518d41d2de096ae72e4a529b0af141a3f7681cd6e0546898af294801939aa33ab5f4f7d89f9192afb77448bfe396aad34a5d081f8ac29811887be22743d1fb3bd65089e895c7350220935815008b4b384ae6fddef6953db958fa3e1e45f60ff26a3099e14b9ed23373986e08f61e4d07a853153d4c31b4f14895dd1d42104956d2398e7d2905f01aff8a177be0b9a1297951f780bff8c42b48c7ed454aebe853c7157e62bc825d856464e564ccb79abe9d5126fdf379a933013aae5294e137060d38e696f7ae9666b9f20ffd34cc9265c91ba4646d4a48e200fe9212db11bada60960c4674fe +M = 7c91de21b40081aeaddedeed4425e7c013 + +ModInv = 1375c5321f6599aae9f4a13df1be90e11b +A = 7b6c9d125febb853a73f8a330241921585351f9f375b5994eed45ca17afd68227cfb69273381c88bbbacf2563db9e2bbeac3851ca241e9c843d39e279a7ee6d91fc40f365cbb3444e0a34ab749d39337519d442636c0472ecb5f89724dbb5559b6bd3aaf56685adf3ecfb635a73747f9e0b4ea7773bae5e0bf2ca51ecc728665223fa426e1cc55bc90e95a17bcdd700b427f32a3a57eaa75e88d1d5dcbaa34b2a3f8019d5c6993235228d0abd363db61f4ef49e37fba9d81b60cd0c7f0d5487aa59ef3e725dba647b057c8f78c7eeaad5e6525e3df327c20f0a2a4454bfb84cb23a94efa2819b409680775a280c5fb2f +M = 76c3c53871d62fd875f4d115d861e1f806 + +ModInv = 226e085a362b04276db35e0f7e5223254d +A = 1a167234225dd95567dd6c36d4cfb64a731baae0679c5a95271a85b1a4891268c4c95e1675979ba3774ef23d5706565f5ee1b471b1bdff42a9c0e70d83716499f7e85cd3c9385f5e74410cdbc0f3a6848d4ba8acc8ee372ff9e7d9b584fee9e4c91ce46e3c41fc42669d906eb2f5e27eba8104e194c5144bfba26452842cb9d70ef94f02ca1d0bea9db5a14e4408f2f8cd2a51c54e64f2ddb13d9ed4517d73f50c16c9b8037f55c4aa3d3d806b4e2af8df9cf03e704aa2105a819cca9eb4a85810d01a47b8cf73943ce10b09978326639f5c0bdb48f2139834c2ecb50bf1a11fe486db83e476bf8f8c0546a019f04e5 +M = 387a5e8e68041023af9affd133279201f8 + +ModInv = 7ea279798582289c2d5e82dee0b330a +A = -57600f68d41c9dd82595a44d90ec320b0974a2746d1c369a303300a4534c6cf5aebfcba17606e3729b0eef1a4c2dd55678c82893f24d1c08d2427aa8542afd69258b667db0f1402cf236be8ffc7fa2891818088f84a8c019f15d101da564e403896765b231d67aa45f04d4f086b120fbef66f748ed51df7fcb83df84be6205399eae1e2ee5e22758cc98e3facf3e332660985f30406553dfdea4e37fef0ab6add20e92c3e02b2d79691d0de47063fe1487b6ec18cdc4558d4831fcff5ab4e6a36bd357d2d9865c9e6d811b2f8cbb49c63d5c536c944da55b065719567b3cae9ddbf385b76ee2b1e9e8e140b9d17e3f62de +M = f9fd500a90ebd3452152f639ebac545 + +ModInv = 27e6cd32e2b829657435821dbdb81b14 +A = -57721688997ae27f2d080fd06ec9584029df020e508daed88eed6af06b035e6e24057356e982634944108e9fa00df59649651f8bba723489a7df1b671cbf988b584dd4af515e6949d8b880dfac2e054a3d53737ba728cefa49a9cc0744fa8e9ac5a8c9974231322c8dfe84744bd6a1fbc89f8f3b9e8f7bddb5737b26f8062a8f749a8846b3a3cc412b485add730e05bad31c662ecd8fd3e12038847e6ad1751fbafc22d604fbd255e770535f100e544b35c2c648ab35897af8a295358a0b9c46c7773ddfae2d74367600d557ae730cc0c0a3a774d4b259d42daa8620c32a5e629176cc270102a2a0cead3dc2789f45d71d +M = 3558148edbfa3ba79d27b7806983cba7 + +ModInv = 1f1acf4ca5f0c500df3684b16c059f88 +A = -91fbd366b143a345a97f67903495507b89f7f63cdd634d3dfacfa61a6e680a8e3136c20f231a1859d2442a5475dd07b93ef8bba16f53fc1ff0adf6c8824500a97f2c472022f8ee2df78cb8f89c15d070ced71312254b4f65cf11b66a1b000577807be3247972a49659703ed8747c355f28867d4ab432f070beacb3462cdf7bc7ec813c84a7f579ded1e4006a0a68a60bb989012a5e76a14e5fc6eadafb67163d59702468d03da16c9f0b52d34bee2452a281cf0500804fdfbf228f4f2a9bead26637b019c4ebcd7dd617e34ad93a9dcd06f14bae6bc1e280068a710da859e5d8b63dad35770919a1c8168a38550863d3f3 +M = 9324b8f490a191364399a265461718c3 + +ModInv = c5d4b3f952b68e1e3607cefd63f0fb +A = bf108f5ddc16aacec54dd141e9cd25db52ade39761c80a1bb5d866cb968b041a7a3b3d0085dca170f82e2724d21541f791381dd8b82be709c6a9b3495a72d14c62c908d6556f3bd42c2faed4040ff096558de2cf4b7c887b7273dc780f9849e8269d52b2af1cba1eacf2ef24ba3f72091c770e412e85c669febe6cfc257b92abd848702b0e567ceb3e0ad28736d434419cac924d8ed3f08f4d435eefd6c24c48d8892332f35240d315b911d1787b9fd32f66d8081ca5202a843a5bd97e8fe65f3f3e061a0b93e041eda4c41b3828c516aae94535c2f91feddb2cd559ba969dd8f6687e0dd89dec7aad49308bb43f22079f69 +M = dcba4451b13efad3390076ff2b2c4a + +ModInv = 5117a87b44526d245debc1d4d9b9a3 +A = -6ec3f7e6f70df7692e0278e0f0f129da549cbffa87c3385a4022d0fb2b9b0d65d7d492586176475a1d657deb7aa9852f771863abb17da55470dd6800255337a0bcb4f59cf3a1d48c76e0675f5ed8b887cd28a58f327532deaafe22990ee929714aed0aa5a96a9c3b7808b4b749c5d44eb562cd3a85819c98b73e76de11362d6560c71016a8bdf4f47084829f96af2cd2e3100fd05d09e6d7850040a73484cb54f9ca76713ae9a927e1056e25818b0708af2c82b62ff13ebc75a6128227ebd53a95df916547f0c96d9dad66bc8834923d78479c4f8cf354db61d18b6670e80774af759c06cf6c9faa7bfc8fb41616c47bc9b3 +M = c29cb3b7202629ae6a2b7e15b3439e + +ModInv = 2a1dfaf03df10696d4cb529b192e4b +A = -1b18f4081b356fb906161a75a4d6ae5a2391a162deb29aed1a03ac410e81f2654876d74ddd653f44172f1576dc232b0525df159b0a934b4675276ba855bb249d12e3025d101a539be964e57dab0bbc0910ac84e312e970da68af9113976e69c2b0a69e94caa75c732c96497e94c00127fc50aaab2b9b645aec62c2d301eaf4c0b72eca378de86eba0f36f2f4bd7c47b2af25818c88dae3a405b1c730a8416e215b87eb19daa61e76317ab5c35361e4a52c37a6d349e56bac15d6f7ef50a3dd88feb9f0e634169cf3d53904a79d53d89752f6a6b7984cfd7cff6a356df6f2647f416d3c9cde57e4b86f8de9c96d08c6092011 +M = 80cfbb2f17d0f2727f8dc803f74a85 + +ModInv = 67f85bfde0c4b1f5fde9804f5752 +A = ac794ecc4101863167c225b2eaa4d24d659c23895d0851c024e5a19406c81b6bfcfa3cf537d4bb8ef9aaecb87f4c34599bcd186d9d49e455286278e19efff6f2c2a0e81faf81cfdc2dd06477a95c6fb6bc2304d74bf89de223e1f7678865b843441bf436394085eaf8061b73c2d7ffab76fa5793a5e057c36f5ce89ef020952429f7c6670b069ae0646dfa22416b1a5fbd7351f122225065af0b3637ee2365f69006b6923a62be25a5ce5e0624c283fe43cd55e262a65c238b0a274e766716804a83d3189a2256bd94902b175b8eb5a18e7cbb000179f059cef742ec37147338e617c48e503cb38db5333f85d5b37b5e7dbec4 +M = 83cd0c9604390fbef6dfcd3dc0d7 + +ModInv = 6850810c00149ce0cf1dbaf41691 +A = d43b39c1c876dae65c0edb8e09b72a6f4e6dfd39f90281a5cbf24377c336e7f62b12c1d6e274ed1513e585b451ce26c834709731261c83c5b65cd07947fd84ebd68d9169b949488c4ede02735dd7a61f39b0adbe12288c0ad5c3816694305580887f0a1db82297710b0631dc890c0dfbb33c9c4207b3b7a511dccda2801302ba031e7321a5445510ed109d9319c986d24d6da857d68466f1f0ed1dda03a0612be5f2f04a36ec09ee2d3758ea65812b606c8c792977c053ebcdf778ae232e2789812d55eadddc2f5bc720408dadb431a6f7f9861a05ba2b0785dd689cb5a066ae58f71a342ebe6f7df59c724159e82974f8147 +M = 8479538fccd2026a9edfa19a3eda + +ModInv = 12ac071fb37c427caa1ffa82be25 +A = -e350896c87944e2715771efc913afc419622e8a1a2c9ca4df3178af974ce1aa4da589eea04f70ccea937dece1a3a133a953d8ce5f020cd39344e89d699c983110d7a42f4329f8b835c8e3b6bfcadcdd37928820d8111e7305140a6bd49611bc4e8c1b463f6f4beca023d0ddb31741bb4fede42185ddc4b56f059b511ab79108371e9a2e9e5ac5752b4ceb08511d764cf7fddabaedb28922164c9b50869df42feda3f40c7e08071ca3f51448e93144924787d80d77fe9e07f83dc116af7e547e5309832c86ef9c3b9924f1c456ec1ae131fcb1c93e9b4ce4a1b34d0c162ae6aa064b15de5e5e6f3eefc5b86a61357348471acdb +M = 874a617d3c7f615378ad9867a664 + +ModInv = 73a07a20288757d83f81d2751 +A = -da575bdedaf59315029e4c63641b3d624e077b1cac757442cb7363541d135008ac9808de2490a07525d7e0ae0e0b58234bb53e1c62fa85cfdfc0f3cea8df9f9ea60f76851880c7de955277f6a0837284ba42621e63e7b0657e3e8649172ed022cc0f302b40610cc08afc48c341750092c4c435dbe95a245dc947fff2863c580c53bc917f21997fd33ba564157362200a8cfdf0515cf49123f34084a42bbe370df2d5977ae61e637b1710aa791d1f287d33467c689784b645aff633dd196671373d21a219daa83edafefad0fd27f7884d21c02db3a97ec8285995a18738e5c2dfcc2910e2d8c5fecd43fd1c9b705931820e8bf93b +M = 86b6668ec499291c056a68447a + +ModInv = 2ec4cb090a4b3a028a51d1dea +A = a4c7fcb35d749ebda4fe5cb3a8e28244cec5bb33c72e018c00f8d4c738d575c0a83db58e77d5e1b69c403978c120f1cb15d7bd3d2bd87b291f0301d3c08100600377c240a32fdacfe3756fd3ea2a5ae403cf325bfcdf63fe99883015ac91985d82f20e4a11e2e11a698b5cec3f7c0e7b8cdf0b962ef907db600a27771530ab4c8c1f5fa5b76d748b9920b1a9428f60f333bdb00abf5a48a21f8cad86afebeb19e90dc7ef219f178037367f77935af14c7a87bfc0cff630313fe7edfa353425e117ba798361d6576c5e6dfe83dd329c5cb6aa8179487b5cb14c455979ef90db149d613760fafc92323d2c15204d3ac88769c3b107 +M = 53413fe79780af04b76ebe7789 + +ModInv = 83f9054a9279d8387d18f45bd +A = f331c517efe3c19d6a1355154fdf09ec837fb794d042a3af3d02c4848f64d6617788c93d672e3ef5ab1cb083b4d5e709d0c1d69305683b95461be39ffe2658e0b56e1484d4f89817097a04afa1a1812759c0b6ea7720d7c9edadc256afe61f6e878e44dbca7899ff153ff2c3e044747248a51429adbd677ea7ac6f2a629fc4abc11aa0acd87e1eafd34f4068d7c12e7d780222e0c446fcf4af417260448c07fba25fb3fc61754567617b86c3a4974c8336170f48ec0fed2db78978276881cee1742839e873da4a98f716fe680296dcba9c7629649b4f3096e5b0680e873cda1386da2d8235ccb1ec1bae60f035cd1887e3ba54ed +M = 2c9882aceecfafacb01e244ab5 + +ModInv = c671a9a405876b8b9c425235 +A = cbcab3621760cea80c5108a17641edab4181207ba61f58b28d386db34d397c770eb7434bf7b00f0de907025ad19f8607c192a259102dfdbbcb64c11ec455fe0da555b1038c28ecb4e986434e6541e148034a6759b8045ecae4932144de99f4167a577ed48aa53aa10eb4ed6cb84253e6ea5c7845d5637f5a7e3f7c2b178ab6d128211878ab9fd79976176cf5f87f6315e35b7810e34b1e96161315f44893fb472820e21475f90ff37c2e35bb8bac38b28e58e5d37b9387759ebb422a41de9d91a2ec9e86a3054f7582bd73fe27fbd0ea974ace0dd5681f6ace02cef975655614b1872768cec6972de55bea4ea258d34040b7c1a6cf +M = ea7d2dfaf8a6ed6e2f31bc7a + +ModInv = 9487298f587cfd38a4769abd +A = -4c27dd9427ecbccebc9457e7b9e340802bcc625e353f080639dca57c68fb10c4506582b330f3c80af19545d61c727258b32aa8fbebedcbb6909f8b59ca5b901204e653b9e2ac1d769b9de6edf5b297766ad5413a9a994b4a905ab09c06845edccceac7d0d916f54ef40daa0cd4a2782f9120c49bdb3b3a7a97fcdf260d05738bcab9c42ad96105d90c4d3701bc92a50d68c67f8f92ea527266e5c63106f3f83afcfe2e096e5cbca3d34c0f5147ce52f9869059113cdbd50f636b80c41eb6e8e32885d384bc122752e69553b89fc8f6ac0dd62689edf9d51bd080cf54d06f11608396a10541c7f4dd2f9907f91345c9a34db973a7dd +M = f149e8f8926cdb707574194a + +ModInv = 11cb7f1566cacd4c201ce0d +A = e02fbf4b429078e3addc549cd61db35298e1b9ff58265718e29075b119f17afe47ed5d037b043d42a75e3eaeac219be628628e3759dc4928d993c213a18cdb3793a7201df8c9c02131825574d8c0bf2f5df5bb942af9fb385e5a73a0d5d87f528e8faf583207419670557dab3d17c93377bac83cedc89b4e6698c50ace4babf12172793d66b320a9163ce61c5f7b1bc8e947a26e95e9044a7088aeeb106f48130c3bae3315bae185e89ae57d27279d7b0d1661f9abcb600c4739e1315562c0703ed8b926fcca00090d3847ca98e7fd8ae782e5c1df76568e59a09cc872750cf3ace61260ea980f88e14c592d2775cc68f5a36a6b2f +M = 21ec522c5baf8e9a775d7926 + +ModInv = 52cf911c15617bf3662718 +A = 24f0f6e93e943310960d99a32e9a26dcafed5f0f6fbbd092a947dc848063ae3d34a668840e1b58c714c80f5cb636e892c03555b7b474624b3862ed4215127c849b3f0680b02eb69583315d044aa93b898cd011005999b16f535a4d461fe60dc8bf78b1c8ff2efb05487de32e74e5579510861ad99519fa99e692bdc95afbf3bdd118f8280ade127da11d2b057e390706bde946c43d97f494c1119dafad1933ab5c0c9974d53435e35fbbb2667fc3f150ce8cc2b36433bf6638315b910f02682a4bd969146a4f8488bdae9995a0c67c1a79c167ff5ec27422f78de98c9e7c56ecef8f54cd4d81a0a5a8726165b939b71137d045a0b5a8 +M = ce1d1ffb9a14ac10bf8f19 + +ModInv = 410121db68d373307ab7aa +A = a183e22f08ff470ac3e9bed60191eab5b4a1bc0c30e81c3311cdc831724ef777df1ba03864e6330ca63d0032ec07777dfb2bccb409ead583fa33127b3481298d143918e04ced381e7b4d6abd4bc4ae7aae9dd6e8bd150727730d00ef66438bd6d77e4a448d81fc714306806e108e411cb41f97e3c7b61d49b2e8ea9fa5db2c8f770a9621ca12723ef29c38fccd61728eef385414e1a98da6fae02d45060e7405f63cd3ceb46df31a073239e94d9a17c098a1677fed772eaf56f9bfa249c7fbbf770595f5306bb74a659669f26a804d06478e19f3b10057df40d27e70bec567d3a6dbc567c3a2fd3eb4d0fc22c5ca866593efaaf68cf +M = fdc0a3cc971e0005fa9e11 + +ModInv = 4a621a4d439e9db5b1ecfb +A = -2a6ae8667642792f5b6303cbf53ca74d83f7b635225f6a05e0b7e5ca59cd73823d13ca60529ee96d739f4a27c34339eb076f8d71c4da139b12917c2242de1af9c4a2cea81bd259b7d6f48b78848e4e3e5b464b6459f39bd12be9cabe9c8568534542fb5234d88ae2d400837f2e1184a3ae49924e06f51dc720f90dd3dd89e156ca6d8c983ccc47a7a26ed3bd7a74d0f20d7c8716214a3e84ae0299ab9a625aefb3ca5b3c28fc869bf8cb65cba1d6a62a12426250a50daf598df92848082e42920f3a2c362491f8c6232718982bd010e9ec53f6e57a2eb8cad9b84cd94c4e5e724e7fc0026b0d502eab84187db0cb2f5b2153c0fa84d1 +M = b663e92aaece715972c734 + +ModInv = b2536becc88b1efcfa3 +A = 60326857755da8e48a9ae9005b98b5a38fda14bc55678fa203e2b2b9d1236cc47d190f78e423d37d8997070581a7cfb1869a622b40118ca3796d92ad3bdef1b64f683234e8a5b12a7c19c4f581db8c2f4fd92b93b01c11ec102a0466f52dba4e429ecbc84d2ce481fc2260c3d33424f2b38f1d0384601ba3cdda880aa1e846010db3ae4b376da3a39f3b3d7bc4b0d781a052ed0bdee526ed9d23d84fac0e1be32c98305531786e084bc613b9237015315d35861564584291c770ad52a91c8c46c70d52f0733d03a3e4a973e144955e246da050b4b671f33562dc021fec3adc696fea29a6ed589981beda890d5384ad25666b81a8191ba1 +M = caa678bd1fddb37b7ce + +ModInv = 189e8d9e37d7c1f8601 +A = -dee4e2b5bbafcf433f956e291df2c880de9b8b1c7290ca14fe951ad2ac7adce88a9baeef1803e9f899306b4b956c4964dd28b0e22ad5e2a323354f8b211bc4d6db934531c158e4f1f8d4a936c6f39bdd7e583a0e9bc5b62af878ef870310de185e61268fc043a6308b8efec17a93250f0a2d0de8a048a4c9a282e239a4eafe9d236a1eae4ebcaa406be754e8da808cf59a263a2cb9edafd341b76a91846173232d17b17ab32741f99e78ffdd9aefd17a84b375dacaa6555eb9d39b1cfa4bca153c9505c9ac7042ad2f4a7e143eea633f82f4e35fe1d653090c33a1ebb93805be07f51224d94b4ff3c24cb429f7e2f5b0d188f967387f77 +M = de61696c2c18942b06a + +ModInv = 572672d065d0a6b2efc1 +A = -6bf3d31bb56801830e097e26fa072f74d0e6e9632eb53b2cc60983c6630cfb3fe201c68eb4acbad52cc623676374914534cc06e988f86338e0be6f8bcf4f15a112d842d36a6c8eaf7a970ddfde8d2bd213489237fa0f452fe281eb284bd31ee3c26f63b4955d5370cb7d6da9df0d0c0d1ea851596b63f2b399245f28907a85acf6bca72726913665ab9d52ac80ee34472a7e955a82aeb57667fcf4e30bb017833c3e8d248eb0049961aa2f130ff9dba3d5431f871e1acbd0054c851408a1aa08861a6c83668be2f811df78f75d91f23f073cedc75ce263baea819fe38044dbb203ad531c4f169159a81f1234edba1fa542ba4d23be2193 +M = e6e079b841da3eb2aba6 + +ModInv = 7d6e0124a5f08d29c9 +A = a7c085f7b02f6e0776e4b1aed6bfbf696863726679a9ec46bd9a9f1aa31e9999e82b95be739980a82203f580998e168562c9e0d541c37e612826454000af132f783f8283e39b344a6072bd8dc44f570020f984c9f96bebfd7fdb4f66816f58e8828a42fd2b1ac9309c4b6cd4498aa4ad9b792ab7b250b519e4d1d31f4a5ecf8352b980cea2d4220afaeb2b0a38840ec0186e30f6cdf7c18aec41ebc7e7c79c28595bd641fc4cd7be99465c71f094a4e4846402568915109e792c95fe933aa00138ebd61c4ac09c0168d20c585f25fb0e76e29ba6d01174c19943d3e0ed95488a3bac43bf0ed0c1b0a9ea400101bb8c1bed5306cdda2dab0b +M = 7fab59e5387fe35cd3 + +ModInv = 15005142ce84615d2d +A = -c9ede55130efa600993311befa20dc8bf1aadfe59dd9022b7139459211d1dd89e4063a21360ceee06aad3c920147d33677549615d0e24bc28110e65dff61fbd5b6eb8204796eae7816f90e65c824a0676465ca1c50383085a63a5b81d99b18dce07439f78edcfcba4f7d1ea72cb8f117c0b7dde801dfa141da47315431057170b011ff4573a86c30d468c3f1083c7cc184e617b6549e992b4b18b3643278391bcaadf35ea79c5d5539bc59ab5abd6ae20de082f5fe8a549fc96e2bcf5ea89415c3505cbfb97f16afa2154033e769688441cc3a37213ad2538b62c062795f9afeddebb89f945999c47107f8188d2d2f963c7d749b75df0853 +M = 5886247da20c354f78 + +ModInv = 349786a5766e0edaf9 +A = -71b8472116cb778503e002185cc66d7bacb10859703e8337cf247dedb4ddcf7a8433aba2a6879a86c95c348a025f1a6668af4c8f0bb9e38961a702d52c795de0cdca1d758f2108216254c99b10a30ff4019e9f90f0542fc331dd0f86ea6f755e7485e839a5505bda22af1064a1b1cab358ecfeb80858fb1ba00db140fd422cc5b30d2008677e120cfcfbf0cd16877ac8de44a95933090a7ab0f722582c3143fef65c87f06e12190a34d485e5a9b9d19b81a2cd55154c7db38d13f2e75fcf64780dfb1d01b3acc0726ae985283ae530ada14781935bb999ee05ba865ef97ebc32ee8752fefc3c8e99ab6949d74f27cf1063bcc050105751bc +M = 6799cd5517481eca0f + +ModInv = 2a08b6a965fcd91d +A = c8fffc2eb05cc228bfd920b7f6682598d7fc56619c764c52739ffb6a5241058d66407da4f29c47952d99d0cdcde6515622a0bac823f39e2358db0607f5b8a15f71d4ad7a188bd24890823b8eba5f6ab62af3126c22c214dba7f5d5010c5b65d775a08b70a5cf6eba342580f2efe613186cbf9af036b5b2328a6300fe8b2ff8b95fc8cbb8e031f81854adefa53851990ba266279615a5346dd9ee5cbf8386b4689f1c147f9fe4459c722c3125140cde90ff46a69163a9c1bfdab586ac0f3e7a8d10121a3a6962c2d529ce9cc06bd96de23ea37ca7f6dcd6c795de723cbd376bbea54e5b56ad56f0afd7c74962227e844370fc899f5d5d1031a5 +M = 304a9100793014b0 + +ModInv = 3f7f35e9d77b884e +A = -a6a02724effc36c56cc56359405ba4ae711b7c710eeb407bf7d3fcfb0627e6d72820078a3291005f29b8df5add9b5bc0516477db4a0013418a4315aab54202de3d88191e9e04644253506023a973eacc60909c50c3d82de949d34f3a36d65f7aa08bd74d23c6661a95c5d0a12aa693465ca247685e0cc72d96b00d091c7db60ee863a52368a1f103e8d822136cd0f6be89ca08c8800ba5257819007a55e5ff68527bb5deebb17412012ed023c155251e6d7e2991f50be81c0ae42b132a91ba987a2f5d802da4ef8f3d902180d23c67c6560819233122991ac7992c53bdbb411d16aeb5da11867c7bbc877e14b99d2003842cc8320d6d19e5b +M = 60df956905053883 + +ModInv = 60813816ef255 +A = 1e095f0607525c26fb2cec07eb56fdc01dc9f65b3468ba1589a8fa4d234e03c9ae5c638f04d57ee60bc8e681a5137b675be02ddd84a6625bd2fe1ef0564e8c5960de8cd811d6412bb55f7246341ed6652b29cb35ee44319fa6d652a0f52008475d6a1bf9c83aeb2a593f25a42182bb998676126898fca48a6511de2337413b871226828c4b56c2e452de3081202901ffc7f27061932aa866ce304f91aff3eca5b772cc0e7a9946c41f1cccc20fb447f3f5eef9d33e47677cec095a99422493d45b6a6661d1d5278345be59b128bce505e69355419db52ac07135e3e1f3e11deaae13096787aa72efe5fae9229eea435457769eb9ba1a7b0e7b47 +M = f313ece76920b + +ModInv = 8684b639a200f6 +A = -45cb2b7768d19b8f449ba3070adb8499f61f65d78372e837a350f6e563f6613f131c4b8ea98d71f8720b2d5576ce2bc16dc5d13a0b43f4def6a7d548458a7c8409417f771d18bedbddcec6e8625b8c1bdbaaabbc495ebda5615ed2a8df51a9f7c4638e2f68a5298bd28383a73744b78974f8d0f43a07fa214e6584a69aea86abc72580db2a2063c2cec01405053406af6893032fa896e9b0094ad82857fe9048fd0756fb345009f825aebded953ec42126a8bd8bf762ef54a12c4e463649e2247e155747c7eb414ffd614f25073b54f91b2a05d43d012836242c9994c0b75f83de046ceade31b4c8b4ce4b7b4501a48cb67b73041fed7b03e258 +M = 89de66a08a0d15 + +ModInv = 8478fe4549a5 +A = -e18d1db1cea2617b741726fa675433e953bfcdf0fa885ebb0a898839b082d2f2ba44b1088931cbb44c7dc51138d2d0f51b700c319dad7471590208b3b085cd97e3a763a2c09bd59ab35b45035bf67cd9b07cfbe86f63f9cb9da966bb6b0ec734d63a8607f0c724f726bf28d5952e776c6c0c1e85cefaeb5804634a562d313fb6acea239df38aaaa867029488d22bd72562ee1ca6c3be52d1e14c64d2379910301a2ec4665fb458c15eedbac79973452393ff19a3044c56931a0e792e43974fcbc177f8b45828454109ed69da220d19ef2140c7c33c9fb7ca78927ad5b10bb3c4aaea8df2933bf779771571c4bf11bff27952350cb3023072ce1455 +M = 951c1cef5cc2 + +ModInv = 516a640041 +A = -f05e8e230fe9a937cb75ba6854316d29d55003856404dcd595515e3f31b0c6cb1ea24ae323d03c22cbd02a798a60729f1ca4d2abbb63b13fc7c796713fcfde7627f7310a233e6eb5770516a80e080341144a7b616a96ed78b91f8a297c6914eca8141c6ab084536032ba3a4d0d9e015a7abdb9d901b7bda93473927b3e1e5a6f8cec552be166d6edc80f2e5a97ea1315dea97e6ebd0bb7a4494c6d1053005126d7a4c07687c93f40c0da560ea279cb9ebe125b2b98cca7a0afebfab3e19698bedb53bfef7fb0ca91a3f0560af8629197db07fdcd6110ebf350f31599fa798ba6b145c11634651c0d7d616dcdb307065cc9a1c0058c242b9620646f +M = 49638482efb8 + +ModInv = 373de6c2efc3 +A = c98a28f01c3cd7fed8420e057e5ef098a1be53749a00b5ec04ab65e17a82e8d908ea008d26823ffc4bc6e4bae6b83b59bdd4604166b89603b28bafff869e7189f6913a70ce87300aa81919b6fc3bd965af6eed9ecefb779300847484c56d0f83e197dd9b793d5b5da3dae5c793844d6594f52198f75e5a2cc54b4ff2247d3903e8826778b1155406d50c905b0e4ca9e095bf8c5cec48b5c602dc85575466190d693ca8136d1e64fe5b83ef4ee323b083364dd5fbe8f3654468a80b1ccce7b9006e6a9fc096eb17992e8cdc4b80ebe4e2876adf4046a6bce168ef401d04bc6f90660e59a4112626c70a70ef52d65a1b8012934e001b19e6ba3cdc0e +M = 538f94c76513 + +ModInv = 56798b8a3 +A = -dbd2809e05a7fcf1cd9b19fd40e1e7bc9b20b882f841ea490e4d7100a0effa5042845831693c817cee33e08cd6040c89ea94b803425e86e5f26b893c68be2176a4afbe9dcc678d0d2c9189748bbb91759f16531c9f8c6f669de89e99b33d54778d6a9739c9d8d00d9118bdeb283f38d06cd7fcf62664afb045fec6d02b60d7f2c8a4415e8c2696a890a242c45b616c5c8ac6bb5dd5e20b0bbdfa20e8b4e8785638ce338c3bd5eb6674d77fa7c2403079e65fdc7454716355fa4a7d58266779becc91e043c8084c5ce983c15d5e8bb5f162bd6bc265c64932bf993496c33897640cf257631c110a75628b6c95dfd987358b3d0ed824ac541fe3d83598 +M = 43e2e8379f + +ModInv = 280733973e +A = -a729359a39ad28310335f5d39e0535bc4f09b9990f7b5538ec879b1727801f029a2d527d05228d7ecb1b50a52549bed1b3d12eebd2d647a6cea7c02b45c69e3eebcb8293b39cc3b80ce26ef9ef404351202306df8e30c99ec431fdea011f8e57e4b9d31fccd241ffdbf06be9a5fed9bf0a673cc82a0cc247e2198f30191c69dd6a82989e2b6a674871bbc4ee063a8190f1bff9894f00023aede780ce811330c2a66626aade5019335cd56363a72b3bf27b314b01cfc4af99e6586ae46614c3fd0f5eb5c2d24e8d55768bf62b2ba1381b795d8fd0e31cbf069dce79628ec9b98ff04f3639edf199da8df6529c0fbf8abe4b4537aa127f43a45afd9be +M = ae015071e9 + +ModInv = a6896c71 +A = c7e27fa50faebc3eeec971e4723826657cc070d69df7e7a4814d87f7ddcd9f066cd753bd041bb65caf9700aa22d7a1cf78db76065c8d02c38d63efe95e806d68dfa73084c8eda258dffc4a04fcd0258b59856db0adb4bec89b3be6a77ffc8e2179469cfe35230d40ec311fd092dbf04877247260d0c2ff2ea3cb854d0c3e970db0447c4aa0dace324514a1ce14c57cf4bf01a65c083e0b9e17ac987df786e4f5c2faba2d8bb97563f96405946c99ce8d43e224caec3d0fd7161d7bb4d1f730511ad669613d88ed3107755b4bec834de953d9402233110b4d35bb30977235921e2082c0d08eff490b4952398d90ca7431db57d1efb871e31fbb32fc5707 +M = b5266aa6 + +ModInv = 39472c61 +A = -1143293e595737da8c74718889b6085223e3213810f7fcf8109c323621dae8461a51b324c85d02f3ca39f275b2ee37fcf828f9401466653b549554c0550819ad854a18d8134b15a42f73c41d3c53550dff793d0ca83192756ef4cd626b9c3ddaa7567cc54a9d802ba4968dd8baada6d46b6e134feff1a8727133b8813a39ff44bd2a2721debfd529d31437dd1505d2bba6c417d4d29ab09a71a3917eb0c599302a7579b9dc08b99cf2873759f6a3684e156f31cee61064ece2dce320810a842d3208f25c253c41cc2a3c53a2808c687ecc88be89846f376bc21ed4da5f4c4d501181d7ec3eab9e8c69a0a35949675cc5fb0716a8ef209ea975887d09df +M = 4283d2c0 + +ModInv = 5a49ef +A = 53bdc34797c42393446abe564059b9ae5c8f1fca7da27744001a6aa45fe0a0f09780597538cbc54be01c0ef8e010faaced226972f683de11ee00366dadc088177abd25fbab1ba70b967adf354788d4dd79d3b5834f4cecb736d877f1caf0ba49c19fc0a9c8beb070e38434d57084ddfa7fa4ffe9ec11c63d5f77bb3a6a06131db61884f42b4b548a84a5b43d43188b3890644f3d4e7b37d72e4af69787709d9b532aba4e6c3686ff0de26a7698065aab0a377f90ade7bc38d756d0055979a2da95a83ec33dd6887e840043e58844c2354e2bb7740a63c1d8fac168fb90d7b938451ee325faa633406bc44dc2a627940eee3cba6f875c2e84496e7857dd87 +M = 63eb18 + +ModInv = 873e78 +A = -22d8c8d223191db66fda084a766f9b1639263e52de231f39cf9a354b1e0232b6e0758bcf5ec21c5c57cb987dec8407d75befe9847142850d30f05abe986775d5ce18ebd90c0265c90f87a381d5dfc823f411f0b7cd55c93c3fbdfb31a36d3a59c162b54e8daa06d0cb0c3078ff5ac509706031bb3fcbe6853c81c7648e7e111b3025829dbeed8dc378970722756e9cc801420c9a57566951a33f196ee3496022e729fb649d4d3628587ec46bc1291e6248070b1913dc19025fcd669f99ff61f8416310d7543a3b64d0a991d86fb8602ac25bf929aa915f0aea68001d5229877f77b22c5c6316f266f24a7a44668ed66887a3a5561782152bf8818ec8d8bc +M = 8d7f51 + +ModInv = 49c141 +A = -89be8eb5140f16f4488157241955b91dddd91389b372a341738c837a7935bef7e268ffe976ab60581ccace1d62e05b4c8012ede7bd0cffb88309fadb890859001ac9406329bc65b00a2d35d148805071950eadec6f117d836e77af67d461e4163207d094499602f0ee99731c94521919e93ad11745ad498893101c593af514aa4e719d3c7dec00a61f933d6c51e370eb9a0a96263ae6c5e818fac0433cbd7dabe929c4a334bfc6cd75e9bb049a79d7a7a3cc8c3d5f169293de8fc88b28756bad6be28e7aa6e99f19950499dd251de512148239292d22e255accb1a466884f3f49249dc28ff90a5aec7978306d03bf38b2ffc80a4df5a51c9bc701e7ea419 +M = 4ac87f + +ModInv = 3689 +A = 22d6f1b2f7e3c5d8b01228758794ff56f3dc1e5ab454991f034d3ce913db63cb9981d335f267e2a19011bf47d0ad488b2e14dc23b8deff9b9d66bf15ec8d6a34613cb3b2a1a79ed1838657a709128695c4baabacf529a3bdf7385745384a466b83c8dabe1eee42c5333576c64921f33dca31bdc9675ed64cd61cb8c77e5c8aa594fd462d6aa8c126da84cff205f73375f6ca79345b8e88b8d0ad50bc69875ec91bce530a6d003d5b671c33a7531f14a805c38d96690531904413fe28cc3fc0a9b6f671fde19ded2d2805203a4f78c5768f3b6fc9d1e6af1eee64497631e346ecccd9c2a80c1e43e90459d0c91756ccab85e77994ed711708addeefd3e824c1 +M = 5592 + +ModInv = 418d +A = -64e9e3e3e7f088411d99e18eb67daec5648c5009ac23485fcb437d2e575b0d18c6da92f384e903c38ed33b1c27d3e45141002ef698e7cd1fc52784276ec104009d67445ce5f27d6507fc13606cae0ef66f7cbe7e0c1022bd9716e0ee84551638a12ea10f616e9bad9bcc1da330bef6ba8ac9811bc40132d020df8b5078b90bfbd11640e21db1f17247acdfe772dcfd3f498c55fd7366507adc0d7c20077e29963683a01fb0ff9a8b9ffb3c8e150f3862a421673c86e2bd63cab27cc9b648c9b7536d79ced02692f834dc965d6ff265bd69a95d69c3fb39e7adfb65301a30ceb7ec27398f70b9829135558764684dc01a3f15f3f3f8476c21f05718691a351d +M = 5cef + +ModInv = 1519 +A = da097c9f54174682ad7b2995dc92d048bb61a937059dd8d2edc1b903a7c25b0d595dcd237d7d5afac93911c30708d929a8c55a4b7d31b971265f9a2f538869451301b6079a6983e1f1a8187118a3d5b93ec71d01b93595603794cb5bf204c5f16b0d87ed1aeaff89c15cc77b11bdaca41e8f9603993e59eabc836032e84a9105279060ccb7370adedbaeb0de19c956d52aacddd845a986ac05fc357e1664b52a3ccd6c09db640a38f3c028cedb52df430cadb3320b9bb8f6d847a359d19634c24996cf023054c29c7e5ebe31418ca9060312b74f83553be40b3bd61e57a01b8e1fc50e0cb6cf4193cdc4a3ce725eed8450ee0a5c1d08695d8789a113c268e5 +M = 1817 + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = fffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffff + +ModInv = fffe +A = -1 +M = ffff + +ModInv = fffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = aaaa5554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 5555aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = aaaa5554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 5555aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = fffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = fffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = aaaa5554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 5555aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = aaaa5554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 5555aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = fffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = fffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = aaaa5554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 5555aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = aaaa5554 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = 5555aaab +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffff + +ModInv = fffffffe +A = -1 +M = ffffffff + +ModInv = fffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = fffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = fffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = fffffffffffe +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = fffffffffffe +A = -1 +M = ffffffffffff + +ModInv = fffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 8888444422221110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 7777bbbbddddeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = eeeeddddbbbb7776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 1111222244448889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = aaaaaaaa55555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 55555555aaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = aaaaaaaa55555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 55555555aaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = eeeeddddbbbb7776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 1111222244448889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 8888444422221110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 7777bbbbddddeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = fffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = fffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 8888444422221110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 7777bbbbddddeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = eeeeddddbbbb7776 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = 1111222244448889 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffff + +ModInv = fffffffffffffffe +A = -1 +M = ffffffffffffffff + +ModInv = d6b56b5ab5ad5ad6ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 294a94a54a52a5295295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = f7bddef77bdeef7bbdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 8422108842110844211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = f7bddef77bdeef7bbdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 8422108842110844211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = d6b56b5ab5ad5ad6ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 294a94a54a52a5295295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = d6b56b5ab5ad5ad6ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 294a94a54a52a5295295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = f7bddef77bdeef7bbdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 8422108842110844211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = f7bddef77bdeef7bbdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 8422108842110844211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = d6b56b5ab5ad5ad6ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 294a94a54a52a5295295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = d6b56b5ab5ad5ad6ad6a +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = 294a94a54a52a5295295 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = fffffffffffffffffffe +A = -1 +M = ffffffffffffffffffff + +ModInv = aaaaaaaaaaaa555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = 555555555555aaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaa555555555554 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = 555555555555aaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffff + +ModInv = 8102020404080810102020404080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 7efdfdfbfbf7f7efefdfdfbfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fdfbefdf7efdf7efbf7efbf7dfbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 204102081020810408104082041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = a952952a52a52a54a54a54a94a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 56ad6ad5ad5ad5ab5ab5ab56b56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fdfbefdf7efdf7efbf7efbf7dfbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 204102081020810408104082041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 8102020404080810102020404080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 7efdfdfbfbf7f7efefdfdfbfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 8102020404080810102020404080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 7efdfdfbfbf7f7efefdfdfbfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fdfbefdf7efdf7efbf7efbf7dfbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 204102081020810408104082041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = a952952a52a52a54a54a54a94a94 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = 56ad6ad5ad5ad5ab5ab5ab56b56b +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 80804040202010100808040402020100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 7f7fbfbfdfdfefeff7f7fbfbfdfdfeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = a4a49494929252524a4a494929292524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 5b5b6b6b6d6dadadb5b5b6b6d6d6dadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeeddddddddbbbbbbbb77777776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 11111111222222224444444488888889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 88888888444444442222222211111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 77777777bbbbbbbbddddddddeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = fefefdfdfbfbf7f7efefdfdfbfbf7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 1010202040408081010202040408081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = dadad6d6b6b6b5b5adad6d6d6b6b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 2525292949494a4a525292929494a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaa5555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 5555555555555555aaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaa5555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 5555555555555555aaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = dadad6d6b6b6b5b5adad6d6d6b6b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 2525292949494a4a525292929494a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = fefefdfdfbfbf7f7efefdfdfbfbf7f7e +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = 1010202040408081010202040408081 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffff + +ModInv = f7bdef7bbdef7bdeef7bdef77bdef7bddef7bdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 842108442108421108421088421084221084211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfdff7fbfeff7fbfeff7fdfeff7fdfeffbfdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 40200804010080401008020100802010040201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a525294a529294a529494a5294a4a5294a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = f7bdef7bbdef7bdeef7bdef77bdef7bddef7bdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 842108442108421108421088421084221084211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 9224491224891244892244912248912448922448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfdff7fbfeff7fbfeff7fdfeff7fdfeffbfdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 40200804010080401008020100802010040201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a525294a529294a529494a5294a4a5294a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 9224491224891244892244912248912448922448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 9224491224891244892244912248912448922448 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb7 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa954aa554aa554aa552aa552aa552a9552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab556ab55aab55aab55aad55aad55aad56aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4949252494925249492524a492924a492924a492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6dadb6b6dadb6b6dadb5b6d6db5b6d6db5b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80100100100200200200200400400400400800800800 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84104208210410820841042082104108208410420820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7befbdf7defbef7df7befbdf7defbef7df7befbdf7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeddbbb76eeddbbb76eeddbb776edddbb776edddbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 11224448911224448911224488912224488912224489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84104208210410820841042082104108208410420820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7befbdf7defbef7df7befbdf7defbef7df7befbdf7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80100100100200200200200400400400400800800800 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4949252494925249492524a492924a492924a492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6dadb6b6dadb6b6dadb5b6d6db5b6d6db5b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa954aa554aa554aa552aa552aa552a9552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab556ab55aab55aab55aad55aad55aad56aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeeeeeeddddddddddddbbbbbbbbbbbb777777777776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 111111111111222222222222444444444444888888888889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaa555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888888888888444444444444222222222222111111111110 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777777777777bbbbbbbbbbbbddddddddddddeeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888844442222111108888444422221111088884444222211111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9244912449224892249124491248922489244912449224892248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6dbb6edbb6ddb76ddb6edbb6edb76ddb76dbb6edbb6ddb76ddb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6b6b5adad6b6b5adad6b6b5ad6d6b5b5ad6d6b5b5ad6d6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2529494a52529494a52529494a529294a4a529294a4a529294a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884422211088444221108884422111088442221108844422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbdddeef77bbbddeef777bbddeeef77bbdddeef77bbbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fff7ff7ff7ff7ffbffbffbffbffdffdffdffdffeffeffeffeffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8008008008004004004004002002002002001001001001001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fdf7dfbefbf7df7efbefbf7df7efbefdf7df7efbefdf7dfbefbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 208204104082081041040820810410208208104102082041041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fff7ff7ff7ff7ffbffbffbffbffdffdffdffdffeffeffeffeffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8008008008004004004004002002002002001001001001001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884422211088444221108884422111088442221108844422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbdddeef77bbbddeef777bbddeeef77bbdddeef77bbbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6b6b5adad6b6b5adad6b6b5ad6d6b5b5ad6d6b5b5ad6d6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2529494a52529494a52529494a529294a4a529294a4a529294a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5ab56ad56ad5ab55ab56ad56ad5ab56ab56ad5aad5ab56ab56ad5aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a54a952a952a54aa54a952a952a54a954a952a552a54a954a952a55 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaa5555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffbffdffefff7ffbffefff7ffbffdffefff7ffdffefff7ffbffdffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 40020010008004001000800400200100080020010008004002001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb76edbb76eddb76eddbb6eddbb76ddbb76edbb76eddb76eddbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12244891244891224891224491224489224489124489122489122449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952a54a54a952a52a54a952952a54a94a952a54a54a952a52a54a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad5ab5ab56ad5ad5ab56ad6ad5ab56b56ad5ab5ab56ad5ad5ab56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaa5555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80020004000800100020004000800100020004000800100020004000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5ab56ad56ad5ab55ab56ad56ad5ab56ab56ad5aad5ab56ab56ad5aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a54a952a952a54aa54a952a952a54a954a952a552a54a954a952a55 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffbffdffefff7ffbffefff7ffbffdffefff7ffdffefff7ffbffdffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 40020010008004001000800400200100080020010008004002001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88421108422108442108442108842110842210842210844210884210 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bdeef7bddef7bbdef7bbdef77bdeef7bddef7bddef7bbdef77bdef +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6b5ad6b5ad6ad6b5ad6b5ad5ad6b5ad6b5ab5ad6b5ad6b56b5ad6b5ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 294a5294a5295294a5294a52a5294a5294a54a5294a5294a94a5294a5295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 842108421084108421084210421084210842084210842108210842108420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdef7bdef7bef7bdef7bdefbdef7bdef7bdf7bdef7bdef7def7bdef7bdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 842108421084108421084210421084210842084210842108210842108420 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdef7bdef7bef7bdef7bdefbdef7bdef7bdf7bdef7bdef7def7bdef7bdf +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000400020001000080004000200010000800040002000100008000400020000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8420841082104210420841082108210420841084108210420842084108210420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdf7bef7defbdefbdf7bef7def7defbdf7bef7bef7defbdf7bdf7bef7defbdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4a4a49494949492929292525252524a4a4a4a494949492929292925252524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b5b5b6b6b6b6b6d6d6d6dadadadadb5b5b5b5b6b6b6b6d6d6d6d6dadadadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dadadadad6d6d6d6b6b6b6b6b5b5b5b5adadadad6d6d6d6d6b6b6b6b5b5b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2525252529292929494949494a4a4a4a525252529292929294949494a4a4a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1000200040008001000200040008001000200040008001000200040008001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9248924492249124892449244922491248924492249224912489244922491248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db76dbb6ddb6edb76dbb6dbb6ddb6edb76dbb6ddb6ddb6edb76dbb6ddb6edb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeeeeeeeeeeddddddddddddddddbbbbbbbbbbbbbbbb7777777777777776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1111111111111111222222222222222244444444444444448888888888888889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8888888888888888444444444444444422222222222222221111111111111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7777777777777777bbbbbbbbbbbbbbbbddddddddddddddddeeeeeeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdef7def7bef7bdefbdef7def7bdf7bdefbdef7bef7bdf7bdef7def7bef7bde +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 421082108410842104210821084208421042108410842084210821084108421 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa54a954a952a552a54a954a952a552a54aa54a952a952a54aa54a952a952a54 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55ab56ab56ad5aad5ab56ab56ad5aad5ab55ab56ad56ad5ab55ab56ad56ad5ab +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6b56b56b56b56b56b5ab5ab5ab5ab5ab5ad5ad5ad5ad5ad5ad6ad6ad6ad6ad6ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 294a94a94a94a94a94a54a54a54a54a54a52a52a52a52a52a5295295295295295295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84104108208208410410420820841041042082082104104208208210410410820820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7befbef7df7df7befbefbdf7df7befbefbdf7df7defbefbdf7df7defbefbef7df7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f77777bbbbbddddddeeeeef777777bbbbbdddddeeeeeef77777bbbbbbdddddeeeeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8888844444222222111110888888444442222211111108888844444422222111111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbef7defbdf7befbdf7bef7defbef7defbdf7bef7df7bef7defbdf7defbdf7bef7de +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 4108210420841042084108210410821042084108208410821042082104208410821 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddb76ddb76edbb6edbb6eddb76ddb76ddbb6edbb6edbb76ddb76ddb76edbb6edbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12248922489124491244912248922489224491244912448922489224891244912449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ff7f7f7f7fbfbfbfbfdfdfdfdfefefefeff7f7f7f7fbfbfbfbfdfdfdfdfefefefefe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 808080804040404020202020101010100808080804040404020202020101010101 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6d6db5b6d6db5b6d6db5b6d6db5b6d6db6b6dadb6b6dadb6b6dadb6b6dadb6b6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2492924a492924a492924a492924a492924949252494925249492524949252494925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92244892244891244891224891224491224489224489124489122489122449122448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb76ddbb76edbb76eddb76eddbb6eddbb76ddbb76edbb76eddb76eddbb6eddbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5555aaaab55556aaaad55556aaaad5555aaaab55556aaaab55556aaaad5555aaaaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaaa55554aaaa955552aaaa955552aaaa55554aaaa955554aaaa955552aaaa55555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92244892244891244891224891224491224489224489124489122489122449122448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb76ddbb76edbb76eddb76eddbb6eddbb76ddbb76edbb76eddb76eddbb6eddbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6d6db5b6d6db5b6d6db5b6d6db5b6d6db6b6dadb6b6dadb6b6dadb6b6dadb6b6da +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2492924a492924a492924a492924a492924949252494925249492524949252494925 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8842108842108442108422108422108421108421088421084421084421084221084211084210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bdef77bdef7bbdef7bddef7bddef7bdeef7bdef77bdef7bbdef7bbdef7bddef7bdeef7bdef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4949292524a4a4949292524a494949292524a494929292524a494929252524a4949292524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b6b6d6dadb5b5b6b6d6dadb5b6b6b6d6dadb5b6b6d6d6dadb5b6b6d6dadadb5b6b6d6dadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeddddbbbb7776eeeddddbbbb7776eeeddddbbbb7776eeeddddbbbb7776eeeddddbbbb7776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1111222244448889111222244448889111222244448889111222244448889111222244448889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8040100401004020080200802010040100401008020080200804010040100402008020080200 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fbfeffbfeffbfdff7fdff7fdfeffbfeffbfeff7fdff7fdff7fbfeffbfeffbfdff7fdff7fdff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfdfeff7fdfeff7fbfdff7fbfdfeff7fdfeff7fbfeff7fbfdfeffbfdfeff7fbfeff7fbfdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 40201008020100804020080402010080201008040100804020100402010080401008040201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952952952952952952a52a52a52a52a52a52a54a54a54a54a54a54a54a94a94a94a94a94a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad6ad6ad6ad6ad6ad5ad5ad5ad5ad5ad5ad5ab5ab5ab5ab5ab5ab5ab56b56b56b56b56b56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6ad5ab56b56ad5ab5ab56ad5ad5ab56ad6ad5ab56b56ad5ab5ab56ad5ad5ab56ad6ad5ab56a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2952a54a94a952a54a54a952a52a54a952952a54a94a952a54a54a952a52a54a952952a54a95 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffbfffeffffbfffeffffbfffeffffbfffeffff7fffdffff7fffdffff7fffdffff7fffdfffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 400010000400010000400010000400010000800020000800020000800020000800020001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffbfffeffffbfffeffffbfffeffffbfffeffff7fffdffff7fffdffff7fffdffff7fffdfffe +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 400010000400010000400010000400010000800020000800020000800020000800020001 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a5294a5294a4a5294a5294a529494a5294a5294a529294a5294a5294a525294a5294a5294a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5ad6b5ad6b5b5ad6b5ad6b5ad6b6b5ad6b5ad6b5ad6d6b5ad6b5ad6b5adad6b5ad6b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa552aa552a954aa554aa552a954aa954aa552a9552a954aa552aa552a954aa554aa552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab55aad55aad56ab55aab55aad56ab556ab55aad56aad56ab55aad55aad56ab55aab55aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edbb6edb76ddb76dbb6edbb6ddb76ddb6edbb6edb76ddb76dbb6edbb6ddb76ddb6edbb6edb76ddb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12449124892248924491244922489224912449124892248924491244922489224912449124892249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfeffbfdff7fdfeffbfeff7fdff7fdfeffbfeff7fdff7fbfeffbfeff7fdff7fbfeffbfdff7fdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 401004020080201004010080200802010040100802008040100401008020080401004020080201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 82040810208102040820408102081020408204081020410204081040810204102040810408102040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7dfbf7efdf7efdfbf7dfbf7efdf7efdfbf7dfbf7efdfbefdfbf7efbf7efdfbefdfbf7efbf7efdfbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa552aa552a954aa554aa552a954aa954aa552a9552a954aa552aa552a954aa554aa552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab55aad55aad56ab55aab55aad56ab556ab55aad56aad56ab55aad55aad56ab55aab55aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84210842108421082108421084210842084210842108421042108421084210841084210842108420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdef7bdef7bdef7def7bdef7bdef7bdf7bdef7bdef7bdefbdef7bdef7bdef7bef7bdef7bdef7bdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 82040810208102040820408102081020408204081020410204081040810204102040810408102040 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7dfbf7efdf7efdfbf7dfbf7efdf7efdfbf7dfbf7efdfbefdfbf7efbf7efdfbefdfbf7efbf7efdfbf +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 912244891224448912244891122448912244489122448912224489122448891224489122244891224488 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eddbb76eddbbb76eddbb76eeddbb76eddbbb76eddbb76edddbb76eddbb776eddbb76edddbb76eddbb77 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb76eddbb6eddbb76eddb76eddbb76eddb76eddbb76edbb76eddbb76edbb76eddbb76ddbb76eddbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 122448912244912244891224891224489122489122448912448912244891244891224489224489122449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 810204081020204081020408081020408102020408102040408102040810102040810204040810204080 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7efdfbf7efdfdfbf7efdfbf7f7efdfbf7efdfdfbf7efdfbfbf7efdfbf7efefdfbf7efdfbfbf7efdfbf7f +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884422110884442211088442221108844221110884422110888442211088444221108844222110884422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbddeef77bbbddeef77bbdddeef77bbddeeef77bbddeef777bbddeef77bbbddeef77bbdddeef77bbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb6db76db6db76db6db76db6dbb6db6dbb6db6dbb6db6ddb6db6ddb6db6ddb6db6edb6db6edb6db6edb6db6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1249248924924892492489249244924924492492449249224924922492492249249124924912492491249249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d55aab555aab556aab556aad556aad556aad55aaad55aab555aab556aab556aab556aad556aad55aaad55aaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aa554aaa554aa9554aa9552aa9552aa9552aa5552aa554aaa554aa9554aa9554aa9552aa9552aa5552aa555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8010020020040080080100200200400800801002002004004008010010020040040080100100200400400800 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffdffdffbff7ff7feffdffdffbff7ff7feffdffdffbffbff7feffeffdffbffbff7feffeffdffbffbff7ff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefdfbf7efefdfbf7efefdfbf7efdfdfbf7efdfdfbf7efdfbfbf7efdfbfbf7efdfbf7f7efdfbf7f7efdfbf7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 102040810102040810102040810202040810202040810204040810204040810204080810204080810204081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 294a94a54a52a5295294a94a54a52a5295294a94a54a52a5295294a94a54a52a5295294a94a54a52a5295295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d55aab555aab556aab556aad556aad556aad55aaad55aab555aab556aab556aab556aad556aad55aaad55aaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aa554aaa554aa9554aa9552aa9552aa9552aa5552aa554aaa554aa9554aa9554aa9552aa9552aa5552aa555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8410821041082104108210420821042082104208210420841042084104208410420841082084108208410820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bef7defbef7defbef7defbdf7defbdf7defbdf7defbdf7befbdf7befbdf7befbdf7bef7df7bef7df7bef7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884422110884442211088442221108844221110884422110888442211088444221108844222110884422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbddeef77bbbddeef77bbdddeef77bbddeeef77bbddeef777bbddeef77bbbddeef77bbdddeef77bbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa54a952a552a54a952a552a54a952a952a54a952a952a54a954a952a54a954a952a54aa54a952a54aa54a952a54 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55ab56ad5aad5ab56ad5aad5ab56ad56ad5ab56ad56ad5ab56ab56ad5ab56ab56ad5ab55ab56ad5ab55ab56ad5ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6dadb6dadb6dadb6dadb6d6db6d6db6d6db6d6db6d6db6b6db6b6db6b6db6b6db6b6db5b6db5b6db5b6db5b6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249252492524925249252492924929249292492924929249492494924949249492494924a4924a4924a4924a4925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeedddddbbbbb77776eeeedddddbbbb77776eeeedddddbbbbb77776eeeeddddbbbbb77776eeeedddddbbbbb7776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 11112222244444888891111222224444888891111222224444488889111122224444488889111122222444448889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88442110844211084421108442110844211084421108442210884221088422108842210884221088422108842210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbddef77bddef77bddef77bddef77bddef77bddef77bddef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edbb6ddb6edb76dbb6ddb6edb76dbb6edb76dbb6ddb6edb76dbb6ddb6edb76ddb6edb76dbb6ddb6edb76dbb6ddb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12449224912489244922491248924491248924492249124892449224912489224912489244922491248924492249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 81010101010202020202020404040404040808080808081010101010102020202020204040404040408080808080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7efefefefefdfdfdfdfdfdfbfbfbfbfbfbf7f7f7f7f7f7efefefefefefdfdfdfdfdfdfbfbfbfbfbfbf7f7f7f7f7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80000080000040000040000020000020000010000010000008000008000004000004000002000002000001000000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffff7fffffbfffffbfffffdfffffdfffffefffffeffffff7fffff7fffffbfffffbfffffdfffffdfffffeffffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d555556aaaaaad555556aaaaaad555555aaaaaad555555aaaaaab555555aaaaaab5555556aaaaab5555556aaaaaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaaaa95555552aaaaa95555552aaaaaa5555552aaaaaa5555554aaaaaa5555554aaaaaa9555554aaaaaa9555555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffbffffefffff7ffffdfffff7ffffbffffefffffbffffdfffff7ffffdffffefffffbffffefffff7ffffdffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 400001000008000020000080000400001000004000020000080000200001000004000010000080000200001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaa555552aaaa955552aaaa955554aaaaa55554aaaaa555552aaaa555552aaaa955554aaaa955554aaaaa55554 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55555aaaaad55556aaaad55556aaaab55555aaaab55555aaaaad5555aaaaad55556aaaab55556aaaab55555aaaab +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4a4a4a4a49494949494949292929292925252525252524a4a4a4a4a4a494949494949292929292929252525252524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b5b5b5b5b6b6b6b6b6b6b6d6d6d6d6d6dadadadadadadb5b5b5b5b5b5b6b6b6b6b6b6d6d6d6d6d6d6dadadadadadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeeeeeeeeeeeeeeeeeeddddddddddddddddddddddddbbbbbbbbbbbbbbbbbbbbbbbb777777777777777777777776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 111111111111111111111111222222222222222222222222444444444444444444444444888888888888888888888889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa555555555555555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555555555555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dadadadadadad6d6d6d6d6d6b6b6b6b6b6b6b5b5b5b5b5b5adadadadadad6d6d6d6d6d6d6b6b6b6b6b6b5b5b5b5b5b5a +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2525252525252929292929294949494949494a4a4a4a4a4a525252525252929292929292949494949494a4a4a4a4a4a5 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeddbb76edddbb76eddbb776eddbb76edddbb76eddbb776eddbb76eeddbb76eddbbb76eddbb76eeddbb76eddbbb76eddbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1122448912224489122448891224489122244891224488912244891122448912244489122448911224489122444891224489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a49492524949252494925249492524949252494925249492524a492924a492924a492924a492924a492924a492924a492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6dadb6b6dadb6b6dadb6b6dadb6b6dadb6b6dadb6b6dadb5b6d6db5b6d6db5b6d6db5b6d6db5b6d6db5b6d6db5b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8208104102082041040820810410208204102082041040820810410208204104082041040820810410208204104082081040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7df7efbefdf7dfbefbf7df7efbefdf7dfbefdf7dfbefbf7df7efbefdf7dfbefbf7dfbefbf7df7efbefdf7dfbefbf7df7efbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249224924892492249244924912492449248924922492489249124924492491249224924892492249244924912492449248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6ddb6db76db6ddb6dbb6db6edb6dbb6db76db6ddb6db76db6edb6dbb6db6edb6ddb6db76db6ddb6dbb6db6edb6dbb6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8080404020201010080804040202010100808040402020101008080404020201010080804040202010100808040402020100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5aad56ab55aad5aad56ab55aad56ad56ab55aad56ad56ab55aad56ab56ab55aad56ab56ab55aad56ab55ab55aad56ab55aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a552a954aa552a552a954aa552a952a954aa552a952a954aa552a954a954aa552a954a954aa552a954aa54aa552a954aa55 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffefffffefffffdfffffdfffffbfffffbfffff7fffff7ffffefffffefffffdfffffdfffffbfffffbfffff7fffff7ffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 10000010000020000020000040000040000080000080000100000100000200000200000400000400000800000800001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fff7ff7ff7ff7ff7ff7ff7ff7ffbffbffbffbffbffbffbffbffdffdffdffdffdffdffdffdffeffeffeffeffeffeffeffeffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8008008008008008008008004004004004004004004004002002002002002002002002001001001001001001001001001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d555555aaaaaaad5555556aaaaaab5555556aaaaaab5555555aaaaaaad5555556aaaaaad5555556aaaaaab5555555aaaaaaa +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaaaaa55555552aaaaaa95555554aaaaaa95555554aaaaaaa55555552aaaaaa95555552aaaaaa95555554aaaaaaa5555555 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a525292929494a4a4a525292929494a4a4a525292929494a4a4a52525292949494a4a52525292949494a4a52525292949494a4a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5adad6d6d6b6b5b5b5adad6d6d6b6b5b5b5adad6d6d6b6b5b5b5adadad6d6b6b6b5b5adadad6d6b6b6b5b5adadad6d6b6b6b5b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db5b6db6b6db6b6db6d6db6dadb6dadb6db5b6db6b6db6b6db6d6db6d6db6dadb6db5b6db5b6db6b6db6d6db6d6db6dadb6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 24924a49249492494924929249252492524924a49249492494924929249292492524924a4924a492494924929249292492524925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92449224892449224892449224892449124892449124892449124892249124892249124892249124492249124492249124492248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6dbb6ddb76dbb6ddb76dbb6ddb76dbb6edb76dbb6edb76dbb6edb76ddb6edb76ddb6edb76ddb6edbb6ddb6edbb6ddb6edbb6ddb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6d6b6b5adad6d6b5b5adad6b6b5b5ad6d6b6b5adad6d6b5b5adad6b6b5b5ad6d6b6b5adad6d6b5b5adad6b6b5b5ad6d6b6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 252929494a52529294a4a52529494a4a52929494a52529294a4a52529494a4a52929494a52529294a4a52529494a4a52929494a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffff7fffff7fffffbfffffbfffffdfffffdfffffefffffeffffff7fffff7fffffbfffffbfffffdfffffdfffffefffffefffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80000080000040000040000020000020000010000010000008000008000004000004000002000002000001000001000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952952a52a54a54a94a952952a52a54a54a54a94a952952a52a54a54a94a952952a52a52a54a54a94a952952a52a54a54a94a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad6ad5ad5ab5ab56b56ad6ad5ad5ab5ab5ab56b56ad6ad5ad5ab5ab56b56ad6ad5ad5ad5ab5ab56b56ad6ad5ad5ab5ab56b56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaa5552aa5552aa9552aa9552aa9554aa9554aaa554aaa554aaa5552aa5552aa5552aa9552aa9554aa9554aa9554aaa554aaa554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555aaad55aaad556aad556aad556aab556aab555aab555aab555aaad55aaad55aaad556aad556aab556aab556aab555aab555aab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6d6b6b5adad6d6b5b5adad6b6b5b5ad6d6b6b5adad6d6b5b5adad6b6b5b5ad6d6b6b5adad6d6b5b5adad6b6b5b5ad6d6b6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 252929494a52529294a4a52529494a4a52929494a52529294a4a52529494a4a52929494a52529294a4a52529494a4a52929494a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdef7bdefbdef7bdefbdef7bdef7def7bdef7def7bdef7def7bdef7bef7bdef7bef7bdef7bef7bdef7bdf7bdef7bdf7bdef7bde +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 4210842104210842104210842108210842108210842108210842108410842108410842108410842108420842108420842108421 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6db6db6db6db6db6db6db6db6db6db6b6db6db6db6db6db6db6db6db6db6db6db6d6db6db6db6db6db6db6db6db6db6db6db6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249249249249249249249249249249249249492492492492492492492492492492492492924924924924924924924924924924924925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6db6db6db6db6db6db6db6db6db6db6b6db6db6db6db6db6db6db6db6db6db6db6d6db6db6db6db6db6db6db6db6db6db6db6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249249249249249249249249249249249249492492492492492492492492492492492492924924924924924924924924924924924925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6db6db6db6db6db6db6db6db6db6db6b6db6db6db6db6db6db6db6db6db6db6db6d6db6db6db6db6db6db6db6db6db6db6db6da +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249249249249249249249249249249249249492492492492492492492492492492492492924924924924924924924924924924924925 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9122448912244891122448912244891222448912244891222448912244891224448912244891224448912244891224488912244891224488 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eddbb76eddbb76eeddbb76eddbb76edddbb76eddbb76edddbb76eddbb76eddbbb76eddbb76eddbbb76eddbb76eddbb776eddbb76eddbb77 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeeeeeeeeeeeeeeeeeeeeeeddddddddddddddddddddddddddddbbbbbbbbbbbbbbbbbbbbbbbbbbbb7777777777777777777777777776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1111111111111111111111111111222222222222222222222222222244444444444444444444444444448888888888888888888888888889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffffdffffff7fffffeffffffbfffffeffffffdffffff7fffffdffffffbfffffeffffffbffffff7fffffdffffff7fffffeffffffbfffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2000000800000100000040000010000002000000800000200000040000010000004000000800000200000080000010000004000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8842210844211084221088421108442108842210844211084221088421108442108842210844211084221088421108442108842210844210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bddef7bbdeef7bddef77bdeef7bbdef77bddef7bbdeef7bddef77bdeef7bbdef77bddef7bbdeef7bddef77bdeef7bbdef77bddef7bbdef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8888888888888888888888888888444444444444444444444444444422222222222222222222222222221111111111111111111111111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7777777777777777777777777777bbbbbbbbbbbbbbbbbbbbbbbbbbbbddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000000400000010000000400000010000000400000010000000400000020000000800000020000000800000020000000800000020000000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffffffbffffffefffffffbffffffefffffffbffffffefffffffbffffffdfffffff7ffffffdfffffff7ffffffdfffffff7ffffffdfffffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9122448912244891122448912244891222448912244891222448912244891224448912244891224448912244891224488912244891224488 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eddbb76eddbb76eeddbb76eddbb76edddbb76eddbb76edddbb76eddbb76eddbbb76eddbb76eddbbb76eddbb76eddbb776eddbb76eddbb77 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaa9554aaa5552aa9554aaa5552aa9554aaa5554aaa5552aa9554aaa5552aa9554aaa5552aaa5552aa9554aaa5552aa9554aaa5552aa9554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5556aab555aaad556aab555aaad556aab555aaab555aaad556aab555aaad556aab555aaad555aaad556aab555aaad556aab555aaad556aab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8040100802010040200804010080201004020080201004020080401008020100402008040100402008040100802010040200804010080200 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fbfeff7fdfeffbfdff7fbfeff7fdfeffbfdff7fdfeffbfdff7fbfeff7fdfeffbfdff7fbfeffbfdff7fbfeff7fdfeffbfdff7fbfeff7fdff +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 91222444889112224448891222444889112224448891122444889112224448891122244889112224448891122244489112224448891122244488 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6edddbbb776eedddbbb776edddbbb776eedddbbb776eeddbbb776eedddbbb776eedddbb776eedddbbb776eedddbbb76eedddbbb776eedddbbb77 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80401004010040100402008020080200802008040100401004010040100802008020080200802010040100401004010040200802008020080200 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fbfeffbfeffbfeffbfdff7fdff7fdff7fdff7fbfeffbfeffbfeffbfeff7fdff7fdff7fdff7fdfeffbfeffbfeffbfeffbfdff7fdff7fdff7fdff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84104104104208208208208410410410410820820820821041041041042082082082084104104104108208208208210410410410420820820820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7befbefbefbdf7df7df7df7befbefbefbef7df7df7df7defbefbefbefbdf7df7df7df7befbefbefbef7df7df7df7defbefbefbefbdf7df7df7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa552a954aa554aa552a954aa552aa552a954aa552a9552a954aa552a954aa954aa552a954aa554aa552a954aa552aa552a954aa552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab55aad56ab55aab55aad56ab55aad55aad56ab55aad56aad56ab55aad56ab556ab55aad56ab55aab55aad56ab55aad55aad56ab55aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbb776edddbb776edddbb776edddbb776edddbb776edddbb776edddbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 11224448911224448911224448911224448911224448911224448911224488912224488912224488912224488912224488912224488912224489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d56aad56aad56aad56aad56aad56aad55aad55aad55aad55aad55aad55aab55aab55aab55aab55aab55aab556ab556ab556ab556ab556ab556aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a9552a9552a9552a9552a9552a9552aa552aa552aa552aa552aa552aa554aa554aa554aa554aa554aa554aa954aa954aa954aa954aa954aa955 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a94a54a52a5295294a94a54a52a5295294a94a54a52a5295294a94a54a52a5295294a94a54a52a5295294a94a54a52a5295294a94a54a52a5294 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfdff7fbfeff7fdfeffbfdff7fbfeff7fdfeff7fdfeffbfdff7fbfeff7fdfeffbfdff7fbfeff7fbfeff7fdfeffbfdff7fbfeff7fdfeffbfdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 402008040100802010040200804010080201008020100402008040100802010040200804010080401008020100402008040100802010040201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4924924949249249292492492524924924a49249249292492492524924924a49249249492492492524924924a49249249492492492924924924 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6db6b6db6db6d6db6db6dadb6db6db5b6db6db6d6db6db6dadb6db6db5b6db6db6b6db6db6dadb6db6db5b6db6db6b6db6db6d6db6db6db +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 922489224892244912449124489224892248912449124491224892248922449124491244892248922489124491244912248922489224491244912448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddb76ddb76ddbb6edbb6edbb76ddb76ddb76edbb6edbb6eddb76ddb76ddbb6edbb6edbb76ddb76ddb76edbb6edbb6eddb76ddb76ddbb6edbb6edbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6b5ad6b5ad6b5ad6b5ad6b56b5ad6b5ad6b5ad6b5ad6b5ab5ad6b5ad6b5ad6b5ad6b5ad5ad6b5ad6b5ad6b5ad6b5ad6ad6b5ad6b5ad6b5ad6b5ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 294a5294a5294a5294a5294a94a5294a5294a5294a5294a54a5294a5294a5294a5294a52a5294a5294a5294a5294a5295294a5294a5294a5294a5295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 802008020080100401004010020080200802004010040100200802008020040100401004008020080200401004010040080200802008010040100400 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fdff7fdff7feffbfeffbfeffdff7fdff7fdffbfeffbfeffdff7fdff7fdffbfeffbfeffbff7fdff7fdffbfeffbfeffbff7fdff7fdff7feffbfeffbff +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffefffdfffbfff7ffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1000200040008001000200040008001000200040008001000200040008001000200040008001000200040008001000200040008001000200040008001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb6eddbb6eddb76eddb76eddb76edbb76edbb76edbb76ddbb76ddbb76ddbb6eddbb6eddbb6eddb76eddb76eddb76edbb76edbb76edbb76ddbb76ddbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1224491224491224891224891224891244891244891244892244892244892244912244912244912248912248912248912448912448912448922448922449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa954aa954aa954aa954aa954aa554aa554aa554aa554aa554aa554aa552aa552aa552aa552aa552aa552aa552a9552a9552a9552a9552a9552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab556ab556ab556ab556ab556ab55aab55aab55aab55aab55aab55aab55aad55aad55aad55aad55aad55aad55aad56aad56aad56aad56aad56aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249248924924492492449249224924912492491249248924924492492449249224924922492491249248924924892492449249224924922492491249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db76db6dbb6db6dbb6db6ddb6db6edb6db6edb6db76db6dbb6db6dbb6db6ddb6db6ddb6db6edb6db76db6db76db6dbb6db6ddb6db6ddb6db6edb6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb6db6db76db6db6dbb6db6db6dbb6db6db6ddb6db6db6edb6db6db6edb6db6db76db6db6db76db6db6dbb6db6db6ddb6db6db6ddb6db6db6edb6db6db6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1249249248924924924492492492449249249224924924912492492491249249248924924924892492492449249249224924924922492492491249249249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f77bbbddeeef77bbbddeeef777bbdddeef777bbdddeeef77bbbddeeef77bbbdddeef777bbdddeef777bbbddeeef77bbbddeeef777bbdddeef777bbdddeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 884442211108844422111088844222110888442221110884442211108844422211088844222110888444221110884442211108884422211088844222111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fdf7df7df7df7efbefbefbefbf7df7df7df7dfbefbefbefbefdf7df7df7df7efbefbefbefbf7df7df7df7dfbefbefbefbefdf7df7df7df7efbefbefbefbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 208208208208104104104104082082082082041041041041020820820820810410410410408208208208204104104104102082082082081041041041041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaa5555554aaaaaa95555554aaaaaa95555552aaaaaa55555552aaaaaa5555554aaaaaaa5555554aaaaaa95555552aaaaaa95555552aaaaaa5555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555555aaaaaab5555556aaaaaab5555556aaaaaad555555aaaaaaad555555aaaaaab5555555aaaaaab5555556aaaaaad5555556aaaaaad555555aaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884422110884422111088442211088442221108844221108844222110884422110884442211088442211088444221108844221108884422110884422110 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbddeef77bbddeeef77bbddeef77bbdddeef77bbddeef77bbdddeef77bbddeef77bbbddeef77bbddeef77bbbddeef77bbddeef777bbddeef77bbddeef +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5556aaab5555aaaad5556aaab5555aaaad5556aaab5555aaaad5556aaab5555aaaad5556aaab5555aaaad5556aaab5555aaaad5556aaab5555aaaad5556aaaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaa95554aaaa55552aaa95554aaaa55552aaa95554aaaa55552aaa95554aaaa55552aaa95554aaaa55552aaa95554aaaa55552aaa95554aaaa55552aaa95555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6b5ad5ad6b56b5ad6ad6b5ab5ad6b56b5ad5ad6b5ab5ad6ad6b5ad5ad6b56b5ad6ad6b5ab5ad6b56b5ad5ad6b5ab5ad6ad6b5ad5ad6b56b5ad6ad6b5ab5ad6a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 294a52a5294a94a5295294a54a5294a94a52a5294a54a5295294a52a5294a94a5295294a54a5294a94a52a5294a54a5295294a52a5294a94a5295294a54a5295 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84208420841084108210821042104210420842084108410821082108210421042084208410841084108210821042104208420842084108410821082104210420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdf7bdf7bef7bef7def7defbdefbdefbdf7bdf7bef7bef7def7def7defbdefbdf7bdf7bef7bef7bef7def7defbdefbdf7bdf7bdf7bef7bef7def7defbdefbdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92489248924492449224922491249124892489244924492449224922491249124892489244924492249224922491249124892489244924492249224912491248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db76db76dbb6dbb6ddb6ddb6edb6edb76db76dbb6dbb6dbb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6edb6edb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffdfffffff7ffffffdfffffff7ffffffdfffffff7ffffffdfffffff7ffffffefffffffbffffffefffffffbffffffefffffffbffffffefffffffbffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2000000080000002000000080000002000000080000002000000080000001000000040000001000000040000001000000040000001000000040000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 82081040820410208104082041020810408204102082041020810408204102081040820410208104082041040820410208104082041020810408204102081040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7df7efbf7dfbefdf7efbf7dfbefdf7efbf7dfbefdf7dfbefdf7efbf7dfbefdf7efbf7dfbefdf7efbf7dfbefbf7dfbefdf7efbf7dfbefdf7efbf7dfbefdf7efbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefefefefefefefefdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbf7f7f7f7f7f7f7f7efefefefefefefefdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbf7f7f7f7f7f7f7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1010101010101010202020202020202040404040404040408080808080808081010101010101010202020202020202040404040404040408080808080808081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80808080808080804040404040404040202020202020202010101010101010100808080808080808040404040404040402020202020202020101010101010100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfefefefefefefefeff7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfefefefefefefeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffdff7feffbff7fdffbfeffdff7fdffbfeffdff7feffbff7fdff7feffbff7fdffbfeffdff7feffbfeffdff7feffbff7fdffbfeffbff7fdffbfeffdff7feffbfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 200801004008020040100200802004010020080100400802008010040080200401002008010040100200801004008020040100400802004010020080100401 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88442110884221108442110884221108442210884221108442210884221108442210884421108442210884421108442210884421108842210884421108842210 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bbdeef77bddeef7bbdeef77bddeef7bbddef77bddeef7bbddef77bddeef7bbddef77bbdeef7bbddef77bbdeef7bbddef77bbdeef77bddef77bbdeef77bddef +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdf7bef7def7defbdf7bef7bef7defbdf7bdf7bef7defbdefbdf7bef7def7defbdf7bef7bef7defbdf7bdf7bef7defbdefbdf7bef7def7defbdf7bef7bef7defbde +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 42084108210821042084108410821042084208410821042104208410821082104208410841082104208420841082104210420841082108210420841084108210421 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eedddbbb776edddbbb776eeddbbb776eedddbb776eedddbb776eedddbbb76eedddbbb776edddbbb776eeddbbb776eeddbbb776eedddbb776eedddbbb76eedddbbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 112224448891222444889112244488911222448891122244889112224448911222444889122244488911224448891122444889112224488911222444891122244489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4949292524a49292524a49492524a49492924a4949292524949292524a49292524a49492524a49492924a4949292524949292524a49292524a49492524a49492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9224491224491224491224891224891224891244891244891244892244892244892244912244912244912248912248912248912448912448912448922448922448922448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb6eddbb6eddbb6eddb76eddb76eddb76edbb76edbb76edbb76ddbb76ddbb76ddbb6eddbb6eddbb6eddb76eddb76eddb76edbb76edbb76edbb76ddbb76ddbb76ddbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8010010020020040040040080080100100200200200400400800801001001002002004004008008008010010020020040040040080080100100200200200400400800800 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffeffdffdffbffbffbff7ff7feffeffdffdffdffbffbff7ff7feffeffeffdffdffbffbff7ff7ff7feffeffdffdffbffbffbff7ff7feffeffdffdffdffbffbff7ff7ff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a5252529292949494a4a4a525252529292949494a4a4a525252929292949494a4a4a525252929294949494a4a4a5252529292949494a4a4a4a5252529292949494a4a4a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5adadad6d6d6b6b6b5b5b5adadadad6d6d6b6b6b5b5b5adadad6d6d6d6b6b6b5b5b5adadad6d6d6b6b6b6b5b5b5adadad6d6d6b6b6b5b5b5b5adadad6d6d6b6b6b5b5b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a94a54a5295294a94a52a5294a94a54a5295294a54a52a5294a94a54a5295294a54a52a5294a94a52a5295294a54a52a5294a94a52a5295294a54a5295294a94a52a5294 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56b5ab5ad6ad6b56b5ad5ad6b56b5ab5ad6ad6b5ab5ad5ad6b56b5ab5ad6ad6b5ab5ad5ad6b56b5ad5ad6ad6b5ab5ad5ad6b56b5ad5ad6ad6b5ab5ad6ad6b56b5ad5ad6b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a492524925249292492924949249492494924a4924a492524925249252492924929249492494924a4924a4924a492524925249292492924929249492494924a4924a4924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6dadb6dadb6d6db6d6db6b6db6b6db6b6db5b6db5b6dadb6dadb6dadb6d6db6d6db6b6db6b6db5b6db5b6db5b6dadb6dadb6d6db6d6db6d6db6b6db6b6db5b6db5b6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa552a552a952a952a954a954aa54aa54aa552a552a952a952a954a954aa54aa54aa552a552a552a952a954a954a954aa54aa552a552a552a952a954a954a954aa54aa54 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55aad5aad56ad56ad56ab56ab55ab55ab55aad5aad56ad56ad56ab56ab55ab55ab55aad5aad5aad56ad56ab56ab56ab55ab55aad5aad5aad56ad56ab56ab56ab55ab55ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249249124924912492491249249124924922492492249249224924922492492249249244924924492492449249244924924492492489249248924924892492489249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db6edb6db6edb6db6edb6db6edb6db6ddb6db6ddb6db6ddb6db6ddb6db6ddb6db6dbb6db6dbb6db6dbb6db6dbb6db6dbb6db6db76db6db76db6db76db6db76db6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a49292494925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7777bbbbbddddeeeeef77777bbbbdddddeeeef77777bbbbbddddeeeeef7777bbbbbdddddeeeef77777bbbbdddddeeeeef7777bbbbbddddeeeeef77777bbbbdddddeeeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888844444222211111088888444422222111108888844444222211111088884444422222111108888844442222211111088884444422221111108888844442222211111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8204081020408104081020408102041020408102040810408102040810204102040810204082040810204081020810204081020408204081020408102081020408102040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7dfbf7efdfbf7efbf7efdfbf7efdfbefdfbf7efdfbf7efbf7efdfbf7efdfbefdfbf7efdfbf7dfbf7efdfbf7efdf7efdfbf7efdfbf7dfbf7efdfbf7efdf7efdfbf7efdfbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249249124924912492491249249124924922492492249249224924922492492249249244924924492492449249244924924492492489249248924924892492489249248 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db6edb6db6edb6db6edb6db6edb6db6ddb6db6ddb6db6ddb6db6ddb6db6ddb6db6dbb6db6dbb6db6dbb6db6dbb6db6dbb6db6db76db6db76db6db76db6db76db6db7 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88844222110888442221108844422111088444221110884422211088844222110888442211108844422111088444221108884422211088844222110884442211108844422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbdddeef777bbdddeef77bbbddeeef77bbbddeeef77bbdddeef777bbdddeef777bbddeeef77bbbddeeef77bbbddeef777bbdddeef777bbdddeef77bbbddeeef77bbbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a5294a5294a5294a5294a525294a5294a5294a5294a5294a529294a5294a5294a5294a5294a529494a5294a5294a5294a5294a5294a4a5294a5294a5294a5294a5294a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5ad6b5ad6b5ad6b5ad6b5adad6b5ad6b5ad6b5ad6b5ad6b5ad6d6b5ad6b5ad6b5ad6b5ad6b5ad6b6b5ad6b5ad6b5ad6b5ad6b5ad6b5b5ad6b5ad6b5ad6b5ad6b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb6ddb6dbb6db76db6edb6ddb6dbb6db76db6edb6ddb6db76db6edb6ddb6dbb6db76db6edb6ddb6dbb6db76db6edb6dbb6db76db6edb6ddb6dbb6db76db6edb6ddb6dbb6db6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12492249244924892491249224924492489249124922492489249124922492449248924912492249244924892491249244924892491249224924492489249124922492449249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4a49494949292925252524a4a49494949292925252524a4a49494949292925252524a4a4a494949292929252524a4a4a494949292929252524a4a4a494949292929252524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b5b6b6b6b6d6d6dadadadb5b5b6b6b6b6d6d6dadadadb5b5b6b6b6b6d6d6dadadadb5b5b5b6b6b6d6d6d6dadadb5b5b5b6b6b6d6d6d6dadadb5b5b5b6b6b6d6d6d6dadadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7bdef7bdef7bdef7bdef7bdef7bbdef7bdef7bdef7bdef7bdef7bdeef7bdef7bdef7bdef7bdef7bdef77bdef7bdef7bdef7bdef7bdef7bddef7bdef7bdef7bdef7bdef7bdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8421084210842108421084210844210842108421084210842108421108421084210842108421084210884210842108421084210842108422108421084210842108421084211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbefbef7df7defbefbef7df7defbefbef7df7defbefbdf7df7defbefbdf7df7defbefbdf7df7befbefbdf7df7befbefbdf7df7befbef7df7df7befbef7df7df7befbef7df7de +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 4104108208210410410820821041041082082104104208208210410420820821041042082084104104208208410410420820841041082082084104108208208410410820821 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a5294a5294a5294a5294a525294a5294a5294a5294a5294a529294a5294a5294a5294a5294a529494a5294a5294a5294a5294a5294a4a5294a5294a5294a5294a5294a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5ad6b5ad6b5ad6b5ad6b5adad6b5ad6b5ad6b5ad6b5ad6b5ad6d6b5ad6b5ad6b5ad6b5ad6b5ad6b6b5ad6b5ad6b5ad6b5ad6b5ad6b5b5ad6b5ad6b5ad6b5ad6b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4a49494949292925252524a4a49494949292925252524a4a49494949292925252524a4a4a494949292929252524a4a4a494949292929252524a4a4a494949292929252524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b5b6b6b6b6d6d6dadadadb5b5b6b6b6b6d6d6dadadadb5b5b6b6b6b6d6d6dadadadb5b5b5b6b6b6d6d6d6dadadb5b5b5b6b6b6d6d6d6dadadb5b5b5b6b6b6d6d6d6dadadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80100100100100100100100100100100100200200200200200200200200200200200200400400400400400400400400400400400400800800800800800800800800800800800 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffeffeffeffeffeffeffeffeffeffeffdffdffdffdffdffdffdffdffdffdffdffdffbffbffbffbffbffbffbffbffbffbffbffbff7ff7ff7ff7ff7ff7ff7ff7ff7ff7ff7ff +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888888888888888888888888888888888888444444444444444444444444444444444444222222222222222222222222222222222222111111111111111111111111111111111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777777777777777777777777777777777777bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbddddddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa555555555555555555555555555555555555555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555555555555555555555555555555555555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeddddddddddddddddddddddddddddddddddddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb777777777777777777777777777777777776 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 111111111111111111111111111111111111222222222222222222222222222222222222444444444444444444444444444444444444888888888888888888888888888888888889 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a94a5294a5294a94a5294a5294a94a5294a5294a54a5294a5294a54a5294a5294a54a5294a5294a52a5294a5294a52a5294a5294a52a5294a5294a5295294a5294a5295294a5294a5294 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56b5ad6b5ad6b56b5ad6b5ad6b56b5ad6b5ad6b5ab5ad6b5ad6b5ab5ad6b5ad6b5ab5ad6b5ad6b5ad5ad6b5ad6b5ad5ad6b5ad6b5ad5ad6b5ad6b5ad6ad6b5ad6b5ad6ad6b5ad6b5ad6b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fdf7df7df7df7dfbefbefbefbefbefdf7df7df7df7df7efbefbefbefbefdf7df7df7df7df7efbefbefbefbefbf7df7df7df7df7efbefbefbefbefbf7df7df7df7df7dfbefbefbefbefbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 208208208208204104104104104102082082082082081041041041041020820820820820810410410410410408208208208208104104104104104082082082082082041041041041041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffffffdffffffffbffffffff7fffffffeffffffffdffffffff7fffffffeffffffffdffffffffbffffffff7fffffffeffffffffbffffffff7fffffffeffffffffdffffffffbfffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 20000000040000000080000000100000000200000000800000001000000002000000004000000008000000010000000040000000080000000100000000200000000400000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7bbddef77bbdeef77bddeef77bddeef7bbddef77bbddef77bbdeef77bddeef77bddeef7bbddef77bbdeef77bbdeef77bddeef7bbddeef7bbddef77bbdeef77bbdeef77bddeef7bbddee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 844221088442110884221108842211084422108844221088442110884221108842211084422108844211088442110884221108442211084422108844211088442110884221108442211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dadadad6d6d6b6b6b6b5b5b5adadadad6d6d6b6b6b6b5b5b5adadadad6d6d6b6b6b6b5b5b5adadad6d6d6d6b6b6b5b5b5b5adadad6d6d6d6b6b6b5b5b5b5adadad6d6d6d6b6b6b5b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2525252929294949494a4a4a52525252929294949494a4a4a52525252929294949494a4a4a525252929292949494a4a4a4a525252929292949494a4a4a4a525252929292949494a4a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000100002000040000800010000200004000080001000020000200004000080001000020000400008000100002000040000400008000100002000040000800010000200004000080000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffdffffdffffbffff7fffeffffdffffbffff7fffeffffdffffbffffbffff7fffeffffdffffbffff7fffeffffdffffbffff7ffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefdfbfbf7efefdfbfbf7efefdfbf7f7efdfdfbf7f7efdfdfbf7efefdfbfbf7efefdfbfbf7efdfdfbf7f7efdfdfbf7f7efdfbfbf7efefdfbfbf7efefdfbf7f7efdfdfbf7f7efdfdfbf7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 102040408101020404081010204080810202040808102020408101020404081010204040810202040808102020408081020404081010204040810102040808102020408081020204081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6db5b6dadb6d6db6b6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494924a4925249292494925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fff7ff7ff7ff7ff7ff7ff7ff7ff7ff7ff7ff7ffbffbffbffbffbffbffbffbffbffbffbffbffdffdffdffdffdffdffdffdffdffdffdffdffeffeffeffeffeffeffeffeffeffeffeffeffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8008008008008008008008008008008008004004004004004004004004004004004004002002002002002002002002002002002002001001001001001001001001001001001001001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8844211084421108442110844211084421108442110844211084421108442110844211084422108842210884221088422108842210884221088422108842210884221088422108842210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbdeef7bbddef77bddef77bddef77bddef77bddef77bddef77bddef77bddef77bddef77bddef77bddef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4924a4924a4924a4924a4924a4924a4924a4924949249492494924949249492494924949249292492924929249292492924929249292492524925249252492524925249252492524924 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db5b6db5b6db5b6db5b6db5b6db5b6db5b6db6b6db6b6db6b6db6b6db6b6db6b6db6b6db6d6db6d6db6d6db6d6db6d6db6d6db6d6db6dadb6dadb6dadb6dadb6dadb6dadb6dadb6db +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80401008020080401004020080201004010080200804010040200804010040200802010040100802008040100402008020100402008020100401008020080401004020080201004010080200 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fbfeff7fdff7fbfeffbfdff7fdfeffbfeff7fdff7fbfeffbfdff7fbfeffbfdff7fdfeffbfeff7fdff7fbfeffbfdff7fdfeffbfdff7fdfeffbfeff7fdff7fbfeffbfdff7fdfeffbfeff7fdff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84208410821042084108210420841084108210420841082104208410821042104208410821042084108210420842084108210420841082104208410821082104208410821042084108210420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdf7bef7defbdf7bef7defbdf7bef7bef7defbdf7bef7defbdf7bef7defbdefbdf7bef7defbdf7bef7defbdf7bdf7bef7defbdf7bef7defbdf7bef7def7defbdf7bef7defbdf7bef7defbdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a49494929252524a49494929252524a49494929252524a49494929252524a49494929252524a4a494929292524a4a494929292524a4a494929292524a4a494929292524a4a494929292524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b6b6b6d6dadadb5b6b6b6d6dadadb5b6b6b6d6dadadb5b6b6b6d6dadadb5b6b6b6d6dadadb5b5b6b6d6d6dadb5b5b6b6d6d6dadb5b5b6b6d6d6dadb5b5b6b6d6d6dadb5b5b6b6d6d6dadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80001000010000200002000020000400004000080000800008000100001000020000200002000040000400004000080000800010000100001000020000200004000040000400008000080000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffeffffeffffdffffdffffdffffbffffbffff7ffff7ffff7fffeffffeffffdffffdffffdffffbffffbffffbffff7ffff7fffeffffeffffeffffdffffdffffbffffbffffbffff7ffff7ffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa552a954aa552a9552a954aa552a954aa552aa552a954aa552a954aa552aa552a954aa552a954aa554aa552a954aa552a954aa554aa552a954aa552a954aa954aa552a954aa552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab55aad56ab55aad56aad56ab55aad56ab55aad55aad56ab55aad56ab55aad55aad56ab55aad56ab55aab55aad56ab55aad56ab55aab55aad56ab55aad56ab556ab55aad56ab55aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb76ddbb76ddbb76edbb76edbb76edbb76eddb76eddb76eddb76eddbb6eddbb6eddbb6eddbb76ddbb76ddbb76ddbb76edbb76edbb76edbb76eddb76eddb76eddb76eddbb6eddbb6eddbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12244892244892244891244891244891244891224891224891224891224491224491224491224489224489224489224489124489124489124489122489122489122489122449122449122449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7bddef77bdeef7bbdef77bddef7bbdeef7bddef77bdeef7bbdef77bddef7bbdeef7bddef77bdeef7bbdef77bddef7bbdeef7bddef77bdeef7bbdef77bddef7bbdeef7bddef77bdeef7bbdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8422108842110844210884221084421108422108842110844210884221084421108422108842110844210884221084421108422108842110844210884221084421108422108842110844211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaa95554aaaa95554aaaa95554aaaa95554aaaa55554aaaa55554aaaa55554aaaa55554aaaa55552aaaa55552aaaa55552aaaa55552aaaa55552aaa955552aaa955552aaa955552aaa95554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55556aaab55556aaab55556aaab55556aaab5555aaaab5555aaaab5555aaaab5555aaaab5555aaaad5555aaaad5555aaaad5555aaaad5555aaaad5556aaaad5556aaaad5556aaaad5556aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa5555555555555555555555555555555555555555555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555555555555555555555555555555555555555555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffffffeffffffffeffffffffeffffffffeffffffffdffffffffdffffffffdffffffffdffffffffbffffffffbffffffffbffffffffbffffffff7ffffffff7ffffffff7ffffffff7fffffffe +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 100000000100000000100000000100000000200000000200000000200000000200000000400000000400000000400000000400000000800000000800000000800000000800000001 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f777bbbdddeeeef777bbbddddeeef777bbbddddeeef777bbbbdddeeef7777bbbdddeeef7777bbbdddeeeef777bbbdddeeeef777bbbddddeeef777bbbbdddeeef777bbbbdddeeef7777bbbdddeeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88844422211110888444222211108884442222111088844442221110888844422211108888444222111108884442221111088844422221110888444422211108884444222111088884442221111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 800400200100040020010008002001000800200100080040010008004002000800400200080040020010004002001000400200100080020010008004001000800400100080040020008004002000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffbffdffefffbffdffefff7ffdffefff7ffdffefff7ffbffefff7ffbffdfff7ffbffdfff7ffbffdffefffbffdffefffbffdffefff7ffdffefff7ffbffefff7ffbffefff7ffbffdfff7ffbffdfff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 924492249124492249124892249124892449124892449224892449224912449224912489224912489244912489244922489244922491244922491248922491248924491248924492248924492248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6dbb6ddb6edbb6ddb6edb76ddb6edb76dbb6edb76dbb6ddb76dbb6ddb6edbb6ddb6edb76ddb6edb76dbb6edb76dbb6ddb76dbb6ddb6edbb6ddb6edb76ddb6edb76dbb6edb76dbb6ddb76dbb6ddb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8421084210842108421084210842108410842108421084210842108421084210421084210842108421084210842108420842108421084210842108421084210821084210842108421084210842108420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdef7bdef7bdef7bdef7bdef7bdef7bef7bdef7bdef7bdef7bdef7bdef7bdefbdef7bdef7bdef7bdef7bdef7bdef7bdf7bdef7bdef7bdef7bdef7bdef7bdef7def7bdef7bdef7bdef7bdef7bdef7bdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884422110884422110884442211088442211088442211108844221108844221108844422110884422110884422211088442211088442211088844221108844221108844222110884422110884422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbddeef77bbddeef77bbbddeef77bbddeef77bbddeeef77bbddeef77bbddeef77bbbddeef77bbddeef77bbdddeef77bbddeef77bbddeef777bbddeef77bbddeef77bbdddeef77bbddeef77bbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4924a492494924929249292492524924a4924a492494924929249292492524924a4924a492494924929249252492524924a49249492494924929249252492524924a492494924949249292492524924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db5b6db6b6db6d6db6d6db6dadb6db5b6db5b6db6b6db6d6db6d6db6dadb6db5b6db5b6db6b6db6d6db6dadb6dadb6db5b6db6b6db6b6db6d6db6dadb6dadb6db5b6db6b6db6b6db6d6db6dadb6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa954aa554aa552aa552a9552a954aa954aa554aa552aa552aa552a9552a954aa954aa554aa552aa552a9552a954aa954aa554aa554aa552aa552a9552a954aa954aa554aa552aa552a9552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab556ab55aab55aad55aad56aad56ab556ab55aab55aad55aad55aad56aad56ab556ab55aab55aad55aad56aad56ab556ab55aab55aab55aad55aad56aad56ab556ab55aab55aad55aad56aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6ad5ab56ad5ab56ad6ad5ab56ad5ab56ad6ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab56b56ad5ab56ad5ab56b56ad5ab56ad5ab56a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2952a54a952a54a952952a54a952a54a952952a54a952a54a952a52a54a952a54a952a52a54a952a54a952a54a54a952a54a952a54a54a952a54a952a54a94a952a54a952a54a94a952a54a952a54a95 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eedddbb776eeddbbb76eedddbb776edddbbb76eeddbbb776edddbb776eeddbbb76eedddbb776edddbbb76eeddbbb776edddbb776eeddbbb76eedddbb776edddbbb76eeddbbb776edddbb776eeddbbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1122244889112244489112224488912224448911224448891222448891122444891122244889122244489112244488912224488911224448911222448891222444891122444889122244889112244489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8020080200802008010040100401004008020080200802004010040100401004008020080200802004010040100401002008020080200802004010040100401002008020080200801004010040100400 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fdff7fdff7fdff7feffbfeffbfeffbff7fdff7fdff7fdffbfeffbfeffbfeffbff7fdff7fdff7fdffbfeffbfeffbfeffdff7fdff7fdff7fdffbfeffbfeffbfeffdff7fdff7fdff7feffbfeffbfeffbff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249249224924924892492492249249248924924922492492489249249224924924892492492249249244924924912492492449249249124924924492492491249249244924924912492492449249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db6ddb6db6db76db6db6ddb6db6db76db6db6ddb6db6db76db6db6ddb6db6db76db6db6ddb6db6dbb6db6db6edb6db6dbb6db6db6edb6db6dbb6db6db6edb6db6dbb6db6db6edb6db6dbb6db6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6ad5ab56ad5ab56ad6ad5ab56ad5ab56ad6ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab56b56ad5ab56ad5ab56b56ad5ab56ad5ab56a +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2952a54a952a54a952952a54a952a54a952952a54a952a54a952a52a54a952a54a952a52a54a952a54a952a54a54a952a54a952a54a54a952a54a952a54a94a952a54a952a54a94a952a54a952a54a95 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88442210884421108844211088422110844221108442210884421108844211088422110844221108442210884422108844211088422110884221108442210884422108844211088422110884221108442210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bbddef77bbdeef77bbdeef77bddeef7bbddeef7bbddef77bbdeef77bbdeef77bddeef7bbddeef7bbddef77bbddef77bbdeef77bddeef77bddeef7bbddef77bbddef77bbdeef77bddeef77bddeef7bbddef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a94a94a54a54a52a5295295294a94a54a54a52a5295295294a94a54a54a52a5295295294a94a54a54a52a52a5295294a94a94a54a52a52a5295294a94a94a54a52a52a5295294a94a94a54a52a52a5295294 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56b56b5ab5ab5ad5ad6ad6ad6b56b5ab5ab5ad5ad6ad6ad6b56b5ab5ab5ad5ad6ad6ad6b56b5ab5ab5ad5ad5ad6ad6b56b56b5ab5ad5ad5ad6ad6b56b56b5ab5ad5ad5ad6ad6b56b56b5ab5ad5ad5ad6ad6b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a529294a4a529294a4a529294a4a529294a4a529294a4a529294a4a529294a4a529294a4a529294a4a52529494a52529494a52529494a52529494a52529494a52529494a52529494a52529494a52529494a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6d6b5b5ad6d6b5b5ad6d6b5b5ad6d6b5b5ad6d6b5b5ad6d6b5b5ad6d6b5b5ad6d6b5b5ad6d6b5b5adad6b6b5adad6b6b5adad6b6b5adad6b6b5adad6b6b5adad6b6b5adad6b6b5adad6b6b5adad6b6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d556aaad556aaad555aaad555aaab555aaab555aaab5556aab5556aaad556aaad556aaad555aaad555aaab555aaab5556aab5556aab5556aaad556aaad555aaad555aaad555aaab555aaab5556aab5556aaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aa95552aa95552aaa5552aaa5554aaa5554aaa5554aaa9554aaa95552aa95552aa95552aaa5552aaa5554aaa5554aaa9554aaa9554aaa95552aa95552aaa5552aaa5552aaa5554aaa5554aaa9554aaa9555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6db5b6db6db6b6db6db6d6db6db6dadb6db6db5b6db6db6b6db6db6b6db6db6d6db6db6dadb6db6db5b6db6db6b6db6db6d6db6db6d6db6db6dadb6db6db5b6db6db6b6db6db6d6db6db6dadb6db6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 24924924a4924924949249249292492492524924924a492492494924924949249249292492492524924924a492492494924924929249249292492492524924924a4924924949249249292492492524924925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80000400002000010000080000400002000008000040000200001000008000040000100000800004000020000100000800002000010000080000400002000010000040000200001000008000040000200000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffffbffffdffffefffff7ffffbffffdfffff7ffffbffffdffffefffff7ffffbffffefffff7ffffbffffdffffefffff7ffffdffffefffff7ffffbffffdffffefffffbffffdffffefffff7ffffbffffdfffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84210842084210841084210821084210421084208421084108421082108421042108420842108410842108210842104210842084210841084210821084210421084208421084108421082108421042108420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ff7f7f7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefeff7f7f7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 808080808080808080804040404040404040404020202020202020202020101010101010101010100808080808080808080804040404040404040404020202020202020202020101010101010101010101 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbefbefbdf7df7defbefbef7df7df7befbefbdf7df7defbefbef7df7df7defbefbef7df7df7befbefbdf7df7defbefbef7df7df7befbefbef7df7df7befbefbdf7df7defbefbef7df7df7befbefbdf7df7de +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 4104104208208210410410820820841041042082082104104108208208210410410820820841041042082082104104108208208410410410820820841041042082082104104108208208410410420820821 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a492492492492924924924924a492492492492924924924924a492492492492924924924924a4924924924925249249249249492492492492524924924924949249249249252492492492494924924924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6db6db6d6db6db6db6db5b6db6db6db6d6db6db6db6db5b6db6db6db6d6db6db6db6db5b6db6db6db6dadb6db6db6db6b6db6db6db6dadb6db6db6db6b6db6db6db6dadb6db6db6db6b6db6db6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5aad56ad56ab56ab55aad5aad56ad56ab56ab55aad5aad56ad56ab55ab55aad5aad56ad56ab55ab55aad5aad56ab56ab55ab55aad5aad56ab56ab55ab55aad56ad56ab56ab55ab55aad56ad56ab56ab55aa +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a552a952a954a954aa552a552a952a954a954aa552a552a952a954aa54aa552a552a952a954aa54aa552a552a954a954aa54aa552a552a954a954aa54aa552a952a954a954aa54aa552a952a954a954aa55 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa555555555555555555555555555555555555555555555555555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555555555555555555555555555555555555555555555555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 810204081020408102040810102040810204081020408102020408102040810204081020204081020408102040810204040810204081020408102040408102040810204081020408081020408102040810204080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7efdfbf7efdfbf7efdfbf7efefdfbf7efdfbf7efdfbf7efdfdfbf7efdfbf7efdfbf7efdfdfbf7efdfbf7efdfbf7efdfbfbf7efdfbf7efdfbf7efdfbfbf7efdfbf7efdfbf7efdfbf7f7efdfbf7efdfbf7efdfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fdfbf7efdfbf7efdfbf7efdf7efdfbf7efdfbf7efdfbf7efbf7efdfbf7efdfbf7efdfbf7dfbf7efdfbf7efdfbf7efdfbefdfbf7efdfbf7efdfbf7efdf7efdfbf7efdfbf7efdfbf7efbf7efdfbf7efdfbf7efdfbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 20408102040810204081020810204081020408102040810408102040810204081020408204081020408102040810204102040810204081020408102081020408102040810204081040810204081020408102041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 800200080020004001000400080020008002000400100040008002000800100040010004000800200080010004001000200080020008001000400100020008002000400100040010002000800200040010004000 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffdfff7ffdfffbffefffbfff7ffdfff7ffdfffbffefffbfff7ffdfff7ffefffbffefffbfff7ffdfff7ffefffbffefffdfff7ffdfff7ffefffbffefffdfff7ffdfffbffefffbffefffdfff7ffdfffbffefffbfff +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9122244889122244889122244889122244889122244889122244889122244889122244889122244889122244489112244489112244489112244489112244489112244489112244489112244489112244489112244488 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6edddbb776edddbb776edddbb776edddbb776edddbb776edddbb776edddbb776edddbb776edddbb776edddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb76eeddbbb77 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6ad6ad5ad5ab5ab5ab56b56ad6ad6ad5ad5ab5ab5ab56b56ad6ad6ad5ad5ab5ab5ab56b56ad6ad6ad5ad5ab5ab56b56b56ad6ad5ad5ad5ab5ab56b56b56ad6ad5ad5ad5ab5ab56b56b56ad6ad5ad5ad5ab5ab56b56a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2952952a52a54a54a54a94a952952952a52a54a54a54a94a952952952a52a54a54a54a94a952952952a52a54a54a94a94a952952a52a52a54a54a94a94a952952a52a52a54a54a94a94a952952a52a52a54a54a94a95 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9111111111111122222222222222244444444444444888888888888889111111111111122222222222222244444444444444488888888888889111111111111112222222222222244444444444444488888888888888 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eeeeeeeeeeeeedddddddddddddddbbbbbbbbbbbbbb777777777777776eeeeeeeeeeeeedddddddddddddddbbbbbbbbbbbbbbb77777777777776eeeeeeeeeeeeeeddddddddddddddbbbbbbbbbbbbbbb77777777777777 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8102040808102040408102020408101020408081020404081020204081020204081010204080810204040810202040810102040808102040408102040408102020408101020408081020404081020204081010204080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7efdfbf7f7efdfbfbf7efdfdfbf7efefdfbf7f7efdfbfbf7efdfdfbf7efdfdfbf7efefdfbf7f7efdfbfbf7efdfdfbf7efefdfbf7f7efdfbfbf7efdfbfbf7efdfdfbf7efefdfbf7f7efdfbfbf7efdfdfbf7efefdfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952952952952952952952952952952952952952952a52a52a52a52a52a52a52a52a52a52a52a52a52a52a54a54a54a54a54a54a54a54a54a54a54a54a54a54a54a94a94a94a94a94a94a94a94a94a94a94a94a94a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad6ad6ad6ad6ad6ad6ad6ad6ad6ad6ad6ad6ad6ad5ad5ad5ad5ad5ad5ad5ad5ad5ad5ad5ad5ad5ad5ad5ab5ab5ab5ab5ab5ab5ab5ab5ab5ab5ab5ab5ab5ab5ab56b56b56b56b56b56b56b56b56b56b56b56b56b56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4924949249292492524924a49249292492524924a49249492492524924a49249492492924924a4924949249292492524924949249292492524924a49249292492524924a49249492492524924a49249492492924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6b6db6d6db6dadb6db5b6db6d6db6dadb6db5b6db6b6db6dadb6db5b6db6b6db6d6db6db5b6db6b6db6d6db6dadb6db6b6db6d6db6dadb6db5b6db6d6db6dadb6db5b6db6b6db6dadb6db5b6db6b6db6d6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9244912449124491244912449124492248922489224892248922489224912449124491244912449124491248922489224892248922489224892449124491244912449124491244922489224892248922489224892248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6dbb6edbb6edbb6edbb6edbb6edbb6ddb76ddb76ddb76ddb76ddb76ddb6edbb6edbb6edbb6edbb6edbb6edb76ddb76ddb76ddb76ddb76ddb76dbb6edbb6edbb6edbb6edbb6edbb6ddb76ddb76ddb76ddb76ddb76ddb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeeeeeeedddddddddbbbbbbbbb777777776eeeeeeeedddddddddbbbbbbbb777777776eeeeeeeedddddddddbbbbbbbbb777777776eeeeeeeeddddddddbbbbbbbbb777777776eeeeeeeedddddddddbbbbbbbbb77777776 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1111111122222222244444444488888888911111111222222222444444448888888891111111122222222244444444488888888911111111222222224444444448888888891111111122222222244444444488888889 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeddbb776eddbbb76eddbbb76edddbb76eeddbb76eeddbb776eddbbb76eddbbb76edddbb76eeddbb76eeddbb776eddbb776eddbbb76edddbb76edddbb76eeddbb776eddbb776eddbbb76edddbb76edddbb76eeddbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1122448891224448912244489122244891122448911224488912244489122444891222448911224489112244889122448891224448912224489122244891122448891224488912244489122244891222448911224489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4a4a4949494929292925252524a4a4a4a4949494929292925252524a4a4a494949494929292925252524a4a4a494949492929292925252524a4a4a494949492929292525252524a4a4a4949494929292925252524 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b5b5b6b6b6b6d6d6d6dadadadb5b5b5b5b6b6b6b6d6d6d6dadadadb5b5b5b6b6b6b6b6d6d6d6dadadadb5b5b5b6b6b6b6d6d6d6d6dadadadb5b5b5b6b6b6b6d6d6d6dadadadadb5b5b5b6b6b6b6d6d6d6dadadadb +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80804020100804020100804020201008040201008040201008080402010080402010080402020100804020100804020100804040201008040201008040201010080402010080402010080404020100804020100804020100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7fbfdfeff7fbfdfeff7fbfdfdfeff7fbfdfeff7fbfdfeff7f7fbfdfeff7fbfdfeff7fbfdfdfeff7fbfdfeff7fbfdfeff7fbfbfdfeff7fbfdfeff7fbfdfefeff7fbfdfeff7fbfdfeff7fbfbfdfeff7fbfdfeff7fbfdfeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a492492492492524924924924929249249249249292492492492494924924924924a4924924924924a49249249249252492492492492524924924924929249249249249492492492492494924924924924a4924924924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6db6db6dadb6db6db6db6d6db6db6db6db6d6db6db6db6db6b6db6db6db6db5b6db6db6db6db5b6db6db6db6dadb6db6db6db6dadb6db6db6db6d6db6db6db6db6b6db6db6db6db6b6db6db6db6db5b6db6db6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f77bbbdddeef777bbbddeeef777bbdddeeef77bbbdddeef777bbbddeeef777bbbddeeef777bbdddeeef77bbbdddeef777bbbddeeef777bbdddeeef777bbdddeeef77bbbdddeef777bbbddeeef777bbdddeeef77bbbdddeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8844422211088844422111088844222111088444222110888444221110888444221110888442221110884442221108884442211108884422211108884422211108844422211088844422111088844222111088444222111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80000200000400000800002000004000008000020000040000080000100000400000800001000004000008000010000020000080000100000200000800001000002000004000010000020000040000100000200000400000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffffdfffffbfffff7ffffdfffffbfffff7ffffdfffffbfffff7ffffefffffbfffff7ffffefffffbfffff7ffffefffffdfffff7ffffefffffdfffff7ffffefffffdfffffbffffefffffdfffffbffffefffffdfffffbfffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa54a952a54a952a54aa54a952a54a952a54a954a952a54a952a54a952a952a54a952a54a952a552a54a952a54a952a54aa54a952a54a952a54a954a952a54a952a54a952a952a54a952a54a952a552a54a952a54a952a54 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55ab56ad5ab56ad5ab55ab56ad5ab56ad5ab56ab56ad5ab56ad5ab56ad56ad5ab56ad5ab56ad5aad5ab56ad5ab56ad5ab55ab56ad5ab56ad5ab56ab56ad5ab56ad5ab56ad56ad5ab56ad5ab56ad5aad5ab56ad5ab56ad5ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92244912248912448922449122489124489224491224891244892244912248912448922449122489124489224491224891244892244912248912448922449122489124489224491224891244892244912248912448922448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb6eddb76edbb76ddbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 91122244488911222244488911222444488911222444889111222444889112222444889112224448889112224448891112224448891122244448891122244488891122244488911222244488911222444488911222444888 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eedddbbb776eeddddbbb776eedddbbbb776eedddbbb776eeedddbbb776eeddddbbb776eedddbbb7776eedddbbb776eeedddbbb776eedddbbbb776eedddbbb7776eedddbbb776eeddddbbb776eedddbbbb776eedddbbb777 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80100200400801001002004008010020020040080100200400400801002004004008010020040080080100200400801001002004008010020020040080100200200400801002004004008010020040080080100200400800 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffdffbff7feffeffdffbff7feffdffdffbff7feffdffbffbff7feffdffbffbff7feffdffbff7ff7feffdffbff7feffeffdffbff7feffdffdffbff7feffdffdffbff7feffdffbffbff7feffdffbff7ff7feffdffbff7ff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80804020100804020100804020201008040201008040201008080402010080402010080402020100804020100804020100804040201008040201008040201010080402010080402010080404020100804020100804020100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7fbfdfeff7fbfdfeff7fbfdfdfeff7fbfdfeff7fbfdfeff7f7fbfdfeff7fbfdfeff7fbfdfdfeff7fbfdfeff7fbfdfeff7fbfbfdfeff7fbfdfeff7fbfdfefeff7fbfdfeff7fbfdfeff7fbfbfdfeff7fbfdfeff7fbfdfeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 842108421084210842108421084210842108210842108421084210842108421084210842084210842108421084210842108421084210421084210842108421084210842108421084108421084210842108421084210842108420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdef7bdef7bdef7bdef7bdef7bdef7bdef7def7bdef7bdef7bdef7bdef7bdef7bdef7bdf7bdef7bdef7bdef7bdef7bdef7bdef7bdefbdef7bdef7bdef7bdef7bdef7bdef7bdef7bef7bdef7bdef7bdef7bdef7bdef7bdef7bdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a5294a5294a5294a5294a5294a5294a4a5294a5294a5294a5294a5294a5294a529494a5294a5294a5294a5294a5294a5294a529294a5294a5294a5294a5294a5294a5294a525294a5294a5294a5294a5294a5294a5294a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6d6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5adad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a5294a5294a5294a5294a5294a5294a5294a4a5294a5294a5294a5294a5294a5294a529494a5294a5294a5294a5294a5294a5294a529294a5294a5294a5294a5294a5294a5294a525294a5294a5294a5294a5294a5294a5294a4 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6d6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5adad6b5ad6b5ad6b5ad6b5ad6b5ad6b5ad6b5b +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8844211084422108842211084421108842210884221108442110884221088442110844221088422108844211084422108842211084421108442210884221108442110884221088442110844211088422108844211084422108842210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bbdeef7bbddef77bddeef7bbdeef77bddef77bddeef7bbdeef77bddef77bbdeef7bbddef77bddef77bbdeef7bbddef77bddeef7bbdeef7bbddef77bddeef7bbdeef77bddef77bbdeef7bbdeef77bddef77bbdeef7bbddef77bddef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249249248924924924892492492449249249244924924922492492492249249249224924924912492492491249249248924924924892492492449249249244924924924492492492249249249224924924912492492491249249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db6db76db6db6db76db6db6dbb6db6db6dbb6db6db6ddb6db6db6ddb6db6db6ddb6db6db6edb6db6db6edb6db6db76db6db6db76db6db6dbb6db6db6dbb6db6db6dbb6db6db6ddb6db6db6ddb6db6db6edb6db6db6edb6db6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a4949492929252524a4a4949492929252524a4a4949492929252524a4a49492929252524a4a4949492929252524a4a4949492929252524a4a49494929252524a4a4949492929252524a4a4949492929252524a4a49494929292524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b6b6b6d6d6dadadb5b5b6b6b6d6d6dadadb5b5b6b6b6d6d6dadadb5b5b6b6d6d6dadadb5b5b6b6b6d6d6dadadb5b5b6b6b6d6d6dadadb5b5b6b6b6d6dadadb5b5b6b6b6d6d6dadadb5b5b6b6b6d6d6dadadb5b5b6b6b6d6d6dadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6b5b5ad6b5b5ad6b5b5ad6b5b5ad6b5b5ad6b5b5ad6b6b5ad6b6b5ad6b6b5ad6b6b5ad6b6b5ad6b6b5ad6b6b5ad6d6b5ad6d6b5ad6d6b5ad6d6b5ad6d6b5ad6d6b5ad6d6b5adad6b5adad6b5adad6b5adad6b5adad6b5adad6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 25294a4a5294a4a5294a4a5294a4a5294a4a5294a4a529494a529494a529494a529494a529494a529494a529494a529294a529294a529294a529294a529294a529294a529294a525294a525294a525294a525294a525294a525294a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a492494924925249249492492524924a492492924924a492492924924a4924949249252492494924925249249492492924924a492492924924a4924929249252492494924925249249492492524924a492492924924a492492924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6b6db6dadb6db6b6db6dadb6db5b6db6d6db6db5b6db6d6db6db5b6db6b6db6dadb6db6b6db6dadb6db6b6db6d6db6db5b6db6d6db6db5b6db6d6db6dadb6db6b6db6dadb6db6b6db6dadb6db5b6db6d6db6db5b6db6d6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8001000100020002000200040004000400080008000800100010001000200020002000400040004000800080008001000100010002000200020004000400040008000800080010001000100020002000200040004000400080008000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffefffefffdfffdfffdfffbfffbfffbfff7fff7fff7ffefffefffefffdfffdfffdfffbfffbfffbfff7fff7fff7ffefffefffefffdfffdfffdfffbfffbfffbfff7fff7fff7ffefffefffefffdfffdfffdfffbfffbfffbfff7fff7fff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000000000004000000000002000000000001000000000000800000000000400000000000200000000000100000000000080000000000040000000000020000000000010000000000008000000000004000000000002000000000000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffffffffffbfffffffffffdfffffffffffeffffffffffff7fffffffffffbfffffffffffdfffffffffffeffffffffffff7fffffffffffbfffffffffffdfffffffffffeffffffffffff7fffffffffffbfffffffffffdffffffffffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9111112222222444444488888891111112222224444444888888911111122222224444444888889111111222222244444448888889111112222222444444488888891111112222222444444888888911111122222224444444888888 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eeeeedddddddbbbbbbb7777776eeeeeeddddddbbbbbbb7777776eeeeeedddddddbbbbbbb777776eeeeeedddddddbbbbbbb7777776eeeeedddddddbbbbbbb7777776eeeeeedddddddbbbbbb7777776eeeeeedddddddbbbbbbb777777 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffffffffeffffffffffdffffffffffbffffffffffbffffffffff7fffffffffeffffffffffeffffffffffdffffffffffbffffffffff7ffffffffff7fffffffffeffffffffffdffffffffffdffffffffffbffffffffff7fffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 100000000002000000000040000000000400000000008000000000100000000001000000000020000000000400000000008000000000080000000001000000000020000000000200000000004000000000080000000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8888844444222221111108888844444222221111088888444442222211111088888444442222111110888884444422222111110888884444222221111108888844444222221111108888444442222211111088888444442222211110 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77777bbbbbdddddeeeeef77777bbbbbdddddeeeef77777bbbbbdddddeeeeef77777bbbbbddddeeeeef77777bbbbbdddddeeeeef77777bbbbdddddeeeeef77777bbbbbdddddeeeeef7777bbbbbdddddeeeeef77777bbbbbdddddeeeef +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 82040810408102081020408204081040810204102040820408102081020410204082040810208102041020408104081020810204082040810408102041020408204081040810204102040820408102081020410204081040810208102040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7dfbf7efbf7efdf7efdfbf7dfbf7efbf7efdfbefdfbf7dfbf7efdf7efdfbefdfbf7dfbf7efdf7efdfbefdfbf7efbf7efdf7efdfbf7dfbf7efbf7efdfbefdfbf7dfbf7efbf7efdfbefdfbf7dfbf7efdf7efdfbefdfbf7efbf7efdf7efdfbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dadad6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6b6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5adad6d6b6b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 25252929494a4a5252929494a4a5252929494a4a5252929494a4a525292949494a4a5252929494a4a5252929494a4a5252929494a4a5252929494a4a525292929494a4a5252929494a4a5252929494a4a5252929494a4a5252929494a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdef7bef7bdefbdef7bdf7bdef7def7bdf7bdef7bef7bdefbdef7bef7bdef7def7bdf7bdef7bef7bdefbdef7bef7bdef7def7bdf7bdef7def7bdefbdef7bef7bdef7def7bdf7bdef7def7bdefbdef7bef7bdefbdef7bdf7bdef7def7bde +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 4210841084210421084208421082108420842108410842104210841084210821084208421084108421042108410842108210842084210821084210421084108421082108420842108210842104210841084210421084208421082108421 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88422108442108842210844210884221084421088422108442108842110844210884211084421088421108442108842110842210884211084221088421108422108842110842210844211084221084421108422108442110842210844210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bddef7bbdef77bddef7bbdef77bddef7bbdef77bddef7bbdef77bdeef7bbdef77bdeef7bbdef77bdeef7bbdef77bdeef7bddef77bdeef7bddef77bdeef7bddef77bdeef7bddef7bbdeef7bddef7bbdeef7bddef7bbdeef7bddef7bbdef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a49492924a49492524a49292524a492925249492924a49492524a49492524a492925249492924a49492924a49492524a492925249492925249492924a49492524a49292524a492925249492924a49492524a49492524a492925249492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6d6db5b6b6dadb5b6d6dadb5b6d6dadb6b6d6db5b6b6dadb5b6b6dadb5b6d6dadb6b6d6db5b6b6d6db5b6b6dadb5b6d6dadb6b6d6dadb6b6d6db5b6b6dadb5b6d6dadb5b6d6dadb6b6d6db5b6b6dadb5b6b6dadb5b6d6dadb6b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefefefefdfdfdfdfbfbfbfbf7f7f7f7efefefefdfdfdfdfbfbfbfbf7f7f7f7efefefefdfdfdfdfbfbfbfbf7f7f7f7efefefefdfdfdfdfbfbfbfbf7f7f7f7efefefefdfdfdfdfbfbfbfbf7f7f7f7efefefefdfdfdfdfbfbfbfbf7f7f7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1010101020202020404040408080808101010102020202040404040808080810101010202020204040404080808081010101020202020404040408080808101010102020202040404040808080810101010202020204040404080808081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfdfeffbfdfeff7fdfeff7fdfeff7fbfeff7fbfeff7fbfdff7fbfdff7fbfdfeffbfdfeffbfdfeff7fdfeff7fdfeff7fbfeff7fbfeff7fbfdff7fbfdff7fbfdfeffbfdfeffbfdfeff7fdfeff7fdfeff7fbfeff7fbfeff7fbfdff7fbfdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 402010040201008020100802010080401008040100804020080402008040201004020100402010080201008020100804010080401008040200804020080402010040201004020100802010080201008040100804010080402008040201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffff7ffffffffff7ffffffffff7ffffffffff7ffffffffffbffffffffffbffffffffffbffffffffffbffffffffffdffffffffffdffffffffffdffffffffffdffffffffffeffffffffffeffffffffffeffffffffffeffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 800000000008000000000080000000000800000000004000000000040000000000400000000004000000000020000000000200000000002000000000020000000000100000000001000000000010000000000100000000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84210421082108410842084210421082108410841084208421042108210841084208421042104210821084108420842104210821084108420842084210421082108410842084210421082108210841084208421042108210841084208420 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bdefbdef7def7bef7bdf7bdefbdef7def7bef7bef7bdf7bdefbdef7def7bef7bdf7bdefbdefbdef7def7bef7bdf7bdefbdef7def7bef7bdf7bdf7bdefbdef7def7bef7bdf7bdefbdef7def7def7bef7bdf7bdefbdef7def7bef7bdf7bdf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6db5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 24949292524a4949292524a4949292524a49492524a4949292524a4949292524a4949292524949292524a4949292524a4949292524a49492924a4949292524a4949292524a4949292524a49292524a4949292524a4949292524a49492925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d6b5ad6b56b5ad6b5ab5ad6b5ad5ad6b5ad6ad6b5ad6ad6b5ad6b56b5ad6b5ab5ad6b5ad5ad6b5ad5ad6b5ad6ad6b5ad6b56b5ad6b5ab5ad6b5ab5ad6b5ad5ad6b5ad6ad6b5ad6b56b5ad6b56b5ad6b5ab5ad6b5ad5ad6b5ad6ad6b5ad6a +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 294a5294a94a5294a54a5294a52a5294a5295294a5295294a5294a94a5294a54a5294a52a5294a52a5294a5295294a5294a94a5294a54a5294a54a5294a52a5294a5295294a5294a94a5294a94a5294a54a5294a52a5294a5295294a5295 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb6edb6edb6ddb6ddb6ddb6dbb6dbb6dbb6db76db76db76db6edb6edb6edb6ddb6ddb6dbb6dbb6dbb6db76db76db76db6edb6edb6edb6ddb6ddb6ddb6dbb6dbb6db76db76db76db6edb6edb6edb6ddb6ddb6ddb6dbb6dbb6dbb6db76db76db6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 124912491249224922492249244924492449248924892489249124912491249224922492449244924492489248924892491249124912492249224922492449244924892489248924912491249124922492249224924492449244924892489249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefefefefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbfbfbfbfbf7f7f7f7f7f7f7f7f7f7f7f7efefefefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbfbfbfbfbf7f7f7f7f7f7f7f7f7f7f7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 10101010101010101010101020202020202020202020202040404040404040404040404080808080808080808080808101010101010101010101010202020202020202020202020404040404040404040404040808080808080808080808081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888888888888888888888888888888888888888888888888444444444444444444444444444444444444444444444444222222222222222222222222222222222222222222222222111111111111111111111111111111111111111111111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777777777777777777777777777777777777777777777777bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbddddddddddddddddddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdefbdefbdef7def7def7def7bef7bef7bef7bdf7bdf7bdefbdefbdefbdef7def7def7def7bef7bef7bdf7bdf7bdf7bdefbdefbdefbdef7def7def7bef7bef7bef7bdf7bdf7bdf7bdefbdefbdef7def7def7def7bef7bef7bef7bdf7bdf7bde +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 42104210421082108210821084108410841084208420842104210421042108210821082108410841084208420842084210421042104210821082108410841084108420842084208421042104210821082108210841084108410842084208421 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa954aa554aa552a9552a954aa954aa552aa552a9552a954aa554aa552aa552a954aa954aa552aa552a9552a954aa554aa552aa552a954aa954aa554aa552a9552a954aa554aa552aa552a954aa954aa554aa552a9552a954aa954aa552aa552a954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556ab55aab55aad56aad56ab556ab55aad55aad56aad56ab55aab55aad55aad56ab556ab55aad55aad56aad56ab55aab55aad55aad56ab556ab55aab55aad56aad56ab55aab55aad55aad56ab556ab55aab55aad56aad56ab556ab55aad55aad56ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb76eddbb76eddbb76eddbb76ddbb76eddbb76eddbb76eddbb76edbb76eddbb76eddbb76eddbb76edbb76eddbb76eddbb76eddbb76eddb76eddbb76eddbb76eddbb76eddb76eddbb76eddbb76eddbb76eddbb6eddbb76eddbb76eddbb76eddbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1224489122448912244891224489224489122448912244891224489124489122448912244891224489124489122448912244891224489122489122448912244891224489122489122448912244891224489122449122448912244891224489122449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d56aad56aad56aad56aad56aad56aad56aad56aad56aad56aad55aad55aad55aad55aad55aad55aad55aad55aad55aad55aab55aab55aab55aab55aab55aab55aab55aab55aab55aab556ab556ab556ab556ab556ab556ab556ab556ab556ab556aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a9552a9552a9552a9552a9552a9552a9552a9552a9552a9552aa552aa552aa552aa552aa552aa552aa552aa552aa552aa554aa554aa554aa554aa554aa554aa554aa554aa554aa554aa954aa954aa954aa954aa954aa954aa954aa954aa954aa955 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8842108421084210844210842108421084221084210842108421088421084210842108442108421084210842110842108421084210884210842108421084221084210842108421108421084210842108442108421084210842210842108421084210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bdef7bdef7bdef7bbdef7bdef7bdef7bddef7bdef7bdef7bdef77bdef7bdef7bdef7bbdef7bdef7bdef7bdeef7bdef7bdef7bdef77bdef7bdef7bdef7bddef7bdef7bdef7bdeef7bdef7bdef7bdef7bbdef7bdef7bdef7bddef7bdef7bdef7bdef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fdf7df7df7df7df7df7efbefbefbefbefbefbefdf7df7df7df7df7df7dfbefbefbefbefbefbefbf7df7df7df7df7df7df7efbefbefbefbefbefbefdf7df7df7df7df7df7dfbefbefbefbefbefbefbf7df7df7df7df7df7df7efbefbefbefbefbefbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 208208208208208208104104104104104104102082082082082082082041041041041041041040820820820820820820810410410410410410410208208208208208208204104104104104104104082082082082082082081041041041041041041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ff7f7f7f7f7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefeff7f7f7f7f7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80808080808080808080808040404040404040404040404020202020202020202020202010101010101010101010101008080808080808080808080804040404040404040404040402020202020202020202020201010101010101010101010101 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000000000000800000000000080000000000008000000000000400000000000040000000000004000000000000400000000000020000000000002000000000000200000000000020000000000001000000000000100000000000010000000000000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffffffffffff7ffffffffffff7ffffffffffff7ffffffffffffbffffffffffffbffffffffffffbffffffffffffbffffffffffffdffffffffffffdffffffffffffdffffffffffffdffffffffffffeffffffffffffeffffffffffffefffffffffffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952a54a952a54a952a54a952a54a54a952a54a952a54a952a54a952952a54a952a54a952a54a952a54a54a952a54a952a54a952a54a952a52a54a952a54a952a54a952a54a94a952a54a952a54a952a54a952a52a54a952a54a952a54a952a54a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad5ab56ad5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab56ad5ab56ad6ad5ab56ad5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ab56ad5ab56b56ad5ab56ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ab56ad5ab56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9111222224444488891111222224444888891111222224444888891111222244444888891112222244444888891112222244444888911112222244444888911112222244448888911112222444448888911112222444448888911122222444448888 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eeedddddbbbbb7776eeeedddddbbbb77776eeeedddddbbbb77776eeeeddddbbbbb77776eeedddddbbbbb77776eeedddddbbbbb7776eeeedddddbbbbb7776eeeedddddbbbb77776eeeeddddbbbbb77776eeeeddddbbbbb77776eeedddddbbbbb7777 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8842108421084210844210842108421084221084210842108421088421084210842108442108421084210842110842108421084210884210842108421084221084210842108421108421084210842108442108421084210842210842108421084210 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bdef7bdef7bdef7bbdef7bdef7bdef7bddef7bdef7bdef7bdef77bdef7bdef7bdef7bbdef7bdef7bdef7bdeef7bdef7bdef7bdef77bdef7bdef7bdef7bddef7bdef7bdef7bdeef7bdef7bdef7bdef7bbdef7bdef7bdef7bddef7bdef7bdef7bdef +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a494925249492924a4929252494925249492924a492925249492524a492924a492925249492524a492924a492925249492524a492924a494925249492524a492924a494925249492524a492924a494925249492924a492924a494925249492924a492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6dadb6b6d6db5b6d6dadb6b6dadb6b6d6db5b6d6dadb6b6dadb5b6d6db5b6d6dadb6b6dadb5b6d6db5b6d6dadb6b6dadb5b6d6db5b6b6dadb6b6dadb5b6d6db5b6b6dadb6b6dadb5b6d6db5b6b6dadb6b6d6db5b6d6db5b6b6dadb6b6d6db5b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84108210410821041082104108210410821041082104108210420821042082104208210420821042082104208210420821042084104208410420841042084104208410420841042084104208410820841082084108208410820841082084108208410820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7bef7defbef7defbef7defbef7defbef7defbef7defbef7defbdf7defbdf7defbdf7defbdf7defbdf7defbdf7defbdf7defbdf7befbdf7befbdf7befbdf7befbdf7befbdf7befbdf7befbdf7bef7df7bef7df7bef7df7bef7df7bef7df7bef7df7bef7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80080040020020010008008004002002001000800400400200100100080040040020010008008004002002001000800800400200100100080040040020010010008004002002001000800800400200200100080040040020010010008004004002001000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ff7ffbffdffdffefff7ff7ffbffdffdffefff7ffbffbffdffeffefff7ffbffbffdffefff7ff7ffbffdffdffefff7ff7ffbffdffeffefff7ffbffbffdffeffefff7ffbffdffdffefff7ff7ffbffdffdffefff7ffbffbffdffeffefff7ffbffbffdffefff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 82082041040820820410408208104104082081041020820810410208204104102082041040820820410408208104104082081041020820810410208204104102082041040820820410408208104104082081041020820810410208204104102082041040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7df7dfbefbf7df7dfbefbf7df7efbefbf7df7efbefdf7df7efbefdf7dfbefbefdf7dfbefbf7df7dfbefbf7df7efbefbf7df7efbefdf7df7efbefdf7dfbefbefdf7dfbefbf7df7dfbefbf7df7efbefbf7df7efbefdf7df7efbefdf7dfbefbefdf7dfbefbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80004000200010000800040002000100008000400020001000080004000200010000800040002000100008000400020001000080004000200010000800040002000100008000400020001000080004000200010000800040002000100008000400020000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdfffeffff7fffbfffdffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7bbddeef77bbddeef77bbddeef77bddeef77bbddeef77bbddeef77bbdeef77bbddeef77bbddeef77bbddef77bbddeef77bbddeef77bbddeef7bbddeef77bbddeef77bbddeef77bddeef77bbddeef77bbddeef77bbdeef77bbddeef77bbddeef77bbddee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8442211088442211088442211088422110884422110884422110884421108844221108844221108844221088442211088442211088442211084422110884422110884422110884221108844221108844221108844211088442211088442211088442211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaa555554aaaaa9555554aaaaa9555552aaaaa5555552aaaaa555554aaaaa9555554aaaaa9555552aaaaa5555552aaaaa555554aaaaaa555554aaaaa9555552aaaaa9555552aaaaa555554aaaaaa555554aaaaa9555552aaaaa9555552aaaaa555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555555aaaaab555556aaaaab555556aaaaad55555aaaaaad55555aaaaab555556aaaaab555556aaaaad55555aaaaaad55555aaaaab555555aaaaab555556aaaaad555556aaaaad55555aaaaab555555aaaaab555556aaaaad555556aaaaad55555aaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaa5552aa5552aa5552aa5552aa9552aa9552aa9552aa9552aa9554aa9554aa9554aa9554aaa554aaa554aaa554aaa554aaa5552aa5552aa5552aa5552aa5552aa9552aa9552aa9552aa9554aa9554aa9554aa9554aa9554aaa554aaa554aaa554aaa554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 555aaad55aaad55aaad55aaad556aad556aad556aad556aad556aab556aab556aab556aab555aab555aab555aab555aab555aaad55aaad55aaad55aaad55aaad556aad556aad556aad556aab556aab556aab556aab556aab555aab555aab555aab555aab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 91111112222222444444448888889111111222222224444444888888891111112222222444444448888889111111122222224444444888888891111112222222244444448888889111111122222224444444488888891111112222222244444448888888 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eeeeeedddddddbbbbbbbb7777776eeeeeeddddddddbbbbbbb77777776eeeeeedddddddbbbbbbbb7777776eeeeeeedddddddbbbbbbb77777776eeeeeeddddddddbbbbbbb7777776eeeeeeedddddddbbbbbbbb7777776eeeeeeddddddddbbbbbbb7777777 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 800040002000080004000200008000400020000800040002000080004000100008000400010000800040001000080004000100008000200010000800020001000080002000100008000200010000400020001000040002000100004000200010000400020000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffbfffdffff7fffbfffdffff7fffbfffdffff7fffbfffdffff7fffbfffeffff7fffbfffeffff7fffbfffeffff7fffbfffeffff7fffdfffeffff7fffdfffeffff7fffdfffeffff7fffdfffeffffbfffdfffeffffbfffdfffeffffbfffdfffeffffbfffdffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888844442222111088884444222111108888444222211110888444422221110888844442221111088884442222111108884444222211108888444422211110888844422221111088844442222111088884444222111108888444222211110888444422221110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7777bbbbddddeeef7777bbbbdddeeeef7777bbbddddeeeef777bbbbddddeeef7777bbbbdddeeeef7777bbbddddeeeef777bbbbddddeeef7777bbbbdddeeeef7777bbbddddeeeef777bbbbddddeeef7777bbbbdddeeeef7777bbbddddeeeef777bbbbddddeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7777bbbbdddddeeeef7777bbbbbddddeeeeef7777bbbbdddddeeeef77777bbbbddddeeeeef7777bbbbdddddeeeef77777bbbbddddeeeeef7777bbbbbddddeeeef77777bbbbddddeeeeef7777bbbbbddddeeeef77777bbbbdddddeeeef7777bbbbbddddeeeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88884444222221111088884444422221111108888444422222111108888844442222111110888844442222211110888884444222211111088884444422221111088888444422221111108888444442222111108888844442222211110888844444222211111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ff7f7fbfbfdfdfdfefeff7f7f7fbfbfdfdfefefeff7f7fbfbfbfdfdfefefeff7f7fbfbfdfdfdfefeff7f7f7fbfbfdfdfdfefeff7f7fbfbfbfdfdfefefeff7f7fbfbfbfdfdfefeff7f7f7fbfbfdfdfdfefeff7f7f7fbfbfdfdfefefeff7f7fbfbfbfdfdfefefe +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8080404020202010100808080404020201010100808040404020201010100808040402020201010080808040402020201010080804040402020101010080804040402020101008080804040202020101008080804040202010101008080404040202010101 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb76dbb6ddb6edb6edb76dbb6ddb6edb6edb76dbb6ddb6edb6edb76dbb6ddb6ddb6edb76dbb6ddb6ddb6edb76dbb6ddb6ddb6edb76dbb6dbb6ddb6edb76dbb6dbb6ddb6edb76dbb6dbb6ddb6edb76db76dbb6ddb6edb76db76dbb6ddb6edb76db76dbb6ddb6edb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1248924492249124912489244922491249124892449224912491248924492249224912489244922492249124892449224922491248924492449224912489244924492249124892449244922491248924892449224912489248924492249124892489244922491249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9249249249224924924924492492492489249249249224924924924492492492489249249249124924924924492492492489249249249124924924922492492492489249249249124924924922492492492449249249249124924924922492492492449249249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db6db6ddb6db6db6dbb6db6db6db76db6db6db6ddb6db6db6dbb6db6db6db76db6db6db6edb6db6db6dbb6db6db6db76db6db6db6edb6db6db6ddb6db6db6db76db6db6db6edb6db6db6ddb6db6db6dbb6db6db6db6edb6db6db6ddb6db6db6dbb6db6db6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6b6db6d6db6dadb6db6b6db6d6db6dadb6db5b6db6d6db6dadb6db5b6db6b6db6dadb6db5b6db6b6db6d6db6db5b6db6b6db6d6db6dadb6db6b6db6d6db6dadb6db5b6db6d6db6dadb6db5b6db6b6db6dadb6db5b6db6b6db6d6db6db5b6db6b6db6d6db6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 24924949249292492524924949249292492524924a49249292492524924a49249492492524924a49249492492924924a4924949249292492524924949249292492524924a49249292492524924a49249492492524924a49249492492924924a49249492492924925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bdefbdef7bdf7bdef7bef7bdef7def7bde +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 421084108421082108421042108420842108410842108210842104210842084210841084210821084210421084208421084108421082108421042108420842108410842108210842104210842084210841084210821084210421084208421084108421082108421 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffffffffff7fffffffffffbfffffffffffdfffffffffffeffffffffffff7fffffffffffbfffffffffffdfffffffffffeffffffffffff7fffffffffffbfffffffffffdfffffffffffeffffffffffff7fffffffffffbfffffffffffdfffffffffffefffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000000000004000000000002000000000001000000000000800000000000400000000000200000000000100000000000080000000000040000000000020000000000010000000000008000000000004000000000002000000000001000000000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb76edbb76eddbb6eddbb76edbb76eddb76eddbb76ddbb76eddb76eddbb76ddbb76edbb76eddbb6eddbb76edbb76eddbb6eddbb76ddbb76eddb76eddbb76ddbb76eddb76eddbb6eddbb76edbb76eddbb6eddbb76edbb76eddb76eddbb76ddbb76eddb76eddbb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1224489124489122449122448912448912248912244892244891224891224489224489124489122449122448912448912244912244892244891224891224489224489122489122449122448912448912244912244891244891224891224489224489122489122449 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8884442221110888442221110888444221110888444222110888444222111088444222111088844422111088844422211088844422211108844422211108884422211108884442221108884442221110884442221110888442221110888444221110888444222110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbbdddeeef777bbdddeeef777bbbddeeef777bbbdddeef777bbbdddeeef77bbbdddeeef777bbbddeeef777bbbdddeef777bbbdddeeef77bbbdddeeef777bbdddeeef777bbbdddeef777bbbdddeeef77bbbdddeeef777bbdddeeef777bbbddeeef777bbbdddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9244922491248924491248924492249124492249124892449124892449224912449224912489244912489244922491244922491248924492248924492249124892249124892449224892449224912489224912489244922489244922491248922491248924492248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6dbb6ddb6edb76dbb6edb76dbb6ddb6edbb6ddb6edb76dbb6edb76dbb6ddb6edbb6ddb6edb76dbb6edb76dbb6ddb6edbb6ddb6edb76dbb6ddb76dbb6ddb6edb76ddb6edb76dbb6ddb76dbb6ddb6edb76ddb6edb76dbb6ddb76dbb6ddb6edb76ddb6edb76dbb6ddb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a94a5294a5294a5294a94a5294a5294a5294a54a5294a5294a5294a52a5294a5294a5294a52a5294a5294a5294a5295294a5294a5294a5294a94a5294a5294a5294a54a5294a5294a5294a54a5294a5294a5294a52a5294a5294a5294a5295294a5294a5294a5294 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56b5ad6b5ad6b5ad6b56b5ad6b5ad6b5ad6b5ab5ad6b5ad6b5ad6b5ad5ad6b5ad6b5ad6b5ad5ad6b5ad6b5ad6b5ad6ad6b5ad6b5ad6b5ad6b56b5ad6b5ad6b5ad6b5ab5ad6b5ad6b5ad6b5ab5ad6b5ad6b5ad6b5ad5ad6b5ad6b5ad6b5ad6ad6b5ad6b5ad6b5ad6b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80040020008004001000800200100040020008004002000800400100080020010004002000800400100080040010008002001000400200080040010008002001000800200100040020008004001000800200100040020010004002000800400100080020010004002000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffbffdfff7ffbffefff7ffdffefffbffdfff7ffbffdfff7ffbffefff7ffdffefffbffdfff7ffbffefff7ffbffefff7ffdffefffbffdfff7ffbffefff7ffdffefff7ffdffefffbffdfff7ffbffefff7ffdffefffbffdffefffbffdfff7ffbffefff7ffdffefffbffdfff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88888888888444444444422222222222111111111108888888888444444444442222222222111111111108888888888844444444442222222222111111111110888888888844444444442222222222211111111110888888888844444444444222222222211111111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77777777777bbbbbbbbbbdddddddddddeeeeeeeeeef7777777777bbbbbbbbbbbddddddddddeeeeeeeeeef77777777777bbbbbbbbbbddddddddddeeeeeeeeeeef7777777777bbbbbbbbbbdddddddddddeeeeeeeeeef7777777777bbbbbbbbbbbddddddddddeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbdefbdef7def7bef7bef7bdf7bdefbdef7def7def7bef7bdf7bdefbdefbdef7def7bef7bdf7bdf7bdefbdef7def7bef7bef7bdf7bdefbdef7def7def7bef7bdf7bdefbdefbdef7def7bef7bdf7bdf7bdefbdef7def7bef7bef7bdf7bdefbdef7def7def7bef7bdf7bde +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 4210421082108410841084208421042108210821084108420842104210421082108410842084208421042108210841084108420842104210821082108410842084210421042108210841084208420842104210821084108410842084210421082108210841084208421 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7efefdfdfbfbf7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081010202040408081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4924924924924925249249249249249292492492492492494924924924924924a4924924924924925249249249249249292492492492492494924924924924924a4924924924924925249249249249249292492492492492494924924924924924a4924924924924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6db6db6db6dadb6db6db6db6db6d6db6db6db6db6db6b6db6db6db6db6db5b6db6db6db6db6dadb6db6db6db6db6d6db6db6db6db6db6b6db6db6db6db6db5b6db6db6db6db6dadb6db6db6db6db6d6db6db6db6db6db6b6db6db6db6db6db5b6db6db6db6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80200400802004008010040080100200801002004010020040100200400802004008010040080100200801002008010020040100200400802004008010040080100400801002008010020040100200400802004008020040080100400801002008010020040100200400 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fdffbff7fdffbff7feffbff7feffdff7feffdffbfeffdffbfeffdffbff7fdffbff7feffbff7feffdff7feffdff7feffdffbfeffdffbff7fdffbff7feffbff7feffbff7feffdff7feffdffbfeffdffbff7fdffbff7fdffbff7feffbff7feffdff7feffdffbfeffdffbff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a94a94a94a54a54a52a52a5295295294a94a94a54a54a52a52a5295295294a94a94a54a54a54a52a52a5295295294a94a94a54a54a52a52a5295295294a94a94a54a54a52a52a52a5295295294a94a94a54a54a52a52a5295295294a94a94a54a54a52a52a5295295294 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56b56b56b5ab5ab5ad5ad5ad6ad6ad6b56b56b5ab5ab5ad5ad5ad6ad6ad6b56b56b5ab5ab5ab5ad5ad5ad6ad6ad6b56b56b5ab5ab5ad5ad5ad6ad6ad6b56b56b5ab5ab5ad5ad5ad5ad6ad6ad6b56b56b5ab5ab5ad5ad5ad6ad6ad6b56b56b5ab5ab5ad5ad5ad6ad6ad6b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fdfbefdf7efdf7efbf7dfbf7dfbefdf7efdf7efbf7dfbf7dfbefdf7efdf7efbf7dfbf7dfbefdf7efdf7efbf7dfbf7dfbefdf7efdf7efbf7efbf7dfbefdfbefdf7efbf7efbf7dfbefdfbefdf7efbf7efbf7dfbefdfbefdf7efbf7efbf7dfbefdfbefdf7efbf7efbf7dfbe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2041020810208104082040820410208102081040820408204102081020810408204082041020810208104082040820410208102081040810408204102041020810408104082041020410208104081040820410204102081040810408204102041020810408104082041 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d55555555555555aaaaaaaaaaaaaaad555555555555556aaaaaaaaaaaaaab555555555555556aaaaaaaaaaaaaab555555555555555aaaaaaaaaaaaaaad555555555555556aaaaaaaaaaaaaad555555555555556aaaaaaaaaaaaaab555555555555555aaaaaaaaaaaaaaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaaaaaaaaaaaaa5555555555555552aaaaaaaaaaaaaa9555555555555554aaaaaaaaaaaaaa9555555555555554aaaaaaaaaaaaaaa5555555555555552aaaaaaaaaaaaaa9555555555555552aaaaaaaaaaaaaa9555555555555554aaaaaaaaaaaaaaa555555555555555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92449124491244912449124491244912449224892248922489224892248922489224892449124491244912449124491244912449124892248922489224892248922489224892249124491244912449124491244912449124492248922489224892248922489224892248 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6dbb6edbb6edbb6edbb6edbb6edbb6edbb6ddb76ddb76ddb76ddb76ddb76ddb76ddb76dbb6edbb6edbb6edbb6edbb6edbb6edbb6edb76ddb76ddb76ddb76ddb76ddb76ddb76ddb6edbb6edbb6edbb6edbb6edbb6edbb6edbb6ddb76ddb76ddb76ddb76ddb76ddb76ddb7 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbefbefbefbefbefbefbefbefbefbefbefbef7df7df7df7df7df7df7df7df7df7df7df7defbefbefbefbefbefbefbefbefbefbefbefbdf7df7df7df7df7df7df7df7df7df7df7df7befbefbefbefbefbefbefbefbefbefbefbef7df7df7df7df7df7df7df7df7df7df7df7de +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 41041041041041041041041041041041041082082082082082082082082082082082082104104104104104104104104104104104104208208208208208208208208208208208208410410410410410410410410410410410410820820820820820820820820820820820821 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 924924924924924924924924924924924924924924924924924924924924924924924924492492492492492492492492492492492492492492492492492492492492492492492492249249249249249249249249249249249249249249249249249249249249249249249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6dbb6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6ddb6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbefbefbefbefbefbefbefbefbefbefbefbef7df7df7df7df7df7df7df7df7df7df7df7defbefbefbefbefbefbefbefbefbefbefbefbdf7df7df7df7df7df7df7df7df7df7df7df7befbefbefbefbefbefbefbefbefbefbefbef7df7df7df7df7df7df7df7df7df7df7df7de +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 41041041041041041041041041041041041082082082082082082082082082082082082104104104104104104104104104104104104208208208208208208208208208208208208410410410410410410410410410410410410820820820820820820820820820820820821 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffbfdfeff7fbfdfeff7fbfdfeff7fbfeff7fbfdfeff7fbfdfeff7fbfdfeff7fdfeff7fbfdfeff7fbfdfeff7fbfdfeffbfdfeff7fbfdfeff7fbfdfeff7fbfdff7fbfdfeff7fbfdfeff7fbfdfeff7fbfeff7fbfdfeff7fbfdfeff7fbfdfeff7fdfeff7fbfdfeff7fbfdfeff7fbfdfe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 40201008040201008040201008040100804020100804020100804020100802010080402010080402010080402010040201008040201008040201008040200804020100804020100804020100804010080402010080402010080402010080201008040201008040201008040201 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dadad6d6b6b6b5b5adad6d6d6b6b5b5adadad6d6b6b5b5b5adad6d6b6b6b5b5adad6d6d6b6b5b5adadad6d6b6b5b5b5adad6d6b6b6b5b5adad6d6d6b6b5b5adadad6d6b6b5b5b5adad6d6b6b6b5b5adad6d6d6b6b5b5adadad6d6b6b5b5b5adad6d6b6b6b5b5adad6d6d6b6b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2525292949494a4a525292929494a4a525252929494a4a4a525292949494a4a525292929494a4a525252929494a4a4a525292949494a4a525292929494a4a525252929494a4a4a525292949494a4a525292929494a4a525252929494a4a4a525292949494a4a525292929494a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8888444422221111088884444222211110888844442222111108888444422221111088884444222211110888844442222111108888444422221111088884444222211110888844442222111108888444422221111088884444222211110888844442222111108888444422221110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8204081020408102040810204102040810204081020408102081020408102040810204081040810204081020408102040820408102040810204081020410204081020408102040810208102040810204081020408104081020408102040810204082040810204081020408102040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7dfbf7efdfbf7efdfbf7efdfbefdfbf7efdfbf7efdfbf7efdf7efdfbf7efdfbf7efdfbf7efbf7efdfbf7efdfbf7efdfbf7dfbf7efdfbf7efdfbf7efdfbefdfbf7efdfbf7efdfbf7efdf7efdfbf7efdfbf7efdfbf7efbf7efdfbf7efdfbf7efdfbf7dfbf7efdfbf7efdfbf7efdfbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa54aa54a954a952a952a552a552a54aa54a954a952a952a552a552a54aa54a954a952a952a952a552a54aa54a954a952a952a952a552a54aa54a954a954a952a952a552a54aa54a954a954a952a952a552a54aa54aa54a954a952a952a552a54aa54aa54a954a952a952a552a54 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55ab55ab56ab56ad56ad5aad5aad5ab55ab56ab56ad56ad5aad5aad5ab55ab56ab56ad56ad56ad5aad5ab55ab56ab56ad56ad56ad5aad5ab55ab56ab56ab56ad56ad5aad5ab55ab56ab56ab56ad56ad5aad5ab55ab55ab56ab56ad56ad5aad5ab55ab55ab56ab56ad56ad5aad5ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8004001000400100040010004001000400100040010004001000400100040010004001000400100040010004001000400100040010004002000800200080020008002000800200080020008002000800200080020008002000800200080020008002000800200080020008002000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffefffbffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff7ffdfff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb76dbb6dbb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6edb6edb76db76dbb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6edb6edb76db76dbb6dbb6ddb6ddb6edb6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1248924492449224922491249124892489244924492249224912491248924892449244922491249124892489244924492249224912491248924892449244922492249124912489248924492249224912491248924892449244922492249124912489248924492449224922491249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 81020408102040810204081020408102020408102040810204081020408102040408102040810204081020408102040808102040810204081020408102040810102040810204081020408102040810202040810204081020408102040810204040810204081020408102040810204080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7efdfbf7efdfbf7efdfbf7efdfbf7efdfdfbf7efdfbf7efdfbf7efdfbf7efdfbfbf7efdfbf7efdfbf7efdfbf7efdfbf7f7efdfbf7efdfbf7efdfbf7efdfbf7efefdfbf7efdfbf7efdfbf7efdfbf7efdfdfbf7efdfbf7efdfbf7efdfbf7efdfbfbf7efdfbf7efdfbf7efdfbf7efdfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefefefefefefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbfbfbfbfbfbfbf7f7f7f7f7f7f7f7f7f7f7f7f7f7efefefefefefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbfbfbfbfbfbfbf7f7f7f7f7f7f7f7f7f7f7f7f7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1010101010101010101010101010202020202020202020202020202040404040404040404040404040408080808080808080808080808081010101010101010101010101010202020202020202020202020202040404040404040404040404040408080808080808080808080808081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaa95555552aaaaaa5555552aaaaaa5555554aaaaaa5555554aaaaaa9555554aaaaaa95555552aaaaa95555552aaaaaa5555552aaaaaa5555554aaaaaa5555554aaaaaa9555554aaaaaa95555552aaaaa95555552aaaaaa5555552aaaaaa5555554aaaaaa5555554aaaaaa9555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555556aaaaaad555555aaaaaad555555aaaaaab555555aaaaaab5555556aaaaab5555556aaaaaad555556aaaaaad555555aaaaaad555555aaaaaab555555aaaaaab5555556aaaaab5555556aaaaaad555556aaaaaad555555aaaaaad555555aaaaaab555555aaaaaab5555556aaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb6db6edb6db6ddb6db6dbb6db6db76db6db6edb6db6ddb6db6dbb6db6db76db6db6edb6db6ddb6db6dbb6db6db76db6db6edb6db6ddb6db6dbb6db6db76db6db6edb6db6ddb6db6dbb6db6db76db6db6edb6db6ddb6db6dbb6db6db76db6db6edb6db6ddb6db6dbb6db6db76db6db6 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 12492491249249224924924492492489249249124924922492492449249248924924912492492249249244924924892492491249249224924924492492489249249124924922492492449249248924924912492492249249244924924892492491249249224924924492492489249249 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5b5ad6b5adad6b5ad6d6b5ad6b6b5ad6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 25294a529294a529494a5294a4a5294a525294a529294a529494a5294a4a5294a525294a529294a529494a5294a4a5294a525294a529294a529494a5294a4a5294a525294a529294a529494a5294a4a5294a525294a529294a529494a5294a4a5294a525294a529294a529494a5294a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80808080808080808080808080804040404040404040404040404040202020202020202020202020202010101010101010101010101010100808080808080808080808080808040404040404040404040404040402020202020202020202020202020101010101010101010101010100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7f7f7f7f7f7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7fbfbfbfbfbfbfbfbfbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5555556aaaaaab55555556aaaaaab55555556aaaaaab55555556aaaaaab5555555aaaaaaab5555555aaaaaaab5555555aaaaaaab5555555aaaaaaad5555555aaaaaaad5555555aaaaaaad5555555aaaaaaad5555556aaaaaaad5555556aaaaaaad5555556aaaaaaad5555556aaaaaaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaaaaa95555554aaaaaaa95555554aaaaaaa95555554aaaaaaa95555554aaaaaaa55555554aaaaaaa55555554aaaaaaa55555554aaaaaaa55555552aaaaaaa55555552aaaaaaa55555552aaaaaaa55555552aaaaaa955555552aaaaaa955555552aaaaaa955555552aaaaaa95555555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6b6dadb6b6dadb5b6d6db5b6d6db5b6b6dadb6b6dadb6b6d6db5b6d6db5b6d6dadb6b6dadb6b6d6db5b6d6db5b6d6dadb6b6dadb6b6dadb5b6d6db5b6d6db5b6b6dadb6b6dadb6b6d6db5b6d6db5b6b6dadb6b6dadb6b6d6db5b6d6db5b6d6dadb6b6dadb6b6dadb5b6d6db5b6d6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2494925249492524a492924a492924a4949252494925249492924a492924a4929252494925249492924a492924a4929252494925249492524a492924a492924a4949252494925249492924a492924a4949252494925249492924a492924a4929252494925249492524a492924a492925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88884442221110888444222111088844422211108884442221110888444222111088844422221110888444222111088844422211108884442221110888444222111088844422211108884444222111088844422211108884442221110888444222111088844422211108884442221110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbddddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef777bbbdddeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d56ab55aab55aad56aad56ab55aab55aad56aad56ab556ab55aad55aad56ab556ab55aad55aad56aad56ab55aab55aad56aad56ab55aab55aad55aad56ab556ab55aad55aad56ab556ab55aab55aad56aad56ab55aab55aad56aad56ab556ab55aad55aad56ab556ab55aad55aad56aa +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a954aa554aa552a9552a954aa554aa552a9552a954aa954aa552aa552a954aa954aa552aa552a9552a954aa554aa552a9552a954aa554aa552aa552a954aa954aa552aa552a954aa954aa554aa552a9552a954aa554aa552a9552a954aa954aa552aa552a954aa954aa552aa552a955 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4a49494929252524a4a49492929252524a49494929292524a4a49494929252524a4a49492929252524a49494929292524a4a49494929252524a4a49492929252524a49494929292524a4a49494929252524a4a49492929252524a49494929292524a4a49494929252524a4a494929292524 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b5b6b6b6d6dadadb5b5b6b6d6d6dadadb5b6b6b6d6d6dadb5b5b6b6b6d6dadadb5b5b6b6d6d6dadadb5b6b6b6d6d6dadb5b5b6b6b6d6dadadb5b5b6b6d6d6dadadb5b6b6b6d6d6dadb5b5b6b6b6d6dadadb5b5b6b6d6d6dadadb5b6b6b6d6d6dadb5b5b6b6b6d6dadadb5b5b6b6d6d6dadb +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5555aaaab55555aaaab55555aaaab55556aaaab55556aaaab55556aaaad55556aaaad55556aaaad55556aaaad5555aaaaad5555aaaaad5555aaaab55555aaaab55555aaaab55556aaaab55556aaaab55556aaaab55556aaaad55556aaaad55556aaaad5555aaaaad5555aaaaad5555aaaaa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2aaaa55554aaaaa55554aaaaa55554aaaa955554aaaa955554aaaa955552aaaa955552aaaa955552aaaa955552aaaa555552aaaa555552aaaa55554aaaaa55554aaaaa55554aaaa955554aaaa955554aaaa955554aaaa955552aaaa955552aaaa955552aaaa555552aaaa555552aaaa55555 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 924912492249224924492489248924912492249224924492449248924912491249224924492449248924892491249224922492449248924892491249124922492449244924892491249124922492249244924892489249124922492249244924492489249124912492249244924492489248 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6edb6ddb6ddb6dbb6db76db76db6edb6ddb6ddb6dbb6dbb6db76db6edb6edb6ddb6dbb6dbb6db76db76db6edb6ddb6ddb6dbb6db76db76db6edb6edb6ddb6dbb6dbb6db76db6edb6edb6ddb6ddb6dbb6db76db76db6edb6ddb6ddb6dbb6dbb6db76db6edb6edb6ddb6dbb6dbb6db76db7 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8102040408101020404081020204080810202040808102040408101020404081010204080810202040808102020408101020404081010204040810202040808102020408081020404081010204040810102040808102020408081020204081010204040810102040408102020408081020204080 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7efdfbfbf7efefdfbfbf7efdfdfbf7f7efdfdfbf7f7efdfbfbf7efefdfbfbf7efefdfbf7f7efdfdfbf7f7efdfdfbf7efefdfbfbf7efefdfbfbf7efdfdfbf7f7efdfdfbf7f7efdfbfbf7efefdfbfbf7efefdfbf7f7efdfdfbf7f7efdfdfbf7efefdfbfbf7efefdfbfbf7efdfdfbf7f7efdfdfbf7f +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000100001000010000200002000020000200004000040000400004000080000800008000080001000010000100001000020000200002000020000400004000040000400008000080000800008000100001000010000100002000020000200002000040000400004000040000800008000080000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fffeffffeffffeffffdffffdffffdffffdffffbffffbffffbffffbffff7ffff7ffff7ffff7fffeffffeffffeffffeffffdffffdffffdffffdffffbffffbffffbffffbffff7ffff7ffff7ffff7fffeffffeffffeffffeffffdffffdffffdffffdffffbffffbffffbffffbffff7ffff7ffff7ffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8010010010020020020020040040040040080080080080100100100100200200200200400400400400800800800801001001001002002002002004004004004008008008008010010010010020020020020040040040040080080080080100100100100200200200200400400400400800800800 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7feffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff7feffeffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff7feffeffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff7feffeffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff7feffeffeffeffdffdffdffdffbffbffbffbff7ff7ff7ff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eedddbb776edddbb776eeddbbb76eeddbbb776edddbb776edddbbb76eeddbbb76eedddbb776edddbb776eeddbbb76eeddbbb776edddbb776edddbbb76eeddbbb76eedddbb776edddbb776eeddbbb76eeddbbb776edddbb776edddbbb76eeddbbb76eedddbb776edddbb776eeddbbb76eeddbbb76 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1122244889122244889112244489112244488912224488912224448911224448911222448891222448891122444891122444889122244889122244489112244489112224488912224488911224448911224448891222448891222444891122444891122244889122244889112244489112244489 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a49492924a49492924a49492924a49492924a49492924a49492924a49492524a49492524a49492524a49492524a49492524a49492524a49492524a49292524a49292524a49292524a49292524a49292524a49292524a492925249492925249492925249492925249492925249492925249492924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6b6d6db5b6b6d6db5b6b6d6db5b6b6d6db5b6b6d6db5b6b6d6db5b6b6dadb5b6b6dadb5b6b6dadb5b6b6dadb5b6b6dadb5b6b6dadb5b6b6dadb5b6d6dadb5b6d6dadb5b6d6dadb5b6d6dadb5b6d6dadb5b6d6dadb5b6d6dadb6b6d6dadb6b6d6dadb6b6d6dadb6b6d6dadb6b6d6dadb6b6d6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 9122244488912224448891222444889112244488911224448891122444889112224488911222448891122244489112224448911222444891122244488912224448891222444889122244488911224448891122444889112224488911222448891122244889112224448911222444891122244488 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6edddbbb776edddbbb776edddbbb776eeddbbb776eeddbbb776eeddbbb776eedddbb776eedddbb776eedddbbb76eedddbbb76eedddbbb76eedddbbb776edddbbb776edddbbb776edddbbb776eeddbbb776eeddbbb776eedddbb776eedddbb776eedddbb776eedddbbb76eedddbbb76eedddbbb77 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8842108422108421088421084221084210884210842210842108842108422108421088421084221084210884210842210842108842108422108421084421084211084210844210842110842108442108421108421084421084211084210844210842110842108442108421108421084421084210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bdef7bddef7bdef77bdef7bddef7bdef77bdef7bddef7bdef77bdef7bddef7bdef77bdef7bddef7bdef77bdef7bddef7bdef77bdef7bddef7bdef7bbdef7bdeef7bdef7bbdef7bdeef7bdef7bbdef7bdeef7bdef7bbdef7bdeef7bdef7bbdef7bdeef7bdef7bbdef7bdeef7bdef7bbdef7bdef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffffdffffbffff7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffbffff7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffdffff7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffdffffbffff7fffeffffdffffbfffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 200004000080001000020000400008000100002000040000800010000200004000080001000040000800010000200004000080001000020000400008000100002000040000800010000200008000100002000040000800010000200004000080001000020000400008000100002000040001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = edb6db6db6db6db6dbb6db6db6db6db6db6edb6db6db6db6db6db76db6db6db6db6db6ddb6db6db6db6db6db6edb6db6db6db6db6dbb6db6db6db6db6db6ddb6db6db6db6db6db76db6db6db6db6db6dbb6db6db6db6db6db6edb6db6db6db6db6db76db6db6db6db6db6ddb6db6db6db6db6db6 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1249249249249249244924924924924924912492492492492492489249249249249249224924924924924924912492492492492492449249249249249249224924924924924924892492492492492492449249249249249249124924924924924924892492492492492492249249249249249249 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 91111111111111111112222222222222222222244444444444444444444888888888888888888891111111111111111111222222222222222222224444444444444444444488888888888888888889111111111111111111122222222222222222222444444444444444444448888888888888888888 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6eeeeeeeeeeeeeeeeeeddddddddddddddddddddbbbbbbbbbbbbbbbbbbbb77777777777777777776eeeeeeeeeeeeeeeeeeeddddddddddddddddddddbbbbbbbbbbbbbbbbbbbb77777777777777777776eeeeeeeeeeeeeeeeeeeddddddddddddddddddddbbbbbbbbbbbbbbbbbbbb7777777777777777777 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80000000000000020000000000000004000000000000000800000000000000100000000000000020000000000000004000000000000000800000000000000100000000000000020000000000000004000000000000000800000000000000100000000000000020000000000000004000000000000000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffffffffffffffdfffffffffffffffbfffffffffffffff7ffffffffffffffefffffffffffffffdfffffffffffffffbfffffffffffffff7ffffffffffffffefffffffffffffffdfffffffffffffffbfffffffffffffff7ffffffffffffffefffffffffffffffdfffffffffffffffbfffffffffffffff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924a492924949252492924a49252494924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db5b6d6db6b6dadb6d6db5b6dadb6b6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80804040202010100808040402020101008080404020201010080804040202010100808040402020101008080404020201010080804040202010100808040402020101008080404020201010080804040202010100808040402020101008080404020201010080804040202010100808040402020100 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfefeff7f7fbfbfdfdfeff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 92492489249248924924492492449249244924922492492249249224924912492491249249124924892492489249248924924492492449249244924922492492249249224924912492491249249124924892492489249248924924492492449249244924922492492249249224924912492491249248 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6db6db76db6db76db6dbb6db6dbb6db6dbb6db6ddb6db6ddb6db6ddb6db6edb6db6edb6db6edb6db76db6db76db6db76db6dbb6db6dbb6db6dbb6db6ddb6db6ddb6db6ddb6db6edb6db6edb6db6edb6db76db6db76db6db76db6dbb6db6dbb6db6dbb6db6ddb6db6ddb6db6ddb6db6edb6db6edb6db7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefdfbfbf7efefdfbfbf7efefdfbfbf7efefdfbf7f7efdfdfbf7f7efdfdfbf7f7efdfdfbf7f7efdfbfbf7efefdfbfbf7efefdfbfbf7efefdfbfbf7efdfdfbf7f7efdfdfbf7f7efdfdfbf7f7efdfdfbf7efefdfbfbf7efefdfbfbf7efefdfbfbf7efefdfbf7f7efdfdfbf7f7efdfdfbf7f7efdfdfbf7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1020404081010204040810102040408101020408081020204080810202040808102020408081020404081010204040810102040408101020404081020204080810202040808102020408081020204081010204040810102040408101020404081010204080810202040808102020408081020204081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88421084210842108421088421084210842108421088421084210842108421084421084210842108421084421084210842108421084421084210842108421084221084210842108421084221084210842108421084221084210842108421084211084210842108421084211084210842108421084210 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 77bdef7bdef7bdef7bdef77bdef7bdef7bdef7bdef77bdef7bdef7bdef7bdef7bbdef7bdef7bdef7bdef7bbdef7bdef7bdef7bdef7bbdef7bdef7bdef7bdef7bddef7bdef7bdef7bdef7bddef7bdef7bdef7bdef7bddef7bdef7bdef7bdef7bdeef7bdef7bdef7bdef7bdeef7bdef7bdef7bdef7bdef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5aad56ab56ab55aad56ad56ab55aad5aad56ab55ab55aad56ad56ab55aad5aad56ab55ab55aad56ab56ab55aad56ad56ab55ab55aad56ab56ab55aad56ad56ab55aad5aad56ab56ab55aad56ad56ab55aad5aad56ab55ab55aad56ab56ab55aad5aad56ab55ab55aad56ab56ab55aad56ad56ab55aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a552a954a954aa552a952a954aa552a552a954aa54aa552a952a954aa552a552a954aa54aa552a954a954aa552a952a954aa54aa552a954a954aa552a952a954aa552a552a954a954aa552a952a954aa552a552a954aa54aa552a954a954aa552a552a954aa54aa552a954a954aa552a952a954aa55 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6db6db6b6db6db6db6dadb6db6db6db6b6db6db6db6dadb6db6db6db6b6db6db6db6dadb6db6db6db6b6db6db6db6dadb6db6db6db6b6db6db6db6d6db6db6db6db5b6db6db6db6d6db6db6db6db5b6db6db6db6d6db6db6db6db5b6db6db6db6d6db6db6db6db5b6db6db6db6d6db6db6db6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2492492492494924924924925249249249249492492492492524924924924949249249249252492492492494924924924925249249249249492492492492924924924924a492492492492924924924924a492492492492924924924924a492492492492924924924924a492492492492924924924925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = ffeffeffdffdffdffbffbffbff7ff7ff7feffeffeffdffdffdffbffbffbff7ff7ff7feffeffeffdffdffbffbffbff7ff7ff7feffeffeffdffdffdffbffbffbff7ff7ff7feffeffeffdffdffdffbffbff7ff7ff7feffeffeffdffdffdffbffbffbff7ff7ff7feffeffeffdffdffdffbffbffbff7ff7fe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 100100200200200400400400800800801001001002002002004004004008008008010010010020020040040040080080080100100100200200200400400400800800801001001002002002004004008008008010010010020020020040040040080080080100100100200200200400400400800801 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffff7ffffffbffffffbffffffdffffffeffffffefffffff7ffffff7ffffffbffffffdffffffdffffffeffffffefffffff7ffffffbffffffbffffffdffffffdffffffefffffff7ffffff7ffffffbffffffbffffffdffffffeffffffefffffff7ffffff7ffffffbffffffdffffffdffffffeffffffe +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000000400000040000002000000100000010000000800000080000004000000200000020000001000000100000008000000400000040000002000000200000010000000800000080000004000000400000020000001000000100000008000000800000040000002000000200000010000001 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 820408204082040810408104081020810208102041020410204082040820408104081040810208102081020410204102040820408204081040810408102081020810204102041020408204082040810408104081020810208102041020410204082040820408104081040810208102081020410204102040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7dfbf7dfbf7dfbf7efbf7efbf7efdf7efdf7efdfbefdfbefdfbf7dfbf7dfbf7efbf7efbf7efdf7efdf7efdfbefdfbefdfbf7dfbf7dfbf7efbf7efbf7efdf7efdf7efdfbefdfbefdfbf7dfbf7dfbf7efbf7efbf7efdf7efdf7efdfbefdfbefdfbf7dfbf7dfbf7efbf7efbf7efdf7efdf7efdfbefdfbefdfbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 922489224892248922489224491244912449124491244912248922489224892248922489124491244912449124491244892248922489224892248922449124491244912449124491224892248922489224892248912449124491244912449124489224892248922489224892244912449124491244912448 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 6ddb76ddb76ddb76ddb76ddbb6edbb6edbb6edbb6edbb6eddb76ddb76ddb76ddb76ddb76edbb6edbb6edbb6edbb6edbb76ddb76ddb76ddb76ddb76ddbb6edbb6edbb6edbb6edbb6eddb76ddb76ddb76ddb76ddb76edbb6edbb6edbb6edbb6edbb76ddb76ddb76ddb76ddb76ddbb6edbb6edbb6edbb6edbb7 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 800008000080000400004000020000200002000010000100000800008000040000400004000020000200001000010000080000800008000040000400002000020000100001000010000080000800004000040000200002000020000100001000008000080000400004000040000200002000010000100000 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffff7ffff7ffffbffffbffffdffffdffffdffffeffffefffff7ffff7ffffbffffbffffbffffdffffdffffeffffefffff7ffff7ffff7ffffbffffbffffdffffdffffeffffeffffefffff7ffff7ffffbffffbffffdffffdffffdffffeffffefffff7ffff7ffffbffffbffffbffffdffffdffffeffffefffff +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6dadb6b6d6dadb5b6d6dadb5b6b6dadb5b6b6d6db5b6b6d6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 24949292524949292524a49292524a49492524a49492924a4949292524949292524a49292524a49492524a49492924a4949292524949292524a49292524a49492524a49492924a4949292524949292524a49292524a49492524a49492924a4949292524949292524a49292524a49492524a49492924a49492925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8001000200020004000400080008001000100020002000400040008000800100010002000200040004000800080010001000200020004000400080008001000100020002000400040008000800100010002000200040004000800080010001000200020004000400080008001000100020002000400040008000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff7ffefffefffdfffdfffbfffbfff7fff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8888888888884444444444442222222222221111111111110888888888888444444444444222222222222111111111111088888888888844444444444422222222222211111111111108888888888884444444444442222222222221111111111110888888888888444444444444222222222222111111111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777777777777bbbbbbbbbbbbddddddddddddeeeeeeeeeeeef777777777777bbbbbbbbbbbbddddddddddddeeeeeeeeeeeef777777777777bbbbbbbbbbbbddddddddddddeeeeeeeeeeeef777777777777bbbbbbbbbbbbddddddddddddeeeeeeeeeeeef777777777777bbbbbbbbbbbbddddddddddddeeeeeeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8020080200401004010020080200401004010020080200801004010020080200801004010040080200801004010040080200802004010040080200802004010040100200802004010040100200802008010040100200802008010040100400802008010040100400802008020040100400802008020040100400 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fdff7fdffbfeffbfeffdff7fdffbfeffbfeffdff7fdff7feffbfeffdff7fdff7feffbfeffbff7fdff7feffbfeffbff7fdff7fdffbfeffbff7fdff7fdffbfeffbfeffdff7fdffbfeffbfeffdff7fdff7feffbfeffdff7fdff7feffbfeffbff7fdff7feffbfeffbff7fdff7fdffbfeffbff7fdff7fdffbfeffbff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fbef7defbdf7bef7defbdf7bef7defbdf7bef7defbdf7bef7df7bef7defbdf7bef7defbdf7bef7defbdf7bef7defbdf7befbdf7bef7defbdf7bef7defbdf7bef7defbdf7bef7defbdf7defbdf7bef7defbdf7bef7defbdf7bef7defbdf7bef7defbef7defbdf7bef7defbdf7bef7defbdf7bef7defbdf7bef7de +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 410821042084108210420841082104208410821042084108208410821042084108210420841082104208410821042084104208410821042084108210420841082104208410821042082104208410821042084108210420841082104208410821041082104208410821042084108210420841082104208410821 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6b5ad6d6b5ad6b5b5ad6b5adad6b5ad6b6b5ad6b5adad6b5ad6d6b5ad6b5b5ad6b5ad6d6b5ad6b6b5ad6b5adad6b5ad6d6b5ad6b5b5ad6b5ad6d6b5ad6b6b5ad6b5adad6b5ad6b6b5ad6b5b5ad6b5ad6d6b5ad6b6b5ad6b5adad6b5ad6b6b5ad6b5b5ad6b5ad6d6b5ad6b5b5ad6b5adad6b5ad6b6b5ad6b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 25294a529294a5294a4a5294a525294a529494a5294a525294a529294a5294a4a5294a529294a529494a5294a525294a529294a5294a4a5294a529294a529494a5294a525294a529494a5294a4a5294a529294a529494a5294a525294a529494a5294a4a5294a529294a5294a4a5294a525294a529494a5294a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fefefdfdfbfbf7f7f7efefdfdfbfbfbf7f7efefdfdfdfbfbf7f7efefdfdfdfbfbf7f7efefefdfdfbfbf7f7f7efefdfdfbfbf7f7f7efefdfdfbfbfbf7f7efefdfdfdfbfbf7f7efefefdfdfbfbf7f7efefefdfdfbfbf7f7f7efefdfdfbfbfbf7f7efefdfdfbfbfbf7f7efefdfdfdfbfbf7f7efefefdfdfbfbf7f7e +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 101020204040808081010202040404080810102020204040808101020202040408081010102020404080808101020204040808081010202040404080810102020204040808101010202040408081010102020404080808101020204040408081010202040404080810102020204040808101010202040408081 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dadadadadad6d6d6d6d6b6b6b6b6b6b5b5b5b5b5adadadadadad6d6d6d6d6b6b6b6b6b6b5b5b5b5b5adadadadadad6d6d6d6d6b6b6b6b6b6b5b5b5b5b5adadadadad6d6d6d6d6d6b6b6b6b6b5b5b5b5b5b5adadadadad6d6d6d6d6d6b6b6b6b6b5b5b5b5b5b5adadadadad6d6d6d6d6d6b6b6b6b6b5b5b5b5b5a +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2525252525292929292949494949494a4a4a4a4a52525252525292929292949494949494a4a4a4a4a52525252525292929292949494949494a4a4a4a4a525252525292929292929494949494a4a4a4a4a4a525252525292929292929494949494a4a4a4a4a4a525252525292929292929494949494a4a4a4a4a5 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a4924924a4924924949249249492492492924924929249249252492492524924924a4924924a49249249492492492924924929249249252492492524924924a4924924a49249249492492494924924929249249252492492524924924a4924924a49249249492492494924924929249249292492492524924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6db5b6db6db6b6db6db6b6db6db6d6db6db6d6db6db6dadb6db6dadb6db6db5b6db6db5b6db6db6b6db6db6d6db6db6d6db6db6dadb6db6dadb6db6db5b6db6db5b6db6db6b6db6db6b6db6db6d6db6db6dadb6db6dadb6db6db5b6db6db5b6db6db6b6db6db6b6db6db6d6db6db6d6db6db6dadb6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eeddbbb76edddbb76eeddbb776eddbbb76eeddbb776eddbbb76edddbb76eeddbb776edddbb76eeddbb776eddbbb76edddbb76eeddbbb76edddbb76eeddbb776eddbbb76edddbb776eddbbb76edddbb76eeddbb776eddbbb76eeddbb776eddbbb76edddbb76eeddbb776edddbb76eeddbb776eddbbb76edddbb76 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1122444891222448911224488912244489112244889122444891222448911224488912224489112244889122444891222448911224448912224489112244889122444891222448891224448912224489112244889122444891122448891224448912224489112244889122244891122448891224448912224489 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aaaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554aaa95552aaa5554 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab5556aaad555aaab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 84104208210410820841042082104108208410420821041082084104208210410820841042082104108208410420821041082084104208210410820841042082104108208410420821041082084104208210410820841042082104108208410420821041082084104208210410820841042082104108208410420820 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7defbef7df7befbdf7df +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a49292494924a49252494924a49252492924a4925249292494925249292494924a49292494924a49252494924a49252492924a4925249292494925249292494924a49292494924a49252494924a49252492924a4925249292494925249292494924a49292494924a49252494924a49252492924a4925249292494924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6d6db6b6db5b6dadb6b6db5b6dadb6d6db5b6dadb6d6db6b6dadb6d6db6b6db5b6d6db6b6db5b6dadb6b6db5b6dadb6d6db5b6dadb6d6db6b6dadb6d6db6b6db5b6d6db6b6db5b6dadb6b6db5b6dadb6d6db5b6dadb6d6db6b6dadb6d6db6b6db5b6d6db6b6db5b6dadb6b6db5b6dadb6d6db5b6dadb6d6db6b6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88844221108884422110888442211088444221108844422110884442211088442221108844222110884422211088442211108844221110884422111088442211088844221108884422110888442211088444221108844422110884442211088442221108844222110884422211088442211108844221110884422110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 777bbddeef777bbddeef777bbddeef77bbbddeef77bbbddeef77bbbddeef77bbdddeef77bbdddeef77bbdddeef77bbddeeef77bbddeeef77bbddeeef77bbddeef777bbddeef777bbddeef777bbddeef77bbbddeef77bbbddeef77bbbddeef77bbdddeef77bbdddeef77bbdddeef77bbddeeef77bbddeeef77bbddeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = db6db6db6db6d6db6db6db6db6b6db6db6db6db5b6db6db6db6d6db6db6db6db6b6db6db6db6db5b6db6db6db6dadb6db6db6db6b6db6db6db6db5b6db6db6db6dadb6db6db6db6d6db6db6db6db5b6db6db6db6dadb6db6db6db6d6db6db6db6db6b6db6db6db6dadb6db6db6db6d6db6db6db6db6b6db6db6db6da +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 249249249249292492492492494924924924924a49249249249292492492492494924924924924a49249249249252492492492494924924924924a49249249249252492492492492924924924924a4924924924925249249249249292492492492494924924924925249249249249292492492492494924924924925 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a49249249249249249292492492492492492494924924924924924924a49249249249249249252492492492492492494924924924924924924a49249249249249249252492492492492492492924924924924924924a4924924924924924925249249249249249249292492492492492492494924924924924924924 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5b6db6db6db6db6db6d6db6db6db6db6db6db6b6db6db6db6db6db6db5b6db6db6db6db6db6dadb6db6db6db6db6db6b6db6db6db6db6db6db5b6db6db6db6db6db6dadb6db6db6db6db6db6d6db6db6db6db6db6db5b6db6db6db6db6db6dadb6db6db6db6db6db6d6db6db6db6db6db6db6b6db6db6db6db6db6db +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a52929494a4a52929494a4a52529494a4a52529494a4a52529294a4a5252929494a5252929494a5252929494a4a52929494a4a52529494a4a52529494a4a52529294a4a52529294a4a5252929494a5252929494a4a52929494a4a52929494a4a52529494a4a52529294a4a52529294a4a5252929494a5252929494a4 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 5ad6d6b6b5b5ad6d6b6b5b5adad6b6b5b5adad6b6b5b5adad6d6b5b5adad6d6b6b5adad6d6b6b5adad6d6b6b5b5ad6d6b6b5b5adad6b6b5b5adad6b6b5b5adad6d6b5b5adad6d6b5b5adad6d6b6b5adad6d6b6b5b5ad6d6b6b5b5ad6d6b6b5b5adad6b6b5b5adad6d6b5b5adad6d6b5b5adad6d6b6b5adad6d6b6b5b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952952952952a52a52a52a52a54a54a54a54a94a94a94a94a952952952952a52a52a52a52a54a54a54a54a94a94a94a94a952952952952a52a52a52a52a54a54a54a54a54a94a94a94a952952952952952a52a52a52a54a54a54a54a54a94a94a94a952952952952952a52a52a52a54a54a54a54a54a94a94a94a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad6ad6ad6ad5ad5ad5ad5ad5ab5ab5ab5ab56b56b56b56b56ad6ad6ad6ad5ad5ad5ad5ad5ab5ab5ab5ab56b56b56b56b56ad6ad6ad6ad5ad5ad5ad5ad5ab5ab5ab5ab5ab56b56b56b56ad6ad6ad6ad6ad5ad5ad5ad5ab5ab5ab5ab5ab56b56b56b56ad6ad6ad6ad6ad5ad5ad5ad5ab5ab5ab5ab5ab56b56b56b56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 88888884444444222222111111108888888444444222222211111110888888444444422222221111110888888844444422222221111111088888844444442222222111111088888884444444222222111111108888884444444222222211111108888888444444422222211111110888888844444422222221111110 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7777777bbbbbbbddddddeeeeeeef7777777bbbbbbdddddddeeeeeeef777777bbbbbbbdddddddeeeeeef7777777bbbbbbdddddddeeeeeeef777777bbbbbbbdddddddeeeeeef7777777bbbbbbbddddddeeeeeeef777777bbbbbbbdddddddeeeeeef7777777bbbbbbbddddddeeeeeeef7777777bbbbbbdddddddeeeeeef +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 80804020100804020100804020100804020201008040201008040201008040201008040402010080402010080402010080402010080804020100804020100804020100804020101008040201008040201008040201008040202010080402010080402010080402010080404020100804020100804020100804020100 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7f7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7f7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfefeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = a952a54a952a54a952a54a952a54a952a54a54a952a54a952a54a952a54a952a54a952a52a54a952a54a952a54a952a54a952a54a952952a54a952a54a952a54a952a54a952a54a94a952a54a952a54a952a54a952a54a952a54a54a952a54a952a54a952a54a952a54a952a52a54a952a54a952a54a952a54a952a54a94 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 56ad5ab56ad5ab56ad5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab56ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ab56ad5ab56ad5ab56ad6ad5ab56ad5ab56ad5ab56ad5ab56ad5ab56b56ad5ab56ad5ab56ad5ab56ad5ab56ad5ab5ab56ad5ab56ad5ab56ad5ab56ad5ab56ad5ad5ab56ad5ab56ad5ab56ad5ab56ad5ab56b +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5ab56ad5ab56ad5ab56ad5ab56ad5ab56ad56ad5ab56ad5ab56ad5ab56ad5ab56ad5ab55ab56ad5ab56ad5ab56ad5ab56ad5ab56ad56ad5ab56ad5ab56ad5ab56ad5ab56ad5ab56ab56ad5ab56ad5ab56ad5ab56ad5ab56ad5aad5ab56ad5ab56ad5ab56ad5ab56ad5ab56ab56ad5ab56ad5ab56ad5ab56ad5ab56ad5aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a54a952a54a952a54a952a54a952a54a952a952a54a952a54a952a54a952a54a952a54aa54a952a54a952a54a952a54a952a54a952a952a54a952a54a952a54a952a54a952a54a954a952a54a952a54a952a54a952a54a952a552a54a952a54a952a54a952a54a952a54a954a952a54a952a54a952a54a952a54a952a55 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = eddbb76eddbb76eddbb76eddbb76eddbb76edbb76eddbb76eddbb76eddbb76eddbb76eddb76eddbb76eddbb76eddbb76eddbb76eddbb6eddbb76eddbb76eddbb76eddbb76eddbb76ddbb76eddbb76eddbb76eddbb76eddbb76edbb76eddbb76eddbb76eddbb76eddbb76eddb76eddbb76eddbb76eddbb76eddbb76eddbb6 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 122448912244891224489122448912244891244891224489122448912244891224489122489122448912244891224489122448912244912244891224489122448912244891224489224489122448912244891224489122448912448912244891224489122448912244891224891224489122448912244891224489122449 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeef7777bbbbddddeeeee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 888844442222111108888444422221111088884444222211110888844442222111108888444422221111088884444222211110888844442222111108888444422221111088884444222211110888844442222111108888444422221111088884444222211110888844442222111108888444422221111088884444222211111 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = f7bdef7bdef77bdef7bdef7bbdef7bdef7bddef7bdef7bdeef7bdef7bdef77bdef7bdef7bbdef7bdef7bddef7bdef7bdeef7bdef7bdef77bdef7bdef7bbdef7bdef7bddef7bdef7bdeef7bdef7bdef77bdef7bdef7bbdef7bdef7bddef7bdef7bdeef7bdef7bdef77bdef7bdef7bbdef7bdef7bddef7bdef7bdeef7bdef7bdee +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 842108421088421084210844210842108422108421084211084210842108842108421084421084210842210842108421108421084210884210842108442108421084221084210842110842108421088421084210844210842108422108421084211084210842108842108421084421084210842210842108421108421084211 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8020040080100400801002004010020040080200400801002008010020040100200400801004008010020080100200400802004008010040080100200401002004008020040080100200801002004010020040080100400801002008010020040080200400801004008010020040100200400802004008010020080100200400 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7fdffbff7feffbff7feffdffbfeffdffbff7fdffbff7feffdff7feffdffbfeffdffbff7feffbff7feffdff7feffdffbff7fdffbff7feffbff7feffdffbfeffdffbff7fdffbff7feffdff7feffdffbfeffdffbff7feffbff7feffdff7feffdffbff7fdffbff7feffbff7feffdffbfeffdffbff7fdffbff7feffdff7feffdffbff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8208104082041040820410208104102081040820410408204102082041020810408208104082041020820410208104102081040820410408204102081041020810408208104082041020820410208104082081040820410408204102081041020810408204104082041020820410208104082081040820410208204102081040 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7df7efbf7dfbefbf7dfbefdf7efbefdf7efbf7dfbefbf7dfbefdf7dfbefdf7efbf7df7efbf7dfbefdf7dfbefdf7efbefdf7efbf7dfbefbf7dfbefdf7efbefdf7efbf7df7efbf7dfbefdf7dfbefdf7efbf7df7efbf7dfbefbf7dfbefdf7efbefdf7efbf7dfbefbf7dfbefdf7dfbefdf7efbf7df7efbf7dfbefdf7dfbefdf7efbf +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffff7ffffffffffffff7ffffffffffffff7ffffffffffffff7ffffffffffffffbffffffffffffffbffffffffffffffbffffffffffffffbffffffffffffffdffffffffffffffdffffffffffffffdffffffffffffffdffffffffffffffeffffffffffffffeffffffffffffffeffffffffffffffeffffffffffffffe +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8000000000000008000000000000008000000000000008000000000000004000000000000004000000000000004000000000000004000000000000002000000000000002000000000000002000000000000002000000000000001000000000000001000000000000001000000000000001000000000000001 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 8008004002001000800400200100080040020010008004002001000800400200100080040020010008004004002001000800400200100080040020010008004002001000800400200100080040020010008004002002001000800400200100080040020010008004002001000800400200100080040020010008004002001000 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 7ff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff7ffbffdffefff +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa54aa54aa54aa54a954a954a954a954a952a952a952a952a552a552a552a552a54aa54aa54aa54a954a954a954a954a952a952a952a952a552a552a552a552a54aa54aa54aa54aa54a954a954a954a952a952a952a952a952a552a552a552a54aa54aa54aa54aa54a954a954a954a952a952a952a952a952a552a552a552a54 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 55ab55ab55ab55ab56ab56ab56ab56ab56ad56ad56ad56ad5aad5aad5aad5aad5ab55ab55ab55ab56ab56ab56ab56ab56ad56ad56ad56ad5aad5aad5aad5aad5ab55ab55ab55ab55ab56ab56ab56ab56ad56ad56ad56ad56ad5aad5aad5aad5ab55ab55ab55ab55ab56ab56ab56ab56ad56ad56ad56ad56ad5aad5aad5aad5ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = d5aad5aad5aad5aad56ad56ad56ad56ab56ab56ab56ab56ab55ab55ab55ab55aad5aad5aad5aad5aad56ad56ad56ad56ab56ab56ab56ab56ab55ab55ab55ab55aad5aad5aad5aad56ad56ad56ad56ad56ab56ab56ab56ab55ab55ab55ab55ab55aad5aad5aad5aad56ad56ad56ad56ad56ab56ab56ab56ab55ab55ab55ab55aa +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 2a552a552a552a552a952a952a952a954a954a954a954a954aa54aa54aa54aa552a552a552a552a552a952a952a952a954a954a954a954a954aa54aa54aa54aa552a552a552a552a952a952a952a952a954a954a954a954aa54aa54aa54aa54aa552a552a552a552a952a952a952a952a954a954a954a954aa54aa54aa54aa55 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = aa9552aa552aa554aa954aa9552a9552aa554aa554aa9552a9552aa552aa554aa954aa9552aa552aa554aa554aa9552a9552aa552aa554aa954aa9552aa552aa554aa554aa9552a9552aa554aa554aa954aa9552aa552aa554aa554aa9552a9552aa554aa554aa954aa9552aa552aa554aa954aa9552a9552aa554aa554aa954 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 556aad55aad55aab556ab556aad56aad55aab55aab556aad56aad55aad55aab556ab556aad55aad55aab55aab556aad56aad55aad55aab556ab556aad55aad55aab55aab556aad56aad55aab55aab556ab556aad55aad55aab55aab556aad56aad55aab55aab556ab556aad55aad55aab556ab556aad56aad55aab55aab556ab +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = dad6b5b5ad6b6b5ad6d6b5adad6b5b5ad6b6b5ad6b6b5ad6d6b5adad6b5b5ad6b6b5ad6d6b5ad6d6b5adad6b5b5ad6b6b5ad6d6b5adad6b5adad6b5b5ad6b6b5ad6d6b5adad6b5b5ad6b5b5ad6b6b5ad6d6b5adad6b5b5ad6b6b5ad6b6b5ad6d6b5adad6b5b5ad6b6b5ad6d6b5ad6d6b5adad6b5b5ad6b6b5ad6d6b5adad6b5a +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 25294a4a529494a529294a525294a4a529494a529494a529294a525294a4a529494a529294a529294a525294a4a529494a529294a525294a525294a4a529494a529294a525294a4a5294a4a529494a529294a525294a4a529494a529494a529294a525294a4a529494a529294a529294a525294a4a529494a529294a525294a5 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +A = -1 +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000 + +ModInv = effff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000 + +ModInv = effffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000 + +ModInv = effffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000 + +ModInv = effffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000 + +ModInv = effffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000 + +ModInv = effffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = 1 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000001000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000000000000000100000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffffffff000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffff000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffffffff000000000000000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000100000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001 +A = ffffffffffffffffffffffffffffffff00000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffeffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffffffff00000000000000000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e0000000000000000000000000000000000010000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000010000000000000000000000000001 +A = ffffffffffffffffffffffffffff0000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000010000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffff +A = -ffffffffffffffffffffffffffff0000000000000000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effffffffffffffffffff000000000000000000000000000000000000000000000001000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffff000000000000000000000000000000000000000000000001000000000000000000000001 +A = ffffffffffffffffffffffff000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffff000000000000000000000000000000000000000000000001000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffff +A = -ffffffffffffffffffffffff000000000000000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffffffffffeffffffffffffffffffff000000000000000000000000000000000000000100000000000000000000fffffffffffffffffffffffffffffffffffffffeffffffffffffffffffff000000000000000000000000000000000000000100000000000000000001 +A = ffffffffffffffffffff00000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000000000000000000000000000000000000000100000000000000000000fffffffffffffffffffffffffffffffffffffffeffffffffffffffffffff000000000000000000000000000000000000000100000000000000000000fffffffffffffffffffffffffffffffffffffffeffffffffffffffffffff +A = -ffffffffffffffffffff00000000000000000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effff000000000000000000000000000000010000000000000000fffffffffffffffffffffffffffffffeffffffffffffffff000000000000000000000000000000010000000000000000fffffffffffffffffffffffffffffffeffffffffffffffff000000000000000000000000000000010000000000000001 +A = ffffffffffffffff0000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffffffffffffffeffffffffffffffff000000000000000000000000000000010000000000000000fffffffffffffffffffffffffffffffeffffffffffffffff000000000000000000000000000000010000000000000000fffffffffffffffffffffffffffffffeffffffffffffffff +A = -ffffffffffffffff0000000000000001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e00000000000000000001000000000000fffffffffffffffffffffffeffffffffffff000000000000000000000001000000000000fffffffffffffffffffffffeffffffffffff000000000000000000000001000000000000fffffffffffffffffffffffeffffffffffff000000000000000000000001000000000001 +A = ffffffffffff000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffffffffffffffeffffffffffff000000000000000000000001000000000000fffffffffffffffffffffffeffffffffffff000000000000000000000001000000000000fffffffffffffffffffffffeffffffffffff000000000000000000000001000000000000fffffffffffffffffffffffeffffffffffff +A = -ffffffffffff000000000001 +M = f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = e000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000001 +A = ffffffff00000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff000000000000000100000000fffffffffffffffeffffffff +A = -ffffffff00000001 +M = f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = effff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010001 +A = ffff0001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +ModInv = fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff000000010000fffffffeffff +A = -ffff0001 +M = f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +Title = ModInv negative tests (auto) + +ModInv = -1 +A = -64 +M = 1 + +ModInv = -1 +A = -63 +M = 1 + +ModInv = -1 +A = -62 +M = 1 + +ModInv = -1 +A = -61 +M = 1 + +ModInv = -1 +A = -60 +M = 1 + +ModInv = -1 +A = -5f +M = 1 + +ModInv = -1 +A = -5e +M = 1 + +ModInv = -1 +A = -5d +M = 1 + +ModInv = -1 +A = -5c +M = 1 + +ModInv = -1 +A = -5b +M = 1 + +ModInv = -1 +A = -5a +M = 1 + +ModInv = -1 +A = -59 +M = 1 + +ModInv = -1 +A = -58 +M = 1 + +ModInv = -1 +A = -57 +M = 1 + +ModInv = -1 +A = -56 +M = 1 + +ModInv = -1 +A = -55 +M = 1 + +ModInv = -1 +A = -54 +M = 1 + +ModInv = -1 +A = -53 +M = 1 + +ModInv = -1 +A = -52 +M = 1 + +ModInv = -1 +A = -51 +M = 1 + +ModInv = -1 +A = -50 +M = 1 + +ModInv = -1 +A = -4f +M = 1 + +ModInv = -1 +A = -4e +M = 1 + +ModInv = -1 +A = -4d +M = 1 + +ModInv = -1 +A = -4c +M = 1 + +ModInv = -1 +A = -4b +M = 1 + +ModInv = -1 +A = -4a +M = 1 + +ModInv = -1 +A = -49 +M = 1 + +ModInv = -1 +A = -48 +M = 1 + +ModInv = -1 +A = -47 +M = 1 + +ModInv = -1 +A = -46 +M = 1 + +ModInv = -1 +A = -45 +M = 1 + +ModInv = -1 +A = -44 +M = 1 + +ModInv = -1 +A = -43 +M = 1 + +ModInv = -1 +A = -42 +M = 1 + +ModInv = -1 +A = -41 +M = 1 + +ModInv = -1 +A = -40 +M = 1 + +ModInv = -1 +A = -3f +M = 1 + +ModInv = -1 +A = -3e +M = 1 + +ModInv = -1 +A = -3d +M = 1 + +ModInv = -1 +A = -3c +M = 1 + +ModInv = -1 +A = -3b +M = 1 + +ModInv = -1 +A = -3a +M = 1 + +ModInv = -1 +A = -39 +M = 1 + +ModInv = -1 +A = -38 +M = 1 + +ModInv = -1 +A = -37 +M = 1 + +ModInv = -1 +A = -36 +M = 1 + +ModInv = -1 +A = -35 +M = 1 + +ModInv = -1 +A = -34 +M = 1 + +ModInv = -1 +A = -33 +M = 1 + +ModInv = -1 +A = -32 +M = 1 + +ModInv = -1 +A = -31 +M = 1 + +ModInv = -1 +A = -30 +M = 1 + +ModInv = -1 +A = -2f +M = 1 + +ModInv = -1 +A = -2e +M = 1 + +ModInv = -1 +A = -2d +M = 1 + +ModInv = -1 +A = -2c +M = 1 + +ModInv = -1 +A = -2b +M = 1 + +ModInv = -1 +A = -2a +M = 1 + +ModInv = -1 +A = -29 +M = 1 + +ModInv = -1 +A = -28 +M = 1 + +ModInv = -1 +A = -27 +M = 1 + +ModInv = -1 +A = -26 +M = 1 + +ModInv = -1 +A = -25 +M = 1 + +ModInv = -1 +A = -24 +M = 1 + +ModInv = -1 +A = -23 +M = 1 + +ModInv = -1 +A = -22 +M = 1 + +ModInv = -1 +A = -21 +M = 1 + +ModInv = -1 +A = -20 +M = 1 + +ModInv = -1 +A = -1f +M = 1 + +ModInv = -1 +A = -1e +M = 1 + +ModInv = -1 +A = -1d +M = 1 + +ModInv = -1 +A = -1c +M = 1 + +ModInv = -1 +A = -1b +M = 1 + +ModInv = -1 +A = -1a +M = 1 + +ModInv = -1 +A = -19 +M = 1 + +ModInv = -1 +A = -18 +M = 1 + +ModInv = -1 +A = -17 +M = 1 + +ModInv = -1 +A = -16 +M = 1 + +ModInv = -1 +A = -15 +M = 1 + +ModInv = -1 +A = -14 +M = 1 + +ModInv = -1 +A = -13 +M = 1 + +ModInv = -1 +A = -12 +M = 1 + +ModInv = -1 +A = -11 +M = 1 + +ModInv = -1 +A = -10 +M = 1 + +ModInv = -1 +A = -f +M = 1 + +ModInv = -1 +A = -e +M = 1 + +ModInv = -1 +A = -d +M = 1 + +ModInv = -1 +A = -c +M = 1 + +ModInv = -1 +A = -b +M = 1 + +ModInv = -1 +A = -a +M = 1 + +ModInv = -1 +A = -9 +M = 1 + +ModInv = -1 +A = -8 +M = 1 + +ModInv = -1 +A = -7 +M = 1 + +ModInv = -1 +A = -6 +M = 1 + +ModInv = -1 +A = -5 +M = 1 + +ModInv = -1 +A = -4 +M = 1 + +ModInv = -1 +A = -3 +M = 1 + +ModInv = -1 +A = -2 +M = 1 + +ModInv = -1 +A = -1 +M = 1 + +ModInv = -1 +A = 0 +M = 1 + +ModInv = -1 +A = 1 +M = 1 + +ModInv = -1 +A = 2 +M = 1 + +ModInv = -1 +A = 3 +M = 1 + +ModInv = -1 +A = 4 +M = 1 + +ModInv = -1 +A = 5 +M = 1 + +ModInv = -1 +A = 6 +M = 1 + +ModInv = -1 +A = 7 +M = 1 + +ModInv = -1 +A = 8 +M = 1 + +ModInv = -1 +A = 9 +M = 1 + +ModInv = -1 +A = a +M = 1 + +ModInv = -1 +A = b +M = 1 + +ModInv = -1 +A = c +M = 1 + +ModInv = -1 +A = d +M = 1 + +ModInv = -1 +A = e +M = 1 + +ModInv = -1 +A = f +M = 1 + +ModInv = -1 +A = 10 +M = 1 + +ModInv = -1 +A = 11 +M = 1 + +ModInv = -1 +A = 12 +M = 1 + +ModInv = -1 +A = 13 +M = 1 + +ModInv = -1 +A = 14 +M = 1 + +ModInv = -1 +A = 15 +M = 1 + +ModInv = -1 +A = 16 +M = 1 + +ModInv = -1 +A = 17 +M = 1 + +ModInv = -1 +A = 18 +M = 1 + +ModInv = -1 +A = 19 +M = 1 + +ModInv = -1 +A = 1a +M = 1 + +ModInv = -1 +A = 1b +M = 1 + +ModInv = -1 +A = 1c +M = 1 + +ModInv = -1 +A = 1d +M = 1 + +ModInv = -1 +A = 1e +M = 1 + +ModInv = -1 +A = 1f +M = 1 + +ModInv = -1 +A = 20 +M = 1 + +ModInv = -1 +A = 21 +M = 1 + +ModInv = -1 +A = 22 +M = 1 + +ModInv = -1 +A = 23 +M = 1 + +ModInv = -1 +A = 24 +M = 1 + +ModInv = -1 +A = 25 +M = 1 + +ModInv = -1 +A = 26 +M = 1 + +ModInv = -1 +A = 27 +M = 1 + +ModInv = -1 +A = 28 +M = 1 + +ModInv = -1 +A = 29 +M = 1 + +ModInv = -1 +A = 2a +M = 1 + +ModInv = -1 +A = 2b +M = 1 + +ModInv = -1 +A = 2c +M = 1 + +ModInv = -1 +A = 2d +M = 1 + +ModInv = -1 +A = 2e +M = 1 + +ModInv = -1 +A = 2f +M = 1 + +ModInv = -1 +A = 30 +M = 1 + +ModInv = -1 +A = 31 +M = 1 + +ModInv = -1 +A = 32 +M = 1 + +ModInv = -1 +A = 33 +M = 1 + +ModInv = -1 +A = 34 +M = 1 + +ModInv = -1 +A = 35 +M = 1 + +ModInv = -1 +A = 36 +M = 1 + +ModInv = -1 +A = 37 +M = 1 + +ModInv = -1 +A = 38 +M = 1 + +ModInv = -1 +A = 39 +M = 1 + +ModInv = -1 +A = 3a +M = 1 + +ModInv = -1 +A = 3b +M = 1 + +ModInv = -1 +A = 3c +M = 1 + +ModInv = -1 +A = 3d +M = 1 + +ModInv = -1 +A = 3e +M = 1 + +ModInv = -1 +A = 3f +M = 1 + +ModInv = -1 +A = 40 +M = 1 + +ModInv = -1 +A = 41 +M = 1 + +ModInv = -1 +A = 42 +M = 1 + +ModInv = -1 +A = 43 +M = 1 + +ModInv = -1 +A = 44 +M = 1 + +ModInv = -1 +A = 45 +M = 1 + +ModInv = -1 +A = 46 +M = 1 + +ModInv = -1 +A = 47 +M = 1 + +ModInv = -1 +A = 48 +M = 1 + +ModInv = -1 +A = 49 +M = 1 + +ModInv = -1 +A = 4a +M = 1 + +ModInv = -1 +A = 4b +M = 1 + +ModInv = -1 +A = 4c +M = 1 + +ModInv = -1 +A = 4d +M = 1 + +ModInv = -1 +A = 4e +M = 1 + +ModInv = -1 +A = 4f +M = 1 + +ModInv = -1 +A = 50 +M = 1 + +ModInv = -1 +A = 51 +M = 1 + +ModInv = -1 +A = 52 +M = 1 + +ModInv = -1 +A = 53 +M = 1 + +ModInv = -1 +A = 54 +M = 1 + +ModInv = -1 +A = 55 +M = 1 + +ModInv = -1 +A = 56 +M = 1 + +ModInv = -1 +A = 57 +M = 1 + +ModInv = -1 +A = 58 +M = 1 + +ModInv = -1 +A = 59 +M = 1 + +ModInv = -1 +A = 5a +M = 1 + +ModInv = -1 +A = 5b +M = 1 + +ModInv = -1 +A = 5c +M = 1 + +ModInv = -1 +A = 5d +M = 1 + +ModInv = -1 +A = 5e +M = 1 + +ModInv = -1 +A = 5f +M = 1 + +ModInv = -1 +A = 60 +M = 1 + +ModInv = -1 +A = 61 +M = 1 + +ModInv = -1 +A = 62 +M = 1 + +ModInv = -1 +A = 63 +M = 1 + +ModInv = -1 +A = -63 +M = 3 + +ModInv = -1 +A = -60 +M = 3 + +ModInv = -1 +A = -5d +M = 3 + +ModInv = -1 +A = -5a +M = 3 + +ModInv = -1 +A = -57 +M = 3 + +ModInv = -1 +A = -54 +M = 3 + +ModInv = -1 +A = -51 +M = 3 + +ModInv = -1 +A = -4e +M = 3 + +ModInv = -1 +A = -4b +M = 3 + +ModInv = -1 +A = -48 +M = 3 + +ModInv = -1 +A = -45 +M = 3 + +ModInv = -1 +A = -42 +M = 3 + +ModInv = -1 +A = -3f +M = 3 + +ModInv = -1 +A = -3c +M = 3 + +ModInv = -1 +A = -39 +M = 3 + +ModInv = -1 +A = -36 +M = 3 + +ModInv = -1 +A = -33 +M = 3 + +ModInv = -1 +A = -30 +M = 3 + +ModInv = -1 +A = -2d +M = 3 + +ModInv = -1 +A = -2a +M = 3 + +ModInv = -1 +A = -27 +M = 3 + +ModInv = -1 +A = -24 +M = 3 + +ModInv = -1 +A = -21 +M = 3 + +ModInv = -1 +A = -1e +M = 3 + +ModInv = -1 +A = -1b +M = 3 + +ModInv = -1 +A = -18 +M = 3 + +ModInv = -1 +A = -15 +M = 3 + +ModInv = -1 +A = -12 +M = 3 + +ModInv = -1 +A = -f +M = 3 + +ModInv = -1 +A = -c +M = 3 + +ModInv = -1 +A = -9 +M = 3 + +ModInv = -1 +A = -6 +M = 3 + +ModInv = -1 +A = -3 +M = 3 + +ModInv = -1 +A = 0 +M = 3 + +ModInv = -1 +A = 3 +M = 3 + +ModInv = -1 +A = 6 +M = 3 + +ModInv = -1 +A = 9 +M = 3 + +ModInv = -1 +A = c +M = 3 + +ModInv = -1 +A = f +M = 3 + +ModInv = -1 +A = 12 +M = 3 + +ModInv = -1 +A = 15 +M = 3 + +ModInv = -1 +A = 18 +M = 3 + +ModInv = -1 +A = 1b +M = 3 + +ModInv = -1 +A = 1e +M = 3 + +ModInv = -1 +A = 21 +M = 3 + +ModInv = -1 +A = 24 +M = 3 + +ModInv = -1 +A = 27 +M = 3 + +ModInv = -1 +A = 2a +M = 3 + +ModInv = -1 +A = 2d +M = 3 + +ModInv = -1 +A = 30 +M = 3 + +ModInv = -1 +A = 33 +M = 3 + +ModInv = -1 +A = 36 +M = 3 + +ModInv = -1 +A = 39 +M = 3 + +ModInv = -1 +A = 3c +M = 3 + +ModInv = -1 +A = 3f +M = 3 + +ModInv = -1 +A = 42 +M = 3 + +ModInv = -1 +A = 45 +M = 3 + +ModInv = -1 +A = 48 +M = 3 + +ModInv = -1 +A = 4b +M = 3 + +ModInv = -1 +A = 4e +M = 3 + +ModInv = -1 +A = 51 +M = 3 + +ModInv = -1 +A = 54 +M = 3 + +ModInv = -1 +A = 57 +M = 3 + +ModInv = -1 +A = 5a +M = 3 + +ModInv = -1 +A = 5d +M = 3 + +ModInv = -1 +A = 60 +M = 3 + +ModInv = -1 +A = 63 +M = 3 + +ModInv = -1 +A = -64 +M = 5 + +ModInv = -1 +A = -5f +M = 5 + +ModInv = -1 +A = -5a +M = 5 + +ModInv = -1 +A = -55 +M = 5 + +ModInv = -1 +A = -50 +M = 5 + +ModInv = -1 +A = -4b +M = 5 + +ModInv = -1 +A = -46 +M = 5 + +ModInv = -1 +A = -41 +M = 5 + +ModInv = -1 +A = -3c +M = 5 + +ModInv = -1 +A = -37 +M = 5 + +ModInv = -1 +A = -32 +M = 5 + +ModInv = -1 +A = -2d +M = 5 + +ModInv = -1 +A = -28 +M = 5 + +ModInv = -1 +A = -23 +M = 5 + +ModInv = -1 +A = -1e +M = 5 + +ModInv = -1 +A = -19 +M = 5 + +ModInv = -1 +A = -14 +M = 5 + +ModInv = -1 +A = -f +M = 5 + +ModInv = -1 +A = -a +M = 5 + +ModInv = -1 +A = -5 +M = 5 + +ModInv = -1 +A = 0 +M = 5 + +ModInv = -1 +A = 5 +M = 5 + +ModInv = -1 +A = a +M = 5 + +ModInv = -1 +A = f +M = 5 + +ModInv = -1 +A = 14 +M = 5 + +ModInv = -1 +A = 19 +M = 5 + +ModInv = -1 +A = 1e +M = 5 + +ModInv = -1 +A = 23 +M = 5 + +ModInv = -1 +A = 28 +M = 5 + +ModInv = -1 +A = 2d +M = 5 + +ModInv = -1 +A = 32 +M = 5 + +ModInv = -1 +A = 37 +M = 5 + +ModInv = -1 +A = 3c +M = 5 + +ModInv = -1 +A = 41 +M = 5 + +ModInv = -1 +A = 46 +M = 5 + +ModInv = -1 +A = 4b +M = 5 + +ModInv = -1 +A = 50 +M = 5 + +ModInv = -1 +A = 55 +M = 5 + +ModInv = -1 +A = 5a +M = 5 + +ModInv = -1 +A = 5f +M = 5 + +ModInv = -1 +A = -63 +M = 6 + +ModInv = -1 +A = -5d +M = 6 + +ModInv = -1 +A = -57 +M = 6 + +ModInv = -1 +A = -51 +M = 6 + +ModInv = -1 +A = -4b +M = 6 + +ModInv = -1 +A = -45 +M = 6 + +ModInv = -1 +A = -3f +M = 6 + +ModInv = -1 +A = -39 +M = 6 + +ModInv = -1 +A = -33 +M = 6 + +ModInv = -1 +A = -2d +M = 6 + +ModInv = -1 +A = -27 +M = 6 + +ModInv = -1 +A = -21 +M = 6 + +ModInv = -1 +A = -1b +M = 6 + +ModInv = -1 +A = -15 +M = 6 + +ModInv = -1 +A = -f +M = 6 + +ModInv = -1 +A = -9 +M = 6 + +ModInv = -1 +A = -3 +M = 6 + +ModInv = -1 +A = 3 +M = 6 + +ModInv = -1 +A = 9 +M = 6 + +ModInv = -1 +A = f +M = 6 + +ModInv = -1 +A = 15 +M = 6 + +ModInv = -1 +A = 1b +M = 6 + +ModInv = -1 +A = 21 +M = 6 + +ModInv = -1 +A = 27 +M = 6 + +ModInv = -1 +A = 2d +M = 6 + +ModInv = -1 +A = 33 +M = 6 + +ModInv = -1 +A = 39 +M = 6 + +ModInv = -1 +A = 3f +M = 6 + +ModInv = -1 +A = 45 +M = 6 + +ModInv = -1 +A = 4b +M = 6 + +ModInv = -1 +A = 51 +M = 6 + +ModInv = -1 +A = 57 +M = 6 + +ModInv = -1 +A = 5d +M = 6 + +ModInv = -1 +A = 63 +M = 6 + +ModInv = -1 +A = -62 +M = 7 + +ModInv = -1 +A = -5b +M = 7 + +ModInv = -1 +A = -54 +M = 7 + +ModInv = -1 +A = -4d +M = 7 + +ModInv = -1 +A = -46 +M = 7 + +ModInv = -1 +A = -3f +M = 7 + +ModInv = -1 +A = -38 +M = 7 + +ModInv = -1 +A = -31 +M = 7 + +ModInv = -1 +A = -2a +M = 7 + +ModInv = -1 +A = -23 +M = 7 + +ModInv = -1 +A = -1c +M = 7 + +ModInv = -1 +A = -15 +M = 7 + +ModInv = -1 +A = -e +M = 7 + +ModInv = -1 +A = -7 +M = 7 + +ModInv = -1 +A = 0 +M = 7 + +ModInv = -1 +A = 7 +M = 7 + +ModInv = -1 +A = e +M = 7 + +ModInv = -1 +A = 15 +M = 7 + +ModInv = -1 +A = 1c +M = 7 + +ModInv = -1 +A = 23 +M = 7 + +ModInv = -1 +A = 2a +M = 7 + +ModInv = -1 +A = 31 +M = 7 + +ModInv = -1 +A = 38 +M = 7 + +ModInv = -1 +A = 3f +M = 7 + +ModInv = -1 +A = 46 +M = 7 + +ModInv = -1 +A = 4d +M = 7 + +ModInv = -1 +A = 54 +M = 7 + +ModInv = -1 +A = 5b +M = 7 + +ModInv = -1 +A = 62 +M = 7 + +ModInv = -1 +A = -63 +M = 9 + +ModInv = -1 +A = -60 +M = 9 + +ModInv = -1 +A = -5d +M = 9 + +ModInv = -1 +A = -5a +M = 9 + +ModInv = -1 +A = -57 +M = 9 + +ModInv = -1 +A = -54 +M = 9 + +ModInv = -1 +A = -51 +M = 9 + +ModInv = -1 +A = -4e +M = 9 + +ModInv = -1 +A = -4b +M = 9 + +ModInv = -1 +A = -48 +M = 9 + +ModInv = -1 +A = -45 +M = 9 + +ModInv = -1 +A = -42 +M = 9 + +ModInv = -1 +A = -3f +M = 9 + +ModInv = -1 +A = -3c +M = 9 + +ModInv = -1 +A = -39 +M = 9 + +ModInv = -1 +A = -36 +M = 9 + +ModInv = -1 +A = -33 +M = 9 + +ModInv = -1 +A = -30 +M = 9 + +ModInv = -1 +A = -2d +M = 9 + +ModInv = -1 +A = -2a +M = 9 + +ModInv = -1 +A = -27 +M = 9 + +ModInv = -1 +A = -24 +M = 9 + +ModInv = -1 +A = -21 +M = 9 + +ModInv = -1 +A = -1e +M = 9 + +ModInv = -1 +A = -1b +M = 9 + +ModInv = -1 +A = -18 +M = 9 + +ModInv = -1 +A = -15 +M = 9 + +ModInv = -1 +A = -12 +M = 9 + +ModInv = -1 +A = -f +M = 9 + +ModInv = -1 +A = -c +M = 9 + +ModInv = -1 +A = -9 +M = 9 + +ModInv = -1 +A = -6 +M = 9 + +ModInv = -1 +A = -3 +M = 9 + +ModInv = -1 +A = 0 +M = 9 + +ModInv = -1 +A = 3 +M = 9 + +ModInv = -1 +A = 6 +M = 9 + +ModInv = -1 +A = 9 +M = 9 + +ModInv = -1 +A = c +M = 9 + +ModInv = -1 +A = f +M = 9 + +ModInv = -1 +A = 12 +M = 9 + +ModInv = -1 +A = 15 +M = 9 + +ModInv = -1 +A = 18 +M = 9 + +ModInv = -1 +A = 1b +M = 9 + +ModInv = -1 +A = 1e +M = 9 + +ModInv = -1 +A = 21 +M = 9 + +ModInv = -1 +A = 24 +M = 9 + +ModInv = -1 +A = 27 +M = 9 + +ModInv = -1 +A = 2a +M = 9 + +ModInv = -1 +A = 2d +M = 9 + +ModInv = -1 +A = 30 +M = 9 + +ModInv = -1 +A = 33 +M = 9 + +ModInv = -1 +A = 36 +M = 9 + +ModInv = -1 +A = 39 +M = 9 + +ModInv = -1 +A = 3c +M = 9 + +ModInv = -1 +A = 3f +M = 9 + +ModInv = -1 +A = 42 +M = 9 + +ModInv = -1 +A = 45 +M = 9 + +ModInv = -1 +A = 48 +M = 9 + +ModInv = -1 +A = 4b +M = 9 + +ModInv = -1 +A = 4e +M = 9 + +ModInv = -1 +A = 51 +M = 9 + +ModInv = -1 +A = 54 +M = 9 + +ModInv = -1 +A = 57 +M = 9 + +ModInv = -1 +A = 5a +M = 9 + +ModInv = -1 +A = 5d +M = 9 + +ModInv = -1 +A = 60 +M = 9 + +ModInv = -1 +A = 63 +M = 9 + +ModInv = -1 +A = -5f +M = a + +ModInv = -1 +A = -55 +M = a + +ModInv = -1 +A = -4b +M = a + +ModInv = -1 +A = -41 +M = a + +ModInv = -1 +A = -37 +M = a + +ModInv = -1 +A = -2d +M = a + +ModInv = -1 +A = -23 +M = a + +ModInv = -1 +A = -19 +M = a + +ModInv = -1 +A = -f +M = a + +ModInv = -1 +A = -5 +M = a + +ModInv = -1 +A = 5 +M = a + +ModInv = -1 +A = f +M = a + +ModInv = -1 +A = 19 +M = a + +ModInv = -1 +A = 23 +M = a + +ModInv = -1 +A = 2d +M = a + +ModInv = -1 +A = 37 +M = a + +ModInv = -1 +A = 41 +M = a + +ModInv = -1 +A = 4b +M = a + +ModInv = -1 +A = 55 +M = a + +ModInv = -1 +A = 5f +M = a + +ModInv = -1 +A = -63 +M = b + +ModInv = -1 +A = -58 +M = b + +ModInv = -1 +A = -4d +M = b + +ModInv = -1 +A = -42 +M = b + +ModInv = -1 +A = -37 +M = b + +ModInv = -1 +A = -2c +M = b + +ModInv = -1 +A = -21 +M = b + +ModInv = -1 +A = -16 +M = b + +ModInv = -1 +A = -b +M = b + +ModInv = -1 +A = 0 +M = b + +ModInv = -1 +A = b +M = b + +ModInv = -1 +A = 16 +M = b + +ModInv = -1 +A = 21 +M = b + +ModInv = -1 +A = 2c +M = b + +ModInv = -1 +A = 37 +M = b + +ModInv = -1 +A = 42 +M = b + +ModInv = -1 +A = 4d +M = b + +ModInv = -1 +A = 58 +M = b + +ModInv = -1 +A = 63 +M = b + +ModInv = -1 +A = -63 +M = c + +ModInv = -1 +A = -5d +M = c + +ModInv = -1 +A = -57 +M = c + +ModInv = -1 +A = -51 +M = c + +ModInv = -1 +A = -4b +M = c + +ModInv = -1 +A = -45 +M = c + +ModInv = -1 +A = -3f +M = c + +ModInv = -1 +A = -39 +M = c + +ModInv = -1 +A = -33 +M = c + +ModInv = -1 +A = -2d +M = c + +ModInv = -1 +A = -27 +M = c + +ModInv = -1 +A = -21 +M = c + +ModInv = -1 +A = -1b +M = c + +ModInv = -1 +A = -15 +M = c + +ModInv = -1 +A = -f +M = c + +ModInv = -1 +A = -9 +M = c + +ModInv = -1 +A = -3 +M = c + +ModInv = -1 +A = 3 +M = c + +ModInv = -1 +A = 9 +M = c + +ModInv = -1 +A = f +M = c + +ModInv = -1 +A = 15 +M = c + +ModInv = -1 +A = 1b +M = c + +ModInv = -1 +A = 21 +M = c + +ModInv = -1 +A = 27 +M = c + +ModInv = -1 +A = 2d +M = c + +ModInv = -1 +A = 33 +M = c + +ModInv = -1 +A = 39 +M = c + +ModInv = -1 +A = 3f +M = c + +ModInv = -1 +A = 45 +M = c + +ModInv = -1 +A = 4b +M = c + +ModInv = -1 +A = 51 +M = c + +ModInv = -1 +A = 57 +M = c + +ModInv = -1 +A = 5d +M = c + +ModInv = -1 +A = 63 +M = c + +ModInv = -1 +A = -5b +M = d + +ModInv = -1 +A = -4e +M = d + +ModInv = -1 +A = -41 +M = d + +ModInv = -1 +A = -34 +M = d + +ModInv = -1 +A = -27 +M = d + +ModInv = -1 +A = -1a +M = d + +ModInv = -1 +A = -d +M = d + +ModInv = -1 +A = 0 +M = d + +ModInv = -1 +A = d +M = d + +ModInv = -1 +A = 1a +M = d + +ModInv = -1 +A = 27 +M = d + +ModInv = -1 +A = 34 +M = d + +ModInv = -1 +A = 41 +M = d + +ModInv = -1 +A = 4e +M = d + +ModInv = -1 +A = 5b +M = d + +ModInv = -1 +A = -5b +M = e + +ModInv = -1 +A = -4d +M = e + +ModInv = -1 +A = -3f +M = e + +ModInv = -1 +A = -31 +M = e + +ModInv = -1 +A = -23 +M = e + +ModInv = -1 +A = -15 +M = e + +ModInv = -1 +A = -7 +M = e + +ModInv = -1 +A = 7 +M = e + +ModInv = -1 +A = 15 +M = e + +ModInv = -1 +A = 23 +M = e + +ModInv = -1 +A = 31 +M = e + +ModInv = -1 +A = 3f +M = e + +ModInv = -1 +A = 4d +M = e + +ModInv = -1 +A = 5b +M = e + +ModInv = -1 +A = -64 +M = f + +ModInv = -1 +A = -63 +M = f + +ModInv = -1 +A = -60 +M = f + +ModInv = -1 +A = -5f +M = f + +ModInv = -1 +A = -5d +M = f + +ModInv = -1 +A = -5a +M = f + +ModInv = -1 +A = -57 +M = f + +ModInv = -1 +A = -55 +M = f + +ModInv = -1 +A = -54 +M = f + +ModInv = -1 +A = -51 +M = f + +ModInv = -1 +A = -50 +M = f + +ModInv = -1 +A = -4e +M = f + +ModInv = -1 +A = -4b +M = f + +ModInv = -1 +A = -48 +M = f + +ModInv = -1 +A = -46 +M = f + +ModInv = -1 +A = -45 +M = f + +ModInv = -1 +A = -42 +M = f + +ModInv = -1 +A = -41 +M = f + +ModInv = -1 +A = -3f +M = f + +ModInv = -1 +A = -3c +M = f + +ModInv = -1 +A = -39 +M = f + +ModInv = -1 +A = -37 +M = f + +ModInv = -1 +A = -36 +M = f + +ModInv = -1 +A = -33 +M = f + +ModInv = -1 +A = -32 +M = f + +ModInv = -1 +A = -30 +M = f + +ModInv = -1 +A = -2d +M = f + +ModInv = -1 +A = -2a +M = f + +ModInv = -1 +A = -28 +M = f + +ModInv = -1 +A = -27 +M = f + +ModInv = -1 +A = -24 +M = f + +ModInv = -1 +A = -23 +M = f + +ModInv = -1 +A = -21 +M = f + +ModInv = -1 +A = -1e +M = f + +ModInv = -1 +A = -1b +M = f + +ModInv = -1 +A = -19 +M = f + +ModInv = -1 +A = -18 +M = f + +ModInv = -1 +A = -15 +M = f + +ModInv = -1 +A = -14 +M = f + +ModInv = -1 +A = -12 +M = f + +ModInv = -1 +A = -f +M = f + +ModInv = -1 +A = -c +M = f + +ModInv = -1 +A = -a +M = f + +ModInv = -1 +A = -9 +M = f + +ModInv = -1 +A = -6 +M = f + +ModInv = -1 +A = -5 +M = f + +ModInv = -1 +A = -3 +M = f + +ModInv = -1 +A = 0 +M = f + +ModInv = -1 +A = 3 +M = f + +ModInv = -1 +A = 5 +M = f + +ModInv = -1 +A = 6 +M = f + +ModInv = -1 +A = 9 +M = f + +ModInv = -1 +A = a +M = f + +ModInv = -1 +A = c +M = f + +ModInv = -1 +A = f +M = f + +ModInv = -1 +A = 12 +M = f + +ModInv = -1 +A = 14 +M = f + +ModInv = -1 +A = 15 +M = f + +ModInv = -1 +A = 18 +M = f + +ModInv = -1 +A = 19 +M = f + +ModInv = -1 +A = 1b +M = f + +ModInv = -1 +A = 1e +M = f + +ModInv = -1 +A = 21 +M = f + +ModInv = -1 +A = 23 +M = f + +ModInv = -1 +A = 24 +M = f + +ModInv = -1 +A = 27 +M = f + +ModInv = -1 +A = 28 +M = f + +ModInv = -1 +A = 2a +M = f + +ModInv = -1 +A = 2d +M = f + +ModInv = -1 +A = 30 +M = f + +ModInv = -1 +A = 32 +M = f + +ModInv = -1 +A = 33 +M = f + +ModInv = -1 +A = 36 +M = f + +ModInv = -1 +A = 37 +M = f + +ModInv = -1 +A = 39 +M = f + +ModInv = -1 +A = 3c +M = f + +ModInv = -1 +A = 3f +M = f + +ModInv = -1 +A = 41 +M = f + +ModInv = -1 +A = 42 +M = f + +ModInv = -1 +A = 45 +M = f + +ModInv = -1 +A = 46 +M = f + +ModInv = -1 +A = 48 +M = f + +ModInv = -1 +A = 4b +M = f + +ModInv = -1 +A = 4e +M = f + +ModInv = -1 +A = 50 +M = f + +ModInv = -1 +A = 51 +M = f + +ModInv = -1 +A = 54 +M = f + +ModInv = -1 +A = 55 +M = f + +ModInv = -1 +A = 57 +M = f + +ModInv = -1 +A = 5a +M = f + +ModInv = -1 +A = 5d +M = f + +ModInv = -1 +A = 5f +M = f + +ModInv = -1 +A = 60 +M = f + +ModInv = -1 +A = 63 +M = f + +ModInv = -1 +A = -55 +M = 11 + +ModInv = -1 +A = -44 +M = 11 + +ModInv = -1 +A = -33 +M = 11 + +ModInv = -1 +A = -22 +M = 11 + +ModInv = -1 +A = -11 +M = 11 + +ModInv = -1 +A = 0 +M = 11 + +ModInv = -1 +A = 11 +M = 11 + +ModInv = -1 +A = 22 +M = 11 + +ModInv = -1 +A = 33 +M = 11 + +ModInv = -1 +A = 44 +M = 11 + +ModInv = -1 +A = 55 +M = 11 + +ModInv = -1 +A = -63 +M = 12 + +ModInv = -1 +A = -5d +M = 12 + +ModInv = -1 +A = -57 +M = 12 + +ModInv = -1 +A = -51 +M = 12 + +ModInv = -1 +A = -4b +M = 12 + +ModInv = -1 +A = -45 +M = 12 + +ModInv = -1 +A = -3f +M = 12 + +ModInv = -1 +A = -39 +M = 12 + +ModInv = -1 +A = -33 +M = 12 + +ModInv = -1 +A = -2d +M = 12 + +ModInv = -1 +A = -27 +M = 12 + +ModInv = -1 +A = -21 +M = 12 + +ModInv = -1 +A = -1b +M = 12 + +ModInv = -1 +A = -15 +M = 12 + +ModInv = -1 +A = -f +M = 12 + +ModInv = -1 +A = -9 +M = 12 + +ModInv = -1 +A = -3 +M = 12 + +ModInv = -1 +A = 3 +M = 12 + +ModInv = -1 +A = 9 +M = 12 + +ModInv = -1 +A = f +M = 12 + +ModInv = -1 +A = 15 +M = 12 + +ModInv = -1 +A = 1b +M = 12 + +ModInv = -1 +A = 21 +M = 12 + +ModInv = -1 +A = 27 +M = 12 + +ModInv = -1 +A = 2d +M = 12 + +ModInv = -1 +A = 33 +M = 12 + +ModInv = -1 +A = 39 +M = 12 + +ModInv = -1 +A = 3f +M = 12 + +ModInv = -1 +A = 45 +M = 12 + +ModInv = -1 +A = 4b +M = 12 + +ModInv = -1 +A = 51 +M = 12 + +ModInv = -1 +A = 57 +M = 12 + +ModInv = -1 +A = 5d +M = 12 + +ModInv = -1 +A = 63 +M = 12 + +ModInv = -1 +A = -5f +M = 13 + +ModInv = -1 +A = -4c +M = 13 + +ModInv = -1 +A = -39 +M = 13 + +ModInv = -1 +A = -26 +M = 13 + +ModInv = -1 +A = -13 +M = 13 + +ModInv = -1 +A = 0 +M = 13 + +ModInv = -1 +A = 13 +M = 13 + +ModInv = -1 +A = 26 +M = 13 + +ModInv = -1 +A = 39 +M = 13 + +ModInv = -1 +A = 4c +M = 13 + +ModInv = -1 +A = 5f +M = 13 + +ModInv = -1 +A = -5f +M = 14 + +ModInv = -1 +A = -55 +M = 14 + +ModInv = -1 +A = -4b +M = 14 + +ModInv = -1 +A = -41 +M = 14 + +ModInv = -1 +A = -37 +M = 14 + +ModInv = -1 +A = -2d +M = 14 + +ModInv = -1 +A = -23 +M = 14 + +ModInv = -1 +A = -19 +M = 14 + +ModInv = -1 +A = -f +M = 14 + +ModInv = -1 +A = -5 +M = 14 + +ModInv = -1 +A = 5 +M = 14 + +ModInv = -1 +A = f +M = 14 + +ModInv = -1 +A = 19 +M = 14 + +ModInv = -1 +A = 23 +M = 14 + +ModInv = -1 +A = 2d +M = 14 + +ModInv = -1 +A = 37 +M = 14 + +ModInv = -1 +A = 41 +M = 14 + +ModInv = -1 +A = 4b +M = 14 + +ModInv = -1 +A = 55 +M = 14 + +ModInv = -1 +A = 5f +M = 14 + +ModInv = -1 +A = -63 +M = 15 + +ModInv = -1 +A = -62 +M = 15 + +ModInv = -1 +A = -60 +M = 15 + +ModInv = -1 +A = -5d +M = 15 + +ModInv = -1 +A = -5b +M = 15 + +ModInv = -1 +A = -5a +M = 15 + +ModInv = -1 +A = -57 +M = 15 + +ModInv = -1 +A = -54 +M = 15 + +ModInv = -1 +A = -51 +M = 15 + +ModInv = -1 +A = -4e +M = 15 + +ModInv = -1 +A = -4d +M = 15 + +ModInv = -1 +A = -4b +M = 15 + +ModInv = -1 +A = -48 +M = 15 + +ModInv = -1 +A = -46 +M = 15 + +ModInv = -1 +A = -45 +M = 15 + +ModInv = -1 +A = -42 +M = 15 + +ModInv = -1 +A = -3f +M = 15 + +ModInv = -1 +A = -3c +M = 15 + +ModInv = -1 +A = -39 +M = 15 + +ModInv = -1 +A = -38 +M = 15 + +ModInv = -1 +A = -36 +M = 15 + +ModInv = -1 +A = -33 +M = 15 + +ModInv = -1 +A = -31 +M = 15 + +ModInv = -1 +A = -30 +M = 15 + +ModInv = -1 +A = -2d +M = 15 + +ModInv = -1 +A = -2a +M = 15 + +ModInv = -1 +A = -27 +M = 15 + +ModInv = -1 +A = -24 +M = 15 + +ModInv = -1 +A = -23 +M = 15 + +ModInv = -1 +A = -21 +M = 15 + +ModInv = -1 +A = -1e +M = 15 + +ModInv = -1 +A = -1c +M = 15 + +ModInv = -1 +A = -1b +M = 15 + +ModInv = -1 +A = -18 +M = 15 + +ModInv = -1 +A = -15 +M = 15 + +ModInv = -1 +A = -12 +M = 15 + +ModInv = -1 +A = -f +M = 15 + +ModInv = -1 +A = -e +M = 15 + +ModInv = -1 +A = -c +M = 15 + +ModInv = -1 +A = -9 +M = 15 + +ModInv = -1 +A = -7 +M = 15 + +ModInv = -1 +A = -6 +M = 15 + +ModInv = -1 +A = -3 +M = 15 + +ModInv = -1 +A = 0 +M = 15 + +ModInv = -1 +A = 3 +M = 15 + +ModInv = -1 +A = 6 +M = 15 + +ModInv = -1 +A = 7 +M = 15 + +ModInv = -1 +A = 9 +M = 15 + +ModInv = -1 +A = c +M = 15 + +ModInv = -1 +A = e +M = 15 + +ModInv = -1 +A = f +M = 15 + +ModInv = -1 +A = 12 +M = 15 + +ModInv = -1 +A = 15 +M = 15 + +ModInv = -1 +A = 18 +M = 15 + +ModInv = -1 +A = 1b +M = 15 + +ModInv = -1 +A = 1c +M = 15 + +ModInv = -1 +A = 1e +M = 15 + +ModInv = -1 +A = 21 +M = 15 + +ModInv = -1 +A = 23 +M = 15 + +ModInv = -1 +A = 24 +M = 15 + +ModInv = -1 +A = 27 +M = 15 + +ModInv = -1 +A = 2a +M = 15 + +ModInv = -1 +A = 2d +M = 15 + +ModInv = -1 +A = 30 +M = 15 + +ModInv = -1 +A = 31 +M = 15 + +ModInv = -1 +A = 33 +M = 15 + +ModInv = -1 +A = 36 +M = 15 + +ModInv = -1 +A = 38 +M = 15 + +ModInv = -1 +A = 39 +M = 15 + +ModInv = -1 +A = 3c +M = 15 + +ModInv = -1 +A = 3f +M = 15 + +ModInv = -1 +A = 42 +M = 15 + +ModInv = -1 +A = 45 +M = 15 + +ModInv = -1 +A = 46 +M = 15 + +ModInv = -1 +A = 48 +M = 15 + +ModInv = -1 +A = 4b +M = 15 + +ModInv = -1 +A = 4d +M = 15 + +ModInv = -1 +A = 4e +M = 15 + +ModInv = -1 +A = 51 +M = 15 + +ModInv = -1 +A = 54 +M = 15 + +ModInv = -1 +A = 57 +M = 15 + +ModInv = -1 +A = 5a +M = 15 + +ModInv = -1 +A = 5b +M = 15 + +ModInv = -1 +A = 5d +M = 15 + +ModInv = -1 +A = 60 +M = 15 + +ModInv = -1 +A = 62 +M = 15 + +ModInv = -1 +A = 63 +M = 15 + +ModInv = -1 +A = -63 +M = 16 + +ModInv = -1 +A = -4d +M = 16 + +ModInv = -1 +A = -37 +M = 16 + +ModInv = -1 +A = -21 +M = 16 + +ModInv = -1 +A = -b +M = 16 + +ModInv = -1 +A = b +M = 16 + +ModInv = -1 +A = 21 +M = 16 + +ModInv = -1 +A = 37 +M = 16 + +ModInv = -1 +A = 4d +M = 16 + +ModInv = -1 +A = 63 +M = 16 + +ModInv = -1 +A = -5c +M = 17 + +ModInv = -1 +A = -45 +M = 17 + +ModInv = -1 +A = -2e +M = 17 + +ModInv = -1 +A = -17 +M = 17 + +ModInv = -1 +A = 0 +M = 17 + +ModInv = -1 +A = 17 +M = 17 + +ModInv = -1 +A = 2e +M = 17 + +ModInv = -1 +A = 45 +M = 17 + +ModInv = -1 +A = 5c +M = 17 + +ModInv = -1 +A = -63 +M = 18 + +ModInv = -1 +A = -5d +M = 18 + +ModInv = -1 +A = -57 +M = 18 + +ModInv = -1 +A = -51 +M = 18 + +ModInv = -1 +A = -4b +M = 18 + +ModInv = -1 +A = -45 +M = 18 + +ModInv = -1 +A = -3f +M = 18 + +ModInv = -1 +A = -39 +M = 18 + +ModInv = -1 +A = -33 +M = 18 + +ModInv = -1 +A = -2d +M = 18 + +ModInv = -1 +A = -27 +M = 18 + +ModInv = -1 +A = -21 +M = 18 + +ModInv = -1 +A = -1b +M = 18 + +ModInv = -1 +A = -15 +M = 18 + +ModInv = -1 +A = -f +M = 18 + +ModInv = -1 +A = -9 +M = 18 + +ModInv = -1 +A = -3 +M = 18 + +ModInv = -1 +A = 3 +M = 18 + +ModInv = -1 +A = 9 +M = 18 + +ModInv = -1 +A = f +M = 18 + +ModInv = -1 +A = 15 +M = 18 + +ModInv = -1 +A = 1b +M = 18 + +ModInv = -1 +A = 21 +M = 18 + +ModInv = -1 +A = 27 +M = 18 + +ModInv = -1 +A = 2d +M = 18 + +ModInv = -1 +A = 33 +M = 18 + +ModInv = -1 +A = 39 +M = 18 + +ModInv = -1 +A = 3f +M = 18 + +ModInv = -1 +A = 45 +M = 18 + +ModInv = -1 +A = 4b +M = 18 + +ModInv = -1 +A = 51 +M = 18 + +ModInv = -1 +A = 57 +M = 18 + +ModInv = -1 +A = 5d +M = 18 + +ModInv = -1 +A = 63 +M = 18 + +ModInv = -1 +A = -64 +M = 19 + +ModInv = -1 +A = -5f +M = 19 + +ModInv = -1 +A = -5a +M = 19 + +ModInv = -1 +A = -55 +M = 19 + +ModInv = -1 +A = -50 +M = 19 + +ModInv = -1 +A = -4b +M = 19 + +ModInv = -1 +A = -46 +M = 19 + +ModInv = -1 +A = -41 +M = 19 + +ModInv = -1 +A = -3c +M = 19 + +ModInv = -1 +A = -37 +M = 19 + +ModInv = -1 +A = -32 +M = 19 + +ModInv = -1 +A = -2d +M = 19 + +ModInv = -1 +A = -28 +M = 19 + +ModInv = -1 +A = -23 +M = 19 + +ModInv = -1 +A = -1e +M = 19 + +ModInv = -1 +A = -19 +M = 19 + +ModInv = -1 +A = -14 +M = 19 + +ModInv = -1 +A = -f +M = 19 + +ModInv = -1 +A = -a +M = 19 + +ModInv = -1 +A = -5 +M = 19 + +ModInv = -1 +A = 0 +M = 19 + +ModInv = -1 +A = 5 +M = 19 + +ModInv = -1 +A = a +M = 19 + +ModInv = -1 +A = f +M = 19 + +ModInv = -1 +A = 14 +M = 19 + +ModInv = -1 +A = 19 +M = 19 + +ModInv = -1 +A = 1e +M = 19 + +ModInv = -1 +A = 23 +M = 19 + +ModInv = -1 +A = 28 +M = 19 + +ModInv = -1 +A = 2d +M = 19 + +ModInv = -1 +A = 32 +M = 19 + +ModInv = -1 +A = 37 +M = 19 + +ModInv = -1 +A = 3c +M = 19 + +ModInv = -1 +A = 41 +M = 19 + +ModInv = -1 +A = 46 +M = 19 + +ModInv = -1 +A = 4b +M = 19 + +ModInv = -1 +A = 50 +M = 19 + +ModInv = -1 +A = 55 +M = 19 + +ModInv = -1 +A = 5a +M = 19 + +ModInv = -1 +A = 5f +M = 19 + +ModInv = -1 +A = -5b +M = 1a + +ModInv = -1 +A = -41 +M = 1a + +ModInv = -1 +A = -27 +M = 1a + +ModInv = -1 +A = -d +M = 1a + +ModInv = -1 +A = d +M = 1a + +ModInv = -1 +A = 27 +M = 1a + +ModInv = -1 +A = 41 +M = 1a + +ModInv = -1 +A = 5b +M = 1a + +ModInv = -1 +A = -63 +M = 1b + +ModInv = -1 +A = -60 +M = 1b + +ModInv = -1 +A = -5d +M = 1b + +ModInv = -1 +A = -5a +M = 1b + +ModInv = -1 +A = -57 +M = 1b + +ModInv = -1 +A = -54 +M = 1b + +ModInv = -1 +A = -51 +M = 1b + +ModInv = -1 +A = -4e +M = 1b + +ModInv = -1 +A = -4b +M = 1b + +ModInv = -1 +A = -48 +M = 1b + +ModInv = -1 +A = -45 +M = 1b + +ModInv = -1 +A = -42 +M = 1b + +ModInv = -1 +A = -3f +M = 1b + +ModInv = -1 +A = -3c +M = 1b + +ModInv = -1 +A = -39 +M = 1b + +ModInv = -1 +A = -36 +M = 1b + +ModInv = -1 +A = -33 +M = 1b + +ModInv = -1 +A = -30 +M = 1b + +ModInv = -1 +A = -2d +M = 1b + +ModInv = -1 +A = -2a +M = 1b + +ModInv = -1 +A = -27 +M = 1b + +ModInv = -1 +A = -24 +M = 1b + +ModInv = -1 +A = -21 +M = 1b + +ModInv = -1 +A = -1e +M = 1b + +ModInv = -1 +A = -1b +M = 1b + +ModInv = -1 +A = -18 +M = 1b + +ModInv = -1 +A = -15 +M = 1b + +ModInv = -1 +A = -12 +M = 1b + +ModInv = -1 +A = -f +M = 1b + +ModInv = -1 +A = -c +M = 1b + +ModInv = -1 +A = -9 +M = 1b + +ModInv = -1 +A = -6 +M = 1b + +ModInv = -1 +A = -3 +M = 1b + +ModInv = -1 +A = 0 +M = 1b + +ModInv = -1 +A = 3 +M = 1b + +ModInv = -1 +A = 6 +M = 1b + +ModInv = -1 +A = 9 +M = 1b + +ModInv = -1 +A = c +M = 1b + +ModInv = -1 +A = f +M = 1b + +ModInv = -1 +A = 12 +M = 1b + +ModInv = -1 +A = 15 +M = 1b + +ModInv = -1 +A = 18 +M = 1b + +ModInv = -1 +A = 1b +M = 1b + +ModInv = -1 +A = 1e +M = 1b + +ModInv = -1 +A = 21 +M = 1b + +ModInv = -1 +A = 24 +M = 1b + +ModInv = -1 +A = 27 +M = 1b + +ModInv = -1 +A = 2a +M = 1b + +ModInv = -1 +A = 2d +M = 1b + +ModInv = -1 +A = 30 +M = 1b + +ModInv = -1 +A = 33 +M = 1b + +ModInv = -1 +A = 36 +M = 1b + +ModInv = -1 +A = 39 +M = 1b + +ModInv = -1 +A = 3c +M = 1b + +ModInv = -1 +A = 3f +M = 1b + +ModInv = -1 +A = 42 +M = 1b + +ModInv = -1 +A = 45 +M = 1b + +ModInv = -1 +A = 48 +M = 1b + +ModInv = -1 +A = 4b +M = 1b + +ModInv = -1 +A = 4e +M = 1b + +ModInv = -1 +A = 51 +M = 1b + +ModInv = -1 +A = 54 +M = 1b + +ModInv = -1 +A = 57 +M = 1b + +ModInv = -1 +A = 5a +M = 1b + +ModInv = -1 +A = 5d +M = 1b + +ModInv = -1 +A = 60 +M = 1b + +ModInv = -1 +A = 63 +M = 1b + +ModInv = -1 +A = -5b +M = 1c + +ModInv = -1 +A = -4d +M = 1c + +ModInv = -1 +A = -3f +M = 1c + +ModInv = -1 +A = -31 +M = 1c + +ModInv = -1 +A = -23 +M = 1c + +ModInv = -1 +A = -15 +M = 1c + +ModInv = -1 +A = -7 +M = 1c + +ModInv = -1 +A = 7 +M = 1c + +ModInv = -1 +A = 15 +M = 1c + +ModInv = -1 +A = 23 +M = 1c + +ModInv = -1 +A = 31 +M = 1c + +ModInv = -1 +A = 3f +M = 1c + +ModInv = -1 +A = 4d +M = 1c + +ModInv = -1 +A = 5b +M = 1c + +ModInv = -1 +A = -57 +M = 1d + +ModInv = -1 +A = -3a +M = 1d + +ModInv = -1 +A = -1d +M = 1d + +ModInv = -1 +A = 0 +M = 1d + +ModInv = -1 +A = 1d +M = 1d + +ModInv = -1 +A = 3a +M = 1d + +ModInv = -1 +A = 57 +M = 1d + +ModInv = -1 +A = -63 +M = 1e + +ModInv = -1 +A = -5f +M = 1e + +ModInv = -1 +A = -5d +M = 1e + +ModInv = -1 +A = -57 +M = 1e + +ModInv = -1 +A = -55 +M = 1e + +ModInv = -1 +A = -51 +M = 1e + +ModInv = -1 +A = -4b +M = 1e + +ModInv = -1 +A = -45 +M = 1e + +ModInv = -1 +A = -41 +M = 1e + +ModInv = -1 +A = -3f +M = 1e + +ModInv = -1 +A = -39 +M = 1e + +ModInv = -1 +A = -37 +M = 1e + +ModInv = -1 +A = -33 +M = 1e + +ModInv = -1 +A = -2d +M = 1e + +ModInv = -1 +A = -27 +M = 1e + +ModInv = -1 +A = -23 +M = 1e + +ModInv = -1 +A = -21 +M = 1e + +ModInv = -1 +A = -1b +M = 1e + +ModInv = -1 +A = -19 +M = 1e + +ModInv = -1 +A = -15 +M = 1e + +ModInv = -1 +A = -f +M = 1e + +ModInv = -1 +A = -9 +M = 1e + +ModInv = -1 +A = -5 +M = 1e + +ModInv = -1 +A = -3 +M = 1e + +ModInv = -1 +A = 3 +M = 1e + +ModInv = -1 +A = 5 +M = 1e + +ModInv = -1 +A = 9 +M = 1e + +ModInv = -1 +A = f +M = 1e + +ModInv = -1 +A = 15 +M = 1e + +ModInv = -1 +A = 19 +M = 1e + +ModInv = -1 +A = 1b +M = 1e + +ModInv = -1 +A = 21 +M = 1e + +ModInv = -1 +A = 23 +M = 1e + +ModInv = -1 +A = 27 +M = 1e + +ModInv = -1 +A = 2d +M = 1e + +ModInv = -1 +A = 33 +M = 1e + +ModInv = -1 +A = 37 +M = 1e + +ModInv = -1 +A = 39 +M = 1e + +ModInv = -1 +A = 3f +M = 1e + +ModInv = -1 +A = 41 +M = 1e + +ModInv = -1 +A = 45 +M = 1e + +ModInv = -1 +A = 4b +M = 1e + +ModInv = -1 +A = 51 +M = 1e + +ModInv = -1 +A = 55 +M = 1e + +ModInv = -1 +A = 57 +M = 1e + +ModInv = -1 +A = 5d +M = 1e + +ModInv = -1 +A = 5f +M = 1e + +ModInv = -1 +A = 63 +M = 1e + +ModInv = -1 +A = -5d +M = 1f + +ModInv = -1 +A = -3e +M = 1f + +ModInv = -1 +A = -1f +M = 1f + +ModInv = -1 +A = 0 +M = 1f + +ModInv = -1 +A = 1f +M = 1f + +ModInv = -1 +A = 3e +M = 1f + +ModInv = -1 +A = 5d +M = 1f + +ModInv = -1 +A = -63 +M = 21 + +ModInv = -1 +A = -60 +M = 21 + +ModInv = -1 +A = -5d +M = 21 + +ModInv = -1 +A = -5a +M = 21 + +ModInv = -1 +A = -58 +M = 21 + +ModInv = -1 +A = -57 +M = 21 + +ModInv = -1 +A = -54 +M = 21 + +ModInv = -1 +A = -51 +M = 21 + +ModInv = -1 +A = -4e +M = 21 + +ModInv = -1 +A = -4d +M = 21 + +ModInv = -1 +A = -4b +M = 21 + +ModInv = -1 +A = -48 +M = 21 + +ModInv = -1 +A = -45 +M = 21 + +ModInv = -1 +A = -42 +M = 21 + +ModInv = -1 +A = -3f +M = 21 + +ModInv = -1 +A = -3c +M = 21 + +ModInv = -1 +A = -39 +M = 21 + +ModInv = -1 +A = -37 +M = 21 + +ModInv = -1 +A = -36 +M = 21 + +ModInv = -1 +A = -33 +M = 21 + +ModInv = -1 +A = -30 +M = 21 + +ModInv = -1 +A = -2d +M = 21 + +ModInv = -1 +A = -2c +M = 21 + +ModInv = -1 +A = -2a +M = 21 + +ModInv = -1 +A = -27 +M = 21 + +ModInv = -1 +A = -24 +M = 21 + +ModInv = -1 +A = -21 +M = 21 + +ModInv = -1 +A = -1e +M = 21 + +ModInv = -1 +A = -1b +M = 21 + +ModInv = -1 +A = -18 +M = 21 + +ModInv = -1 +A = -16 +M = 21 + +ModInv = -1 +A = -15 +M = 21 + +ModInv = -1 +A = -12 +M = 21 + +ModInv = -1 +A = -f +M = 21 + +ModInv = -1 +A = -c +M = 21 + +ModInv = -1 +A = -b +M = 21 + +ModInv = -1 +A = -9 +M = 21 + +ModInv = -1 +A = -6 +M = 21 + +ModInv = -1 +A = -3 +M = 21 + +ModInv = -1 +A = 0 +M = 21 + +ModInv = -1 +A = 3 +M = 21 + +ModInv = -1 +A = 6 +M = 21 + +ModInv = -1 +A = 9 +M = 21 + +ModInv = -1 +A = b +M = 21 + +ModInv = -1 +A = c +M = 21 + +ModInv = -1 +A = f +M = 21 + +ModInv = -1 +A = 12 +M = 21 + +ModInv = -1 +A = 15 +M = 21 + +ModInv = -1 +A = 16 +M = 21 + +ModInv = -1 +A = 18 +M = 21 + +ModInv = -1 +A = 1b +M = 21 + +ModInv = -1 +A = 1e +M = 21 + +ModInv = -1 +A = 21 +M = 21 + +ModInv = -1 +A = 24 +M = 21 + +ModInv = -1 +A = 27 +M = 21 + +ModInv = -1 +A = 2a +M = 21 + +ModInv = -1 +A = 2c +M = 21 + +ModInv = -1 +A = 2d +M = 21 + +ModInv = -1 +A = 30 +M = 21 + +ModInv = -1 +A = 33 +M = 21 + +ModInv = -1 +A = 36 +M = 21 + +ModInv = -1 +A = 37 +M = 21 + +ModInv = -1 +A = 39 +M = 21 + +ModInv = -1 +A = 3c +M = 21 + +ModInv = -1 +A = 3f +M = 21 + +ModInv = -1 +A = 42 +M = 21 + +ModInv = -1 +A = 45 +M = 21 + +ModInv = -1 +A = 48 +M = 21 + +ModInv = -1 +A = 4b +M = 21 + +ModInv = -1 +A = 4d +M = 21 + +ModInv = -1 +A = 4e +M = 21 + +ModInv = -1 +A = 51 +M = 21 + +ModInv = -1 +A = 54 +M = 21 + +ModInv = -1 +A = 57 +M = 21 + +ModInv = -1 +A = 58 +M = 21 + +ModInv = -1 +A = 5a +M = 21 + +ModInv = -1 +A = 5d +M = 21 + +ModInv = -1 +A = 60 +M = 21 + +ModInv = -1 +A = 63 +M = 21 + +ModInv = -1 +A = -55 +M = 22 + +ModInv = -1 +A = -33 +M = 22 + +ModInv = -1 +A = -11 +M = 22 + +ModInv = -1 +A = 11 +M = 22 + +ModInv = -1 +A = 33 +M = 22 + +ModInv = -1 +A = 55 +M = 22 + +ModInv = -1 +A = -64 +M = 23 + +ModInv = -1 +A = -62 +M = 23 + +ModInv = -1 +A = -5f +M = 23 + +ModInv = -1 +A = -5b +M = 23 + +ModInv = -1 +A = -5a +M = 23 + +ModInv = -1 +A = -55 +M = 23 + +ModInv = -1 +A = -54 +M = 23 + +ModInv = -1 +A = -50 +M = 23 + +ModInv = -1 +A = -4d +M = 23 + +ModInv = -1 +A = -4b +M = 23 + +ModInv = -1 +A = -46 +M = 23 + +ModInv = -1 +A = -41 +M = 23 + +ModInv = -1 +A = -3f +M = 23 + +ModInv = -1 +A = -3c +M = 23 + +ModInv = -1 +A = -38 +M = 23 + +ModInv = -1 +A = -37 +M = 23 + +ModInv = -1 +A = -32 +M = 23 + +ModInv = -1 +A = -31 +M = 23 + +ModInv = -1 +A = -2d +M = 23 + +ModInv = -1 +A = -2a +M = 23 + +ModInv = -1 +A = -28 +M = 23 + +ModInv = -1 +A = -23 +M = 23 + +ModInv = -1 +A = -1e +M = 23 + +ModInv = -1 +A = -1c +M = 23 + +ModInv = -1 +A = -19 +M = 23 + +ModInv = -1 +A = -15 +M = 23 + +ModInv = -1 +A = -14 +M = 23 + +ModInv = -1 +A = -f +M = 23 + +ModInv = -1 +A = -e +M = 23 + +ModInv = -1 +A = -a +M = 23 + +ModInv = -1 +A = -7 +M = 23 + +ModInv = -1 +A = -5 +M = 23 + +ModInv = -1 +A = 0 +M = 23 + +ModInv = -1 +A = 5 +M = 23 + +ModInv = -1 +A = 7 +M = 23 + +ModInv = -1 +A = a +M = 23 + +ModInv = -1 +A = e +M = 23 + +ModInv = -1 +A = f +M = 23 + +ModInv = -1 +A = 14 +M = 23 + +ModInv = -1 +A = 15 +M = 23 + +ModInv = -1 +A = 19 +M = 23 + +ModInv = -1 +A = 1c +M = 23 + +ModInv = -1 +A = 1e +M = 23 + +ModInv = -1 +A = 23 +M = 23 + +ModInv = -1 +A = 28 +M = 23 + +ModInv = -1 +A = 2a +M = 23 + +ModInv = -1 +A = 2d +M = 23 + +ModInv = -1 +A = 31 +M = 23 + +ModInv = -1 +A = 32 +M = 23 + +ModInv = -1 +A = 37 +M = 23 + +ModInv = -1 +A = 38 +M = 23 + +ModInv = -1 +A = 3c +M = 23 + +ModInv = -1 +A = 3f +M = 23 + +ModInv = -1 +A = 41 +M = 23 + +ModInv = -1 +A = 46 +M = 23 + +ModInv = -1 +A = 4b +M = 23 + +ModInv = -1 +A = 4d +M = 23 + +ModInv = -1 +A = 50 +M = 23 + +ModInv = -1 +A = 54 +M = 23 + +ModInv = -1 +A = 55 +M = 23 + +ModInv = -1 +A = 5a +M = 23 + +ModInv = -1 +A = 5b +M = 23 + +ModInv = -1 +A = 5f +M = 23 + +ModInv = -1 +A = 62 +M = 23 + +ModInv = -1 +A = -63 +M = 24 + +ModInv = -1 +A = -5d +M = 24 + +ModInv = -1 +A = -57 +M = 24 + +ModInv = -1 +A = -51 +M = 24 + +ModInv = -1 +A = -4b +M = 24 + +ModInv = -1 +A = -45 +M = 24 + +ModInv = -1 +A = -3f +M = 24 + +ModInv = -1 +A = -39 +M = 24 + +ModInv = -1 +A = -33 +M = 24 + +ModInv = -1 +A = -2d +M = 24 + +ModInv = -1 +A = -27 +M = 24 + +ModInv = -1 +A = -21 +M = 24 + +ModInv = -1 +A = -1b +M = 24 + +ModInv = -1 +A = -15 +M = 24 + +ModInv = -1 +A = -f +M = 24 + +ModInv = -1 +A = -9 +M = 24 + +ModInv = -1 +A = -3 +M = 24 + +ModInv = -1 +A = 3 +M = 24 + +ModInv = -1 +A = 9 +M = 24 + +ModInv = -1 +A = f +M = 24 + +ModInv = -1 +A = 15 +M = 24 + +ModInv = -1 +A = 1b +M = 24 + +ModInv = -1 +A = 21 +M = 24 + +ModInv = -1 +A = 27 +M = 24 + +ModInv = -1 +A = 2d +M = 24 + +ModInv = -1 +A = 33 +M = 24 + +ModInv = -1 +A = 39 +M = 24 + +ModInv = -1 +A = 3f +M = 24 + +ModInv = -1 +A = 45 +M = 24 + +ModInv = -1 +A = 4b +M = 24 + +ModInv = -1 +A = 51 +M = 24 + +ModInv = -1 +A = 57 +M = 24 + +ModInv = -1 +A = 5d +M = 24 + +ModInv = -1 +A = 63 +M = 24 + +ModInv = -1 +A = -4a +M = 25 + +ModInv = -1 +A = -25 +M = 25 + +ModInv = -1 +A = 0 +M = 25 + +ModInv = -1 +A = 25 +M = 25 + +ModInv = -1 +A = 4a +M = 25 + +ModInv = -1 +A = -5f +M = 26 + +ModInv = -1 +A = -39 +M = 26 + +ModInv = -1 +A = -13 +M = 26 + +ModInv = -1 +A = 13 +M = 26 + +ModInv = -1 +A = 39 +M = 26 + +ModInv = -1 +A = 5f +M = 26 + +ModInv = -1 +A = -63 +M = 27 + +ModInv = -1 +A = -60 +M = 27 + +ModInv = -1 +A = -5d +M = 27 + +ModInv = -1 +A = -5b +M = 27 + +ModInv = -1 +A = -5a +M = 27 + +ModInv = -1 +A = -57 +M = 27 + +ModInv = -1 +A = -54 +M = 27 + +ModInv = -1 +A = -51 +M = 27 + +ModInv = -1 +A = -4e +M = 27 + +ModInv = -1 +A = -4b +M = 27 + +ModInv = -1 +A = -48 +M = 27 + +ModInv = -1 +A = -45 +M = 27 + +ModInv = -1 +A = -42 +M = 27 + +ModInv = -1 +A = -41 +M = 27 + +ModInv = -1 +A = -3f +M = 27 + +ModInv = -1 +A = -3c +M = 27 + +ModInv = -1 +A = -39 +M = 27 + +ModInv = -1 +A = -36 +M = 27 + +ModInv = -1 +A = -34 +M = 27 + +ModInv = -1 +A = -33 +M = 27 + +ModInv = -1 +A = -30 +M = 27 + +ModInv = -1 +A = -2d +M = 27 + +ModInv = -1 +A = -2a +M = 27 + +ModInv = -1 +A = -27 +M = 27 + +ModInv = -1 +A = -24 +M = 27 + +ModInv = -1 +A = -21 +M = 27 + +ModInv = -1 +A = -1e +M = 27 + +ModInv = -1 +A = -1b +M = 27 + +ModInv = -1 +A = -1a +M = 27 + +ModInv = -1 +A = -18 +M = 27 + +ModInv = -1 +A = -15 +M = 27 + +ModInv = -1 +A = -12 +M = 27 + +ModInv = -1 +A = -f +M = 27 + +ModInv = -1 +A = -d +M = 27 + +ModInv = -1 +A = -c +M = 27 + +ModInv = -1 +A = -9 +M = 27 + +ModInv = -1 +A = -6 +M = 27 + +ModInv = -1 +A = -3 +M = 27 + +ModInv = -1 +A = 0 +M = 27 + +ModInv = -1 +A = 3 +M = 27 + +ModInv = -1 +A = 6 +M = 27 + +ModInv = -1 +A = 9 +M = 27 + +ModInv = -1 +A = c +M = 27 + +ModInv = -1 +A = d +M = 27 + +ModInv = -1 +A = f +M = 27 + +ModInv = -1 +A = 12 +M = 27 + +ModInv = -1 +A = 15 +M = 27 + +ModInv = -1 +A = 18 +M = 27 + +ModInv = -1 +A = 1a +M = 27 + +ModInv = -1 +A = 1b +M = 27 + +ModInv = -1 +A = 1e +M = 27 + +ModInv = -1 +A = 21 +M = 27 + +ModInv = -1 +A = 24 +M = 27 + +ModInv = -1 +A = 27 +M = 27 + +ModInv = -1 +A = 2a +M = 27 + +ModInv = -1 +A = 2d +M = 27 + +ModInv = -1 +A = 30 +M = 27 + +ModInv = -1 +A = 33 +M = 27 + +ModInv = -1 +A = 34 +M = 27 + +ModInv = -1 +A = 36 +M = 27 + +ModInv = -1 +A = 39 +M = 27 + +ModInv = -1 +A = 3c +M = 27 + +ModInv = -1 +A = 3f +M = 27 + +ModInv = -1 +A = 41 +M = 27 + +ModInv = -1 +A = 42 +M = 27 + +ModInv = -1 +A = 45 +M = 27 + +ModInv = -1 +A = 48 +M = 27 + +ModInv = -1 +A = 4b +M = 27 + +ModInv = -1 +A = 4e +M = 27 + +ModInv = -1 +A = 51 +M = 27 + +ModInv = -1 +A = 54 +M = 27 + +ModInv = -1 +A = 57 +M = 27 + +ModInv = -1 +A = 5a +M = 27 + +ModInv = -1 +A = 5b +M = 27 + +ModInv = -1 +A = 5d +M = 27 + +ModInv = -1 +A = 60 +M = 27 + +ModInv = -1 +A = 63 +M = 27 + +ModInv = -1 +A = -5f +M = 28 + +ModInv = -1 +A = -55 +M = 28 + +ModInv = -1 +A = -4b +M = 28 + +ModInv = -1 +A = -41 +M = 28 + +ModInv = -1 +A = -37 +M = 28 + +ModInv = -1 +A = -2d +M = 28 + +ModInv = -1 +A = -23 +M = 28 + +ModInv = -1 +A = -19 +M = 28 + +ModInv = -1 +A = -f +M = 28 + +ModInv = -1 +A = -5 +M = 28 + +ModInv = -1 +A = 5 +M = 28 + +ModInv = -1 +A = f +M = 28 + +ModInv = -1 +A = 19 +M = 28 + +ModInv = -1 +A = 23 +M = 28 + +ModInv = -1 +A = 2d +M = 28 + +ModInv = -1 +A = 37 +M = 28 + +ModInv = -1 +A = 41 +M = 28 + +ModInv = -1 +A = 4b +M = 28 + +ModInv = -1 +A = 55 +M = 28 + +ModInv = -1 +A = 5f +M = 28 + +ModInv = -1 +A = -52 +M = 29 + +ModInv = -1 +A = -29 +M = 29 + +ModInv = -1 +A = 0 +M = 29 + +ModInv = -1 +A = 29 +M = 29 + +ModInv = -1 +A = 52 +M = 29 + +ModInv = -1 +A = -63 +M = 2a + +ModInv = -1 +A = -5d +M = 2a + +ModInv = -1 +A = -5b +M = 2a + +ModInv = -1 +A = -57 +M = 2a + +ModInv = -1 +A = -51 +M = 2a + +ModInv = -1 +A = -4d +M = 2a + +ModInv = -1 +A = -4b +M = 2a + +ModInv = -1 +A = -45 +M = 2a + +ModInv = -1 +A = -3f +M = 2a + +ModInv = -1 +A = -39 +M = 2a + +ModInv = -1 +A = -33 +M = 2a + +ModInv = -1 +A = -31 +M = 2a + +ModInv = -1 +A = -2d +M = 2a + +ModInv = -1 +A = -27 +M = 2a + +ModInv = -1 +A = -23 +M = 2a + +ModInv = -1 +A = -21 +M = 2a + +ModInv = -1 +A = -1b +M = 2a + +ModInv = -1 +A = -15 +M = 2a + +ModInv = -1 +A = -f +M = 2a + +ModInv = -1 +A = -9 +M = 2a + +ModInv = -1 +A = -7 +M = 2a + +ModInv = -1 +A = -3 +M = 2a + +ModInv = -1 +A = 3 +M = 2a + +ModInv = -1 +A = 7 +M = 2a + +ModInv = -1 +A = 9 +M = 2a + +ModInv = -1 +A = f +M = 2a + +ModInv = -1 +A = 15 +M = 2a + +ModInv = -1 +A = 1b +M = 2a + +ModInv = -1 +A = 21 +M = 2a + +ModInv = -1 +A = 23 +M = 2a + +ModInv = -1 +A = 27 +M = 2a + +ModInv = -1 +A = 2d +M = 2a + +ModInv = -1 +A = 31 +M = 2a + +ModInv = -1 +A = 33 +M = 2a + +ModInv = -1 +A = 39 +M = 2a + +ModInv = -1 +A = 3f +M = 2a + +ModInv = -1 +A = 45 +M = 2a + +ModInv = -1 +A = 4b +M = 2a + +ModInv = -1 +A = 4d +M = 2a + +ModInv = -1 +A = 51 +M = 2a + +ModInv = -1 +A = 57 +M = 2a + +ModInv = -1 +A = 5b +M = 2a + +ModInv = -1 +A = 5d +M = 2a + +ModInv = -1 +A = 63 +M = 2a + +ModInv = -1 +A = -56 +M = 2b + +ModInv = -1 +A = -2b +M = 2b + +ModInv = -1 +A = 0 +M = 2b + +ModInv = -1 +A = 2b +M = 2b + +ModInv = -1 +A = 56 +M = 2b + +ModInv = -1 +A = -63 +M = 2c + +ModInv = -1 +A = -4d +M = 2c + +ModInv = -1 +A = -37 +M = 2c + +ModInv = -1 +A = -21 +M = 2c + +ModInv = -1 +A = -b +M = 2c + +ModInv = -1 +A = b +M = 2c + +ModInv = -1 +A = 21 +M = 2c + +ModInv = -1 +A = 37 +M = 2c + +ModInv = -1 +A = 4d +M = 2c + +ModInv = -1 +A = 63 +M = 2c + +ModInv = -1 +A = -64 +M = 2d + +ModInv = -1 +A = -63 +M = 2d + +ModInv = -1 +A = -60 +M = 2d + +ModInv = -1 +A = -5f +M = 2d + +ModInv = -1 +A = -5d +M = 2d + +ModInv = -1 +A = -5a +M = 2d + +ModInv = -1 +A = -57 +M = 2d + +ModInv = -1 +A = -55 +M = 2d + +ModInv = -1 +A = -54 +M = 2d + +ModInv = -1 +A = -51 +M = 2d + +ModInv = -1 +A = -50 +M = 2d + +ModInv = -1 +A = -4e +M = 2d + +ModInv = -1 +A = -4b +M = 2d + +ModInv = -1 +A = -48 +M = 2d + +ModInv = -1 +A = -46 +M = 2d + +ModInv = -1 +A = -45 +M = 2d + +ModInv = -1 +A = -42 +M = 2d + +ModInv = -1 +A = -41 +M = 2d + +ModInv = -1 +A = -3f +M = 2d + +ModInv = -1 +A = -3c +M = 2d + +ModInv = -1 +A = -39 +M = 2d + +ModInv = -1 +A = -37 +M = 2d + +ModInv = -1 +A = -36 +M = 2d + +ModInv = -1 +A = -33 +M = 2d + +ModInv = -1 +A = -32 +M = 2d + +ModInv = -1 +A = -30 +M = 2d + +ModInv = -1 +A = -2d +M = 2d + +ModInv = -1 +A = -2a +M = 2d + +ModInv = -1 +A = -28 +M = 2d + +ModInv = -1 +A = -27 +M = 2d + +ModInv = -1 +A = -24 +M = 2d + +ModInv = -1 +A = -23 +M = 2d + +ModInv = -1 +A = -21 +M = 2d + +ModInv = -1 +A = -1e +M = 2d + +ModInv = -1 +A = -1b +M = 2d + +ModInv = -1 +A = -19 +M = 2d + +ModInv = -1 +A = -18 +M = 2d + +ModInv = -1 +A = -15 +M = 2d + +ModInv = -1 +A = -14 +M = 2d + +ModInv = -1 +A = -12 +M = 2d + +ModInv = -1 +A = -f +M = 2d + +ModInv = -1 +A = -c +M = 2d + +ModInv = -1 +A = -a +M = 2d + +ModInv = -1 +A = -9 +M = 2d + +ModInv = -1 +A = -6 +M = 2d + +ModInv = -1 +A = -5 +M = 2d + +ModInv = -1 +A = -3 +M = 2d + +ModInv = -1 +A = 0 +M = 2d + +ModInv = -1 +A = 3 +M = 2d + +ModInv = -1 +A = 5 +M = 2d + +ModInv = -1 +A = 6 +M = 2d + +ModInv = -1 +A = 9 +M = 2d + +ModInv = -1 +A = a +M = 2d + +ModInv = -1 +A = c +M = 2d + +ModInv = -1 +A = f +M = 2d + +ModInv = -1 +A = 12 +M = 2d + +ModInv = -1 +A = 14 +M = 2d + +ModInv = -1 +A = 15 +M = 2d + +ModInv = -1 +A = 18 +M = 2d + +ModInv = -1 +A = 19 +M = 2d + +ModInv = -1 +A = 1b +M = 2d + +ModInv = -1 +A = 1e +M = 2d + +ModInv = -1 +A = 21 +M = 2d + +ModInv = -1 +A = 23 +M = 2d + +ModInv = -1 +A = 24 +M = 2d + +ModInv = -1 +A = 27 +M = 2d + +ModInv = -1 +A = 28 +M = 2d + +ModInv = -1 +A = 2a +M = 2d + +ModInv = -1 +A = 2d +M = 2d + +ModInv = -1 +A = 30 +M = 2d + +ModInv = -1 +A = 32 +M = 2d + +ModInv = -1 +A = 33 +M = 2d + +ModInv = -1 +A = 36 +M = 2d + +ModInv = -1 +A = 37 +M = 2d + +ModInv = -1 +A = 39 +M = 2d + +ModInv = -1 +A = 3c +M = 2d + +ModInv = -1 +A = 3f +M = 2d + +ModInv = -1 +A = 41 +M = 2d + +ModInv = -1 +A = 42 +M = 2d + +ModInv = -1 +A = 45 +M = 2d + +ModInv = -1 +A = 46 +M = 2d + +ModInv = -1 +A = 48 +M = 2d + +ModInv = -1 +A = 4b +M = 2d + +ModInv = -1 +A = 4e +M = 2d + +ModInv = -1 +A = 50 +M = 2d + +ModInv = -1 +A = 51 +M = 2d + +ModInv = -1 +A = 54 +M = 2d + +ModInv = -1 +A = 55 +M = 2d + +ModInv = -1 +A = 57 +M = 2d + +ModInv = -1 +A = 5a +M = 2d + +ModInv = -1 +A = 5d +M = 2d + +ModInv = -1 +A = 5f +M = 2d + +ModInv = -1 +A = 60 +M = 2d + +ModInv = -1 +A = 63 +M = 2d + +ModInv = -1 +A = -45 +M = 2e + +ModInv = -1 +A = -17 +M = 2e + +ModInv = -1 +A = 17 +M = 2e + +ModInv = -1 +A = 45 +M = 2e + +ModInv = -1 +A = -5e +M = 2f + +ModInv = -1 +A = -2f +M = 2f + +ModInv = -1 +A = 0 +M = 2f + +ModInv = -1 +A = 2f +M = 2f + +ModInv = -1 +A = 5e +M = 2f + +ModInv = -1 +A = -63 +M = 30 + +ModInv = -1 +A = -5d +M = 30 + +ModInv = -1 +A = -57 +M = 30 + +ModInv = -1 +A = -51 +M = 30 + +ModInv = -1 +A = -4b +M = 30 + +ModInv = -1 +A = -45 +M = 30 + +ModInv = -1 +A = -3f +M = 30 + +ModInv = -1 +A = -39 +M = 30 + +ModInv = -1 +A = -33 +M = 30 + +ModInv = -1 +A = -2d +M = 30 + +ModInv = -1 +A = -27 +M = 30 + +ModInv = -1 +A = -21 +M = 30 + +ModInv = -1 +A = -1b +M = 30 + +ModInv = -1 +A = -15 +M = 30 + +ModInv = -1 +A = -f +M = 30 + +ModInv = -1 +A = -9 +M = 30 + +ModInv = -1 +A = -3 +M = 30 + +ModInv = -1 +A = 3 +M = 30 + +ModInv = -1 +A = 9 +M = 30 + +ModInv = -1 +A = f +M = 30 + +ModInv = -1 +A = 15 +M = 30 + +ModInv = -1 +A = 1b +M = 30 + +ModInv = -1 +A = 21 +M = 30 + +ModInv = -1 +A = 27 +M = 30 + +ModInv = -1 +A = 2d +M = 30 + +ModInv = -1 +A = 33 +M = 30 + +ModInv = -1 +A = 39 +M = 30 + +ModInv = -1 +A = 3f +M = 30 + +ModInv = -1 +A = 45 +M = 30 + +ModInv = -1 +A = 4b +M = 30 + +ModInv = -1 +A = 51 +M = 30 + +ModInv = -1 +A = 57 +M = 30 + +ModInv = -1 +A = 5d +M = 30 + +ModInv = -1 +A = 63 +M = 30 + +ModInv = -1 +A = -62 +M = 31 + +ModInv = -1 +A = -5b +M = 31 + +ModInv = -1 +A = -54 +M = 31 + +ModInv = -1 +A = -4d +M = 31 + +ModInv = -1 +A = -46 +M = 31 + +ModInv = -1 +A = -3f +M = 31 + +ModInv = -1 +A = -38 +M = 31 + +ModInv = -1 +A = -31 +M = 31 + +ModInv = -1 +A = -2a +M = 31 + +ModInv = -1 +A = -23 +M = 31 + +ModInv = -1 +A = -1c +M = 31 + +ModInv = -1 +A = -15 +M = 31 + +ModInv = -1 +A = -e +M = 31 + +ModInv = -1 +A = -7 +M = 31 + +ModInv = -1 +A = 0 +M = 31 + +ModInv = -1 +A = 7 +M = 31 + +ModInv = -1 +A = e +M = 31 + +ModInv = -1 +A = 15 +M = 31 + +ModInv = -1 +A = 1c +M = 31 + +ModInv = -1 +A = 23 +M = 31 + +ModInv = -1 +A = 2a +M = 31 + +ModInv = -1 +A = 31 +M = 31 + +ModInv = -1 +A = 38 +M = 31 + +ModInv = -1 +A = 3f +M = 31 + +ModInv = -1 +A = 46 +M = 31 + +ModInv = -1 +A = 4d +M = 31 + +ModInv = -1 +A = 54 +M = 31 + +ModInv = -1 +A = 5b +M = 31 + +ModInv = -1 +A = 62 +M = 31 + +ModInv = -1 +A = -5f +M = 32 + +ModInv = -1 +A = -55 +M = 32 + +ModInv = -1 +A = -4b +M = 32 + +ModInv = -1 +A = -41 +M = 32 + +ModInv = -1 +A = -37 +M = 32 + +ModInv = -1 +A = -2d +M = 32 + +ModInv = -1 +A = -23 +M = 32 + +ModInv = -1 +A = -19 +M = 32 + +ModInv = -1 +A = -f +M = 32 + +ModInv = -1 +A = -5 +M = 32 + +ModInv = -1 +A = 5 +M = 32 + +ModInv = -1 +A = f +M = 32 + +ModInv = -1 +A = 19 +M = 32 + +ModInv = -1 +A = 23 +M = 32 + +ModInv = -1 +A = 2d +M = 32 + +ModInv = -1 +A = 37 +M = 32 + +ModInv = -1 +A = 41 +M = 32 + +ModInv = -1 +A = 4b +M = 32 + +ModInv = -1 +A = 55 +M = 32 + +ModInv = -1 +A = 5f +M = 32 + +ModInv = -1 +A = -63 +M = 33 + +ModInv = -1 +A = -60 +M = 33 + +ModInv = -1 +A = -5d +M = 33 + +ModInv = -1 +A = -5a +M = 33 + +ModInv = -1 +A = -57 +M = 33 + +ModInv = -1 +A = -55 +M = 33 + +ModInv = -1 +A = -54 +M = 33 + +ModInv = -1 +A = -51 +M = 33 + +ModInv = -1 +A = -4e +M = 33 + +ModInv = -1 +A = -4b +M = 33 + +ModInv = -1 +A = -48 +M = 33 + +ModInv = -1 +A = -45 +M = 33 + +ModInv = -1 +A = -44 +M = 33 + +ModInv = -1 +A = -42 +M = 33 + +ModInv = -1 +A = -3f +M = 33 + +ModInv = -1 +A = -3c +M = 33 + +ModInv = -1 +A = -39 +M = 33 + +ModInv = -1 +A = -36 +M = 33 + +ModInv = -1 +A = -33 +M = 33 + +ModInv = -1 +A = -30 +M = 33 + +ModInv = -1 +A = -2d +M = 33 + +ModInv = -1 +A = -2a +M = 33 + +ModInv = -1 +A = -27 +M = 33 + +ModInv = -1 +A = -24 +M = 33 + +ModInv = -1 +A = -22 +M = 33 + +ModInv = -1 +A = -21 +M = 33 + +ModInv = -1 +A = -1e +M = 33 + +ModInv = -1 +A = -1b +M = 33 + +ModInv = -1 +A = -18 +M = 33 + +ModInv = -1 +A = -15 +M = 33 + +ModInv = -1 +A = -12 +M = 33 + +ModInv = -1 +A = -11 +M = 33 + +ModInv = -1 +A = -f +M = 33 + +ModInv = -1 +A = -c +M = 33 + +ModInv = -1 +A = -9 +M = 33 + +ModInv = -1 +A = -6 +M = 33 + +ModInv = -1 +A = -3 +M = 33 + +ModInv = -1 +A = 0 +M = 33 + +ModInv = -1 +A = 3 +M = 33 + +ModInv = -1 +A = 6 +M = 33 + +ModInv = -1 +A = 9 +M = 33 + +ModInv = -1 +A = c +M = 33 + +ModInv = -1 +A = f +M = 33 + +ModInv = -1 +A = 11 +M = 33 + +ModInv = -1 +A = 12 +M = 33 + +ModInv = -1 +A = 15 +M = 33 + +ModInv = -1 +A = 18 +M = 33 + +ModInv = -1 +A = 1b +M = 33 + +ModInv = -1 +A = 1e +M = 33 + +ModInv = -1 +A = 21 +M = 33 + +ModInv = -1 +A = 22 +M = 33 + +ModInv = -1 +A = 24 +M = 33 + +ModInv = -1 +A = 27 +M = 33 + +ModInv = -1 +A = 2a +M = 33 + +ModInv = -1 +A = 2d +M = 33 + +ModInv = -1 +A = 30 +M = 33 + +ModInv = -1 +A = 33 +M = 33 + +ModInv = -1 +A = 36 +M = 33 + +ModInv = -1 +A = 39 +M = 33 + +ModInv = -1 +A = 3c +M = 33 + +ModInv = -1 +A = 3f +M = 33 + +ModInv = -1 +A = 42 +M = 33 + +ModInv = -1 +A = 44 +M = 33 + +ModInv = -1 +A = 45 +M = 33 + +ModInv = -1 +A = 48 +M = 33 + +ModInv = -1 +A = 4b +M = 33 + +ModInv = -1 +A = 4e +M = 33 + +ModInv = -1 +A = 51 +M = 33 + +ModInv = -1 +A = 54 +M = 33 + +ModInv = -1 +A = 55 +M = 33 + +ModInv = -1 +A = 57 +M = 33 + +ModInv = -1 +A = 5a +M = 33 + +ModInv = -1 +A = 5d +M = 33 + +ModInv = -1 +A = 60 +M = 33 + +ModInv = -1 +A = 63 +M = 33 + +ModInv = -1 +A = -5b +M = 34 + +ModInv = -1 +A = -41 +M = 34 + +ModInv = -1 +A = -27 +M = 34 + +ModInv = -1 +A = -d +M = 34 + +ModInv = -1 +A = d +M = 34 + +ModInv = -1 +A = 27 +M = 34 + +ModInv = -1 +A = 41 +M = 34 + +ModInv = -1 +A = 5b +M = 34 + +ModInv = -1 +A = -35 +M = 35 + +ModInv = -1 +A = 0 +M = 35 + +ModInv = -1 +A = 35 +M = 35 + +ModInv = -1 +A = -63 +M = 36 + +ModInv = -1 +A = -5d +M = 36 + +ModInv = -1 +A = -57 +M = 36 + +ModInv = -1 +A = -51 +M = 36 + +ModInv = -1 +A = -4b +M = 36 + +ModInv = -1 +A = -45 +M = 36 + +ModInv = -1 +A = -3f +M = 36 + +ModInv = -1 +A = -39 +M = 36 + +ModInv = -1 +A = -33 +M = 36 + +ModInv = -1 +A = -2d +M = 36 + +ModInv = -1 +A = -27 +M = 36 + +ModInv = -1 +A = -21 +M = 36 + +ModInv = -1 +A = -1b +M = 36 + +ModInv = -1 +A = -15 +M = 36 + +ModInv = -1 +A = -f +M = 36 + +ModInv = -1 +A = -9 +M = 36 + +ModInv = -1 +A = -3 +M = 36 + +ModInv = -1 +A = 3 +M = 36 + +ModInv = -1 +A = 9 +M = 36 + +ModInv = -1 +A = f +M = 36 + +ModInv = -1 +A = 15 +M = 36 + +ModInv = -1 +A = 1b +M = 36 + +ModInv = -1 +A = 21 +M = 36 + +ModInv = -1 +A = 27 +M = 36 + +ModInv = -1 +A = 2d +M = 36 + +ModInv = -1 +A = 33 +M = 36 + +ModInv = -1 +A = 39 +M = 36 + +ModInv = -1 +A = 3f +M = 36 + +ModInv = -1 +A = 45 +M = 36 + +ModInv = -1 +A = 4b +M = 36 + +ModInv = -1 +A = 51 +M = 36 + +ModInv = -1 +A = 57 +M = 36 + +ModInv = -1 +A = 5d +M = 36 + +ModInv = -1 +A = 63 +M = 36 + +ModInv = -1 +A = -64 +M = 37 + +ModInv = -1 +A = -63 +M = 37 + +ModInv = -1 +A = -5f +M = 37 + +ModInv = -1 +A = -5a +M = 37 + +ModInv = -1 +A = -58 +M = 37 + +ModInv = -1 +A = -55 +M = 37 + +ModInv = -1 +A = -50 +M = 37 + +ModInv = -1 +A = -4d +M = 37 + +ModInv = -1 +A = -4b +M = 37 + +ModInv = -1 +A = -46 +M = 37 + +ModInv = -1 +A = -42 +M = 37 + +ModInv = -1 +A = -41 +M = 37 + +ModInv = -1 +A = -3c +M = 37 + +ModInv = -1 +A = -37 +M = 37 + +ModInv = -1 +A = -32 +M = 37 + +ModInv = -1 +A = -2d +M = 37 + +ModInv = -1 +A = -2c +M = 37 + +ModInv = -1 +A = -28 +M = 37 + +ModInv = -1 +A = -23 +M = 37 + +ModInv = -1 +A = -21 +M = 37 + +ModInv = -1 +A = -1e +M = 37 + +ModInv = -1 +A = -19 +M = 37 + +ModInv = -1 +A = -16 +M = 37 + +ModInv = -1 +A = -14 +M = 37 + +ModInv = -1 +A = -f +M = 37 + +ModInv = -1 +A = -b +M = 37 + +ModInv = -1 +A = -a +M = 37 + +ModInv = -1 +A = -5 +M = 37 + +ModInv = -1 +A = 0 +M = 37 + +ModInv = -1 +A = 5 +M = 37 + +ModInv = -1 +A = a +M = 37 + +ModInv = -1 +A = b +M = 37 + +ModInv = -1 +A = f +M = 37 + +ModInv = -1 +A = 14 +M = 37 + +ModInv = -1 +A = 16 +M = 37 + +ModInv = -1 +A = 19 +M = 37 + +ModInv = -1 +A = 1e +M = 37 + +ModInv = -1 +A = 21 +M = 37 + +ModInv = -1 +A = 23 +M = 37 + +ModInv = -1 +A = 28 +M = 37 + +ModInv = -1 +A = 2c +M = 37 + +ModInv = -1 +A = 2d +M = 37 + +ModInv = -1 +A = 32 +M = 37 + +ModInv = -1 +A = 37 +M = 37 + +ModInv = -1 +A = 3c +M = 37 + +ModInv = -1 +A = 41 +M = 37 + +ModInv = -1 +A = 42 +M = 37 + +ModInv = -1 +A = 46 +M = 37 + +ModInv = -1 +A = 4b +M = 37 + +ModInv = -1 +A = 4d +M = 37 + +ModInv = -1 +A = 50 +M = 37 + +ModInv = -1 +A = 55 +M = 37 + +ModInv = -1 +A = 58 +M = 37 + +ModInv = -1 +A = 5a +M = 37 + +ModInv = -1 +A = 5f +M = 37 + +ModInv = -1 +A = 63 +M = 37 + +ModInv = -1 +A = -5b +M = 38 + +ModInv = -1 +A = -4d +M = 38 + +ModInv = -1 +A = -3f +M = 38 + +ModInv = -1 +A = -31 +M = 38 + +ModInv = -1 +A = -23 +M = 38 + +ModInv = -1 +A = -15 +M = 38 + +ModInv = -1 +A = -7 +M = 38 + +ModInv = -1 +A = 7 +M = 38 + +ModInv = -1 +A = 15 +M = 38 + +ModInv = -1 +A = 23 +M = 38 + +ModInv = -1 +A = 31 +M = 38 + +ModInv = -1 +A = 3f +M = 38 + +ModInv = -1 +A = 4d +M = 38 + +ModInv = -1 +A = 5b +M = 38 + +ModInv = -1 +A = -63 +M = 39 + +ModInv = -1 +A = -60 +M = 39 + +ModInv = -1 +A = -5f +M = 39 + +ModInv = -1 +A = -5d +M = 39 + +ModInv = -1 +A = -5a +M = 39 + +ModInv = -1 +A = -57 +M = 39 + +ModInv = -1 +A = -54 +M = 39 + +ModInv = -1 +A = -51 +M = 39 + +ModInv = -1 +A = -4e +M = 39 + +ModInv = -1 +A = -4c +M = 39 + +ModInv = -1 +A = -4b +M = 39 + +ModInv = -1 +A = -48 +M = 39 + +ModInv = -1 +A = -45 +M = 39 + +ModInv = -1 +A = -42 +M = 39 + +ModInv = -1 +A = -3f +M = 39 + +ModInv = -1 +A = -3c +M = 39 + +ModInv = -1 +A = -39 +M = 39 + +ModInv = -1 +A = -36 +M = 39 + +ModInv = -1 +A = -33 +M = 39 + +ModInv = -1 +A = -30 +M = 39 + +ModInv = -1 +A = -2d +M = 39 + +ModInv = -1 +A = -2a +M = 39 + +ModInv = -1 +A = -27 +M = 39 + +ModInv = -1 +A = -26 +M = 39 + +ModInv = -1 +A = -24 +M = 39 + +ModInv = -1 +A = -21 +M = 39 + +ModInv = -1 +A = -1e +M = 39 + +ModInv = -1 +A = -1b +M = 39 + +ModInv = -1 +A = -18 +M = 39 + +ModInv = -1 +A = -15 +M = 39 + +ModInv = -1 +A = -13 +M = 39 + +ModInv = -1 +A = -12 +M = 39 + +ModInv = -1 +A = -f +M = 39 + +ModInv = -1 +A = -c +M = 39 + +ModInv = -1 +A = -9 +M = 39 + +ModInv = -1 +A = -6 +M = 39 + +ModInv = -1 +A = -3 +M = 39 + +ModInv = -1 +A = 0 +M = 39 + +ModInv = -1 +A = 3 +M = 39 + +ModInv = -1 +A = 6 +M = 39 + +ModInv = -1 +A = 9 +M = 39 + +ModInv = -1 +A = c +M = 39 + +ModInv = -1 +A = f +M = 39 + +ModInv = -1 +A = 12 +M = 39 + +ModInv = -1 +A = 13 +M = 39 + +ModInv = -1 +A = 15 +M = 39 + +ModInv = -1 +A = 18 +M = 39 + +ModInv = -1 +A = 1b +M = 39 + +ModInv = -1 +A = 1e +M = 39 + +ModInv = -1 +A = 21 +M = 39 + +ModInv = -1 +A = 24 +M = 39 + +ModInv = -1 +A = 26 +M = 39 + +ModInv = -1 +A = 27 +M = 39 + +ModInv = -1 +A = 2a +M = 39 + +ModInv = -1 +A = 2d +M = 39 + +ModInv = -1 +A = 30 +M = 39 + +ModInv = -1 +A = 33 +M = 39 + +ModInv = -1 +A = 36 +M = 39 + +ModInv = -1 +A = 39 +M = 39 + +ModInv = -1 +A = 3c +M = 39 + +ModInv = -1 +A = 3f +M = 39 + +ModInv = -1 +A = 42 +M = 39 + +ModInv = -1 +A = 45 +M = 39 + +ModInv = -1 +A = 48 +M = 39 + +ModInv = -1 +A = 4b +M = 39 + +ModInv = -1 +A = 4c +M = 39 + +ModInv = -1 +A = 4e +M = 39 + +ModInv = -1 +A = 51 +M = 39 + +ModInv = -1 +A = 54 +M = 39 + +ModInv = -1 +A = 57 +M = 39 + +ModInv = -1 +A = 5a +M = 39 + +ModInv = -1 +A = 5d +M = 39 + +ModInv = -1 +A = 5f +M = 39 + +ModInv = -1 +A = 60 +M = 39 + +ModInv = -1 +A = 63 +M = 39 + +ModInv = -1 +A = -57 +M = 3a + +ModInv = -1 +A = -1d +M = 3a + +ModInv = -1 +A = 1d +M = 3a + +ModInv = -1 +A = 57 +M = 3a + +ModInv = -1 +A = -3b +M = 3b + +ModInv = -1 +A = 0 +M = 3b + +ModInv = -1 +A = 3b +M = 3b + +ModInv = -1 +A = -63 +M = 3c + +ModInv = -1 +A = -5f +M = 3c + +ModInv = -1 +A = -5d +M = 3c + +ModInv = -1 +A = -57 +M = 3c + +ModInv = -1 +A = -55 +M = 3c + +ModInv = -1 +A = -51 +M = 3c + +ModInv = -1 +A = -4b +M = 3c + +ModInv = -1 +A = -45 +M = 3c + +ModInv = -1 +A = -41 +M = 3c + +ModInv = -1 +A = -3f +M = 3c + +ModInv = -1 +A = -39 +M = 3c + +ModInv = -1 +A = -37 +M = 3c + +ModInv = -1 +A = -33 +M = 3c + +ModInv = -1 +A = -2d +M = 3c + +ModInv = -1 +A = -27 +M = 3c + +ModInv = -1 +A = -23 +M = 3c + +ModInv = -1 +A = -21 +M = 3c + +ModInv = -1 +A = -1b +M = 3c + +ModInv = -1 +A = -19 +M = 3c + +ModInv = -1 +A = -15 +M = 3c + +ModInv = -1 +A = -f +M = 3c + +ModInv = -1 +A = -9 +M = 3c + +ModInv = -1 +A = -5 +M = 3c + +ModInv = -1 +A = -3 +M = 3c + +ModInv = -1 +A = 3 +M = 3c + +ModInv = -1 +A = 5 +M = 3c + +ModInv = -1 +A = 9 +M = 3c + +ModInv = -1 +A = f +M = 3c + +ModInv = -1 +A = 15 +M = 3c + +ModInv = -1 +A = 19 +M = 3c + +ModInv = -1 +A = 1b +M = 3c + +ModInv = -1 +A = 21 +M = 3c + +ModInv = -1 +A = 23 +M = 3c + +ModInv = -1 +A = 27 +M = 3c + +ModInv = -1 +A = 2d +M = 3c + +ModInv = -1 +A = 33 +M = 3c + +ModInv = -1 +A = 37 +M = 3c + +ModInv = -1 +A = 39 +M = 3c + +ModInv = -1 +A = 3f +M = 3c + +ModInv = -1 +A = 41 +M = 3c + +ModInv = -1 +A = 45 +M = 3c + +ModInv = -1 +A = 4b +M = 3c + +ModInv = -1 +A = 51 +M = 3c + +ModInv = -1 +A = 55 +M = 3c + +ModInv = -1 +A = 57 +M = 3c + +ModInv = -1 +A = 5d +M = 3c + +ModInv = -1 +A = 5f +M = 3c + +ModInv = -1 +A = 63 +M = 3c + +ModInv = -1 +A = -3d +M = 3d + +ModInv = -1 +A = 0 +M = 3d + +ModInv = -1 +A = 3d +M = 3d + +ModInv = -1 +A = -5d +M = 3e + +ModInv = -1 +A = -1f +M = 3e + +ModInv = -1 +A = 1f +M = 3e + +ModInv = -1 +A = 5d +M = 3e + +ModInv = -1 +A = -63 +M = 3f + +ModInv = -1 +A = -62 +M = 3f + +ModInv = -1 +A = -60 +M = 3f + +ModInv = -1 +A = -5d +M = 3f + +ModInv = -1 +A = -5b +M = 3f + +ModInv = -1 +A = -5a +M = 3f + +ModInv = -1 +A = -57 +M = 3f + +ModInv = -1 +A = -54 +M = 3f + +ModInv = -1 +A = -51 +M = 3f + +ModInv = -1 +A = -4e +M = 3f + +ModInv = -1 +A = -4d +M = 3f + +ModInv = -1 +A = -4b +M = 3f + +ModInv = -1 +A = -48 +M = 3f + +ModInv = -1 +A = -46 +M = 3f + +ModInv = -1 +A = -45 +M = 3f + +ModInv = -1 +A = -42 +M = 3f + +ModInv = -1 +A = -3f +M = 3f + +ModInv = -1 +A = -3c +M = 3f + +ModInv = -1 +A = -39 +M = 3f + +ModInv = -1 +A = -38 +M = 3f + +ModInv = -1 +A = -36 +M = 3f + +ModInv = -1 +A = -33 +M = 3f + +ModInv = -1 +A = -31 +M = 3f + +ModInv = -1 +A = -30 +M = 3f + +ModInv = -1 +A = -2d +M = 3f + +ModInv = -1 +A = -2a +M = 3f + +ModInv = -1 +A = -27 +M = 3f + +ModInv = -1 +A = -24 +M = 3f + +ModInv = -1 +A = -23 +M = 3f + +ModInv = -1 +A = -21 +M = 3f + +ModInv = -1 +A = -1e +M = 3f + +ModInv = -1 +A = -1c +M = 3f + +ModInv = -1 +A = -1b +M = 3f + +ModInv = -1 +A = -18 +M = 3f + +ModInv = -1 +A = -15 +M = 3f + +ModInv = -1 +A = -12 +M = 3f + +ModInv = -1 +A = -f +M = 3f + +ModInv = -1 +A = -e +M = 3f + +ModInv = -1 +A = -c +M = 3f + +ModInv = -1 +A = -9 +M = 3f + +ModInv = -1 +A = -7 +M = 3f + +ModInv = -1 +A = -6 +M = 3f + +ModInv = -1 +A = -3 +M = 3f + +ModInv = -1 +A = 0 +M = 3f + +ModInv = -1 +A = 3 +M = 3f + +ModInv = -1 +A = 6 +M = 3f + +ModInv = -1 +A = 7 +M = 3f + +ModInv = -1 +A = 9 +M = 3f + +ModInv = -1 +A = c +M = 3f + +ModInv = -1 +A = e +M = 3f + +ModInv = -1 +A = f +M = 3f + +ModInv = -1 +A = 12 +M = 3f + +ModInv = -1 +A = 15 +M = 3f + +ModInv = -1 +A = 18 +M = 3f + +ModInv = -1 +A = 1b +M = 3f + +ModInv = -1 +A = 1c +M = 3f + +ModInv = -1 +A = 1e +M = 3f + +ModInv = -1 +A = 21 +M = 3f + +ModInv = -1 +A = 23 +M = 3f + +ModInv = -1 +A = 24 +M = 3f + +ModInv = -1 +A = 27 +M = 3f + +ModInv = -1 +A = 2a +M = 3f + +ModInv = -1 +A = 2d +M = 3f + +ModInv = -1 +A = 30 +M = 3f + +ModInv = -1 +A = 31 +M = 3f + +ModInv = -1 +A = 33 +M = 3f + +ModInv = -1 +A = 36 +M = 3f + +ModInv = -1 +A = 38 +M = 3f + +ModInv = -1 +A = 39 +M = 3f + +ModInv = -1 +A = 3c +M = 3f + +ModInv = -1 +A = 3f +M = 3f + +ModInv = -1 +A = 42 +M = 3f + +ModInv = -1 +A = 45 +M = 3f + +ModInv = -1 +A = 46 +M = 3f + +ModInv = -1 +A = 48 +M = 3f + +ModInv = -1 +A = 4b +M = 3f + +ModInv = -1 +A = 4d +M = 3f + +ModInv = -1 +A = 4e +M = 3f + +ModInv = -1 +A = 51 +M = 3f + +ModInv = -1 +A = 54 +M = 3f + +ModInv = -1 +A = 57 +M = 3f + +ModInv = -1 +A = 5a +M = 3f + +ModInv = -1 +A = 5b +M = 3f + +ModInv = -1 +A = 5d +M = 3f + +ModInv = -1 +A = 60 +M = 3f + +ModInv = -1 +A = 62 +M = 3f + +ModInv = -1 +A = 63 +M = 3f + +ModInv = -1 +A = -64 +M = 41 + +ModInv = -1 +A = -5f +M = 41 + +ModInv = -1 +A = -5b +M = 41 + +ModInv = -1 +A = -5a +M = 41 + +ModInv = -1 +A = -55 +M = 41 + +ModInv = -1 +A = -50 +M = 41 + +ModInv = -1 +A = -4e +M = 41 + +ModInv = -1 +A = -4b +M = 41 + +ModInv = -1 +A = -46 +M = 41 + +ModInv = -1 +A = -41 +M = 41 + +ModInv = -1 +A = -3c +M = 41 + +ModInv = -1 +A = -37 +M = 41 + +ModInv = -1 +A = -34 +M = 41 + +ModInv = -1 +A = -32 +M = 41 + +ModInv = -1 +A = -2d +M = 41 + +ModInv = -1 +A = -28 +M = 41 + +ModInv = -1 +A = -27 +M = 41 + +ModInv = -1 +A = -23 +M = 41 + +ModInv = -1 +A = -1e +M = 41 + +ModInv = -1 +A = -1a +M = 41 + +ModInv = -1 +A = -19 +M = 41 + +ModInv = -1 +A = -14 +M = 41 + +ModInv = -1 +A = -f +M = 41 + +ModInv = -1 +A = -d +M = 41 + +ModInv = -1 +A = -a +M = 41 + +ModInv = -1 +A = -5 +M = 41 + +ModInv = -1 +A = 0 +M = 41 + +ModInv = -1 +A = 5 +M = 41 + +ModInv = -1 +A = a +M = 41 + +ModInv = -1 +A = d +M = 41 + +ModInv = -1 +A = f +M = 41 + +ModInv = -1 +A = 14 +M = 41 + +ModInv = -1 +A = 19 +M = 41 + +ModInv = -1 +A = 1a +M = 41 + +ModInv = -1 +A = 1e +M = 41 + +ModInv = -1 +A = 23 +M = 41 + +ModInv = -1 +A = 27 +M = 41 + +ModInv = -1 +A = 28 +M = 41 + +ModInv = -1 +A = 2d +M = 41 + +ModInv = -1 +A = 32 +M = 41 + +ModInv = -1 +A = 34 +M = 41 + +ModInv = -1 +A = 37 +M = 41 + +ModInv = -1 +A = 3c +M = 41 + +ModInv = -1 +A = 41 +M = 41 + +ModInv = -1 +A = 46 +M = 41 + +ModInv = -1 +A = 4b +M = 41 + +ModInv = -1 +A = 4e +M = 41 + +ModInv = -1 +A = 50 +M = 41 + +ModInv = -1 +A = 55 +M = 41 + +ModInv = -1 +A = 5a +M = 41 + +ModInv = -1 +A = 5b +M = 41 + +ModInv = -1 +A = 5f +M = 41 + +ModInv = -1 +A = -63 +M = 42 + +ModInv = -1 +A = -5d +M = 42 + +ModInv = -1 +A = -57 +M = 42 + +ModInv = -1 +A = -51 +M = 42 + +ModInv = -1 +A = -4d +M = 42 + +ModInv = -1 +A = -4b +M = 42 + +ModInv = -1 +A = -45 +M = 42 + +ModInv = -1 +A = -3f +M = 42 + +ModInv = -1 +A = -39 +M = 42 + +ModInv = -1 +A = -37 +M = 42 + +ModInv = -1 +A = -33 +M = 42 + +ModInv = -1 +A = -2d +M = 42 + +ModInv = -1 +A = -27 +M = 42 + +ModInv = -1 +A = -21 +M = 42 + +ModInv = -1 +A = -1b +M = 42 + +ModInv = -1 +A = -15 +M = 42 + +ModInv = -1 +A = -f +M = 42 + +ModInv = -1 +A = -b +M = 42 + +ModInv = -1 +A = -9 +M = 42 + +ModInv = -1 +A = -3 +M = 42 + +ModInv = -1 +A = 3 +M = 42 + +ModInv = -1 +A = 9 +M = 42 + +ModInv = -1 +A = b +M = 42 + +ModInv = -1 +A = f +M = 42 + +ModInv = -1 +A = 15 +M = 42 + +ModInv = -1 +A = 1b +M = 42 + +ModInv = -1 +A = 21 +M = 42 + +ModInv = -1 +A = 27 +M = 42 + +ModInv = -1 +A = 2d +M = 42 + +ModInv = -1 +A = 33 +M = 42 + +ModInv = -1 +A = 37 +M = 42 + +ModInv = -1 +A = 39 +M = 42 + +ModInv = -1 +A = 3f +M = 42 + +ModInv = -1 +A = 45 +M = 42 + +ModInv = -1 +A = 4b +M = 42 + +ModInv = -1 +A = 4d +M = 42 + +ModInv = -1 +A = 51 +M = 42 + +ModInv = -1 +A = 57 +M = 42 + +ModInv = -1 +A = 5d +M = 42 + +ModInv = -1 +A = 63 +M = 42 + +ModInv = -1 +A = -43 +M = 43 + +ModInv = -1 +A = 0 +M = 43 + +ModInv = -1 +A = 43 +M = 43 + +ModInv = -1 +A = -55 +M = 44 + +ModInv = -1 +A = -33 +M = 44 + +ModInv = -1 +A = -11 +M = 44 + +ModInv = -1 +A = 11 +M = 44 + +ModInv = -1 +A = 33 +M = 44 + +ModInv = -1 +A = 55 +M = 44 + +ModInv = -1 +A = -63 +M = 45 + +ModInv = -1 +A = -60 +M = 45 + +ModInv = -1 +A = -5d +M = 45 + +ModInv = -1 +A = -5c +M = 45 + +ModInv = -1 +A = -5a +M = 45 + +ModInv = -1 +A = -57 +M = 45 + +ModInv = -1 +A = -54 +M = 45 + +ModInv = -1 +A = -51 +M = 45 + +ModInv = -1 +A = -4e +M = 45 + +ModInv = -1 +A = -4b +M = 45 + +ModInv = -1 +A = -48 +M = 45 + +ModInv = -1 +A = -45 +M = 45 + +ModInv = -1 +A = -42 +M = 45 + +ModInv = -1 +A = -3f +M = 45 + +ModInv = -1 +A = -3c +M = 45 + +ModInv = -1 +A = -39 +M = 45 + +ModInv = -1 +A = -36 +M = 45 + +ModInv = -1 +A = -33 +M = 45 + +ModInv = -1 +A = -30 +M = 45 + +ModInv = -1 +A = -2e +M = 45 + +ModInv = -1 +A = -2d +M = 45 + +ModInv = -1 +A = -2a +M = 45 + +ModInv = -1 +A = -27 +M = 45 + +ModInv = -1 +A = -24 +M = 45 + +ModInv = -1 +A = -21 +M = 45 + +ModInv = -1 +A = -1e +M = 45 + +ModInv = -1 +A = -1b +M = 45 + +ModInv = -1 +A = -18 +M = 45 + +ModInv = -1 +A = -17 +M = 45 + +ModInv = -1 +A = -15 +M = 45 + +ModInv = -1 +A = -12 +M = 45 + +ModInv = -1 +A = -f +M = 45 + +ModInv = -1 +A = -c +M = 45 + +ModInv = -1 +A = -9 +M = 45 + +ModInv = -1 +A = -6 +M = 45 + +ModInv = -1 +A = -3 +M = 45 + +ModInv = -1 +A = 0 +M = 45 + +ModInv = -1 +A = 3 +M = 45 + +ModInv = -1 +A = 6 +M = 45 + +ModInv = -1 +A = 9 +M = 45 + +ModInv = -1 +A = c +M = 45 + +ModInv = -1 +A = f +M = 45 + +ModInv = -1 +A = 12 +M = 45 + +ModInv = -1 +A = 15 +M = 45 + +ModInv = -1 +A = 17 +M = 45 + +ModInv = -1 +A = 18 +M = 45 + +ModInv = -1 +A = 1b +M = 45 + +ModInv = -1 +A = 1e +M = 45 + +ModInv = -1 +A = 21 +M = 45 + +ModInv = -1 +A = 24 +M = 45 + +ModInv = -1 +A = 27 +M = 45 + +ModInv = -1 +A = 2a +M = 45 + +ModInv = -1 +A = 2d +M = 45 + +ModInv = -1 +A = 2e +M = 45 + +ModInv = -1 +A = 30 +M = 45 + +ModInv = -1 +A = 33 +M = 45 + +ModInv = -1 +A = 36 +M = 45 + +ModInv = -1 +A = 39 +M = 45 + +ModInv = -1 +A = 3c +M = 45 + +ModInv = -1 +A = 3f +M = 45 + +ModInv = -1 +A = 42 +M = 45 + +ModInv = -1 +A = 45 +M = 45 + +ModInv = -1 +A = 48 +M = 45 + +ModInv = -1 +A = 4b +M = 45 + +ModInv = -1 +A = 4e +M = 45 + +ModInv = -1 +A = 51 +M = 45 + +ModInv = -1 +A = 54 +M = 45 + +ModInv = -1 +A = 57 +M = 45 + +ModInv = -1 +A = 5a +M = 45 + +ModInv = -1 +A = 5c +M = 45 + +ModInv = -1 +A = 5d +M = 45 + +ModInv = -1 +A = 60 +M = 45 + +ModInv = -1 +A = 63 +M = 45 + +ModInv = -1 +A = -5f +M = 46 + +ModInv = -1 +A = -5b +M = 46 + +ModInv = -1 +A = -55 +M = 46 + +ModInv = -1 +A = -4d +M = 46 + +ModInv = -1 +A = -4b +M = 46 + +ModInv = -1 +A = -41 +M = 46 + +ModInv = -1 +A = -3f +M = 46 + +ModInv = -1 +A = -37 +M = 46 + +ModInv = -1 +A = -31 +M = 46 + +ModInv = -1 +A = -2d +M = 46 + +ModInv = -1 +A = -23 +M = 46 + +ModInv = -1 +A = -19 +M = 46 + +ModInv = -1 +A = -15 +M = 46 + +ModInv = -1 +A = -f +M = 46 + +ModInv = -1 +A = -7 +M = 46 + +ModInv = -1 +A = -5 +M = 46 + +ModInv = -1 +A = 5 +M = 46 + +ModInv = -1 +A = 7 +M = 46 + +ModInv = -1 +A = f +M = 46 + +ModInv = -1 +A = 15 +M = 46 + +ModInv = -1 +A = 19 +M = 46 + +ModInv = -1 +A = 23 +M = 46 + +ModInv = -1 +A = 2d +M = 46 + +ModInv = -1 +A = 31 +M = 46 + +ModInv = -1 +A = 37 +M = 46 + +ModInv = -1 +A = 3f +M = 46 + +ModInv = -1 +A = 41 +M = 46 + +ModInv = -1 +A = 4b +M = 46 + +ModInv = -1 +A = 4d +M = 46 + +ModInv = -1 +A = 55 +M = 46 + +ModInv = -1 +A = 5b +M = 46 + +ModInv = -1 +A = 5f +M = 46 + +ModInv = -1 +A = -47 +M = 47 + +ModInv = -1 +A = 0 +M = 47 + +ModInv = -1 +A = 47 +M = 47 + +ModInv = -1 +A = -63 +M = 48 + +ModInv = -1 +A = -5d +M = 48 + +ModInv = -1 +A = -57 +M = 48 + +ModInv = -1 +A = -51 +M = 48 + +ModInv = -1 +A = -4b +M = 48 + +ModInv = -1 +A = -45 +M = 48 + +ModInv = -1 +A = -3f +M = 48 + +ModInv = -1 +A = -39 +M = 48 + +ModInv = -1 +A = -33 +M = 48 + +ModInv = -1 +A = -2d +M = 48 + +ModInv = -1 +A = -27 +M = 48 + +ModInv = -1 +A = -21 +M = 48 + +ModInv = -1 +A = -1b +M = 48 + +ModInv = -1 +A = -15 +M = 48 + +ModInv = -1 +A = -f +M = 48 + +ModInv = -1 +A = -9 +M = 48 + +ModInv = -1 +A = -3 +M = 48 + +ModInv = -1 +A = 3 +M = 48 + +ModInv = -1 +A = 9 +M = 48 + +ModInv = -1 +A = f +M = 48 + +ModInv = -1 +A = 15 +M = 48 + +ModInv = -1 +A = 1b +M = 48 + +ModInv = -1 +A = 21 +M = 48 + +ModInv = -1 +A = 27 +M = 48 + +ModInv = -1 +A = 2d +M = 48 + +ModInv = -1 +A = 33 +M = 48 + +ModInv = -1 +A = 39 +M = 48 + +ModInv = -1 +A = 3f +M = 48 + +ModInv = -1 +A = 45 +M = 48 + +ModInv = -1 +A = 4b +M = 48 + +ModInv = -1 +A = 51 +M = 48 + +ModInv = -1 +A = 57 +M = 48 + +ModInv = -1 +A = 5d +M = 48 + +ModInv = -1 +A = 63 +M = 48 + +ModInv = -1 +A = -49 +M = 49 + +ModInv = -1 +A = 0 +M = 49 + +ModInv = -1 +A = 49 +M = 49 + +ModInv = -1 +A = -25 +M = 4a + +ModInv = -1 +A = 25 +M = 4a + +ModInv = -1 +A = -64 +M = 4b + +ModInv = -1 +A = -63 +M = 4b + +ModInv = -1 +A = -60 +M = 4b + +ModInv = -1 +A = -5f +M = 4b + +ModInv = -1 +A = -5d +M = 4b + +ModInv = -1 +A = -5a +M = 4b + +ModInv = -1 +A = -57 +M = 4b + +ModInv = -1 +A = -55 +M = 4b + +ModInv = -1 +A = -54 +M = 4b + +ModInv = -1 +A = -51 +M = 4b + +ModInv = -1 +A = -50 +M = 4b + +ModInv = -1 +A = -4e +M = 4b + +ModInv = -1 +A = -4b +M = 4b + +ModInv = -1 +A = -48 +M = 4b + +ModInv = -1 +A = -46 +M = 4b + +ModInv = -1 +A = -45 +M = 4b + +ModInv = -1 +A = -42 +M = 4b + +ModInv = -1 +A = -41 +M = 4b + +ModInv = -1 +A = -3f +M = 4b + +ModInv = -1 +A = -3c +M = 4b + +ModInv = -1 +A = -39 +M = 4b + +ModInv = -1 +A = -37 +M = 4b + +ModInv = -1 +A = -36 +M = 4b + +ModInv = -1 +A = -33 +M = 4b + +ModInv = -1 +A = -32 +M = 4b + +ModInv = -1 +A = -30 +M = 4b + +ModInv = -1 +A = -2d +M = 4b + +ModInv = -1 +A = -2a +M = 4b + +ModInv = -1 +A = -28 +M = 4b + +ModInv = -1 +A = -27 +M = 4b + +ModInv = -1 +A = -24 +M = 4b + +ModInv = -1 +A = -23 +M = 4b + +ModInv = -1 +A = -21 +M = 4b + +ModInv = -1 +A = -1e +M = 4b + +ModInv = -1 +A = -1b +M = 4b + +ModInv = -1 +A = -19 +M = 4b + +ModInv = -1 +A = -18 +M = 4b + +ModInv = -1 +A = -15 +M = 4b + +ModInv = -1 +A = -14 +M = 4b + +ModInv = -1 +A = -12 +M = 4b + +ModInv = -1 +A = -f +M = 4b + +ModInv = -1 +A = -c +M = 4b + +ModInv = -1 +A = -a +M = 4b + +ModInv = -1 +A = -9 +M = 4b + +ModInv = -1 +A = -6 +M = 4b + +ModInv = -1 +A = -5 +M = 4b + +ModInv = -1 +A = -3 +M = 4b + +ModInv = -1 +A = 0 +M = 4b + +ModInv = -1 +A = 3 +M = 4b + +ModInv = -1 +A = 5 +M = 4b + +ModInv = -1 +A = 6 +M = 4b + +ModInv = -1 +A = 9 +M = 4b + +ModInv = -1 +A = a +M = 4b + +ModInv = -1 +A = c +M = 4b + +ModInv = -1 +A = f +M = 4b + +ModInv = -1 +A = 12 +M = 4b + +ModInv = -1 +A = 14 +M = 4b + +ModInv = -1 +A = 15 +M = 4b + +ModInv = -1 +A = 18 +M = 4b + +ModInv = -1 +A = 19 +M = 4b + +ModInv = -1 +A = 1b +M = 4b + +ModInv = -1 +A = 1e +M = 4b + +ModInv = -1 +A = 21 +M = 4b + +ModInv = -1 +A = 23 +M = 4b + +ModInv = -1 +A = 24 +M = 4b + +ModInv = -1 +A = 27 +M = 4b + +ModInv = -1 +A = 28 +M = 4b + +ModInv = -1 +A = 2a +M = 4b + +ModInv = -1 +A = 2d +M = 4b + +ModInv = -1 +A = 30 +M = 4b + +ModInv = -1 +A = 32 +M = 4b + +ModInv = -1 +A = 33 +M = 4b + +ModInv = -1 +A = 36 +M = 4b + +ModInv = -1 +A = 37 +M = 4b + +ModInv = -1 +A = 39 +M = 4b + +ModInv = -1 +A = 3c +M = 4b + +ModInv = -1 +A = 3f +M = 4b + +ModInv = -1 +A = 41 +M = 4b + +ModInv = -1 +A = 42 +M = 4b + +ModInv = -1 +A = 45 +M = 4b + +ModInv = -1 +A = 46 +M = 4b + +ModInv = -1 +A = 48 +M = 4b + +ModInv = -1 +A = 4b +M = 4b + +ModInv = -1 +A = 4e +M = 4b + +ModInv = -1 +A = 50 +M = 4b + +ModInv = -1 +A = 51 +M = 4b + +ModInv = -1 +A = 54 +M = 4b + +ModInv = -1 +A = 55 +M = 4b + +ModInv = -1 +A = 57 +M = 4b + +ModInv = -1 +A = 5a +M = 4b + +ModInv = -1 +A = 5d +M = 4b + +ModInv = -1 +A = 5f +M = 4b + +ModInv = -1 +A = 60 +M = 4b + +ModInv = -1 +A = 63 +M = 4b + +ModInv = -1 +A = -5f +M = 4c + +ModInv = -1 +A = -39 +M = 4c + +ModInv = -1 +A = -13 +M = 4c + +ModInv = -1 +A = 13 +M = 4c + +ModInv = -1 +A = 39 +M = 4c + +ModInv = -1 +A = 5f +M = 4c + +ModInv = -1 +A = -63 +M = 4d + +ModInv = -1 +A = -62 +M = 4d + +ModInv = -1 +A = -5b +M = 4d + +ModInv = -1 +A = -58 +M = 4d + +ModInv = -1 +A = -54 +M = 4d + +ModInv = -1 +A = -4d +M = 4d + +ModInv = -1 +A = -46 +M = 4d + +ModInv = -1 +A = -42 +M = 4d + +ModInv = -1 +A = -3f +M = 4d + +ModInv = -1 +A = -38 +M = 4d + +ModInv = -1 +A = -37 +M = 4d + +ModInv = -1 +A = -31 +M = 4d + +ModInv = -1 +A = -2c +M = 4d + +ModInv = -1 +A = -2a +M = 4d + +ModInv = -1 +A = -23 +M = 4d + +ModInv = -1 +A = -21 +M = 4d + +ModInv = -1 +A = -1c +M = 4d + +ModInv = -1 +A = -16 +M = 4d + +ModInv = -1 +A = -15 +M = 4d + +ModInv = -1 +A = -e +M = 4d + +ModInv = -1 +A = -b +M = 4d + +ModInv = -1 +A = -7 +M = 4d + +ModInv = -1 +A = 0 +M = 4d + +ModInv = -1 +A = 7 +M = 4d + +ModInv = -1 +A = b +M = 4d + +ModInv = -1 +A = e +M = 4d + +ModInv = -1 +A = 15 +M = 4d + +ModInv = -1 +A = 16 +M = 4d + +ModInv = -1 +A = 1c +M = 4d + +ModInv = -1 +A = 21 +M = 4d + +ModInv = -1 +A = 23 +M = 4d + +ModInv = -1 +A = 2a +M = 4d + +ModInv = -1 +A = 2c +M = 4d + +ModInv = -1 +A = 31 +M = 4d + +ModInv = -1 +A = 37 +M = 4d + +ModInv = -1 +A = 38 +M = 4d + +ModInv = -1 +A = 3f +M = 4d + +ModInv = -1 +A = 42 +M = 4d + +ModInv = -1 +A = 46 +M = 4d + +ModInv = -1 +A = 4d +M = 4d + +ModInv = -1 +A = 54 +M = 4d + +ModInv = -1 +A = 58 +M = 4d + +ModInv = -1 +A = 5b +M = 4d + +ModInv = -1 +A = 62 +M = 4d + +ModInv = -1 +A = 63 +M = 4d + +ModInv = -1 +A = -63 +M = 4e + +ModInv = -1 +A = -5d +M = 4e + +ModInv = -1 +A = -5b +M = 4e + +ModInv = -1 +A = -57 +M = 4e + +ModInv = -1 +A = -51 +M = 4e + +ModInv = -1 +A = -4b +M = 4e + +ModInv = -1 +A = -45 +M = 4e + +ModInv = -1 +A = -41 +M = 4e + +ModInv = -1 +A = -3f +M = 4e + +ModInv = -1 +A = -39 +M = 4e + +ModInv = -1 +A = -33 +M = 4e + +ModInv = -1 +A = -2d +M = 4e + +ModInv = -1 +A = -27 +M = 4e + +ModInv = -1 +A = -21 +M = 4e + +ModInv = -1 +A = -1b +M = 4e + +ModInv = -1 +A = -15 +M = 4e + +ModInv = -1 +A = -f +M = 4e + +ModInv = -1 +A = -d +M = 4e + +ModInv = -1 +A = -9 +M = 4e + +ModInv = -1 +A = -3 +M = 4e + +ModInv = -1 +A = 3 +M = 4e + +ModInv = -1 +A = 9 +M = 4e + +ModInv = -1 +A = d +M = 4e + +ModInv = -1 +A = f +M = 4e + +ModInv = -1 +A = 15 +M = 4e + +ModInv = -1 +A = 1b +M = 4e + +ModInv = -1 +A = 21 +M = 4e + +ModInv = -1 +A = 27 +M = 4e + +ModInv = -1 +A = 2d +M = 4e + +ModInv = -1 +A = 33 +M = 4e + +ModInv = -1 +A = 39 +M = 4e + +ModInv = -1 +A = 3f +M = 4e + +ModInv = -1 +A = 41 +M = 4e + +ModInv = -1 +A = 45 +M = 4e + +ModInv = -1 +A = 4b +M = 4e + +ModInv = -1 +A = 51 +M = 4e + +ModInv = -1 +A = 57 +M = 4e + +ModInv = -1 +A = 5b +M = 4e + +ModInv = -1 +A = 5d +M = 4e + +ModInv = -1 +A = 63 +M = 4e + +ModInv = -1 +A = -4f +M = 4f + +ModInv = -1 +A = 0 +M = 4f + +ModInv = -1 +A = 4f +M = 4f + +ModInv = -1 +A = -5f +M = 50 + +ModInv = -1 +A = -55 +M = 50 + +ModInv = -1 +A = -4b +M = 50 + +ModInv = -1 +A = -41 +M = 50 + +ModInv = -1 +A = -37 +M = 50 + +ModInv = -1 +A = -2d +M = 50 + +ModInv = -1 +A = -23 +M = 50 + +ModInv = -1 +A = -19 +M = 50 + +ModInv = -1 +A = -f +M = 50 + +ModInv = -1 +A = -5 +M = 50 + +ModInv = -1 +A = 5 +M = 50 + +ModInv = -1 +A = f +M = 50 + +ModInv = -1 +A = 19 +M = 50 + +ModInv = -1 +A = 23 +M = 50 + +ModInv = -1 +A = 2d +M = 50 + +ModInv = -1 +A = 37 +M = 50 + +ModInv = -1 +A = 41 +M = 50 + +ModInv = -1 +A = 4b +M = 50 + +ModInv = -1 +A = 55 +M = 50 + +ModInv = -1 +A = 5f +M = 50 + +ModInv = -1 +A = -63 +M = 51 + +ModInv = -1 +A = -60 +M = 51 + +ModInv = -1 +A = -5d +M = 51 + +ModInv = -1 +A = -5a +M = 51 + +ModInv = -1 +A = -57 +M = 51 + +ModInv = -1 +A = -54 +M = 51 + +ModInv = -1 +A = -51 +M = 51 + +ModInv = -1 +A = -4e +M = 51 + +ModInv = -1 +A = -4b +M = 51 + +ModInv = -1 +A = -48 +M = 51 + +ModInv = -1 +A = -45 +M = 51 + +ModInv = -1 +A = -42 +M = 51 + +ModInv = -1 +A = -3f +M = 51 + +ModInv = -1 +A = -3c +M = 51 + +ModInv = -1 +A = -39 +M = 51 + +ModInv = -1 +A = -36 +M = 51 + +ModInv = -1 +A = -33 +M = 51 + +ModInv = -1 +A = -30 +M = 51 + +ModInv = -1 +A = -2d +M = 51 + +ModInv = -1 +A = -2a +M = 51 + +ModInv = -1 +A = -27 +M = 51 + +ModInv = -1 +A = -24 +M = 51 + +ModInv = -1 +A = -21 +M = 51 + +ModInv = -1 +A = -1e +M = 51 + +ModInv = -1 +A = -1b +M = 51 + +ModInv = -1 +A = -18 +M = 51 + +ModInv = -1 +A = -15 +M = 51 + +ModInv = -1 +A = -12 +M = 51 + +ModInv = -1 +A = -f +M = 51 + +ModInv = -1 +A = -c +M = 51 + +ModInv = -1 +A = -9 +M = 51 + +ModInv = -1 +A = -6 +M = 51 + +ModInv = -1 +A = -3 +M = 51 + +ModInv = -1 +A = 0 +M = 51 + +ModInv = -1 +A = 3 +M = 51 + +ModInv = -1 +A = 6 +M = 51 + +ModInv = -1 +A = 9 +M = 51 + +ModInv = -1 +A = c +M = 51 + +ModInv = -1 +A = f +M = 51 + +ModInv = -1 +A = 12 +M = 51 + +ModInv = -1 +A = 15 +M = 51 + +ModInv = -1 +A = 18 +M = 51 + +ModInv = -1 +A = 1b +M = 51 + +ModInv = -1 +A = 1e +M = 51 + +ModInv = -1 +A = 21 +M = 51 + +ModInv = -1 +A = 24 +M = 51 + +ModInv = -1 +A = 27 +M = 51 + +ModInv = -1 +A = 2a +M = 51 + +ModInv = -1 +A = 2d +M = 51 + +ModInv = -1 +A = 30 +M = 51 + +ModInv = -1 +A = 33 +M = 51 + +ModInv = -1 +A = 36 +M = 51 + +ModInv = -1 +A = 39 +M = 51 + +ModInv = -1 +A = 3c +M = 51 + +ModInv = -1 +A = 3f +M = 51 + +ModInv = -1 +A = 42 +M = 51 + +ModInv = -1 +A = 45 +M = 51 + +ModInv = -1 +A = 48 +M = 51 + +ModInv = -1 +A = 4b +M = 51 + +ModInv = -1 +A = 4e +M = 51 + +ModInv = -1 +A = 51 +M = 51 + +ModInv = -1 +A = 54 +M = 51 + +ModInv = -1 +A = 57 +M = 51 + +ModInv = -1 +A = 5a +M = 51 + +ModInv = -1 +A = 5d +M = 51 + +ModInv = -1 +A = 60 +M = 51 + +ModInv = -1 +A = 63 +M = 51 + +ModInv = -1 +A = -29 +M = 52 + +ModInv = -1 +A = 29 +M = 52 + +ModInv = -1 +A = -53 +M = 53 + +ModInv = -1 +A = 0 +M = 53 + +ModInv = -1 +A = 53 +M = 53 + +ModInv = -1 +A = -63 +M = 54 + +ModInv = -1 +A = -5d +M = 54 + +ModInv = -1 +A = -5b +M = 54 + +ModInv = -1 +A = -57 +M = 54 + +ModInv = -1 +A = -51 +M = 54 + +ModInv = -1 +A = -4d +M = 54 + +ModInv = -1 +A = -4b +M = 54 + +ModInv = -1 +A = -45 +M = 54 + +ModInv = -1 +A = -3f +M = 54 + +ModInv = -1 +A = -39 +M = 54 + +ModInv = -1 +A = -33 +M = 54 + +ModInv = -1 +A = -31 +M = 54 + +ModInv = -1 +A = -2d +M = 54 + +ModInv = -1 +A = -27 +M = 54 + +ModInv = -1 +A = -23 +M = 54 + +ModInv = -1 +A = -21 +M = 54 + +ModInv = -1 +A = -1b +M = 54 + +ModInv = -1 +A = -15 +M = 54 + +ModInv = -1 +A = -f +M = 54 + +ModInv = -1 +A = -9 +M = 54 + +ModInv = -1 +A = -7 +M = 54 + +ModInv = -1 +A = -3 +M = 54 + +ModInv = -1 +A = 3 +M = 54 + +ModInv = -1 +A = 7 +M = 54 + +ModInv = -1 +A = 9 +M = 54 + +ModInv = -1 +A = f +M = 54 + +ModInv = -1 +A = 15 +M = 54 + +ModInv = -1 +A = 1b +M = 54 + +ModInv = -1 +A = 21 +M = 54 + +ModInv = -1 +A = 23 +M = 54 + +ModInv = -1 +A = 27 +M = 54 + +ModInv = -1 +A = 2d +M = 54 + +ModInv = -1 +A = 31 +M = 54 + +ModInv = -1 +A = 33 +M = 54 + +ModInv = -1 +A = 39 +M = 54 + +ModInv = -1 +A = 3f +M = 54 + +ModInv = -1 +A = 45 +M = 54 + +ModInv = -1 +A = 4b +M = 54 + +ModInv = -1 +A = 4d +M = 54 + +ModInv = -1 +A = 51 +M = 54 + +ModInv = -1 +A = 57 +M = 54 + +ModInv = -1 +A = 5b +M = 54 + +ModInv = -1 +A = 5d +M = 54 + +ModInv = -1 +A = 63 +M = 54 + +ModInv = -1 +A = -64 +M = 55 + +ModInv = -1 +A = -5f +M = 55 + +ModInv = -1 +A = -5a +M = 55 + +ModInv = -1 +A = -55 +M = 55 + +ModInv = -1 +A = -50 +M = 55 + +ModInv = -1 +A = -4b +M = 55 + +ModInv = -1 +A = -46 +M = 55 + +ModInv = -1 +A = -44 +M = 55 + +ModInv = -1 +A = -41 +M = 55 + +ModInv = -1 +A = -3c +M = 55 + +ModInv = -1 +A = -37 +M = 55 + +ModInv = -1 +A = -33 +M = 55 + +ModInv = -1 +A = -32 +M = 55 + +ModInv = -1 +A = -2d +M = 55 + +ModInv = -1 +A = -28 +M = 55 + +ModInv = -1 +A = -23 +M = 55 + +ModInv = -1 +A = -22 +M = 55 + +ModInv = -1 +A = -1e +M = 55 + +ModInv = -1 +A = -19 +M = 55 + +ModInv = -1 +A = -14 +M = 55 + +ModInv = -1 +A = -11 +M = 55 + +ModInv = -1 +A = -f +M = 55 + +ModInv = -1 +A = -a +M = 55 + +ModInv = -1 +A = -5 +M = 55 + +ModInv = -1 +A = 0 +M = 55 + +ModInv = -1 +A = 5 +M = 55 + +ModInv = -1 +A = a +M = 55 + +ModInv = -1 +A = f +M = 55 + +ModInv = -1 +A = 11 +M = 55 + +ModInv = -1 +A = 14 +M = 55 + +ModInv = -1 +A = 19 +M = 55 + +ModInv = -1 +A = 1e +M = 55 + +ModInv = -1 +A = 22 +M = 55 + +ModInv = -1 +A = 23 +M = 55 + +ModInv = -1 +A = 28 +M = 55 + +ModInv = -1 +A = 2d +M = 55 + +ModInv = -1 +A = 32 +M = 55 + +ModInv = -1 +A = 33 +M = 55 + +ModInv = -1 +A = 37 +M = 55 + +ModInv = -1 +A = 3c +M = 55 + +ModInv = -1 +A = 41 +M = 55 + +ModInv = -1 +A = 44 +M = 55 + +ModInv = -1 +A = 46 +M = 55 + +ModInv = -1 +A = 4b +M = 55 + +ModInv = -1 +A = 50 +M = 55 + +ModInv = -1 +A = 55 +M = 55 + +ModInv = -1 +A = 5a +M = 55 + +ModInv = -1 +A = 5f +M = 55 + +ModInv = -1 +A = -2b +M = 56 + +ModInv = -1 +A = 2b +M = 56 + +ModInv = -1 +A = -63 +M = 57 + +ModInv = -1 +A = -60 +M = 57 + +ModInv = -1 +A = -5d +M = 57 + +ModInv = -1 +A = -5a +M = 57 + +ModInv = -1 +A = -57 +M = 57 + +ModInv = -1 +A = -54 +M = 57 + +ModInv = -1 +A = -51 +M = 57 + +ModInv = -1 +A = -4e +M = 57 + +ModInv = -1 +A = -4b +M = 57 + +ModInv = -1 +A = -48 +M = 57 + +ModInv = -1 +A = -45 +M = 57 + +ModInv = -1 +A = -42 +M = 57 + +ModInv = -1 +A = -3f +M = 57 + +ModInv = -1 +A = -3c +M = 57 + +ModInv = -1 +A = -3a +M = 57 + +ModInv = -1 +A = -39 +M = 57 + +ModInv = -1 +A = -36 +M = 57 + +ModInv = -1 +A = -33 +M = 57 + +ModInv = -1 +A = -30 +M = 57 + +ModInv = -1 +A = -2d +M = 57 + +ModInv = -1 +A = -2a +M = 57 + +ModInv = -1 +A = -27 +M = 57 + +ModInv = -1 +A = -24 +M = 57 + +ModInv = -1 +A = -21 +M = 57 + +ModInv = -1 +A = -1e +M = 57 + +ModInv = -1 +A = -1d +M = 57 + +ModInv = -1 +A = -1b +M = 57 + +ModInv = -1 +A = -18 +M = 57 + +ModInv = -1 +A = -15 +M = 57 + +ModInv = -1 +A = -12 +M = 57 + +ModInv = -1 +A = -f +M = 57 + +ModInv = -1 +A = -c +M = 57 + +ModInv = -1 +A = -9 +M = 57 + +ModInv = -1 +A = -6 +M = 57 + +ModInv = -1 +A = -3 +M = 57 + +ModInv = -1 +A = 0 +M = 57 + +ModInv = -1 +A = 3 +M = 57 + +ModInv = -1 +A = 6 +M = 57 + +ModInv = -1 +A = 9 +M = 57 + +ModInv = -1 +A = c +M = 57 + +ModInv = -1 +A = f +M = 57 + +ModInv = -1 +A = 12 +M = 57 + +ModInv = -1 +A = 15 +M = 57 + +ModInv = -1 +A = 18 +M = 57 + +ModInv = -1 +A = 1b +M = 57 + +ModInv = -1 +A = 1d +M = 57 + +ModInv = -1 +A = 1e +M = 57 + +ModInv = -1 +A = 21 +M = 57 + +ModInv = -1 +A = 24 +M = 57 + +ModInv = -1 +A = 27 +M = 57 + +ModInv = -1 +A = 2a +M = 57 + +ModInv = -1 +A = 2d +M = 57 + +ModInv = -1 +A = 30 +M = 57 + +ModInv = -1 +A = 33 +M = 57 + +ModInv = -1 +A = 36 +M = 57 + +ModInv = -1 +A = 39 +M = 57 + +ModInv = -1 +A = 3a +M = 57 + +ModInv = -1 +A = 3c +M = 57 + +ModInv = -1 +A = 3f +M = 57 + +ModInv = -1 +A = 42 +M = 57 + +ModInv = -1 +A = 45 +M = 57 + +ModInv = -1 +A = 48 +M = 57 + +ModInv = -1 +A = 4b +M = 57 + +ModInv = -1 +A = 4e +M = 57 + +ModInv = -1 +A = 51 +M = 57 + +ModInv = -1 +A = 54 +M = 57 + +ModInv = -1 +A = 57 +M = 57 + +ModInv = -1 +A = 5a +M = 57 + +ModInv = -1 +A = 5d +M = 57 + +ModInv = -1 +A = 60 +M = 57 + +ModInv = -1 +A = 63 +M = 57 + +ModInv = -1 +A = -63 +M = 58 + +ModInv = -1 +A = -4d +M = 58 + +ModInv = -1 +A = -37 +M = 58 + +ModInv = -1 +A = -21 +M = 58 + +ModInv = -1 +A = -b +M = 58 + +ModInv = -1 +A = b +M = 58 + +ModInv = -1 +A = 21 +M = 58 + +ModInv = -1 +A = 37 +M = 58 + +ModInv = -1 +A = 4d +M = 58 + +ModInv = -1 +A = 63 +M = 58 + +ModInv = -1 +A = -59 +M = 59 + +ModInv = -1 +A = 0 +M = 59 + +ModInv = -1 +A = 59 +M = 59 + +ModInv = -1 +A = -63 +M = 5a + +ModInv = -1 +A = -5f +M = 5a + +ModInv = -1 +A = -5d +M = 5a + +ModInv = -1 +A = -57 +M = 5a + +ModInv = -1 +A = -55 +M = 5a + +ModInv = -1 +A = -51 +M = 5a + +ModInv = -1 +A = -4b +M = 5a + +ModInv = -1 +A = -45 +M = 5a + +ModInv = -1 +A = -41 +M = 5a + +ModInv = -1 +A = -3f +M = 5a + +ModInv = -1 +A = -39 +M = 5a + +ModInv = -1 +A = -37 +M = 5a + +ModInv = -1 +A = -33 +M = 5a + +ModInv = -1 +A = -2d +M = 5a + +ModInv = -1 +A = -27 +M = 5a + +ModInv = -1 +A = -23 +M = 5a + +ModInv = -1 +A = -21 +M = 5a + +ModInv = -1 +A = -1b +M = 5a + +ModInv = -1 +A = -19 +M = 5a + +ModInv = -1 +A = -15 +M = 5a + +ModInv = -1 +A = -f +M = 5a + +ModInv = -1 +A = -9 +M = 5a + +ModInv = -1 +A = -5 +M = 5a + +ModInv = -1 +A = -3 +M = 5a + +ModInv = -1 +A = 3 +M = 5a + +ModInv = -1 +A = 5 +M = 5a + +ModInv = -1 +A = 9 +M = 5a + +ModInv = -1 +A = f +M = 5a + +ModInv = -1 +A = 15 +M = 5a + +ModInv = -1 +A = 19 +M = 5a + +ModInv = -1 +A = 1b +M = 5a + +ModInv = -1 +A = 21 +M = 5a + +ModInv = -1 +A = 23 +M = 5a + +ModInv = -1 +A = 27 +M = 5a + +ModInv = -1 +A = 2d +M = 5a + +ModInv = -1 +A = 33 +M = 5a + +ModInv = -1 +A = 37 +M = 5a + +ModInv = -1 +A = 39 +M = 5a + +ModInv = -1 +A = 3f +M = 5a + +ModInv = -1 +A = 41 +M = 5a + +ModInv = -1 +A = 45 +M = 5a + +ModInv = -1 +A = 4b +M = 5a + +ModInv = -1 +A = 51 +M = 5a + +ModInv = -1 +A = 55 +M = 5a + +ModInv = -1 +A = 57 +M = 5a + +ModInv = -1 +A = 5d +M = 5a + +ModInv = -1 +A = 5f +M = 5a + +ModInv = -1 +A = 63 +M = 5a + +ModInv = -1 +A = -62 +M = 5b + +ModInv = -1 +A = -5b +M = 5b + +ModInv = -1 +A = -54 +M = 5b + +ModInv = -1 +A = -4e +M = 5b + +ModInv = -1 +A = -4d +M = 5b + +ModInv = -1 +A = -46 +M = 5b + +ModInv = -1 +A = -41 +M = 5b + +ModInv = -1 +A = -3f +M = 5b + +ModInv = -1 +A = -38 +M = 5b + +ModInv = -1 +A = -34 +M = 5b + +ModInv = -1 +A = -31 +M = 5b + +ModInv = -1 +A = -2a +M = 5b + +ModInv = -1 +A = -27 +M = 5b + +ModInv = -1 +A = -23 +M = 5b + +ModInv = -1 +A = -1c +M = 5b + +ModInv = -1 +A = -1a +M = 5b + +ModInv = -1 +A = -15 +M = 5b + +ModInv = -1 +A = -e +M = 5b + +ModInv = -1 +A = -d +M = 5b + +ModInv = -1 +A = -7 +M = 5b + +ModInv = -1 +A = 0 +M = 5b + +ModInv = -1 +A = 7 +M = 5b + +ModInv = -1 +A = d +M = 5b + +ModInv = -1 +A = e +M = 5b + +ModInv = -1 +A = 15 +M = 5b + +ModInv = -1 +A = 1a +M = 5b + +ModInv = -1 +A = 1c +M = 5b + +ModInv = -1 +A = 23 +M = 5b + +ModInv = -1 +A = 27 +M = 5b + +ModInv = -1 +A = 2a +M = 5b + +ModInv = -1 +A = 31 +M = 5b + +ModInv = -1 +A = 34 +M = 5b + +ModInv = -1 +A = 38 +M = 5b + +ModInv = -1 +A = 3f +M = 5b + +ModInv = -1 +A = 41 +M = 5b + +ModInv = -1 +A = 46 +M = 5b + +ModInv = -1 +A = 4d +M = 5b + +ModInv = -1 +A = 4e +M = 5b + +ModInv = -1 +A = 54 +M = 5b + +ModInv = -1 +A = 5b +M = 5b + +ModInv = -1 +A = 62 +M = 5b + +ModInv = -1 +A = -45 +M = 5c + +ModInv = -1 +A = -17 +M = 5c + +ModInv = -1 +A = 17 +M = 5c + +ModInv = -1 +A = 45 +M = 5c + +ModInv = -1 +A = -63 +M = 5d + +ModInv = -1 +A = -60 +M = 5d + +ModInv = -1 +A = -5d +M = 5d + +ModInv = -1 +A = -5a +M = 5d + +ModInv = -1 +A = -57 +M = 5d + +ModInv = -1 +A = -54 +M = 5d + +ModInv = -1 +A = -51 +M = 5d + +ModInv = -1 +A = -4e +M = 5d + +ModInv = -1 +A = -4b +M = 5d + +ModInv = -1 +A = -48 +M = 5d + +ModInv = -1 +A = -45 +M = 5d + +ModInv = -1 +A = -42 +M = 5d + +ModInv = -1 +A = -3f +M = 5d + +ModInv = -1 +A = -3e +M = 5d + +ModInv = -1 +A = -3c +M = 5d + +ModInv = -1 +A = -39 +M = 5d + +ModInv = -1 +A = -36 +M = 5d + +ModInv = -1 +A = -33 +M = 5d + +ModInv = -1 +A = -30 +M = 5d + +ModInv = -1 +A = -2d +M = 5d + +ModInv = -1 +A = -2a +M = 5d + +ModInv = -1 +A = -27 +M = 5d + +ModInv = -1 +A = -24 +M = 5d + +ModInv = -1 +A = -21 +M = 5d + +ModInv = -1 +A = -1f +M = 5d + +ModInv = -1 +A = -1e +M = 5d + +ModInv = -1 +A = -1b +M = 5d + +ModInv = -1 +A = -18 +M = 5d + +ModInv = -1 +A = -15 +M = 5d + +ModInv = -1 +A = -12 +M = 5d + +ModInv = -1 +A = -f +M = 5d + +ModInv = -1 +A = -c +M = 5d + +ModInv = -1 +A = -9 +M = 5d + +ModInv = -1 +A = -6 +M = 5d + +ModInv = -1 +A = -3 +M = 5d + +ModInv = -1 +A = 0 +M = 5d + +ModInv = -1 +A = 3 +M = 5d + +ModInv = -1 +A = 6 +M = 5d + +ModInv = -1 +A = 9 +M = 5d + +ModInv = -1 +A = c +M = 5d + +ModInv = -1 +A = f +M = 5d + +ModInv = -1 +A = 12 +M = 5d + +ModInv = -1 +A = 15 +M = 5d + +ModInv = -1 +A = 18 +M = 5d + +ModInv = -1 +A = 1b +M = 5d + +ModInv = -1 +A = 1e +M = 5d + +ModInv = -1 +A = 1f +M = 5d + +ModInv = -1 +A = 21 +M = 5d + +ModInv = -1 +A = 24 +M = 5d + +ModInv = -1 +A = 27 +M = 5d + +ModInv = -1 +A = 2a +M = 5d + +ModInv = -1 +A = 2d +M = 5d + +ModInv = -1 +A = 30 +M = 5d + +ModInv = -1 +A = 33 +M = 5d + +ModInv = -1 +A = 36 +M = 5d + +ModInv = -1 +A = 39 +M = 5d + +ModInv = -1 +A = 3c +M = 5d + +ModInv = -1 +A = 3e +M = 5d + +ModInv = -1 +A = 3f +M = 5d + +ModInv = -1 +A = 42 +M = 5d + +ModInv = -1 +A = 45 +M = 5d + +ModInv = -1 +A = 48 +M = 5d + +ModInv = -1 +A = 4b +M = 5d + +ModInv = -1 +A = 4e +M = 5d + +ModInv = -1 +A = 51 +M = 5d + +ModInv = -1 +A = 54 +M = 5d + +ModInv = -1 +A = 57 +M = 5d + +ModInv = -1 +A = 5a +M = 5d + +ModInv = -1 +A = 5d +M = 5d + +ModInv = -1 +A = 60 +M = 5d + +ModInv = -1 +A = 63 +M = 5d + +ModInv = -1 +A = -2f +M = 5e + +ModInv = -1 +A = 2f +M = 5e + +ModInv = -1 +A = -64 +M = 5f + +ModInv = -1 +A = -5f +M = 5f + +ModInv = -1 +A = -5a +M = 5f + +ModInv = -1 +A = -55 +M = 5f + +ModInv = -1 +A = -50 +M = 5f + +ModInv = -1 +A = -4c +M = 5f + +ModInv = -1 +A = -4b +M = 5f + +ModInv = -1 +A = -46 +M = 5f + +ModInv = -1 +A = -41 +M = 5f + +ModInv = -1 +A = -3c +M = 5f + +ModInv = -1 +A = -39 +M = 5f + +ModInv = -1 +A = -37 +M = 5f + +ModInv = -1 +A = -32 +M = 5f + +ModInv = -1 +A = -2d +M = 5f + +ModInv = -1 +A = -28 +M = 5f + +ModInv = -1 +A = -26 +M = 5f + +ModInv = -1 +A = -23 +M = 5f + +ModInv = -1 +A = -1e +M = 5f + +ModInv = -1 +A = -19 +M = 5f + +ModInv = -1 +A = -14 +M = 5f + +ModInv = -1 +A = -13 +M = 5f + +ModInv = -1 +A = -f +M = 5f + +ModInv = -1 +A = -a +M = 5f + +ModInv = -1 +A = -5 +M = 5f + +ModInv = -1 +A = 0 +M = 5f + +ModInv = -1 +A = 5 +M = 5f + +ModInv = -1 +A = a +M = 5f + +ModInv = -1 +A = f +M = 5f + +ModInv = -1 +A = 13 +M = 5f + +ModInv = -1 +A = 14 +M = 5f + +ModInv = -1 +A = 19 +M = 5f + +ModInv = -1 +A = 1e +M = 5f + +ModInv = -1 +A = 23 +M = 5f + +ModInv = -1 +A = 26 +M = 5f + +ModInv = -1 +A = 28 +M = 5f + +ModInv = -1 +A = 2d +M = 5f + +ModInv = -1 +A = 32 +M = 5f + +ModInv = -1 +A = 37 +M = 5f + +ModInv = -1 +A = 39 +M = 5f + +ModInv = -1 +A = 3c +M = 5f + +ModInv = -1 +A = 41 +M = 5f + +ModInv = -1 +A = 46 +M = 5f + +ModInv = -1 +A = 4b +M = 5f + +ModInv = -1 +A = 4c +M = 5f + +ModInv = -1 +A = 50 +M = 5f + +ModInv = -1 +A = 55 +M = 5f + +ModInv = -1 +A = 5a +M = 5f + +ModInv = -1 +A = 5f +M = 5f + +ModInv = -1 +A = -63 +M = 60 + +ModInv = -1 +A = -5d +M = 60 + +ModInv = -1 +A = -57 +M = 60 + +ModInv = -1 +A = -51 +M = 60 + +ModInv = -1 +A = -4b +M = 60 + +ModInv = -1 +A = -45 +M = 60 + +ModInv = -1 +A = -3f +M = 60 + +ModInv = -1 +A = -39 +M = 60 + +ModInv = -1 +A = -33 +M = 60 + +ModInv = -1 +A = -2d +M = 60 + +ModInv = -1 +A = -27 +M = 60 + +ModInv = -1 +A = -21 +M = 60 + +ModInv = -1 +A = -1b +M = 60 + +ModInv = -1 +A = -15 +M = 60 + +ModInv = -1 +A = -f +M = 60 + +ModInv = -1 +A = -9 +M = 60 + +ModInv = -1 +A = -3 +M = 60 + +ModInv = -1 +A = 3 +M = 60 + +ModInv = -1 +A = 9 +M = 60 + +ModInv = -1 +A = f +M = 60 + +ModInv = -1 +A = 15 +M = 60 + +ModInv = -1 +A = 1b +M = 60 + +ModInv = -1 +A = 21 +M = 60 + +ModInv = -1 +A = 27 +M = 60 + +ModInv = -1 +A = 2d +M = 60 + +ModInv = -1 +A = 33 +M = 60 + +ModInv = -1 +A = 39 +M = 60 + +ModInv = -1 +A = 3f +M = 60 + +ModInv = -1 +A = 45 +M = 60 + +ModInv = -1 +A = 4b +M = 60 + +ModInv = -1 +A = 51 +M = 60 + +ModInv = -1 +A = 57 +M = 60 + +ModInv = -1 +A = 5d +M = 60 + +ModInv = -1 +A = 63 +M = 60 + +ModInv = -1 +A = -61 +M = 61 + +ModInv = -1 +A = 0 +M = 61 + +ModInv = -1 +A = 61 +M = 61 + +ModInv = -1 +A = -5b +M = 62 + +ModInv = -1 +A = -4d +M = 62 + +ModInv = -1 +A = -3f +M = 62 + +ModInv = -1 +A = -31 +M = 62 + +ModInv = -1 +A = -23 +M = 62 + +ModInv = -1 +A = -15 +M = 62 + +ModInv = -1 +A = -7 +M = 62 + +ModInv = -1 +A = 7 +M = 62 + +ModInv = -1 +A = 15 +M = 62 + +ModInv = -1 +A = 23 +M = 62 + +ModInv = -1 +A = 31 +M = 62 + +ModInv = -1 +A = 3f +M = 62 + +ModInv = -1 +A = 4d +M = 62 + +ModInv = -1 +A = 5b +M = 62 + +ModInv = -1 +A = -63 +M = 63 + +ModInv = -1 +A = -60 +M = 63 + +ModInv = -1 +A = -5d +M = 63 + +ModInv = -1 +A = -5a +M = 63 + +ModInv = -1 +A = -58 +M = 63 + +ModInv = -1 +A = -57 +M = 63 + +ModInv = -1 +A = -54 +M = 63 + +ModInv = -1 +A = -51 +M = 63 + +ModInv = -1 +A = -4e +M = 63 + +ModInv = -1 +A = -4d +M = 63 + +ModInv = -1 +A = -4b +M = 63 + +ModInv = -1 +A = -48 +M = 63 + +ModInv = -1 +A = -45 +M = 63 + +ModInv = -1 +A = -42 +M = 63 + +ModInv = -1 +A = -3f +M = 63 + +ModInv = -1 +A = -3c +M = 63 + +ModInv = -1 +A = -39 +M = 63 + +ModInv = -1 +A = -37 +M = 63 + +ModInv = -1 +A = -36 +M = 63 + +ModInv = -1 +A = -33 +M = 63 + +ModInv = -1 +A = -30 +M = 63 + +ModInv = -1 +A = -2d +M = 63 + +ModInv = -1 +A = -2c +M = 63 + +ModInv = -1 +A = -2a +M = 63 + +ModInv = -1 +A = -27 +M = 63 + +ModInv = -1 +A = -24 +M = 63 + +ModInv = -1 +A = -21 +M = 63 + +ModInv = -1 +A = -1e +M = 63 + +ModInv = -1 +A = -1b +M = 63 + +ModInv = -1 +A = -18 +M = 63 + +ModInv = -1 +A = -16 +M = 63 + +ModInv = -1 +A = -15 +M = 63 + +ModInv = -1 +A = -12 +M = 63 + +ModInv = -1 +A = -f +M = 63 + +ModInv = -1 +A = -c +M = 63 + +ModInv = -1 +A = -b +M = 63 + +ModInv = -1 +A = -9 +M = 63 + +ModInv = -1 +A = -6 +M = 63 + +ModInv = -1 +A = -3 +M = 63 + +ModInv = -1 +A = 0 +M = 63 + +ModInv = -1 +A = 3 +M = 63 + +ModInv = -1 +A = 6 +M = 63 + +ModInv = -1 +A = 9 +M = 63 + +ModInv = -1 +A = b +M = 63 + +ModInv = -1 +A = c +M = 63 + +ModInv = -1 +A = f +M = 63 + +ModInv = -1 +A = 12 +M = 63 + +ModInv = -1 +A = 15 +M = 63 + +ModInv = -1 +A = 16 +M = 63 + +ModInv = -1 +A = 18 +M = 63 + +ModInv = -1 +A = 1b +M = 63 + +ModInv = -1 +A = 1e +M = 63 + +ModInv = -1 +A = 21 +M = 63 + +ModInv = -1 +A = 24 +M = 63 + +ModInv = -1 +A = 27 +M = 63 + +ModInv = -1 +A = 2a +M = 63 + +ModInv = -1 +A = 2c +M = 63 + +ModInv = -1 +A = 2d +M = 63 + +ModInv = -1 +A = 30 +M = 63 + +ModInv = -1 +A = 33 +M = 63 + +ModInv = -1 +A = 36 +M = 63 + +ModInv = -1 +A = 37 +M = 63 + +ModInv = -1 +A = 39 +M = 63 + +ModInv = -1 +A = 3c +M = 63 + +ModInv = -1 +A = 3f +M = 63 + +ModInv = -1 +A = 42 +M = 63 + +ModInv = -1 +A = 45 +M = 63 + +ModInv = -1 +A = 48 +M = 63 + +ModInv = -1 +A = 4b +M = 63 + +ModInv = -1 +A = 4d +M = 63 + +ModInv = -1 +A = 4e +M = 63 + +ModInv = -1 +A = 51 +M = 63 + +ModInv = -1 +A = 54 +M = 63 + +ModInv = -1 +A = 57 +M = 63 + +ModInv = -1 +A = 58 +M = 63 + +ModInv = -1 +A = 5a +M = 63 + +ModInv = -1 +A = 5d +M = 63 + +ModInv = -1 +A = 60 +M = 63 + +ModInv = -1 +A = 63 +M = 63 + +ModInv = -1 +A = 23 +M = 380208a9ad45f23d3b1a11df587fd2803bab6c398d88348a7eed8d14f06d3fef701966a0c381e88f38c0c8fd8712b8bc076f3787b9d179e06c0fd4f5f8130c4237730edfafbd67f9619699cfe1988ad9f06c144a025b413f8a9a021ea648a7dd06839eb905b6e6e307d4bedc51431193e6c3f3391a2b8f1ff1fd42a29755d4c13a902931cd447e35b8b6d8fe442e3d437204e52db2221a58008a05a6c4647159c324c9859b810e766ec9d28663ca828dd5f4b3b2e4b06ce60741c7a87ce42c8218072e8c35bf992dc9e9c616612e7696a6cecc1b78e510617311d8a3c2ce6f447ed4d57b1e2feb89414c343c1027c4d1c386bbc4cd613e30d8f16adf91b7584a + +ModInv = -1 +A = b65c1c28 +M = 5036b6eed9ecb4b2740883ad16e4c8ea32a9275e4e5df38a37a623b9188ac6285a13122e614e2bf47af5d1bfe353adcaf5ae635d5f285f0fca9c82b800d7df8b33410027c7c2b3cb62afee4ee315ca51affec0ca1df3f9daa17ff032fa4dfa5465ae8de42971b791cdd860055bbd38e7e27dc67e9ef54a07562b2cbd4c8453324707362bea1d978d8ca29af482fce799cdb895579cdda3426b77bf23b970fe21e40341123cc414d39dec13f9abb97582c6488b09acb4e16c74ce6f291a26bb9d18ffada062c1fb0cf7b4b4e566177f53c2ae80b07aabbf3b842b5c138b31b03dd52ad61d54ff8f735c37e06c7b2ebe57949530fcd9d6fd1d9b62032801 + +ModInv = -1 +A = -bf4e7af5 +M = 1a4f691640b384ba6826e86ea1fd486af8964b4818b235cb4d83c64a04b202f42bcad1974f7f003ee07c7259207e1e5a8958ad302d3e374b53e5f8d205d415f2663808ad7f4e89322c3e8d9dfd6bf76fe7bb1ae6998f2ffd2376c1fdf21211a7324ea816a38e7741bdaae3beaf019daeeaaaa3bc8075ee326db1e799df8c4efb3b1479939c94b3f4a33b29589d819c90fb79bcd2368bd7159bf6bbb58fc9c24293e113028f427d2bb6dfa23e7a2ac704c2bef1f6b80b367149f97c413aef2f88abaec80760aaf3a947a2d4f33c3b072e1f37fe7b9c6bd788120bc3fd70e87a5538b4486c599cb381b6eb58eea34854702a8d4293433e798a0e81f9b0c + +ModInv = -1 +A = ed13d1e9e3 +M = 4f46d73477cf2f4c29cbf3f63a0eb1b35a6054838e38b52609cbd6c1ebfba18f0ca109de6e6f79d605253f307058f10128d7c5d4ba48faaa1ca724868684d6ecfa4d8a6f090025291ee979f5558d858214dd3bf2723deaa933a0a95decd28f49f414602b49af3aa5d629f1f033f58438d7c47d97c5e2ec79bb0e1dc57c47ba500268bfa986502637205c5a84c812ab06c15930b68adb5a900030e56599e90c3b5ef7475278015f97e1bda755fe1f014ef1d7e893b0c9049e85d62cf30e9ba56dd7d3a0ae54913be582490b3b5320dff019a9067509de6e53b861afb70639f08b7f0a674d3ce0216ce6746772b2c753574d99d19c2507759b36af971e + +ModInv = -1 +A = 550c618a9261 +M = b0589224c23874e9c8e3801943aaf51faf3b7004bee4f7ab81fe968e24341020003f9679a5c140bb7aa4415c367095b9eabb84129d9ca5374379d5bc1dd3d8d74ec82648266838ddec9d4f6ebeb4400873189296772783c8c8d2761eac708b0f3b56079573164a9eeb0203b0f2b5d2a7977bac41ec61502ae1fc8851a264abb921a5c0fadf6031265b9716fc96170a27b1519df2e4d9af707c289904b184cfd6dc3c3bff72b36ba95d5ec73fc31a98c7fd59a0026355459390c87cc36492adbb4bb95cda1a4658622ff19b46db76078d954e504890afe0b0ac88b8e57b47b993f3cfc762b8a158e9f0fcf8e6e9d6a12a8161e5fe1b14343b106980 + +ModInv = -1 +A = 83e99c51e692dc1729cb +M = 53b790afb7f2755630e93eb31d33eb744c09d37958411bc7c1c670e891cb7911759e028d9839fed00b3a7a9ce5b10dc2dc7e533d1fd7afb82e31f8d14015e000315726fdf3481df7bed7ea9f3a863febcbdfd41592abd44eb424c3c28b0ee6b86fe1e98e4edf8f406a5b227c81a04703c34253a74c489d28fa3adf23f8b23208fe1080b595a6483a52e03b07a9e4700c56ad99fe6b7c680b208bd4777ea445037df312bbd8cdb722cf4b447209e37ec94342d8627da9974eb673ecd3b8a887110ebba1ebf017d59f628cb3773fb4bef03922bdb2f30dae01b0ac62e8e6bae4f2291bbcccc33d91ee0a0fb51bbcbc51d1598a6de04cece + +ModInv = -1 +A = -7d69e9c4f718fd250c67f3 +M = 6d040c8381aa977c7a6f75873e9e818bf64649d7bb1a57974c64a267006625f3e026a8305f070f1d4c5d0a9973cb7281273cbde36c48f6be6bc5e74a2e289ec5cae06e3dfa64da9887fb480a3145b71d72f3df8ee1f00714991d662633f2e7f04b7f835daa97c130465164efd8c7dc0760ec5a310c5596fc8cccf391a87535d5752a0bc73fe15d7c1c77b545cee1fd0829522935efbd77ebe9c8f758fa24ea2f48b32a1f88c1977388fd6e80614952f7d2778b841936ef8bf64088b0d61e9c28aa3c357882c281618a142b95460ae1769902abf6c2aca486abc2dfa36f4cfde65a9d316bd42f8067ba44ac8ea44814e3e5dfbc1af89 + +ModInv = -1 +A = -9b576d64c4905c0914c25b99 +M = 59a2b4dd8cc9cdd174019caa0457acabb82557b48817c55c80b3d4fc2439859cc9801d2f28250ebab6f8f33ecae299a6f6056eff6f01835404232e1667fdc2294255f1c02dbcfee5984712a2a1d64d0fb267b7a29a152b676579c3964c6993a11012027fc9174a3140ba58c212f9692fb252f9f8cb8ef660ee0dad1c34c91f4452da6c3109761caf2595894f462530a93c39229c3500f0ada69e8ac0a477ba26042ba9689fdc45b198920595771399ac115596030cae6c028ab19637574cb8dc4835d321c0e55a1fb1559d3b5b6a806097d8d8d5ed264a6630108ed79cda2f6b1d5822d7b023fd7e3642408ea4ff6b17a4b406dd29 + +ModInv = -1 +A = -32a7df32756005002635f5bffffb +M = ec63d15784c5df6a2fea7c8fc16c114094e2b129cbd326d3fc3cb21fbabececd4286fdc91d1da49907b0d009cfb87b19abda1e0a003d8d918e7e14dc9bf8a52e018eeff621e7e84222dae03e6d3d6f894ce5987205e6187762a0b90a6cb16d68da32714c92ac60a0d923512beb42979f15cd1df27cc2935283d36dfc36c8056421e6d341c52ba794de84de33fc3422dcbe01110f9489e6a53fa0cc5e6641cb5467820bc0e52aeda7c3a1c0138b59841e3ce26025a70552e53942601adccb0f2aac70eae998164b0447f9b4d1553cfdce84821d200764cab6bc4b0201b9ef9654a4f9d4641a7dc43a457647c54e6f4abb5e253d + +ModInv = -1 +A = -7aafe6aefc3cfa6bb9c4b5ef5e6f +M = 9bf49f4f7feb318d98a39cb015f112713898a05f9b1c46becdba9dca2090322e88f56db9ac4a3d19a50bd95224f1a6bccd52c817cf9e200994227a15d9fd0c6ef60b0e23d547a32dc64ebadd7112add0a85d1154b30e5e594d366349ba623d131335cf59fcc1267da08ee85d62881d4659f8e12e6b7d51232e05b4a5fc6d6c7be79a52b66a33614733554577d71548bf1d0ba13909011db0b12550486a8c28a75ccbe7bd87ef0c736d6f2d6fcffafe5d2ad68c7e7d21dff8a9294ccf49795d300da1d110598034cdf37686425b1d24ce6b7baef40b43280e82e7b379e1d9f5d22d48a986e1a812f12b0e598e2e7270044a9fde + +ModInv = -1 +A = f1ff7a3c304b3f173f75a07f83d2f947 +M = 8bd6f4c31662425272e5ad1f426fb340329a7093e7b0494ffde5b0d054ce1c8a5365178f78625c241be0d127f972f154e4f336862dddfac7f6011af6a1184c581a078fcd5db37631543324d726e0f0e303f5514ed33572ad716cc0286a1d982a6bbd249d3482413f8de8ad949c8092e22930d15b3b37b0c9f24aa79c014953bb6d483b184120e2328f4c97737e5119460bac2084fcb4cbff681be09a36f0fb9eb0293740d1bd4f282c5fe73dfb5235356eb90fc5c9404cef84db9bf29f39203c0836c0e8f4caf8606f50ad6273175b67b17663b860f0bfa54fabc30f7096f41453bbde4befa2a0fe92e52a10c4f3f288b4 + +ModInv = -1 +A = -df36803098d4dddc368b43ae829092bf +M = 655090b140dc89ddedddcd66348a2638070a0de10f9f6dc4e2ee7f5b69ee9c1add5e981ba64838e21ae7d50a5b7e6daccae97553c59895dc4986013b0414f5d0b69e847bcc739637aca3bc1bf38585e0711e96a097f935e75dcebeca55631c376512fa065378a53115ce425271c782bc8947c263695423d570c589d2552462d4a3f17f391ca0d9d4d6b9f8e43360e2757365d61c428edeab183dde9cc2f869f15fb767e4ab733c92e44daa83831b2359962907914a97b1a3aaf99efae1bbddfd53ab4a390ed5e64a0df9433a96754633d4385f5c91c2d1d78b5dd6450cbad018bf122c0589ee168dc4e8d7c2184d6369ee + +ModInv = -1 +A = -bdc8d611ab45f868ea6ceb3add85102adb +M = eba5af92222bc598d8252f26a2eef70089b127af862b63a58c4f58d8c85468a18c2af2d40bc9cc5ca9e08ddb14ad8cc064bbf3b2ce4a244afac8aa286014b54ab9c8828a7d15385a57225a926c98f8c2dd4057e97fd23cbbd068beb8a7985b23070fd333256cf2b55efa5318c0aec7b4f4c63dae07119a906a0483090561626d5be6b03ed23952a9359da810fca0118ca742a22af370e247aef2691a8ef01cdf1b015d7eb80866bcab96323be23d63aa87625223f19479b2a886a72056f367cdf9f3038438cf6a0f56a0f53794c681373d717e3c5bbd9a94059da57b757903e1a5b1d8ef70ada6b4cc37aad3a902b8da + +ModInv = -1 +A = b2baf268d1c3733a2a5861c461dc31850b2b +M = 97949905c11c6d877b401d643ad210b6ebb1ea102a149a86615520a9f6d0b0667fdb904c0f693afd2908f2a7e0f526222d76f1ae5195586bf943ff99a040854215dfcbeee5d42b261ced860dba3f3c3be4dcc2e1360ecb5ed11f65eddeb535a3c3692abf5604670548861e534313b4e165a1a6267de054395a3eeeabad1031227615fc172f7b028b229955d9d26a7ae7f08025d93857a87d06c291d41db254b2ea7f26144e4b01f6393ac434f6d08ff18d6ca9c505ab59b7bd00cabf5fc14e574e12362b2e88ee716b3a7cd01fce8e2570e3fb2f618e4d3f6e0734450b7363dccb5dcf85b65acf354fcb694d2e2a4e + +ModInv = -1 +A = 42900acf09919063135eec447d92234bfe4d580a +M = 2afc752630a05e43537f904508a89b0c5ee1deba5b69e86635dfd48458fb042a5db00a61a15bde29320ebb8e3b4be9be19c2bd7635d6a36eabb625ed6958ef29a6d7e7ba703757876aca5ddb5d40394659d632deb7a7c94b3412e846bd914ed4839a2567e5a8c6489bda8176cc6bd3fe5b396026d3cda24225e38fe086d5f8c2a73f98a326c56fccf934d553bbe66fdd6f98e36417a8919d4bf365c36c50e64183837aac0582dd5a9af454faf6cfe991a43ec2d748e2dddfe96c9bb36ef9c05907512c6a0cd6ec9d528e63445c98f8b9d2ca7c4b2590ef709c952fc888e54a8adf6a064ebfd9ff1f9bb41e6725 + +ModInv = -1 +A = 82b58e27c0982cd4c9829fedbae18510ccca416a4001 +M = d59d33d1e403ce1fd2c0c9ef67e0f531493821a4afc85b5e5835b12ee7a1309ac5ee51693cd1f334a1f94bdccb3eca6ba3cfd3472ab1fbbc2edef6ea913bfc5fb311a87e76d1808633de6fe128a43e755e729b0ee45d68622c7bee30ee31a392cfe0262bcea08be04cd7506e585eee0bbe03578fe8df494d1d0e465030c4f334ff020d81b94ec1c9e06b140c0950e124139c74705ff0eb3ab90f480b9661aab2acbb5279dc67a720d630f90079a2c99a445b1e12bc2691d41108373580613290e274a37881eb7744f15ee088baaaddc058ef99d4b59e545845e342d4bd3663ca4294da87ece1821f753bc6 + +ModInv = -1 +A = 51fa9629e3b0d130c0aee8efa93758512321c99322a5 +M = 1105d25fe6ff966555bf9f54da6abb03ca8270c12c4a1a87ec7c733d3d81ca0981a4c79461d0b15acadae61c0b6eb593102d4ae44a24188b898b2fbfe26f3075b991d2ba5b772103afb5ec8aea02ef7159f58dc539c2f8009b0a7d529da7122c82ed58ab56b9902d6d1e8f90be37ad76c95a7cfedb04122d2f9de8509f12f375b881eadf6ad32cd278e5b72ebc2054019b44213f380315931a037059a4f63284838c441eb0348b7fb3fbaf93ea89784de05a7780acd39fe834f10063c1bd7703d9e265c9e0406bcbd73d9037debf7e1f221974949b2d7243f3537a536fd66c3e02a61a17946e1350897f88 + +ModInv = -1 +A = -4865c7a33f6100f0de716b9bb2f6535a7e07b6dffce8112d9d11 +M = aecac78ed4713dc75fe7b0fc994096c2fa6478d5f5c2f589dffa028025439f68498a3fb82aab32a4be3a11c2ad215a13fefcf1e447e77e935360a0e7670ad107c9c660b768fcbfaa6163f67b71f484c0ce15b3a78266b12e45a871f1e4f0bc44518b478efa56c73d57bf501b83e10e4cacb3360385e48f3057ca8fec676089b1fec32ae7b907d9370f24733ac8c59d892804b60ff0ccec7a0e2f10fc1a6d8f9114881dec77be1923bee3317960f2a69c2a5bee8f25e975dd5ab9d27b71191573762fca454cd798c0f1edde9ee75f5678498234aea4125db1a1e539b311df9ec0b083745380d4e9 + +ModInv = -1 +A = cc28ef928721ea0e4c092d3238dad5c7d4060e868df8de4770a1e8 +M = 27b2a947b1cab0b58efdb9acdc4aa60b1c95fddd7a73b82d8e2a8b8ddbece5f5651e39b7d55fd3dcbc125f3e0a3f7c4dc4c594144fd4d619c3230c8a1a193fc7baaa66c658858d3fadd6245d61b88959d17a9d2e884739b16dde34a82cd29d6af3dc429cbcb660b201874de74ffa649be9fbf048f76026aac08eebd23f878dbb3bcaf3277c92dc3c5f09aa7347b64cd24dfc3a20ebe8ff2efdde229035402d79f1856b83d936582b5155759e48dea1ed519af9bb5a91f7c60c1fbd4f49e1ae0355aed131cee041c1f58275224a1ed42375969f5257ad90cbca83da845ea241259644903193c3 + +ModInv = -1 +A = 49370f9347bf11f729379e2b57b54f05fafc58a83e395b8e9a0d48 +M = ba0024ba264392a674f05885fbd6b18161993e19aacb6476aa9fb4198c26205ab0c4aaa1df73c3d3023cd36987541a178b004baa2afd0a92287e8ef114ee983e32c684bb91479b3a6461b1913e4eb3bf29649a5b31fa2057d435eac24803482e944fa43a558dbee95a4c19f16acfa78fd78d535c6b83a65d44237157d32c90e59b6b3a3dadde227534b6d94c92ed072f77f2138d2b3e521a61cdd828a3607dc79e4768f4a5f711744076485d5a1033eaf43c2c01e51f51e0663e6b7b0930edbf01163974c9d3b676d6952a0ae3935d8cd51513f3f9472ebab110ac876ad2a47183e41762280b + +ModInv = -1 +A = 67c52fdff0f17cba1c2392f10cc4f3ae39b89a01cfe9d7627bffe1 +M = 4f3cdec8a6403317c573a317c33a4288d40437937618128dad6ea5ee5f2a536c38ea766e8c201862b1c8362cdd5512e118d0a9b4adb4b61152413bb028cd75fb94be726b358c7b66522fcd31fa754cef455425577fcf4b9891098f17b984852887d12d6ac48ffac019410301e049526650fc749fab8c68f82d757295412239c0c9cf11d0746698823c5a7da165621640b23733f887b136b3d9488fd03891fcec454d85e5fa7d9399ee7bbd862ad7bf5c5e9adadfab88a493aab1dd7005e22bf0230a13579010a3d6b813a9dc1e74a3e7d3ea7f17742051ea58bb08d1d9a2b0f75bdeea9944d + +ModInv = -1 +A = 79e41ee87b1b4a0eb5422aa12f3e9786a457a917352be67cdbd76923 +M = 37a53e5c1fe3a3d8fc41bc0412a0989a944032228d68f20e1ba2a44b50a98d24594a7b1d89f1d78a7349eb38bde845bedc2b4869d937db91ac4a3ff2b051956e29be65777f1fdde2447e25fe0bf4db3d4a635fa490a0ad91edf9cd521e49e7fe2085ffcd7e44e299568789e4f060b24df5027d157fb35280250f5a91969be77a59092f5123f415bd357b8c46f9b35e6907188056510999ad79222c34b076eeaced47aec513d752a13a6c7ed42d76cb2f022653bca0d32d70c07f3eeead8a64a939b3d9805ce9250223589096b842a6c19f0660748393b5f9201bbf5b9c60a2e07304c73ace + +ModInv = -1 +A = -dc97e11898f2a504fcc0f6f2473ff1919aa4e5cddb414f659532f707456606fe +M = b045cbbde7b326b5dc92147e7247b8af2116292e80e27686d045762889db43d47f37549d3c9b67ef876b6e580a3f108895731d21c8e9fdc8c7748f7ae10e26b8baf27bebce66d2a037c522a386edc0b13e8fc9081339e7b2c2bc5bf625b617cb98caecd28fecc27da5c09b051583d2de27bba3adb2631bb2c3ca7e74fd542bdf7c9fe89f2706b859f27cbb1c4a913d3f2802056031d70064d8cf2b4fb5aa5490f14f91f89caaaad4d687af06980c19b726f94342cc765cb66021f0fff285334618a90bfa0df0c41b4c67be5087e95e519a1519b0ba20674359d00f104a013f693 + +ModInv = -1 +A = c787b48de7ae21896bc644515cb81876e7e37815bf1bd565e4800c4c2db7fb108ef57bc65 +M = b352efe2227cc8390732f9f50be215e34a6e96faa2f500898faa90c91a2401fa7d2284673592af5784c3051933e7176e264bdcc6d63c8df36ad86a7ba9b8a42afa1a5bd879163abe7b3c83dceaeafac62ca36daef885d22f5e49e2039983d467f6a38ce06567fd862082282d50f3799b5cb5fc07eaf75e44ceb8edeef8b5411d1e7254c9c0ffca88c23f94c49693429df280397c52f7442acd8c8422b057fa867c3530942b1d2bc47a2af0b1edbab5592ea719fd754c3aa5c0b9b255fe624df09ee85b397518545c07750acdb62aa2cda05492ef6df985da8285e9d4 + +ModInv = -1 +A = -dafcbc22ff03513b54732daae54c9f0042882e00dde78769f2fda5b7a5528df9b96d34affc7a +M = 5f297da663853421517d27eab004e4783e67ac2a3a97553666dbfe99567c999ac023249c88a9e55f99808850fea4f52dd869f1c7c912a5ab540c2ef1f78a33e97ae7da9d90e6ec2c1e39c50b23d0bcc54f69c2e0e6c53f9c8290cea7bd9bca09d61dd10c7f0ce04ab7fb9aef8fcd7d9e9f6520aaf93f2b83799e8c7d9747a86c973edbf667556adafc8627c340d69f8e0618aa781e3c3ff18fefa30409787d22c88b33718e982a993d474b4e43c1744628707b035d2487baef8d118f8a1d1185cf28fd9f1308d876c0cef9eb59ab59df84f46876252dab753fcb39 + +ModInv = -1 +A = -3b536f80f892a51053b584a825ecd461bcf6e890084b174961c26f57a818f6282530f650a67fc6db +M = d3316b406afed3e1e2e1e87ce3a2cdbc5cfdd401ce3099d0eb5334f7ed71cef4f72fd683fa4f1f126f8b63cb652346e53c75f9c0041f99a06d07d3b1893cf751143727c86be9a198c6635f19012e45b38c1be0d0f434269348517a35ef467434d3528c5e0acc9a2a560c3ca8d540b62d7926a391f5b8142b00d7c9dd8529c71a35bfe3a962c3b7466ed4f9ef51ff060c3bc883d3e3db290682454cf52051ba011301701215275d6693f0f8f51b55228abddb97d6b1b07db22e4c3c6e09f796665e1ef5dc5770e94316db81d3a0aff2b0d174c26b5e3148bb0c + +ModInv = -1 +A = ae1db86bfe2ae698ec53cf4186452a02e7cf31a6ad59d486e3dc563c4a6ffa021a33a6f0626b39316053eee9 +M = d7d84539289010c37911801846159ff86a721d03cbdad7a1d97f88371019cd8ed0b50b6e274128a4b4097773b3847e254d38a7dcd0425240141a14e3c5b8137c70ed723dfcb701dca892487f15cc2ec0c29b29167bf84d6a3e531153b95aabc3659a5aea8d012044f041a6d0951e58b59970032b0ea4934c9f68dbb047c2084a3f24e17610bff4d45ae10628125df50cfc2b51b97d3ae5c057cf97395469ba80096e906c3091a652f55488c72f4304cfd5a3c60afdaac569286e86f48f67ab850448de71f853f6f601e210ea4c9b621328cd090f9e + +ModInv = -1 +A = -5bd4a749ba9081b581bb3e69f22cecad912c5d50a29ceb2046949c2060fe855c3c278649c3c0f7e9842bc46c5ada +M = 1b47fc89f4cbe808463816d5d478cb2234be77f8bd116c3d44f29d40f9075aedcf113361904981f8b835833a6232e109e7a221ae3f9dd209143489b343d4f4951c7aa9e54f1ef87ca18b908d044a3129e52d08e9593373fb2f1dc8be4bd82a9019648a96db83730a21a5e9f8dd226d0c2e64483694096e920a82ce39143c4e6869ce473a7b50883b71042c9222abb096e4ee39f56d54955f7d7b9a7284465b42bb468aef29d06fe3c582c45b04f2f44fcc10dac4bf5e5bbc40aa6ff3a4d47ea2846bf5aec0d62c849fda359b84e1aef79e5705 + +ModInv = -1 +A = 636032d76cfa97d519e094cd856d187daa12b4d3298e83b94a6efc2c78a6d96267b538a1b860163bbb371f3bac1ad1c6 +M = d6c4656919d9d0df9dd019f36c6eea8ac9e522680d09a2d750df7cab96afeb460a3387c1de2bb7088f4148d04fa9b0763c597b03fdc37f69f273f4585ee24e3f52e24571b481c8ab6dc29b33edc339a70ab1afe386a91890635bad1d8c0058a54f1cbfc1f82ec45dc19c948686ce137cc7b2196d78ccd00f4715e960222d9eebecd4ea1ef480b2dc74acda341a1601c189cfc8b81e731228663a11c5320e76660a9a25386abfcf9008ba037f919d172c44a0aa44754d33a45b2bc9f62353e50a407286cd00004663e79478bbbe2e7ea291 + +ModInv = -1 +A = a3b22e297f1530f41aef5cd2f29d5433dc0d13957dc97f1c0fdc37da2cf2b3e6df1f599a6e413f0e50df3d15a236faa571ab +M = 459bef74026427cfbf89576209a1f358c14be614e6a362f47144eaa2b3a9b96355065b646c90200093c7f3547b1d4f69c797a5a5e4ae3a413f8e48c0399b4011ef8bbd03e8eec194de45fa985178a34fa1f950f104498d692ff7b5fdae594ee04e1ac13a6d075a9f63a7c10dd0392b9d5848aaf27e07cef4501e9e3a3dd42818d91b4833894af25fc7107b8cfa670bba04eb37794ec4fdc7503dbb1580ae84dbabd04fcce6425fd87ae6399a6f35ef6b80a34c74a9e2d8dccfbb87bd8d200434fe714e92fe2b526663d9dcb5f95491 + +ModInv = -1 +A = ef8c87694a7e6675586a08c71b43c0c78f3ef07d33b7bc90e1761c17c18845d01a68d8c980754140f8c4028fd8c0694ec48b2f +M = a32f88b368adfeffe84791638d81ddca389e6b90172cc5ff236413486fbcde757e36b5db395498b0f68510ce1336ec4f8433de9657105371636b1799291b193ffc981a4dd64438081a58d08bd06aeef71f4268d8ca813a9421df9e193b394ea5ca8962b6102a019a0d89d1042190c5f56e559e907d163fe2ff93dd5cf18c0b72c98ffbd54187b9b4ee2fce18baaeca5c210524568879f38b6e496e395914e71d0ec1a95ffaa03658cadf729a32e748ec17bed80b5f5bf169255141bb882d8c0f1f146c3eecfcd9be794ac6acbc61 + +ModInv = -1 +A = f62093aedfc0bc0c6ee743b219aa00a2a25a470a6b4d2b8fe92d5b4f8c93ec4a266c18ab7aa9fabe8c20ecc08440c0c1d36f32eb +M = 7352ac79bae655915a49a331a83ad9f890d9231406e5edd6ca830aeb564730578588db3dbe5a75ea0c2f0c8de48f4f483828495a9b696a60e1ff2dcdee404680db0a2e2d47fe3a6bbaeda0ca9c5a5156b625c670edd119a42832ff8daa5a023eba043ab1bd9eec5f2497fd4f11944c28bec04e20f92dbb54550adf8dd8782021b3eba309f7f3ba790f8fdb4ce82e8149ee216a58f39510906f8c5b1cf525d511834379c4f138b89f9f30e5c51560b4f56a863464471774658f8614676b32e083f7b2a83670cbac32f2fcf8e228 + +ModInv = -1 +A = 290ac93d87f97a0e58c8188b08466656a43bd4e23f82e7beefae8a995246cb5358244137344cebedf31cedb5da5abc1e8a52956349 +M = 139af53234ab703ef5c4943171bccc98fa06dae351b9c93a6fe6fa7f8d9aa10bb899dba2650153d82145799bcabe32853dfb49463b8486c5bdaf3c4a443db87cffe0c94da836eca6caab58c6b2113e471ac295cc14d0481d270518004d250999056348f20eaac628a04cbea6682b0b4d1269edd55df8516eeea085ff77180187e3505f3c97caf110172087814fb736c501346a7b1caff3518b0b3f7e6fe920a9a2ab2ff84ab719acea176e52a3020d5e4e62afce35facfa7974c1e2c5a7a3bdfd16a7fee52f738966059dc52 + +ModInv = -1 +A = af5801cb6c4dd0f1110679f1849dc54e59a2a1e3aa8098596c38059e58391a7d636f7d0a5bcfe5134e0dd57f31b7efad06763b32fa4eab +M = f48bcc2e0c1e19b77717ef3137f8a8efc89648377154ffce68ae0fd88b41ae72ad4390ed2d93634f4d2eed88c7e4771394e1c6ab80bb282b615242a5b8849596b319ac71e2971c12886f34c2f4d0a0c7f352a10e9cea195d8705ae5153138f506e6ec2fbfe69ef33fa4b8ca9351ba528dac89b8cd0750147957d6146221622c14d38f6b65491f14b532a181639391a3ab85b0ae1c5adbb4b6730d6537540027938d3b670471250e136a225ab4e07af7273356d10c1fe310587f8959f4df53afc575e8593ae8d1e3c26fa + +ModInv = -1 +A = 57d6346ee85628b8ccf4a0755e6c3528e1f9ee0545203e4b1377bcd091d747818e590e63fadcb2325083808537c5c711bfbeee5ca3512d +M = 78e8a19c03f3fa715a11d0ff2a19493d8d3cbaf8fb6c6beed42da29842484d7e2e9d0a268cdcbc299a1d83c6e3bfe2962bf8eaf416cc38ff0149ba55ff8149e9fb5f72a009a515381f749b8fdaaaa84ac4dc47aac180095962c04a1a3d63406b08d6a774459e8b75d74bcca59f1f0be67bb1e0f11834cf076b72ef0f39c8af570679f4c2b6827a7e941bd6014ecf82dce1563777670718b147f12d75ab63b0e8fa3b1bba3250138c230f5666c7340832d820ced9e822c9cbe2e508beead88d88464b5ee2a06927113dbc + +ModInv = -1 +A = fb7ea36aaf96c9555c1cf6bcbcfbaacbe30f40ea9cf52f8d3e64fd0fcc251e894ba22d86a2d6ab16dddcfd2e32f25de0da7e62d78518a9cfa9 +M = b948da2b6a7780d2b42907914b3d57c4c1fc855e0237dc0984b33d6c690fab90307664d315319cae32c11f510cc94898dce28625c9ae2e332f20d98064353bd3a30719791e3aca259ee9f3f4decf729b7caec282de2e5bf9ae3922749acaeb5237cd333b953671d51e405bc8277c383342a91bd74a54ea1a03209770d2c00442c15e720718202bda44ed80c7e09dfda8b8fb78ee235f798453a2eb9ea3f2f8d616df39be0ff05fd89571c7b0985a8d96b8062a39777e766b3e33fd4907cafab9b3c32ca10d1748fe + +ModInv = -1 +A = ca21e6358257d2805b71bb1b73189e0e41cb0a53edfca5ed23e2e3b6bd95cb573ae063fef6b36f69e0c87758ffa6f7724419730ce294bf8a338c +M = df12f9dd018b5da58a913d4f939d78b987b9a4b06e81d8fc681d8ad4fae2a05ce96dbf089c7f94887c7c1f926ef02412f4f21456fcfe9fd022a5b07a4feb5bf566bc08acd7d998b2c5f8a88d0f80a3946ecbaca7efb0e6ef8b0891e7aeb9c8b5eef6cf89fcbd4dc91cc34b9ddbe8ff855b3a1cfedec50d63f557a6bb0321f92f60583230aad1382068298726cde6f8435bdbbd0ace63c477aa6024b21e2c437a85c4421599a2801d6b836dc02f3626fc90ce647d297c87539227e41f30fdd8e2f0699e858fd0e5 + +ModInv = -1 +A = ceeafca6d1c8e6f76c8af75591bb5e0449a9ef44651f1918c48824da6494546dabd17843b9a48ef3286aef0e0ee1c3f6994cf33806986c8ef78566c983 +M = 818752391688a9b3bb90f1365e808d7d04712236126d85315c72ca2225c6105f9ecc224480f519f8f21838c697cd1cf892df28b7d36364b2a8234138159d86dd472ec74baee2a3cdc631f94a22d41a83982f5b5c6d6edd54ae09f52415f53adc9352c281f38aea416f71b9fd6c66728b959af579e860582f62ebf79ae07e0caf50174bff84cfdb8a8b469c3deedd653a022d6811ecb71d0d7bc17e845c0cceae0c4995c633e0d9c5b8667e9c6f4912ff3a0acb67947768f2e54449782c6f7d454023ddd7 + +ModInv = -1 +A = -7ee349b263d6a37fb6a3e6dacb49940ba4c0bcc23bb113715bebdad4b936b02b83e48efa1eb0f3c308d7796b534f8b02356f7937cef0bc8b075de6bfa195 +M = 35ee7d6f83177189355537ad721bd43a75ea0643126cb7ecd36845e16ffece5b8ac3ff3549cd1209414426cd1624254d1dd09fbab075cb4eaaf531601c74fc88d2009fa888a9eb5f563e92c369d2f36fb30b2940d8bac6ed73e70065beb16fa6c79161f0260f4a1754a8dae112ebdf9de1c2942014fa2fcbf2dacd2396072529fbc685cc1b1c5f0ed4402b3d07bd5778cc27d22921f7b876be0a9ab65c5f8ef347175a842e4b276a58c170f0a5bcc45563079c6a58bdebdf119211869c592c3f202b26 + +ModInv = -1 +A = -3f79af93105832b2c611c12cc11b23978b4fa5f43a218eb615790b7d1383ef780bcf89df6214ad186202c74e0d96af914db765ce977138d13b12d50e852d65c886b2b5 +M = 4280519f416cdd99ed0b73f49cbb0a1ea63ee4c68ddbc5fadf82c09f23fb60a304192f8f1d91033a9cf7723606549bef8a81ae92f56307de7ba1e083a5a2c3e5a5564e6d0e47c26b66054bded1323a446c70647bbdfc6d760f5900caa0273589ae61da007e644be3e52eb9590bfdade005ed8d32250e146b80d5c809e000c9b98f6b61341eec05f713a1acbdb8919471dd82a4f8de57910a232f5e6725302253979d25320ec231d50efc3ae67cd865d85cc79d7c2ffe2df97a0efe90f448 + +ModInv = -1 +A = -89a312bd9e4da63ac4b1064b210238d448e2d174bef787d4d0d709b4e73f6ca94714a39699d02d5a4ac708ead2581cf5b50d3bf13c14c1b0e7c45542e64e5e0f23635 +M = 9bbc04d9fef7733701ecfbf66d932d8b520e031182629cc3ce1a453b34bbe2b1a3af4158c56103c75275ffda51b6343a877f444f6688bb4d1c73479a391bddaf08e2046bb9a61fd23810e05251536bf82d86f4557ede2b4c33c8f3ef87c121dd84a156ca9e350ab3cd4c05827fc1065b1bcb5826e6e0e6f3e1cdadeab103f918a401ce81ebc8c70043dacb03764e4acf14dfc284297abde81a92da9c6efe48dfb8fab43753488195ba47f0f348e9e9d67dd88ed01e9aa2943ddb0e56c82a + +ModInv = -1 +A = 646509fbebfa7985f405692b37b3876a92c9949d0d11315e77b3b56b96a61b9ed5f23d5a30476bbfc78fa808459c94451a4f3654f11b46bd06478e866cc0728910aa5f9ce2 +M = 56e1e3b9e0da0c32f820fe54fe1f2c77510624fdaa4d86dbd8d7494a5617bf1293e4530c55c51173eae23aaabf4a2bcca97e32bbcd1481039e070fa71429a33fd9d11f65640bd07fe7bf7ebc5a9084ff5cf26b6d21ed362e81530ced160aeed26e1707aa7e5cc6210620834683f3b3ed6142a548124b0c1e625925b4dfb7c2c44af46b0ff684f4b02ee0588204f44f5deacf17a3a21d224a1636fc388ab3dca7a72df8da3af1027652fe5b166621f09b0c173642ea0ab7da7892c633 + +ModInv = -1 +A = 6c2c095bcb20a12ea1a0f4b800c60ddd1e08b6618ecea3b7146fbe1df679c43201435c0e8c31281e84358bd6c94786e1e6c839c750af57de6fc2e7b41335f95ea1aa34bc7b5e47 +M = 3319b39280163d1cbd00ddd9a29c5d9cd3a301da3024944e1084f2cb41d220dabfae485b0977cd8c4a00f26b567024ecdef76e363e2d14697651ef5ee4481efec04bd1fd8f143f1c6afc0c99bee1d1125e10cda07178e8330566e5b46f23d15fbb9c00f535e99eaa571817959392c975a6408e631840bfd5aaeb633b505a02ec4e644c48432ebb9849f66a004efe043d04bb9ea9eee4d13ef7d169534a4d7edc37bdb90c1212e38b4bae743549f00fb0b88e73be867ed474b556 + +ModInv = -1 +A = -b4b2f0fa6e11453953dd4e8d70d9d7c01032ec73ba1c3bf7d6b234bd346ad9f36673491745bef0e0b2a777ccfe243fb07c75d5ccd2c27465cd34bce98998ae8b08fb910b1a1d24b3 +M = 3b407737b71314ab57de2de9161080c700fb715ebe42d9f280012a8f9dc791f36ca51b96bd5902e0a7dcd79a9b9993f73f2d55d1b7eca67b0164caa5887e73d6dc033e7f4b3f98480a890539e8c23edefdc0880c9c934560a26e9c72d07f115d119b77399ae37c4826b008bb690bf6e623b68132051b9b0edac21774d3e085f582c347cdd77ec2ea92e55b3322979a58d4be96e85019e08d208330f99e6b47c3a63eca4c81db1cac752526c8cd3fb7e22c21b3d7852d4d870 + +ModInv = -1 +A = -f0439ec3d961c35a3c20a157cfcd6d036aaa6f3870f1e3c014c64352cf92f1ae0f229935603785b683f22ae746080e25d1673a10efee86295c4c2b829bedddf1e3ce4577e552c51297a3f9 +M = 892ac5c286dd18df2fb3c17faf74316139b6d47523208cfa418645c62fca3824d4286382215fa7d289471f1689c62dc7ade7e03253285f8a88c7e4f87d02ae1c68bd1010f7d1c01f82864481c02fdfe580c0bef3b1466ab2f66e338b3689897f894d737d92a1a251ae43dc9cd89d2229f2eee4905c8e086fd4e4f49f743ac35b219e52a1882fc3effeeb59869d1a1fd44f15b72147187b6ba7c5669913114f26417ca0c07abab8b78334334502a449194dcecff8cb0f + +ModInv = -1 +A = -aa68decc75db297b5bab0522ea7f5476d453af040b72ead1ddc5abda017c27527f84f76160ca831abab9fece7778cc361be8aa880958691fbbfbf02d8bc85a0b9136a5c0af7503633152ccf4 +M = 1087e4905a7cf8c5d641a42d759be41f5ecb54c9b730c07af5deb359de818bd7a55d4bc99e642b55e2107d8a90ac63c20609df424100a523669545e9ac3f566f41639c0c8db9513935fae3f3460bd337a5a79e954e71dcf43fc44c70e83d53c3edd0401447393c462aa30f3ac2b5d8b903afb4f00e64043275455160e58e6e6b98d4a6aa9852cf4987797a302e3d9df33035e2ad7db00081b0abed3901aad45e8d5941b45c85e2b99baa1a752898280ca2a8e40d69 + +ModInv = -1 +A = -a4b6f1b1ab0be35eaa8bc47d81cf7ca3c6db308faca3971f4e9c70f467c46a830dab046137225f67ed79a484ad9d14fc5cb7d167277a52040b6d44745dfcdf75806174312f83793fd1a2b17ca257 +M = b6210059af044b34ca88bc5f72ecd97625d2e09ee2f035e7c2b4e0d766de672a1f95bbb51aef59ce772621ed462694eaae5eb4f9ec2e8d158ba3392a87139e16926dee2e0ede5edc4e856d42ef8b1e33c485b44abccd95029808d2ea4f6b963fbfd0c60291915e178b7ef9bd17ab332094c3345c9caae3237cec62f004dab0b995e88b34aefff46b47a6a85b52a38afefe036565e3f1199dfe6bb477a566fdd5f7e6652320aab0e987948532310536f355bca6 + +ModInv = -1 +A = -62db6751aab311cdb75ab5e0463eb40ca63060a78899d2dd66499497356c5585f31f6b4f3bb0fe579586b546a72473cc4ae65792cf04e24b13c44336b92b9a3e5d12d60838d013e6a07dd1306f0ebd +M = c23197de3a4ed9a4da576e0bdb5af01249cc5d24484c570e52f6cd50023d9c613721d073f21829fddb5004f14ea9e673f48e3bfe321912152522e44d8e9c3f158efcc420ce8ea1015660f2cd97df9d29bce108e99ed54afcbd6063f8ebd8d5540566ab25189697a8d069a18cea48eaf330ebe96a09f2811d0498e5d71a380cff50ae66952459be6134fd3b5f7ec8d308cc47eac3a29dc6f93b294a291c22f3a58d7650a48067ab0e4eaa79b70c7b9d6ded32 + +ModInv = -1 +A = f5139b4864bda737a053b7ab821d2f63047c87d7c6db1f1fec8bf63abdbf042c1b04fc4d088b54a8648d798413f6fa86d6540c9b97b1620b97bbc750eec377ad281deadab0b51cd7404250c25edbb32cf36b69eea321 +M = 9a39ff21c4135dbd10b59338980e83a87f19a64880b31dada1686c834a12d747b8a4c7046b279cd4be912c9a1fef0f950556d71a1a659008e3e751148545f52da5ed726e046c6cba156355e599fed67ccdb5a7a1ae248cff7f4159cb588c0eb40502f1e1f53467c6fa7bd4fb9c5358ab0280bb7fc82fc7b46beb2601a9c8bde80703154a98cf6b31de19f0a3b25b7196783ab7489ba03726b7fb659f584ba728a5dc5abf3da13eed58c3c2 + +ModInv = -1 +A = 7d71ff9fa6f223ac79c46d9bdcdc41d8a81af9be06ae170859ea10a53dfa564e085f9cea6cc57a969e9eb92217943dc9819cfa109c293eca5f394fb84e5d9f78fe614b2db56373f965ab6776a873d5b891f4b35396a383 +M = 6f45576b6ccf5af33f24adf6400339fcaf02e101e487e1d03f99848b325cc53db9dba040824940d1429bcc20bf38813b2b46b6dd9248c9aec0e2de27ba2de4a6ce817a02e8a152e84ab2d8320b86cf97324c0d8adcef3839ee30fc1c83381d17968e005baed71b08bdea2bc2dcd6cfbd1b167e15a33dd09fee45e040ade0aa0c3820e5167dc265be5dc18aa67cfc18c2393f6ab1ce8795d6527ccc7d794be4634202374d740013f6f2d4 + +ModInv = -1 +A = -16455efa1ca1f819e87f9ee200eca5b2833d3f9254c513beacbde4fe504d0c21da2ff9f86fd5236a2a38dbe5709263504b6ffdaa3f4c891e7eeb27ab9f68ed55a0ef84657319cebfcbd166233c486cc2d685f15a2aee0973 +M = c4032df9b9a62c6ef1071d8f1b9cc1ad1dd1bf5369876f7dccf20f228e994d1036556d563d86d0f76f48d6c0fbd4e430875d0789f991b5ca4bd18ebd9ae0dc12ce6b449dcd753c778d2822617d42e1c6cae28a74905b7b56a79b29b6ff4e689c7dbd6d3a776a6abf2244451d681a0f6432ebe6e7a534b7e571c4d8c5969bd3eb230b75459a61037d551cb03fb8c7cf19f55e659580083f7e22343903ce6f650d4caa64b1e9f11e1523 + +ModInv = -1 +A = cc577830738e811026860764bf30aba7cab9378a8722e186df756e9372ce0426215c74e94304a0fded81fe3088e75a90212a3b3b70901de06c2bc486eaa7292e7becef86fc647af15c8d484ff1d60cdbc99a4c11dc2038e3 +M = a877ba00a437c0c298e49845889606f6cc4b83b38dc729f50339a6c24d53fc5e77fed243564bbf816a96ebd854cc3d81e748d0db616eef7565b2b47d7806ec4c8919383b792bff6faeaa523eaa626b1d7f87d94a931dafe3214653a9a2b958fd7ca06ed5385c5b281e3883cd3a73f6aa40a7c7cc682a0b319ebd7304478e410afe9c1ff24657be8d71eadc70a158abe3cea4bc1bb98897ee17064407e640386cc73b2a7460a1695022 + +ModInv = -1 +A = 31b8772c2516a27ace065357a85c415ddb2a10e1e82d5bddb45ca245a7e5b179047003162752f16346299539c1e383288c6b923c176231f6d3d4c122964e17be57910a2f87bd7d591db7c9d6fc5f7956b09f649eebd744df6b +M = a30b5d476c7a7ab0ad506cddb575c7fc04d7d2254b13333a9f691e40e779cb38fe565f3dd579dc22206419c34ae1b9eda47dd6427d0af1674027e7292943270b5c0040aa5f593c1d5f85bb5e7e7c09f393f090fd062cdfcf81976c4badf305b8fd547c61d950d2a4eb94381371c31bef9a8355adf3e12dfa5a05869069f62ee2f469af7556f4305134f639013dc4751d5c07d4bf64bc7c5da224fe12b3dbf9e9a838ecc61f6b21d8 + +ModInv = -1 +A = -5bdc2280be8202db78bbdfd3f878b26d554ca9a2708f32fd76dd8e34045545944acee3b00cfbb3640ad4713619ec4b961270a54c9dbe0e7f812432eebab46d09838ab004662815a7ac337dd7fd507fe6944a9f5f2b7a4aa0dbfa +M = f4dbade262c8be030b396d55675303d82aeab5588dbe97d5d2ae78a1122e2f5f50d4126d207828e830d2c362249b9836a4545669780d9e0435c52aa1dabe47b9ee4ca57276859715069c04d641b277c38ba123d7effecd37acff5936d1281713e47f36c8e2deda036daf81ba372ab93b96fecf4ee79b5b9e22d1eb84befdb87b9ae2b23ac49acf5cf2e0a10fbe753cd6f0f62467ee962a07c3f7d9e045f8cce1ecfc0f76cf6f5b + +ModInv = -1 +A = a1e39f90367859b5bdfd000eab1ae60e7ac16daf3ceacbbaeceeb58c01c5dcea2cbff366ee870de170a9a2f2b57ec6762bb43537b20105d9345a8179bbd672ec78faf3653c37aab1f8f5d712b5948beffe5a30bb1ca63dd96e2 +M = bb96a2e9bada925e8f47ebe8ce23e1dfa9493d76a142b75a5c2bd2f8a08e98344fd75b58e07d5d13d13959c7ab3ea87285d71d0e9734c0aa31341887d9ce21156fe823ca320fd618896373fa2d8ecef0fa719a977a2914673ff001ae9016a65417fc43afa16ab209b21999723ff6ea8a0ce9851c516f8b8636ed9713d12f6f317e8cf9ad5b9dbb07d8b6a9a52835162fa4fa78d83cf786fc19cc01ac190841c570ca4939c45573 + +ModInv = -1 +A = -a1e90dd61eb8492499be6a1a317deb5879ae4f2af1488658c371219975ad26fc14a7880b28c5008d59d2d5803e598d1496562956c6c86e2bda291b5318dac332addddfd893e1fda64ba65da6dfe1dc4153c87333fc536a09b384b09d +M = a3821ea75b0e98ca44fdc745e7075b7a19ff76010703b351c15561aa73f36d581ccb135b225de9d6868836775e095cfc1e9ec8fb1ec1ede142374f70fd33da467d91666e69e1d5ca143ca5ccf939a7b10926f2a9cdd08f4c790c2d8b2756747cbf4cc35dae6fdc9d8a9085ea51b233e812f9db5e7af2a22fbffc7eb23217cd548c8aaf0fcc3c6fdfcca60521faafca4d802536c2c92f6187601bc9e0917630ac21c9cbcd9 + +ModInv = -1 +A = 2f3b9ab5583f3ef33491180ea265be45a68a854988104750ecc99800746ecde97b0c8ba6e4ca6c1b8b7ca436eb6d8a75f5c0063f8ff652cb565e3985a4faa151621318bd004b0492374b47011adf893056700a06dcb271f11ab8da192259222f +M = c88cfc62b2ee5d975f67a8743d4688f53d1434ce1422d520124be69a99429627197679af8587ce9de434a67547db16f7e35fa79d2bb66fe38789e2ee0f8a8148faf922e65703d9507a0ce6967a9a128cae520672b649d12c4f34465b856847988afacdadd18bad997b32e077fb4bad6f6703c229efc2abb962a960baaaf62070774c8564578165746200b16230055f4b91d4766405ea7c94d38fd3f916ed021e32 + +ModInv = -1 +A = ce0a1ece3c9c9f6014d68ae48bdea78c82ef57f95f7d2bc8c94a012d04c69f1851007a5c04b64d710309a0271061690d25cde5778e12d54c042c37224a16e5b01d3aa9f766e0d47797505db31abaeb938c37c2f9caa220e33b2159c25c2c0ae45d2d +M = 46b3658cbf72960f89876eae51c96218ca04681ed68a4a830e64ac3eeb30472a298f1e56073d902f9a916f391954f38553d0005661714fca75c6fd9e46262a4fdd0e3fcac3fce91821e85727404e200788cc73895253ce620bbd5432826430712b9d2cfd690cb4d54a664cd4b6b28739ba464f8fe559e9ef4f9da6ef9f2115d73284ab0bb28508650b589897a500503a40fb98f1a885dca96e046016f96752 + +ModInv = -1 +A = 4ef38f216688279336154c23c31845ffca54dc2b3922858cec6a2ddb6a2fe0ae6f0e4c1c8eb5a352348bd11be315f0f29777fc169fd810a5d2c1afba24a9fd9495565e28bb9e60370e5c7ba7c5ddb5462da7bdb6d3c1f00c224c1c5ec4ce45cec07c05 +M = 96e0d0e4929c51a0ddccc6c7d4b2d9784867e8427af1d80437acef50b432885e80c404443c31e8c1aed735883c0774c5e997392a28c0d49a096cdc336775e2802a9d7810092336ba6aefe4fdfc11fa6b677e94dd0b4edc5cc28f7a3ff3b403447e71e78668b6d7bd1e3a200b6dac2c45e659eae7dca75d293f57669c935889cbb8b04c619532f5d8670add7b1197f6f0bd5ead7f58df05f8efea89de81fa + +ModInv = -1 +A = -185d7cb6a6d9a3bbc989d1b97553eaddca6fc308ac2ab7c5624383e733209081e438dd94307d806a952be4f0e6bec99fcdcdfc9d74b56953dcb71b5b418acf8172b6c976b24154af074c876b885a143218cbf1ec4484e0bbbff48b4a9cd4cb22cc743a1b +M = 795c29fe5ab683153e326404b72f6f4e8f8a522ebc72e62024e15f851882a601550eca044b1411cde01da19b1a275761620bc574445c0493af9dc454c3f51b56f1ff25c4e1a7cc9f8373dc429db37e0b5d59d15131d8bcd511d0bd9342a940664f96242f62f6bc2e538f9ab851c2a294c190b1e47118eb89e68f12dca47a6ba45f8f31184d5fd4e61f8de086e3f244f912c9f78c04cab27758ca0834f1 + +ModInv = -1 +A = -13918efc32624c2bcfcc73191996a0fd977c8140054137aeb7cb1aa459970f04d45810e53f272cb2a5e67dd89c925856010097470b5152b61086c5b669146b57f8ad2e086a0c50cce37e47cbe7346e134e6a3d1a164ae069858c9f1e299bcc044ec2a0b9 +M = 55cdc1337d81cbbdef2a7c485b7656afc17698606e8dd09c2701c995ca76c04521c50e56c54719c9c7cf278fb3792f81f8a6da4a47c0a09adcef3f46974cff1d731b817be1b5deb7bc25c5b6fd9f7fbf95bcb576135fb6f09f966f1a5e59b612359664d869519d0549f473f64409406dedf5855faa2d341a4ce00ccea69b4aad4b5e233456b538441e46ce1927c95b0600e7caaa12c04759238eb79c1f + +ModInv = -1 +A = c23739d79273c850093204e088d25d5214f02d150b7c45d2a535094bd130d620c36fadceb7cb70da917b3f07cddb76322cf7d3d6d55dd6ed1a6ef7fb1104a7158dac4e3f84e599f2a7dfd123b304cb76c5f3ca7477602fc5108561539f4fe99781cc0ce04be3 +M = 44d628945d6fcdc259e137daeee39f8377e6fac99bc457417fd1139d61dbfa6572f81f80bb33205c348093c68aed7d0e6cd357b43afc0f8365ce4abd32e9a90fce345fc3dad9d12b631b64e7baefdc98412e851816718f9946d98402ca10e7bf4c26e4a374609b414bba8828a64e9957e2813dbe0f651ffd6c223f93c4c11f10f59509528528b9eaea8a9b0403744830d6b0c27e4ee66fca5c0c6d + +ModInv = -1 +A = 44e28200c6512365031dbabd4a92ae56d39dbdb157fcbf5198ef180b6d6cd61236d9fdabff4d1a1895c31ba3fab1d7c747f7151c32956afcf6d915b164829eb1467dc9ac59e2ea1cea30a2cff4a657f6ad3c15a006fe901f43522c83259b7cf12000110652d7e047a605 +M = c8f3b1b1364616384dfcf08288fd35f4608824b49d8511945a0263918b7bf201db96ae1cce70316e2e323ac276c862c59a3ef8ff23958095cba7ea53bb15c5a7628d6446f549d3c658f31b5898a1832ecff81811cf52eee46a100767aea716796065e327d13f2ffe3277c348797edf18dcfa6a620ead2c13068b3572a67b652f84dc434fdf727d679c2ba4bd8ba8f773a713641f69e70 + +ModInv = -1 +A = e10c610d29789292879409d48aed6988ab52ed0e8254c7de2a3a523152b02821f0195f7bf27af9953070487ecaca0ef21efc6d59a514750496d769884b039d8431e5524fef5d6104f125eef440e5f9e961db471abbde73cde7bfe26a203c78c8f9a55071e4f8f2d70d07ad +M = 151e65bf435cde2ce8df1abdd3abb33a86b233a7f8b03844ce7f142b23322bdccedc9054a23f47a1846ae4c5449eef4c6b0266fa46b86d6cfcb5e48f21fe787cfecab5e3dd9d13cdf5f0704980268b6ba0d6b840f891b73595f0b702536039cde6fe79e06750d244a6914239678bf1281023f01b06bc415495ee29b4bb3630647098ca5aeedd1adaa75aad6a01efd6e39a5babb06e9a + +ModInv = -1 +A = -38f25a53bd58803c57c763f87d195fd7614bf668b47e85d6f58c3440e6dba4cfe9f181a596096ba41db074a7787fca4e9a652e8ddbdc7f0afbce264377cee92c64c5800418bf21d62c9fd554a8e4e0f4f08ddd486df5a1a92f80c6db2322810d8ba99caaf2a42c00c378d9 +M = c846f1351ce8ed0240977df5976c99e4831ea711db17413648e38216f2724c73af016b11ba6a269521bfab497d2cf8505c9082c49dc5104ecc0ca398b4a36a7d9745dd2cf49c2bfda0b0838ec1f6a1709ce32da409ef8ae3ccdb979b1e396ddaba6b2b6613267f3c6f0769e78bdbaca2abb26f05d00791a589480d78e85bbb09630af841eb548f9ee0ed21242ee32c9faf18e00f381a + +ModInv = -1 +A = -cc06939897448c6500f6fbc7d255ea4f8210ad59aeaf959fe6e6506f90dbbe3f7f20779ef0883049fc44e95c09cb900df913dfc705ea2b15eeb44afd7925ac49d5a1161d21623070d5378ea6d35aa084cb655e172d765172f44c5bd44c00c07e7a9169f093b1ead28ec954 +M = 9e8b37a3312de3c6d50e6a868be321ef6882210c87dfaaaa9b059112f1623dde512412a68ad52fb4c1f58dcd14ba34a9fa0d58facd7c4cae8ad4daed16cf12b6f3f85923c41499cabc316ce341f0783af7fb361416114e86d29615a5ad0a7df013a3c0e40791c06b93a58d8ec7f82770ba76c5ace67f594bd588e8afa5dadc3f7ef7edaa69e72a612b82335ddd64a3a1e1751422b74f + +ModInv = -1 +A = -110d2524ef93e8dcaafa8af20b3f76498a350acc4147b541a84032b8f9496610370970519ff56170606286d71c139f056b50bece7d4fe6fb8e361a754735b18826056192987e7d68f7bba6bece0e45dc0ad0c7268f0fac0cc48cff953941337ee9c51647c45c7092379e50b1 +M = 54a878db1ae1b275481168f17894c489bf819dfa32110bf62de6ae09f6bdac65dea129cad2dae9f5dd768927332da1dc76938733863a09411de14ad4de4611ccebfa93ca1f73df604fd59d483a2a20c666d65bf9de4f08d012de0c2f382ef56264f4aca505dafd13c3958bffb399fb4e4c73821dd3a02dc5e5b7688740143d57af9fe0824a6829ac6610cdd68be09d8b0dbef2270e + +ModInv = -1 +A = 715d3203ba264ea57132349c87d0ddb4b621f1a6b1ab47c25056c04e33c4fcdb0f54033f048a6844e5c585cc5967d2f063a55bb3e272fa5b664a061995635fd5fec25dab949ad84129d5d0595026a09c7d17f560e1efcd7750064dc237e0ba07b3fa9115b264abbb090f24111e6e +M = 334b4b233d49a597359868dbe653bd6e52451ac43072ece42f3541e418ea3bec30d3ed4c759ff0f1cc141edc7f3ec77d3301ca0ac1a22240687d4ebac19774ad87a67da5d80656ffbedc9ab293dd168cc0992f17f75b842f4a0882b2cbaedab08cdf2eb0ffb647669544e2dc9b850814b9cd1f8d20571fe19adb08be86ca1d5f513ffbe494639053f0a1afe766a4c84289b607 + +ModInv = -1 +A = 22fccc5573a292d52a33e4c8e901661742cb858a957146a76e57b7730e2c3790f65b77ef38cc324d4b1bfb72b048bf7668e30dd9d04757a719ef4b3662fb978dfec8f591cfcb77cc48199383db77e7cdcaaf58c3d8a158ed37c552873e5262c3852b2d1fcb1d975e5e954b378132e28067 +M = 79b0576570d349b6be360c7e4e28d324402b50f192e6f19105b475c8041524dcf094325711deb257cba217712d40ecb1b91496c8a66c98e227e2b71466a0e346366ad42177db2017d47e48d39dd10a78169432a3d63d8e88d1c4462b4d7fe7a1ec2a7dc68af226e72ee6cce29ad7253f888d72f0f30e0991ada2bea6f05685154eabf1d50d5f7b017eaca76a1f9200f8 + +ModInv = -1 +A = 725730adb7baa7f321ea09c4efaae829455b848f391f1f3aa2acbf3a57f928cfaa1f588c072b2771b66f6874a4a1878f79ced88d23705742d0337af1da5e56333d7265d489ab485f8be246c8125db5676257cde7cc39130c85965ddbe30cc81697e895cbcd74fe88e7da44ca23d5004db341 +M = e12376ebee0186463d346f041209677c7d604598945a8194c4666802838f3d4b7173dc7adc22307616afcfbe0e756a81480d251e29a3f5a33a555e0cd87be317ace97318d379edf56b77e396281117b8f583fa7e45ebf8a3d65c43ddb282e907bfa75906f29afb8814fff410172ca8c6c3611b414ab869b3a43cc6e52dab44e7b85b8d72a0a99968cf75aa76f84a85 + +ModInv = -1 +A = 633a706a0b534a3a3659b7d8a869691d3d0119e162ee9b658f5fa8de046a5abce16b5304874d0ed8e5f17210efe0f6f31615fa517bc7689f84cc36fe6077b3883e9b8606b82edfd084f26f5ba8cdd34b9993daea0525c1712fe561dd578876782684b533a67b66e1685f1f8a510c11d79b13038d +M = 7b98be39463fd73ed9a75a7ad285f5f3c6ab4040f05970a8d1d3b4d60a571e1759c3a7440124a9705d1bc10d29b360fa8d0adde95a98136fae029848e68bfc9928d0e2090d19f85704e1bf47fb14dab1724b116d855810901d4969e27d4a22e1dadfa0a84631fe4dcf53b592c2c326c7ff260c36bba496c37c71e5b1b34e3f164a95fb872e2ae2ba5a6dd16022 + +ModInv = -1 +A = c988e8d995b9917e964d1a2b164e029ffd529cdbeeefef57502534f2757c39877a62b22248d52cba1e91aa47f19402e85b43aed43ac6334708357f5bafa54bcbc270254815c121fc922d83015ad56a11997488c80f5a3b04ead5937dbac46a9d32dc9c1226f01490ac5ea1bed78322381b4d8966ae2b +M = 60925bb1da34e3cb2cb65289462a19d83b72d5e031027311d203464e8bc5bcf94be5459d55fd5fe4a5b90e577859068f91e16f25eedcfee7345a69025fc2391187d2e80c8ad7edde0c36a7d8820f3ef2c60af395a85b8da854bb81d5e645c8cce157f22f77952f083066999e56ff225ea4b80d2e6df06b90084baef4d837f4120d6fcfb5dbba9c7b94e2bc + +ModInv = -1 +A = 5daa3d2575b9377dd5934a7144b936ad72f7d4cd6cf7e3cfa66febefe56da8a6ffbca093cd8d2d19acde403076ef7a85827869dc7f618df3194eb75d292354b13262ff2c515ba7b1a1e7f7355720753daeef59243f412fd70a8b43add5e5f164fe6b746dc91c1b2c570fd106068770827ec5974287a40e7568 +M = b952e8a72ebbca54451bed17a5982eea0b9a24ffbce12fcf74215bbef7e809c4583cb6d56db1b12390b3ae7901dccef7e37bc8063667eacd756e2ab3eb21e3c9cfa4b65137a4d49f80e71bb60fb3e577f33d0dc79e9a1f56a10f58752d81d0b9be448d3982056968794261df63a98ddb73372b072f947bd50c7c8d783bd2dc402cf05d970b594ddf + +ModInv = -1 +A = -1496c5f739073f8f334a78e339e67f196677c1568b08d26de64c915eb30a7700563a8b36ddfc47adc4910e0e78059b5a694295a7defc6a8961cb2cb8b3e4c65271a53d77ecc375b9a691ac1fc8f6071e9c5710191f33d5b29566b4257721c5c42655e021f8700762a0a7883daca6c8c84190ef3cf040d30bd9 +M = cad2e8acf22f351f0bcdf71799e9d531ece8f9ca54522eb18bfe588cfa035b8c33f31a3cfe77520ebee5f9f2b4cd550d1911466a51bd863e256a35c3f40206bf611bd849179149d08a6d67572490855da917c8434e438a73c98b09c31bbeeafd6964809561dc589afbaa4b5d5f3dec72a0f591419db4af82e5202d1612f1c68e2eea286a969c4bd0 + +ModInv = -1 +A = -ad480c5bbf43c33fb4575fa3c3321adecba1e4a340b5f8cf25bb92d23f64b3139941f720391d51265df854ccab6ea60a4123aeacdea5130a870a0123ff66e19af82785dafadf7fda8624ff2a04cdc88f5b64c0125bb073ea9cfcd991f392937814d39b1423186da678f866771910dd2ba0ec10a5b90639eccc04d179 +M = 1cb7b3a40d9cacd8984c30a0cd865d6a7203226552b7aaf8f86b591be494bc30063d456e6e4e18df45d751e69d3d2e31fc85282a43f821ffefaba30e5bc8eedbb00dc6d3f3be914d246e5b52e09a19219427fbffbb48b5351dd7ecec64445f8ec4385fbe3019f91bde2350ba638e4a3c900d9a3ad2c8d9359ec26c8b912cd8058e4dc98afc + +ModInv = -1 +A = 132dd2f06d709ff659b99e9addd6251140949a6084a0b4917bd813adc8281ca117751da62154a736e04b669eb658245a8ad50c4412ed8b258087e2fd6cd9f9834d1c516d471e9d6626f58d8a1ddef06c4aed047f28afbf75958cebb56857b4c37ec760f9e60b6694051168565df6850737ff25ecff9ca13454b27c02 +M = a775ab31f81f8a70cc239774fe0e94ac051f61ee2599cdd3850a7b6877821e3bd604875f08fd795e4dc020b1daef98fe786ab03a34b365d771a6ef88cab9d67f7862e94bbf7cf32f878466c5cbe76f6a6e63d657bce001b46a2fd8146e1fb6b007c9e44333617f33498ff1fe15658b4183030eab83faa2067dce0b960d57d4311f74c65349 + +ModInv = -1 +A = e79163faeb61edbfb032512b8c8793d94e3b20c4fb0a052bff09fd30ca081bc5cfc9ad1b1b4dc7a251423a633f3d675b376af57ea6cae41f819e97e762f06a36c04f248556434b5b0f6e551d19c214460de20870575cfac77838eaefb9976f19a99cfabcdc5402a97b8ad078d5256357fa15155d21e953ec460fbdcf2d +M = be3b3cf5757d4a7cd321c5e9028a570265230211e61c35239c30378291c2d32d4801c684a9d02a0bc33825760c955071fef030b1f2d0c93eb6ff53fc37ff8279d887d37fa0629093c9873a23e385cf7254b514980cec4c11b7bb1b77166666349dced79293dd90ce140bfd029a828207a75f599fff63838ce5431993c8480c290424df71 + +ModInv = -1 +A = -fac07df3e5cae6554b49dd5e7063bb0293c7a9b5e003af814ffa1dfc121ec66121191eab75df20ebc648ae778fb171e3cefda20d2f4a76ce7fbdee7752f30336f51bf7ed88237e795b83e5c10f0df43dbe5eb8905da74226bbf9f8bdcd613532f9ef23779dc6ab99a58db404a8f90a8d83c290492f2086d0ebf2c163b9 +M = 3edc066a46ac87c058ffa3a7411a457347fdddc107b8e9ff3df0880c0c9f65b222feaeda41842575a519f02d8b413fc492707f7c390b6193fe056b9d7d3cd3a97bc2a33d390afc4bcbcb9892d84c70c905fda313c28222866a9ccb221cef9d3963b306343832e41972069c4ce912e8cf42564fdf45294c6301bf244642033ef81ec7d0af + +ModInv = -1 +A = -9541c1bfc7ab212e03bdad28d47a8e683f2890b123ff0722d1936bcc7b9e0a546c01c9de48fdff113a1e39b95d933df5bb140c5026ae82974e236f761b03feefa67fb51024e217d967b89f01d73d95563c55a0475dd320835e0a7be4a8074706aca7215dc56224d015b2388fdce3e638bca46bd70d89987fc91e855cdff8 +M = 642a1d11a6fffca51bdbee16d2b9aeb7fe7f406d95190819ec4413125e5cfbcc2114b8b33f70f44a13b9da9f4e53bb70ae31c4b0f125a7ef828079a78b624494222becf0217c3b8644a1e6d2818addd94d8d21db70a64be685acb714786e9647eb93cea6360399ef512c58c835156fa714a1e9c0cf17c5775ace364fd7eba0299a5287 + +ModInv = -1 +A = 9a06437a41298a64568e24256988dab1c595c4935751a544d88a1aff269ab25b2cbb818161ebbba4c1b5da82883d80bb022869d57e59721b5c3f00344e5ab1e0ef7b00ba95402ddfcefd2e6fceea00247c6beb2a12166c6984b1c36f2ae9cc69248f67154b041e88c96e053f3a2987d29b8652db47179a9a9e7f65abc703cd +M = b3421b6b91b26eefe8acfc78866030d79e9a06830ad2bbf10bb2e4076c57ffbae66fd59b3a6ec98b8b59fbd11934ff9fbe402c432ac4e8dc5fc6febbe2d9815dd82b24d868bf25f4ba50fe38643eb4fb5931bf1e80774913351bbe5f646d8d569a8384b49162870cf5c903adeee9138e184984c3651b5e4c1de7ba5f33e2c5426ef8 + +ModInv = -1 +A = -8e60501d42e7cd1d57531eaa941d67ae7ad37acc9fae1f126e917dcea1407d838604c041de09fd73d9d5980f7a4b5dc2d8db886d48fbd37faa1eef390271eeafcfd71295f9cbf758ca53a6c4c3a0604145a13ff74ad242931a109c8e4ffa25f65a698691181654adcd0d55ee30d6ca326d4cd6b5a29c7d38e88806527b37823b +M = c7b658b9d610aca25d1b6faf864a70fadd64abdb88620d9a8e66174580257880f525893b1791fd9cf624c6fe33479db6f833ef0f5370ba0cc527fcf0041e191962dc74bc0be925835780702a04223907e5730472ba40ab9ba0778ec15da32d9d6412eea878fbd0b1697cef6cc41311c7bbe99f5a7a770e17da8f3f49e7bb1ed9f3 + +ModInv = -1 +A = -89f3f81fc6c4c6af6358e498cac52de3b4d06dfbb625eface86d97ba1cff91c8d17538e7c0828ea3ccc083f137697b9d693d11d0bea74020b8f1498486d4e718e6ca37d12fd56a43ce4084a9bc9de13c3863204b5120d1eb9708b370c95031743879cd9fad3b27ef19af76d6b58538176505b761c562df2ea45b89fe64db6bb9 +M = ead6eb92bf5c8243d4e8bf91fb03d5839541d9d5977ceb53957c2bbb9e538c11eff1b59bbd9f03d7d35171acff0d59d949336cfcbb1b7b8078ef7c3707fb74f3d95d314df16337361a98601530981b997f27c1bb81f67fbabf6dd62953e62999fbe5b0cce2952517880d4357d562a018b995d7a0012500876b2d3f5254ac08cabf + +ModInv = -1 +A = -c9d8770717e2585f27b2a13df704043041d618befac01360990c25e40a07b8aa964c16f4622ff49b030af42ccc1cd9c8145deecb788569e9e2c16899b99de94e46ac455000009b9bd9a21343fdaf16c9723cfc015cf05f45c42cb0d54ef062da44add5fadfbcb85eb0db23ad962f453c2593afb5e3529190e749622c0a85ff4e000c37 +M = 875f0e90e8fbf659e25d75b027bab56c702054c51b90a4c79920b7a1d1f39a6c38f8a83a922c43d2484f0b4ff3a190beedc8f5229d1069650a037fd4dc239fcf7d518165b03894594b1f7248845e5dfa488d68d953c1f725e6d0dcec646fd1586876ec3ce65610a35b84b752c9dbccf6d329544fc0a74bb450b185b04a32 + +ModInv = -1 +A = 187de3ef0345ff50c061478a489ca562363446d1c19a8667eaba0db0727a7935fcaa78ba22663dc9a4749864f33402fe20e168b66967d0a4037ac4a3691448ef17f9c45237c9a9e966a26032741861351468abd7e3429a16645eb8153279df404c32538413d441a8a8819f300fcd1381f9c60e3d35cac4c028f959e54750b05c4497e84f +M = 803e37c1af582a5fc20a40be631e1f9247f8d5bf9947919415c7f83379bc1de91fba0dcc1a19d59ddb494331f6f5bd25d99a62298ef7755b8f5d58ace9f23b18b107fdaa7aabfcd48b4285d2ff3d21b1ec7ed8ff722fb42aa5e620f0a361eb84e61a5d9537fde28c7f76b3d7effae62d30bd48ad7d0d734356eb080be2 + +ModInv = -1 +A = -7970010c962f10291e61d8ba065debb60932d2587e7c74e5bf5de955014025dbc00598fe2510329a9ac8c0868e24c86cdba3c2a12d30a70fd15d1f317816a2e7dbeed3417942a77dea8bff1eb559302cac59ebd4f4cdf0a50faaa0a2db40b0825a50b6e64223e15490cf9e9964fa88cfe96a9e483e56218c987c6e279080c5c716a8265a49889b0930 +M = dc85c9969d8f809ca66c81adb7edd481b523ceb49d481e4b7c5bf8145575792fadbd4125e5cde2040a9d3ec4d5c98d5a2246b4b108ab75f3616fd2981be76df4c493a495fc91d87348998dc34891b027d6e9cb0dd45823d8e68a518b26575bb2bacfce9317a6fb0483893383e3f448b184a08ce87e321659 + +ModInv = -1 +A = a5844962caf963f13cd425b4b37a7a5074262deee331d2dc6b4fa2d83fd2fd0707285556505e1492ab565198befe3ace962c86352ef19cacc013498fda6e1b1ef298629bd189a325a682155313cac1415449ec1c1445d1511f383a5bc8156d89523c8428e753f36cc5058a474c7afa59e7939206668d4dbb8253c548979f87d0245141049a3f2d32bbe3 +M = debc6a354d5015392e252a8b477bbef0f80c3c093bc907c69604b7e3197d4bd24f6c62c868748dde07f3a9bddb08b1f193cdf6a6fe8a061e1a9e4768e75b03ff278974145164afe8b2220b32b6647c86d9d78d93fa30f2074bb3ae9cba51d589b95f555305e8913e5ebdadda00b3ff96cd8c1964e3819e + +ModInv = -1 +A = -b8310561b3944b71c855384ba2f29046a93c7a0f379b765dbfb0a1e8d9c247161c32a68e59df2f1b4f678c4a8964835379a88e0260f670361b80b697fc0d6f2f62c3b671563d7e5303e8d3965cb2a3febe7f9d422e6ab26285a0f01249e47ff7e0bde7fda41f8351656739ef12c601d3749f0e43826da11ab758aa547be3d9f1df80fb4c98cbdb40fe62b3 +M = 5ea1fabecf12cb2495a31be385b13e95cd58b06dda2399208024e697fccb38fcabc041aaf6f24a4ce9c3fc64563f26b4f061d6a374205f88cc7c5f28542c33f0b60546b8ef1e33354769109c7aad10a2e8492890bdd3a934f720c615fea25ef215c943823cb4579166a6613e0b317c28fae78c27424 + +ModInv = -1 +A = c4b5a3e42116952f0fcbd1a0b09a02a297b150656d4f22380678e102c833b34f8cecee15bd914625ab9a80e72d7365d42479402e1f65056571a7fcbd108dbac02665756ec4b542a61d33bddc8140c2632abfdc8116187daeaa8378a976cab6388506a4a6f523342744a7410146d7d11ec6745fea2fce67876657d94692587216707ba705a0886ac39e4a82 +M = aa180a88deb41f83317aed3ad2571731207787bc65bfe8d267f9f478117c031f68ee52cfb1145a7b6fd1f50b4f839e2142be77d986254b5402170fefa588121096fb393119690a198541df366017172d47eb7c4a9da94b24876760d89e134dfd56eb3eee1d057db660d074cbe69d0b06bc3eb65d5fd7 + +ModInv = -1 +A = ea9cbcd1b58b21f27127a32c7b398da6affd269df4fa302d48d1d661cdbebe5ee916a8774fe887db0e9496d3d61c88ca2c9663f41f3ee1cfe7b4405dabbcd4aa0936926d997dee64d37bc163ac307da1fa9c31d1205e937aefb5703ef1391e6273fb29b3e1e6837410d34785e8cb7f6a0cd6dc4bb25b6fe51007c0f71f4795530b3a06885a63874fedced +M = c670ad9bf76c1ceba771770c2a511f15f7ce0e3af1fbf5a83d07d948e21eaa694ed500efdd4033bb585ceb891470a43a97835510992e3959393a2e7da7fb2cdd5b52512a723cd159b5004212d44f0e86575f9346e1e406fa9ca266c02fc48abecf7f2a89f01e5fa3715389a5e3edd43c6270f2fc9337 + +ModInv = -1 +A = d523b7f944f7081be91da1fb48c83b7fc430108b29e4d8ff97d9822268aebc6341fc1b05acd8f3f7fc532d45f53f2b0a556ac41a5a713e59fa1147df6e21136cb5a727ba68b50ae5bde33be6a0681ef23df8623e052414a56eb4283e825dea76979dde5eef9bec73a5fbc15b98d4960dd3ab2ead728b533fb25af584da31b5e273ba232940adfe8e879ac563 +M = 4347f326cefae68e6cd1b5d07b41aa8df7ec152ba0a9bae7ef7d43f4501d224eec20b9e7efeaa1dc4b65c43f4e29a6270bf88563b6fe3c50faf218c2a76645880f9fdfc72bf278f0ee223076267eeb20d0f8cfdbee5df048000798e4667357789f7d072348e9a79b7eecd3d492f0b2f73b6ffd1804 + +ModInv = -1 +A = 62e63d761cf0462f9b7f21ccad526df6c224ff5a320b3835de6c485a75c10371278a1c84e1589e774d5fba3bcb0abf5c47b6a4f7350d7b7c861eebee320fe60b9e11bd0dfdb8f25d326324b8e508afb1393d3c2d8e5896af0315e57958a13aa514aa0d16cd93eb5a18aa8149c9478f3fc3094cbd19d3dce3899afb910bc1d01dcf3e4307f195e41c649d67a567 +M = b76c9b7cb2b6bf3024843ca9bf763269a2b30aaf83ed7455e85ec880fbbdb721d4963fd75109c5fa0f6be01e412aff10976c356c21cdc53150e33996474ce43ec3d2be3b9a3bd2a2a58252c0f27d1de55ec822a93bc261fc29fef28fb512c19547ef2c6284a78bb055b0d663d9b9dcfe008dba77 + +ModInv = -1 +A = d94baecc011004deb2660b266a1a2dcd21fed3f10da6a75b0f476fbd425856a1a51eecd04d7637a390419a9ccbdcb784ca6d02f2a9c695cb7c7768b369918e3c0c754a40b66df797d4d53da18d7123cccff73bc45bddd25d9d7034fad67f234c109143138ae0daf2b2c376239cb6615e240fa1423e7f4b48705777ef36ee7bc0ef165ca1be9f5a522e9338b16b901f8089 +M = 51a4a22d76daf3e29ca1fedcf6ed48fd4e9eeffecfddeed4f9baf8ad049c20e5b1dfcebefde16aff535602906450bbaa73d7e3510405234ff9877ec2a6ccdee3b5102b43ad820d97b0e207ee3065287039f6a5aea0637edea22a06c33f9a9a422b03366a780c43c0b0969fd626463dcf + +ModInv = -1 +A = -cee41acfc552ad1c52bd8e1dfc850768edcf3d720b98f5d51f4e821bafd57d1c0531d3b4b43aecea9e56676d4de1f87fe9773723641b32e66f6d985a917fb206a8fd338bf1a536346efdd3b17dde0335c021ef777369f1368e055ffff81acda7ec01fa3cfc75ca6ded82f6eee03093f299eee660beade9870e777e8b1e0364ae7a89755bc86739599b64d5688e2971a43cb3 +M = 3eb350b35676b038a81808421399dd4e8d9b54449f1cff6edc1b52453ec6b9d56f0de28ce009d40f767e8f37b7381376b3d74cf1c94c5bb1f89cb91e1cb7ac47518401cbfc4b0376618d4fe22240918215a1c38bb5e158701e775bb3fef7f119d7baee75ebfb84fbad9316e64f5cb4 + +ModInv = -1 +A = 617a8cfca88724966175ec32172d8efe91b2078de8ee77687ab52a437a7eade3cd803df09d13be105def81566bd74461ada0122a2283ba76320f1bad8d7d871d6f9b535ddaf698285851af874c4d7652f7473767291c85cc93d613e3e463617d99894cb2d64b26a416207d47d1b2268d84a2f3195133f8adfca40ab5b1db922f81d559d88b7e8e4087fef66eb65ff696812e +M = b1377618e9bf10b3e5b59c42b23b34ebef47db815572733dec382f17a4c5c0da8ac8e4168bea799abeab8842729050dcf4fc40a9373a1928480df06131c79bb9ae8f848a00a6cb9c92533f040d0bfd5b0ca04fbae9a1232d51dc1acf54428587c4599ac51924a66ab29cab0ffdb627 + +ModInv = -1 +A = -8a2f2804723e20ef7d5d7fe65f11373704c08130fce221ad74ddf177e3993e7e6d1f7db4518d92cd43ba46d75898cc8c274a9ca910f4ba6e4309e1abfbfbd26bc7e949a017644962cf3842727975785e109c57a012e64f972a1726f911ab98308412146de26544f1c7713f79b2a7d3a85555dca47776fc61a5b31011fa23b06e2db16d3bafb51f23c3ef2d2b1a4f230bb47835 +M = a4f45d59d7d2a18f495707060f36cc779e1c8d334f0e171e51f3d4ddae5e1af671c0d7da6391e94c7dc71539651c7b584505e6e3db7dfb6af40fc0d3efb068a42bf1bc299101d1ea44e894996aff9aef056997132e7ac5cb9188304c3bcbdcedf34314a8cb5e9b841cf619f8a782 + +ModInv = -1 +A = -ab47b9ab5c96f6a322e83b0e9ec83557d499f95bb6ae844740964d6882a9e545b96d33c15528ea3da67b4c1518db9aeca1e44eadf310704828711a5483b66d1df36b62c4b86548e5a1384034acf2c429f943e1166c012addb2705b16d3e7653d3bb8ccb008be37a2d5bfa52fca4017f06d14d74d528544fce377004ba54581c9f20b7642db0a8ee43840e82e9d2b16a70982ff1151 +M = 6c12dd138d01f4fdb85fa6c6f1e1958f9e7a95f02cab9d867ca7d7a5001c777f9bcbac47ced1ba008bebd8ce67def901346d7b88a6681d284c8a8b5dec9cbcdc3dbbdd75554c825597c1b62f8c4cd24bb81bdacd2596a94d285e19e91cabf56a2126de01354b9e9fa555edf1 + +ModInv = -1 +A = fdce1962270548969b2f63e267dc1976a5260bddd14f7f998cc834d4b61b9efb10b4da8a190a173687e43cbf0fcabadd7203c2705cb9c55d9ef8b4aec29efaeb0a6574b521c0cbe20077d05e7f3a24a6ed889a034d98afe0b2a7c63c29a8b7498647818a29bce1f340fe4af408415f6cb64abb562e6778019cd72410c1b83a9226bb5449ab145066e9204817d59bbfbb48aebeaceac7 +M = 33a8d39a01f05897005a642a0849ddb0bcace23dfd9bac4444a767626c1e15ae12fe069195a50cacfee3f74c4633f82ced70c9d169bf1f866e2775018a18c9a620d6f1ce5f51bac1a0105d33d14097db0f468ddd0c2bc9ad175f6cc979e44cc7f4163457d8c9c1d73078ce + +ModInv = -1 +A = aa5e8628e00b2a2892ee381236261b4c86a0184fd5f01d1e71e06124b2f31c7a322737d7969df8cba2b75784e61efd2f0f91e9c77316f47c01db8a70a0f307700707a02992fe548573a14bb24c0165024816ef5b411323f289e9d1f7a7ae3a49fd424d4eca63c96dc58bd40fc23d74eff8343eea66cc2337b248a9dd328742acc651cee12140206a769fbd78866f5df8a0b86a4f8e68e2 +M = f13113d8d9b7cc1470af438f890021826fc36896209d54d3a84c76cd571522f1e17f8649c9da6522941a2b310f83d2bb7c31c99b9cebdf2b2e412264f7bc6f2e324112942c261430f956d3c64eea966d366b00d6cd4633c4b50c98a42953d69bbb6137190e17b1c1cb3f + +ModInv = -1 +A = -557f4644b95f6e2139d7f7e00656d84ce9e4c193b93ce6f19f1b8f3d420ec83afc0ecbe431042d56e51631ddf5723e003aabab3a900342410136afb6f80414178810c232365c25315a923d111db9a83c5d4d15d9e238018e95791a8b628a3c0507f05d1d986a98f577031e516f802e183321e2766ad679a872a64afdad7bf5c868591fdacde91a22efc07474a0cd24e0be1f8202ff5ca8f55 +M = 3a3dc627485d06723537cb8d90df90115f07ee40363546b18cba645cd3ffc898f55a9aa477b252a43f372cc414bdf48c657b4de7c3531ed19346852c67ae64f77ed0c140468698143b109d67b3c00079a915270a04818d22c1e04af25ecf31097c01d70ec24c9c41 + +ModInv = -1 +A = -75c3d1177ac7fdd2915b468564d667588dbd843f434ca46764dee549d539c70c4e7ec721f2ba7331e7eb1fe7ec27a516f42d2713e9eae24d610216ad6b8b6c7e120a44c300ade16902d7a2f32b1ba51ebefccf821b110941bbbf51f5431fb0701b1f46c3c35e08c38a825f1c3f6ab507756093e72cfb6ddc63106ca20912cdc0504408f5ab2e61cd0350ba5223a2b581e4642218d2d61a9341d7 +M = 46d7ce4c77565386454aadbf6139227ad198ff0bbf61c898ec28ae24b525bdef21dbc5ae12322e47d133eb63e6941a0f282817b52ed9490edb287169b9df04b3062a7c8e979ece0f33f6bf830be4ba5c5296ea69b309d9084fff150222f2931fa69e40a385485a + +ModInv = -1 +A = 8be3f8f8e9d6839a4cf2a551c9cbb7e8f0200d39328f2a181514ada8cba27f8e14594730d79f34347916b1084c3103f49b8bc6741e968a18e2b618fad8e8121ea25c52c471b150b9bef4d4bda1783047e376a554c6743ebffae378caf5579d68953f7e1445c80d6f1d3ec45a7846d873450699ca6916a14a660571520b8ee9f686c0d0b8fc8f7b1c849971dc9552e7965b00a9c3767cdd9ba5dc1a8c +M = b3fa47042b48bef0465f9be140ae20b9aff59b7e8415d766aa86d21b903956e95209bf5f944fdfc3849d5788e9f01b075be57042141a075375d1bc3fa7134b2b160faede5efbab23053ccb61539506270f9cee99b84ea9562d349954ea57ee4156273eee33 + +ModInv = -1 +A = -77d690f45a59ba8876a2ebc8d8f1f2c73f67a7fb7093a069abe5e70fb318b61334683d398c981527cb7b35ad46451a150d8a69c6cfd92bec656f2b943f2ccb66a4c5ee99a20023bcfa7572a9336364db7bf5a7f19aaa517762cc55d1a22546c5c828ef17c77c5eb97a9034b29c1b0b3e9424a8cb967acadc5da83d2fbb894cc3cd4a9b4ebf68c5ecd6d396b8559806e2be0bf13474e4e5b2a03e8ef8dd34fb +M = e6361a5287d14bd2df3cb3c78bdf5c31d5c4493dfc46987cbe995e29207962b864a8ba371b2e938a37178ff8f01cf60845df2e2da312819b8e73924278dda3aef4277c1789979086bf4145b9ed8bfbd7ed3adf913c66d4711bf08cab64457a70d457 + +ModInv = -1 +A = -8015f338fba0adc85c950cbe1cb9c80f8759d0fd484cb4430a7f65cb225aac1668d5281a775400bf42ce34283c6866eb4ccfbfa97999be7e0e5380a255e5fa51f8f3bf1879eb95c2731b2c25bd8a9d194d5c5986faa29d0e4c98daf16e413c9778fbe7485f11a26853711731fc540ac72a1710818af8354178b73e22eab9251c4cfe782de7d74b9e2b0f1caaf838f274190998578dbbd8ca7aedd71ecbbd14f6c9121a55 +M = 8216602e97f65a839d57aadf1d7a94138fd59ca7a81baa6b76172f3d8648dc95d8ffa9ecfa1371c6f606f7c4834393dbfb03ddb9f90fe3cd85a5faf5945a27e751db07a36f10dd2a0871924026c99c3140d0b4a448977f8069da7cde + +ModInv = -1 +A = -c2ebf14b51208cb192f650d6e8bbcca19704b67bf56ad346c517202b3310fb3625e3a398618547943257b8fdf4b44c4315a5f8e96c7a5106c4a61d7750f0ed3e9c01f46f59c72b51732eb20e41e621ce0da123def2bf8c2e73c6631830a64227f0e1b242e2eeb7d11ebdc98bebca9d89b7e8d3e547826604e83a3bac8bc85c8982fd5883c3466c6f358ad455daf2f6775ac0441a06f2e2021481b5e064db5906f28e7613d5 +M = e4f450fbf1d75ab9793e7c31e4fd10a8fe25b6d93469cefbf9dc64015baee4cf35210b07f9582b9b5a55b7006a6c1f8e7395827cd5462681aa47a5e6e814aada52bb18880ebcc620fe33b778d15b290e6d58fd7a2852a4f5640f981 + +ModInv = -1 +A = c5e5255352c514d4cf27d33e1f819e343e4eb203f77453dd0c77375270637fd70c5c0adc8e42a1100c41b7ecedaddff41fe205c70116a21c97d2214d993184ff8e78c9e782d1f8df81f311ccc529e0af3328b9152b56fcc490ee7d1c525f6896028fd2692a84c5442eefc6775d4bf09436d5462775430a78665e12e3c79cb095dbf600084ffd2d2bb4aad9be80359961e56c3583b4f1bc0f0ce1a8c32e9e3b2e77e0b93daf +M = 768b71167175e2f5cd6071769e8fc46f79f05dc91bcac0255844ed7d38894270d110de9b9b7e1fcbe7958ae40d94dc48effe83251fb16fbd40cfb3f17a028a1f4d7ae5e45305061d3150724106563679812ea0961ee2df968277b361 + +ModInv = -1 +A = 853fcad4c4e01a3d747c15c5f243008f28f2cceeea37fa3b47ad37911e92b49987c48a6c3c2de2c6763dc380f3ad6a5ab7eb77e51f8b4394338899dab26a5804ab82239d034407114584cc82d05bef711f872f1e83495e17dcfbf1cff88f2349915e7a9af05b20c2c3f380cde52d95caa4b3dbc04596070588cde48185500af87003066778fb5f2bf1958a32ab914bdbdc351b14455f732558d1447fb1de4533c7417959ddf6d3c9 +M = 4e2cd0fd34a50ca5e41958a7c34d0d9ced9b3d1f2b540b726b8264d53b0838d92d35165e8557b38f38cc05fd703fe504022c34445572c1c09641c18fba5dedd83aea876e376c91f32a904589af86e8cccc78cf501d706f3d6c + +ModInv = -1 +A = -275c2f87e9b4741d86b9eac2c462edafc42dbf3832a49391715e04496c69ba643e1d7b60d3ea24e58ed39007f9d6e0cac037ed39c5c37d67f4705d1df67270f61e6eace817d117c73204b4bfce17adb427b6dff4e9662350f629b9e5e4fe8380424e0a3f4280005e8466ce864dbce6298ff3047afd571d56e97131ff213ad65e4f8bf30c94d46b0a57657df1ae050b5b6b801cf7a13801c12d8b03c2e19d034e7273a272f2d8c82d0f1bb5658f5cdb +M = 277e68488e53d322431fddb5f7b6010bf1c8d2e770ff5e200bcedf2870d198375a154bb0fe220843c2f2f9e64c7e7dc8a562714a675ffc4e5575b1ba127570388a63aec4a3eb068b071c311a96f68abffe56 + +ModInv = -1 +A = f0929bf9609d7a9c5faa0fec67e77d06a6591591b1ca082343e8b5d15a63952a15f0f9994e707c0baf113f507d336dad61a09c36877b9c7543f4702f3fa746dfca4cb9a793ca2c275a49e4e679ec7bad187cf3ae6ed03d0c7eb5fcce0c61dd5e8bd0ff0528fa94f50d699a290957fd9074ca9742b98b11d167676dc42af07b6da4db6c8588ab413d33e073fdea852ac5c77ad34c107fa8a79896d20e068ef6d7b60d08acc2ac20619c86073d850959d66b +M = 87f0a0f384931b7eda6f484e7e7300d6fe642e7278f24ceb6032afb1cc773145772a55c1a8d6a34b3b25d3f6b97a905bf7474fedf919b5160bd495e703bfdc0374e9195b1b80a3170bff1c9743804d25 + +ModInv = -1 +A = -ac670fa4c02cd84051dbd7c28a6fb6f24da699a61680be16c9dd0fba493de55ec99053235b69906ca70f447a766f7984b9996fabb53ed28a04ef51739c2fac3702d8eaa293eebebc84f6c94c4bb2e2758cb26f18d2f4fd509ea1a21613066f86fa988c58274850b4422257b476aab88c6df1b377ed54eb544be021c9b01fe81dc10683910648a0c01153c1134e3bb905461d6f224003170b4b74e1f88800b39e37b6e2358d0eb61b4a10e9b94f6950234fd9 +M = 3f7922c115d35f90aa11ca9664d263270fd06d279120873d3c099ba5b24005387e53e7650f456a7444c07ead6fda09ad7ba5e1fa71ac9076ecab2362c04af892b4765ae4e5367f075f7295c41dc60c + +ModInv = -1 +A = 90c662ecf8523ad82263d2fd4d522732a676688e7d46a64187fbe78a14fb44a778b94795a9562c532c4af3e1572a85a01a63aff88205634b28c14169e08b87d5955bd2926d57311b98c31261e89a11e1bd3686b3b205d041de28f903bdbd89b380fcad8fcd039fd43beea0e974dae285912f4ba5594304764483b2983b089d48e1fa1b6d23f870111a2392973fca3f38d18e9efa117708580a27e5bd46b6682966e24a83e79e6d8144c61655f8f5c526693c043605 +M = ce09106e8cb8a7d3166e77b6ed7724c53df561e11988c9f4940161dcf6b91d14dbd43e5ecb9eff0464de1ae910a3f89b460609a0fc17830c9541ce1debbbc02b6aeb7e9ae579d8e5d4535eec + +ModInv = -1 +A = -d33896324b23354a558e4048b30621494e9b9cdc431c29a1b02e8ecb3a82c46b6252f0e841560b5d0f88b885762c4cdc69a57d9ef08f7567675da75d5f8dc871e4ba7200472f1b282c394c2411a257876498fa72e2bc212d6286c33327b035c6e3240d0971ccdab94b0e0500fa9462366efbee2ebc37ae15595318ee347b6f67b2cfc47bf777f1e5796a8ba8e5904015acaba0848becd0dd3aaedb8712300a68c4d29923cc17c35d2c0133222ab4be7b69246fe9fb35 +M = 3765eb19f17cacdd11f46d22609b0e027ac83adf712810d7c847ea46a58fa99fa39729af964507867fe689132e116eac5c126e2fee1ca0b8be6f92610f6f987cb16a53bb1dd5eebc53b2f3 + +ModInv = -1 +A = 8c199e94f84209de32bcff8c60b8c26b2886b7741da5132473fc6ceb3545b492b147ede859002bbe63ecfed8815d4e70291129824b110d3e7efe58c4de007dc4edd37d7a06bd2ae55a2ce9c736f22b4c1e0c0eeddbb98798271aead15db7096d4a7154474eb37d10e29242e0b151cb2fc8b68d4b8ec43f20182a5908b8078033dac80dc355f786d9c94e5db6d71209124c4527aa431aecfce6245a9cb415168794554307633722ec15ead351ad9eeaede8be6916b0d50499ed07 +M = 1f83952d61622df63229c14e8f7e30e11f55779d9d4cef9b567f99be9c4e4f384dfba3889579f9cc06e581cc1cb96504cecea46181dd189acfdc2f5ae4b142afee96053226e156 + +ModInv = -1 +A = 1205170c425546c8244704265e82e63f46d582b06b2f6dc90c0b7058f8837ddbcf15f091b1a382f72029ab80d0b6119e4899f76378c2c8dc54acc275d978e4b9ee6e1109a4299094985c537f56aef187e46c94f1f63017dfc1d1ff947298d2cd4b5ac8acabe001a8582fcabc1ee05f0106b041691d7736b4271fa46e5016e082dd24959d5c9b7021f715d8cb20c7b7956224ec623519b377188164378d07396d55f62cdc950e1edf0393f328018161d61ae9a2298bbf146d8a09 +M = 17c6a0623cb6047f49c870798862e624ebd865dc3dce3e51eae20401b448d66d1374f5c9c6b4d5bc89f245bcd862b8212a46e442050c9b75e03a09bdd5d629945ecb7828e93d9e + +ModInv = -1 +A = -4bd08047a0ed30cb16ffb00d3e368c59e5fa267b078cdd3911052848fbbc9026c68cc7b9803ec40a66011a14a9ffe2161a3cd4a5d1381e8abba8e0486f35d813d564b4f09530df5d18b8bf19dd71fc7e9fd33ed50bf6f23ad6ee1389ecd1eea90c72e5ec504f4ead110539030cfceabe2b6f770bbf896f2ca5fbda91b990aa85ee524a96eb97498ad7bdb091d4b0da48e57414ab7ea75b77589f73e3958f676962242dcd1099d8ccecc1cf17f28c81792b6a14e022ed91a213ec3a2e3a +M = 4b9dc635cc22a4bc8cfdda373b8db7e05158f693e676f923bae21ee2ea3cfc2adef28cff4aa823181e3179a99eb97781a1385f6e03723674655887e24cf0cdfbab1671b + +ModInv = -1 +A = 35cc3616657eb197d78bcb1bb25c43a575864343df4b5e4215e64980d89608f7f951e15a90a3358261c2cefdac8e04fc792e486ecf8b685c9192e564bb6c006003e0719b365fb1bb9fc5961aa903f6a815f816b3a8d7318191d6c684f6d681ece56caa1d640e6bbdb038b28790c8a8a431349bf89f044d1e44bcd8083073c14e86d17560c4d2d6f4c681df7fbb4b8b57aee186e79085f5eb42622faca90ec169777088277f7c7aa285384bd77fce6a3550e98b3bf77f24a31e88001dc90f +M = 289903d5dbf6a59ef9757c596268848e74a9661a94d555b2dd7b9bdbf35d894936aca9bf57e05a1b869cae49ade90286cd8210763b7208d1c2bc6b6d601f6e876203ef + +ModInv = -1 +A = -ac6b238ad98ba80fd72323205129beef263d06ace2016285a8a2dc3512148b2bf966269c7ed5a8c76fa1fa23eef732ef51eb806ed94d61d351899c948379803ef702960e7bdfe5962dda78042964e6c6bed64e9b725deb9e575a7bb40aff2ca596e308a64744f66fc62ba5bc7b946ced12d9860e31df46bdcef1785454068906df0c1ffa8ec821a415c166d3d5f467ed281da94a56db9ed322923ae875f5168e083db19a660a74e479e405057c018e34b9a3d73a252e23eaae28ee69c2851d +M = 14a322c49e55c511bd9007cc407af4d06204115569eb1bfb1608c1f18604dab9ff6878319b6b6df2e9033c354267169c18900041fe8bf5700dca427db9a37200f563 + +ModInv = -1 +A = -8373d91729ac99099d9fa91d9388216799feaad3589591fba73239a9f36772e234ff88a30e5677e0e38afc51d3bf46a90428feeef6b31bb50e387d60d8be354f53ff164bbffab882e419810d56169858b153d43b18c6f33b2ce8ede9519b54b3945e5e9652435522725d22afe033a402bc2b657116c2404f57fd6a97f325185baecf2ea81ad09137b4237f1cf17a9c686f749b88dbbb709bd1aa848348bd427cf18e6f0e16d8fb6f24ce7ff83d5c3d3bdf588e0dfb1def0e12f0b21e58eaa341d3 +M = eb9f07e5439b3ae99f38451cb89afc06b925d3be7ff4de27c37c781b6bd231c646032369d12388575ab15f13389af7b64742e491753ab598e641343f8a17566d + +ModInv = -1 +A = 97f66f31798df0ecf5def2a3afad8f57c5b2a40b5ea46ff547299909995e056dc95d94d0efc10239eebe203e81b2c09a9202542257d5f13755fa0a1b1ddf34cee1cb9c69408a9f02c0953a517f73bf85b7fe1a3de579475632bbd0bd923a888ff8af58b1fa36518519a335c64efc78fad296a758bad1cd45b8ee7e15bdda6a7163033e0b0290e614ab51ccafe2d34aaa3daf6e3441e8b3a5acd9fb978f89654bb74fb46ac87695db0b4c9c010404d491766628d0967739fcef8102441e58622508 +M = 3513d246936b2df2e4e43a9a21c3ecf220f323450abbad76ee626a130e769233fbc046d12ad7fc2c8090a37eefd4685a6b56bb74199ad2fd2e675ad9b88b0393 + +ModInv = -1 +A = 6035be5fdfb1d5854d5e31811435ba4694cf94ea285e73b321ca45276fcf811c63934444b96bcd1e619fe4426c93835db48cd6d7d3d92d3b310c239bf4b34f02077abf7aa883b81ea86a06ef9091754217932b193d8de93656ca018d8d804a6ee6ec2747f01cbf5c59f9d18caef3e37758f653e12210f608a2427f540fba217a0682cc08205f2bbe6bc58954dae5420431626347a7a2e5ce74c39080570f1bd183d85d5dbab26c9de6a095a06413da3055bf0e14eaad398c1bfbfe4db1215f9e3a3988 +M = c0e2b144da898f5bf91295ca674f38b827d6eceaf18f0db51fad2f6961d9d38a8e9c24b7f78da79563db1dff86a6c2543ad01e8c7b6d0faa32e2f2f9a2ef + +ModInv = -1 +A = 9d476c323776ed2e6a7a6061bef42783a476cdfb1ffa521a868b638a51efb3a9f68ab68aae594af2fdba72aeda74167bba558b2be95fda97fbdaeb7bfb033c401ed6310708d74fa28aa1b52bae71d2f6f61ff8a27d6ecb60bf0d3b1f145a44925ef4aa26bced53e59a9d06dd88fc1595d9aced2782759d4fb95384e1f61ccfdd6c6071de6c891831e176317ae24cd0cac7cc14bf96e45ddc4daa311dd98121ab7296b2805e3d33d90cdef0efb0be1df6648dbe81d19302fcc0ce99253fca2542c09bc865 +M = 3d91058d76082da5d7b68166d2f06f00b2c371680151b532e323163998ae5d1cd76567228ce4b17bd6d9b245fb3f12ad6df0fb5c0707bc22a27e6c8b15 + +ModInv = -1 +A = -976e3440eec5338508eb5750166e36f2a6c96abab5077c67daf0d8bf6a44e49536cc0317ccec4c665e5016f19dfbacd47d443775b4cc3d2b6c65b71c999390f72b6cab48f4c98e45d743081b513d3a20f430105eadee95d8ceced8c0f70b83f6eaf6f768c3527e0a82eee04d85c5852f164d010c91469db4a07e7747af97c2d1430a5ec6361bcd537c3241b947681a0820c49c0f146cabdb0efb78b593d32f225bc758e01c8c62f51fb9d557eebf976f4d6633f0bdbae0103f23ad52e289b45edd5a4b5a1603a445f3 +M = 93e2d250435a74589998f38738b9a93a67593c26547c15bf766b0a40c92744bf0afc85d07c1c148ae2eaa261d45786319ab7cfc2edf9a4c + +ModInv = -1 +A = 5372dff5594827e57e83a4478a053702344e96db12025be94ec19d2984d8129176d30e05d721510e608ea953105fc14ba45363fce559058a90b4bf4f94b862fdf87ede7e2d3b5354a9d7da85204bc072dc7195769577dcd0722c94af8befb7b7ea4b5b33aa9eb812ef4089a92885d3830684d81bb2cca8cac11acdd38f4b0f34cb8741cdfdcdedb68e67e4267544bcccb02f2cf789f6167e592968adfbd5b8ce1d8460327eba1b3f964d601040cb1c2759d86867f4d402025ab6e4f126c4cfeefe7dc26a4f64a070a2 +M = a3576c4273f330dac77f352c8a8d479e64d9c3089196614d55162e87be24561c43b3d26ddad88ad36782fd5ad7c0ffd80f9217feeedf233f + +ModInv = -1 +A = -bd43cd40d830bffd0fdfa95c5172381d75ed4a6e2bac7a77829673bc96aac2c74e4c7c8608c846a49f0b355d73a2a88cd3afbe558a84c3987e9302ee5e117755dc110bf204a061d9ca4f3e8c926fa365fbec0548418d9f6a890f1d3dc4fe5e41abf7fd48607b3b6c72f1f50ca58a5ef33e15bab6d5682c55aee1f71d0601f4f4ade4f76161f2d7f54b747c121739238f10ad4d8398e70194c3528344754d7d6644c9eeba40e2dc1b448d9a0b00ccb0a34e05d298ec50c055f99986f0515f8081ac855520064682bd804bcb048a97 +M = 52a73a6df9bb36687bc1a414ef73f4eb58e4d8d4124dd9b6a9c52346108dd6fe605639bdac7874bc560c2db9b960cfb048cf60 + +ModInv = -1 +A = 2eec3d1ff95b8c551f0a35359e3c30ca5c42e5dcd4d081c736beacb97d5a5a26c5d4bb53857ae0cdec2cfa50b2a3a22ae9610441156d78887d9d597d943582440b7962a689be5939b28d100d04de9d715c396c12f06c78ed79f4c0b50255a166ddcd352cb86cb2aec4543320734930baccb0ff72b095efbed3603430eff4a29db048821ca51570a05a91eb289bac790359e117fca37bdf8a858c6a98400bc89f25e3c9e5d6c796c1da36d2bb516827a7555e0ddcac69a6a965c40232c935994430c7806fa222569e5ed0b2ecc0fa48 +M = dc4d86f1fbeb91758e814902474fe49ad16287dbcb2fc29710f686ec637407fd2a143d41178a762ec3bc30a97d8508b6d899 + +ModInv = -1 +A = -f1bf685e5a78fa052d0d694b01d8dcbe55c9895179c11807c120c3cb31402be30bb3682671879e9939797bf7b6a2d29cbc3b658a7c3f783e16f21830ffb3004ec64fc51c1a25dc029fc098a86c423ad625905dff851ad3afbaf9eff037318ec99f10b68a90b6efc1d54d9eac6530d8d963f0e73fcd9cd0403011dfe9c18bd14ca4a0182afcaf944abb3c2ce1012e85e12ef17db489e18e9783ac770af82290fc8b9cc0d7e9ec2b75eb6438726f73aa7487c2bc2fe4498c8a1c04c791ab050468716ff42074eea0adf3dda46bb5ad5a57 +M = 3f04b9162416946edcdf61629f9d6770c0f3f6352b43997cf59a3e64d71fa88b94827a160a9608d90d94cbc71588e1bb6a + +ModInv = -1 +A = 79d749c770e4545c4b8dbf15233c51683bc503a3d638de1fde422e069c6d6cf61addf350f60b1dd012e3715f986eb667c75d6410be9f21dffe58ec3c01753ced5a574cc54dd946f32ce59e4d2314b1bf9a046833c10443729f89658e0a119ab8b0361ce8f34940623f4907f9c7f3ac72633a4de171952b74390960ed670efeb0b4fa64c505578587405eb9cae3f615d00696c11db21ab383a415569d6d3f1de728ccf915c4d90673038d46f26df12eedb835c9329d50f08a4b73a1abe037ec50d4a7aec50bcd3c0a66642b3efbf9fcd6c +M = bf4d32df9ebb9135e62357fcdb750422c4fbfee01b300a9ada9958bbdbd59c467188b4e86a437158205487fd19bf75ed + +ModInv = -1 +A = -e4ce186e1a3c1f7c55a9fdb9c449af77e5b26b9785beabdddc205005337566f2927dd88f8c909fc3c62b1779428d9d672b207846c6359c9deae6c438bea82d3aef37921b79bfbd241bb3da1424411df35d0317804dc96ce414a3389bf0676d58e8af44beca6331acb2aafb47ced57b39da5340a9d5470e07b20f7efe3aab9ebb5de037762e784df3da0aaa4037b59deabb15ae192aab23539f80ada02662203794e0f7069ed24c878de900c9aab87899c40db1f487cad05938553412052c865fd0de0b8c9fa1504f43a65b3bcb1df74b8a3a15 +M = 91cde6efb64779e8d087341530f2560d0ffa1ce498c38dbaf76dd5b8104f92dd5f75bc264bd5c2844f73d765f1e5 + +ModInv = -1 +A = b1cb8af81e6aaffab11697b1d5e6498e847bf9853021f31e2cbcda6c3b52256aade65c3455a80e0bfe7135b8c9e67779aa70cac10efdb5e3cad1be495114a40235f241033b9d577dbe6d89e76ec37ed82e78e458a530c32aea3b16c189ee481c47f15db96bb5f2c9d7ae5f97173a7e83f8ec980cfc683d75a0364d5cabad95cc803929c2d82808b6be33dbe3531e2d843a036a595f98aecb7e2af26cb744325fafc8635769e9759643e1fbd5bcfd9eb80de8b9b52ebea0eec430556894a682bd77394d7905dce77d5d6208ebb3b33bf91f4fc62 +M = 8c2ebe0cc61031fe482fddc7bab96a1330ad5fbdd6fac8aec0efcbecb566191875c0c66f3451d002fb95106def + +ModInv = -1 +A = 98f7afdde9a1aec33d4e13fe76aab75deb80bbb20d4e959ba11793f69843015a755369f001978215266859b8cc05d1e2d0847be079f9c7f30c515824d016c998be41f61b701d62894603d6e469bbf98f02ab39d0ec09071ea0cef4dba1cf7355d799297f8c105307f29ef2dc2edd1260313f441de19b28387921bdee41982ea8662bdff02c7fdef7096eabd5df2badb9a0427f43330fdb05785e91bd9535497f32428b2f12602db06e3144a8a1256d3e20ea5a8eb107494ca30d75b2c8fd9d46d0c0a42497bb7e3405e292289f01cb71eb524dee9 +M = 6d0f9748a2d25501f590ded85f3396212f36f9f06d1903d0fdb0d0862778e474ce3b8b83033251c0b7655287 + +ModInv = -1 +A = 9df5105912960426818ec9314f51e67562a453007eb5e16225823ba1ba567f27754892023530544ca15013a8a5c153a3f6a88d0e0b06c90ac0ed8a5c84f959a048142e88fb4f2222b559cfa74b03bc0f007088ef7ea1217ab92e7724dd498f67f2c91cb846183fb38b916cb0a09ae1bf31878f5535a5b030fe4118bc3a75922b72bfdde0f28dd5352629cbc1e85ed780596a8eda939c8f7e3b88be2e2e76c899dd006bbaae4a0094a92d14d24b1bb0a07bdfe39a8422851b9a817f0870b20d2b6cebd7b8f504181a4be2ec0721bb9b0ae3f3be976aeb +M = 354897f874e41b9168e6fc4fc7f1d88e578802e9fb4d6d3ad9d5f4b6fb0ba0dbbeb29789d3f07bd72cb502 + +ModInv = -1 +A = 647476e4ae5633cb4e023384458b1f7f54479e1e1a6db0184538f42766e1ca654520c1edc2956175661ec2ec6c590cecd7a57b2afd0ef1fe95d799177868a416f0a6e8ae9a6b50e4a4f5c83daee359065083a44796b0e84288ea9b5b7a865dbc1507a294e287df17651db2f8cc93ff2b66b70a9ccd2a1fd9ba5b6d61e6000c85a9e94b96de3b4cafda248fcddb13b5476689e6c51674ac3faf069563d4872d7b0156c459bb33426b5c1d0f4f3798994a26d23f0dcdb576329d7d31fc6ed70902a97fc4e2a55e525fdd9c48d767fa4f3121ee09e5d0847e49 +M = 91a5fcc9792cbe36fef816aaeec6c8b632393f91dfd76be357b5d8694c005fc2a0551fcef69445cfa3 + +ModInv = -1 +A = -f7e426eb65a3f9b832484c666e5c0ddd1d57d8484f0d07ae54491b8625bfbf8d8a04eeb9f8c8583fb358305308d7d70f4c78addd51ebaa4aa43908e030e696cc032b257485f69724be9b463cfab674d4cf9b5c8e680836fe966b5ebe678b60394d43312a0dc5623c8a4ed9ab7ffb9920e18911fc12f682f5b7b53f9623562ac045af08ef68f4e05e7706b6ef5e79f79439491c3373f4a42470067329723fe04351121c99fd444db1fb7a0d64e34cd0bd1d06baf391c645d831ba03a598ecb72cf2ee7361d15c8049838ab9cb4672d5aa670cb97e2b601de235 +M = 1daead6809a009f3ade24567bbf2b0ce16c78637486faa8ec2bb1af99a798af3bdeed3bdb18f104d + +ModInv = -1 +A = -5071846d9ce6b61d2a94f1a98a3de8ac8deda9fe43551dd39c86e94f9ded2da4f19c51c0272b372f2f160ad7555173dc418799957162a24b85c6725b6f130892c2b582bb58e1e967ad0eb124dff806db233790bb9373f3f32c4ce76551167a958a3631e16c010d5978c41b609aec929f49cab6ef191db3d2ebcccebd78f144606259885c1e3a7d9cf2ea9b5505c2ef4b5855e9b1e7f9c83a25f925739629c2876787a3e66ab515927e1108e76b1a5fc3afa491feb4666de957ca93f2dd820b682ce7833eb5f46d7f272ed4c57b5030d714db7b580d300b7511 +M = d29b25579706e807c6eae9a137fffa297b103c9aed67db721b3e40e63443dfd1cbe64b518ffe3090 + +ModInv = -1 +A = ddcd3c3470f868894e4f3abfcb631f40fed6d20072000460f85df1133302b9f09f592e814bde16983b67d0cc350c86bda2358bf15bec09ff37ee88369b3cfb04738372e9ef9ecd780b093f5150afab148ac90ee2823cb96f623e45548cbd89a36e790a0c306c82cb434f44c7ba47d0dd0a0649bb9f0cd28b0619fb689f704cc724cbb144732182367d212232d18da5d14029eaa1af052b734fcc155f55d86011afd7a25994bbad230560e717914fd494ea142225af3df8e2fddeb4aaf23050fac4498e3f3d213ac84fedbc7bb36c680f73861f54aa858402a6c7 +M = abe335885f07290492c79abf0377187b33debaebac9b584eb831cdecabcd08ae19cffd09c3b14d + +ModInv = -1 +A = 7f1a8569f28988a56aaa3859ea648d1e657ae4591e21bd8dc29d0da77cc7b2d6d5a489464a95f6feaf5af57c3e850a156e1aa9190c21524c7f78ccb2e29e4730c2c3f546c0362a915991704296625e07798f659294df7556073bcbdcfa3f7a6f203c12e4944fb82f2cc6e9d3dde051c167b19f188dbd0c5b1a4d10420c2171a3695e03a8a5b3a385617d89d948b2a761c6fcaeccac11b6153888d3e9ecdf9af5673c03ccd011f19c5b5e93798bbb46a75121215eb2ca40553ef178f55c16e7af2e8d11e14054e37175a3124b3aea2420849829820db1f331f51c1483 +M = d18b4bf09e9f8156d69eba859d8321d64b36359854850686d593bfbbecf04695bc1de1a96a + +ModInv = -1 +A = -eaf36502f56dc2eea1345510a3b9b14dfcd27fbf23dfc885acd9b81dc71c15f697bd93ff0d00a25d5b771c2574826c6ee11c436ebf67d2db6ab0149cddaaf6a7c116a571725398f390b72e2c35eabeadfa2a1856618a53c14c59bd4297fb1dafedea493bb9e2de240c4a562ebf6a51105c784e0abe1e9d5baae36976b8b01323ad4b962f90680ef512f6a1e7c1bf7504eb9dd6950d88548f0dc2547c10496aa9266d31c1dc77ffc35a956a9ee8ce858f81585c4a41ff95cb03897ff9e278a1e65e7bb2c68db4372a796dee5d091e1d971bdb843765c173bafe24064d5817 +M = 86538b7bd740f8edd462d736ae227ffd54fdfcff1680cc77e32a7d3b5585eefd11a946 + +ModInv = -1 +A = 446c1c36af08855d7844afd19c34452f3d9e06295426352a7d34fde0cf330a23cc375c95b1477a6f4c2ec27bbe354bb26e9006125e1ce2df323953ee1dd5436013cd190220f49204f3dd0b9cb1af5e904c724c0063cddcbd7e3baf78746dbe12198708ddd5c42f1b759cb5a90637a827ddaa48ae1353742ced18b60e426a815734320ed55f53af0939109e2f454d0727d6ce710b74ac09b21866886473bc4a665e0d2ff384bc8f94c79059215457485dd9157c17c337d30a72a90a48be402f5f7202893d2fceff7e6c0dfeac59de41f4d1e48a9ff32aefa615830a036d06b74549 +M = 9b771b47ba0444be26cbab565fb6f29c51258f3d16ef9891cdc61130511338df + +ModInv = -1 +A = dd2689c5c964ae73c3b89f17dbad11838dec4cde461f2e551dcd219348ed9ea8b9b52f985d06a3fe52c750de1d0601122856bd4b221b084e35e0252bc7939ffd3cd6cd87a7c87a55078c098009a0520f9f83a3faf7fcf7f0a0bcbfd0f8a6045613e0e4270c55fc5ba8f1f84841d2ffe2477649527a33a7eac03b76c018f00a6f84f7ea062a933f0c1fcb6422b91bcd661d79c7d80b468376acd8d30d1aa9b5b357dd0e7e79596ca9ce75a929478a21efd8663b25283d72ffb709b06b6235ebf4ec7c4aa589b59bc179d35ba9ab4e5419dbc12ff0c1170cd2ccf69960f82d5ccaa161 +M = 804bd5c301c5c2b1f76720c1f1a650957ff7e122a108bb760fe5efe6293cd7 + +ModInv = -1 +A = 8d0adcb31ad5317e63a98b6f75e37312bf6515131faa12727869623f1b1c88135ff660c3a00cc56076db5ad9a95b1a6e94c0a0a2159820b5fb0b03c77a0c7408f5354c871690880cd59a3c681eb8ecef11ca83bdb3a3feb9d258e9029ea0fcd447c3de7ee6d30aed0cf134d341647ddf66edaf6764afb9ddfdfbb1e5c4770b40be468ad20b99184edeea229247353e8be76c232538e16057124ffd0f993a96f3b874304dc1cf87f548f5a77bb34e9f9073c647cb2f89706f0ceb812cdc5d63e318cb6061f382b59a1240fc4d5a85ac842cb2e05511a4a77333da8a950d43aa9c72a5 +M = 1e6b616df6d6940cb92a31c3ddc4010565a4a559ceadaeadfe2c7da2861660 + +ModInv = -1 +A = c4db38a5f6d2027cab30e53724435cff289dcf8d09878e5ee6ee3389c10411601fdc2021f1ffaa9d5f2628ba5b596763e8147347503224b12db96bc807f8051f1570d4f0864704eb173a46c824c4e4fcac235c8783980748a0420bbf3041b5b30e734bcccd65b7a585e3d49e0859412d5563ee0e70f75f67f30919b1691d8d10f110179f542ab9637bdfe7c3a98d1f2cdf55285bce00f3d5629b4e675b7e24f0dbb3e4f3192da1daee7d1451902352248465d121c65b5fa22777631938d0c8cec706be69276f66a233e5d7948ae58b72839e53a057bca6a0f504fe69c72990232a261166 +M = c16ac0709423d9be78b3da2be4456be2b41aa4877ba7c3d106456298d1 + +ModInv = -1 +A = -2bd5156aec7e0dab30abc3ef17bddc0dae7a6db7f8e648b435d81ffd2642f2a3d3acf93220eff05b6b05d26256614c24812592d51508829e0ccb57df50b30970c5d3d5a1e412e69bc2d2dd698b41ba2ef2d2d7d38248f9a43d7dcfbceeb67bc344ed46a5fbfc2283af204fb11691a6c8c5b94c2cee26fe65982e8088f448d3f54068d28cacd3035e28d9951cf2c126f0ce68ca35e7938ca62badeea972543976fe542801fef1c5f6b2ffcdbdce04ba9a40ce42e46aa8a49d491a5f1a59a9badcb61223dfb819a5146af7b5f72a60a5528277bb89184c89928fa4f0cd451cb9fd137f7ec407f8 +M = 1027de65eb66230bf5b6dad020d9f21f1e8e2b85bacb3015b9d385 + +ModInv = -1 +A = -260465ec5a4030105ebc6cbadd1ce7ef2a92db40c34343f8b81e288b9e8dddd42ceffc6457af38fc6c9e573ba4884b4903b83bdbfab6739cb4df5f8aceac208b77d9a14422a4d4272b864c7b219eb692404494f8f25077993344f0cf256884a8427a8550ad420e8619845a85f2d3bc58a2c12114df36bc433cb6306eebe973e6c70e1ee6160953e22b624ce552529903fcc0060aee830c186b6ecd0a82186e413e0bd0a872ebb265b79116f8f473bab290bba7c8063d797761a4e5087e14a829afcb3233c4ce6219735e2320c47dd631778b2d69779f87ac73384fad7d834c70d80462ffd3dc +M = b69f128e4345e727ad7a9e8d6b9f332efdbb0ed2d0d0aa4022c71d + +ModInv = -1 +A = -6f372e05896adb3c5c2b76f4023b665c5d919019fe9f25e4e8b619dd91a5ce314060c71016f33e5178b9add46262006f46336ea390f051eb6b2cd21e1b0c3721d321c3d41ab5840ecc42912066f94b69661a50a5ca63879a98e501b10a2a389e79e74cf0b54ca60d3b196aeb98a98b4a3bdc06683c677c54f1c7698d92c1eeefcf50fe410d4c64b3b7388b7b28275f81fba6625c8cdd57a8a3b07b90f891677b9ac5b10e45ed03728cc3423ed61c5e1b43d7a86f42a7a53bd690e91f9066af401c6f4e8717f912e96b1a7a0160ad441a6947d715087d43eafbd8fa1a7b32b553d3d0e83ee1f893d3 +M = 6ba5d340c94ce4e6a6b898411481ce8924a277e4402ffb87ec + +ModInv = -1 +A = 1ab0a318d0114156d878233b283e50c4a2c4bdabd6e1c2444862007729b141f333227d6e9665726139b14e9fa3f7bfa7bfed17502541419bde3b0ee1c4f6e3b0d46735ab507a7ca85953bb33b80cc9c4239d3f54aa25e057e8231e74bc8c30fb6a22a763394f8288fa2356bf960a9d3d13e9130bd207cded07473a76f3f27b4b53b931604d85607179fec66b2ab1c7f93d6fb7fa1c382b3872363dd46abe18c723cb08a80a5033a23069be6605eb0869b4aa7655a34e17968a9fe40716debf36180f2697aa49b3cecfc29a02ba8a0b10612924e504fdcfedab705b6c6ed3da9b12bb46ac4a37a8c4 +M = ed10c5843e17bb24ee1cbb38d1201da828d257d34626495cdb + +ModInv = -1 +A = 23163d0cfa8f2f58f2a36def3dcc7aa6cfed029f069d2cccf47e2a0ba0de0e0c995274f2c159b24b81893ab978ed944f5f6101f9db2ccbf571e558fa1e12266540f23fa5d7a84c336f30b84d4cdfa29b399ba6f00457230f438bb863443191b6ab5f42b75c15a5e2c82fd180bd3a5d2435987531de42b3c1fc1a169939734bfea5d065bcf4d132223d267eb9949b7a45ae58eda91b5535b805e5ff4c91feabfdfc98e6a091bbc28ed49ffaff89548c216168f151fb2f19906311ab687f45640876a95f8ac491418f62ea70e18d3ca187d32d66d6073ec5ac3f538a9566ab5f111830618275f19ba063 +M = 5ebc20d0b9be0ee9720e2abb7f1f84eeb93add6e923c03c5 + +ModInv = -1 +A = -c02c1c4c12266e0a678b91762bb9acb8f12b41a70201f0095979af127aad62fdc1f8c3444de93cb483655d77b976dd67132c8648f37b47c92dc4a663e3107ee997cb628dd8c3dbe2d893bbaf7bf60739ad81310df3903c38e8cadb85bce5ba7e688824f408a2abd33b6c8b82ec55d74b810e7930c1d975cba3e366b36af27aacdebb241124dd70a85db4b04a3b6ef18d05c050f52c3856b2f7f30c798d5bc574da8d292813d1b6701aa6c4d42611023454cd5d7d2402bd1a3effae7e70314921e36ff834408cbe20c17c2a5b0a9801e031c92e139a50b05e54de64c52c81a6dd72a9f8d78864a49e1cfedd +M = cfb4e5213c289fea4ca3f7a879678dfb719f713ed60b + +ModInv = -1 +A = -ba037999c23ad15a30abad9d11f1cba27070d9342e3587dfbbc6f63efed585abaf926ada2d743eb1c691686ada2d4a0d860c2edcaba21b963f8d2293005f3ff1383132494409f10d1218d0ac4328ec74f4d519b20e54656c5a9096804f9d1858120329aba04205cf7d265188e6e1d8d84685bc8cac2ee4945331ce7ce5a54c34dc729c808feda44583f9a6c0eaa3ad0a7bbbd397a77ab0b31e0c3a1e358496cfbdb940487c7bedd6e49285a1c061fde3873f1eb46a7d68d5e054e5945983f0c9e17923be2eb26a8d24b86cd18d2121cee7728aa0bcd14cd7b435f07704f691ca92352867c3cacb26c7d163d1 +M = 6430fa0c6f04cf191b3df2828c4701155b30989d5e + +ModInv = -1 +A = -d255d1cb64c9e3b9072121875bdac633e4e6ecbc30da549883cdde80b89146b9f828f96ba4a4f74efd3bd79ed1bff2bbe5b0b941101cd926be1f91e3686d58a89576d53a71551a403d18579e1b9d442e534578b3f88d40b0c339f36bfa5ce49382b58dc881ce3f18a5acb114f68f6448b9d041cf57b5f2be676a658c560d58ba9bdbf91f05fcee2042ef70904faefa6adaaea854f0e0e6edeb0964da3d972e39bd78aebb6dac2918863f868f3b68011f8fd348c7c4cae8099a888765a8a848e2c227683c5aaba332e43f2d27f65c2a9707abc9dadbdb418d4c28fce231013f1d7c7d407b54b274ce1e9bb66351 +M = 36d4b45ba071a78dc74d132bb7883c3de7be4e64 + +ModInv = -1 +A = 1fc8892c8b76b05eab89b29ef571f38d43e1ffde92c88e9149912bfa4fd4fd6a235e311282a509928a8c2fd09530d896d3634f2f4b17cf6ea6721837520ed95985aae5bfd719eaff0d52892e366e554e504a6c7dfcf0587e73382c3d317d6a719f22f15edf5caaa3099a91eca7b5c0ab62b8278a3a1564cfab3b4909a854e9b1bab6aa1b3f827e894aef25133c931d82338150fbcf5b06aa665a2df49dcd9b635d1a4f04ed1b9edaa00f886b683d1faadc620b8c17f4da496f0529cf135794bacc6b36bb4610940f5fc9d021ca8fcefe170101073de5d98121336af914f5d1f99bcf98e4de91dc57364dd32c04 +M = 4dc1b8f67ba1a9cdd9985cee44c5030d71c8b4cd + +ModInv = -1 +A = -a4e062ded1dec668f74063438d6f7190abb052459203b95fcec4cac85b9c956ad42f7474bbf50e3d76e1232c5be7ab3be31e73b2311e9fbfb5c4a6a626e64b128b78c6813213551672b0a93262ca307eb4708875b3936146e4d299c85b8801dd978f0242fec5c485fb9761475a6fb14d6c353155d1d7d6e6f1363dfab52754499a5f54a53e605194d1887eeac887df897df79d7dd3d5f5c15507e62f90a4cffbce2dd00bb211d31a09dd6c2d103efa7a5870edfc572cd7335bec71bb046c2c024472a54e861a3795484004ad94bd3bf5143d0cf92d50413ea62b64e60a86989824fb88261fed5dc170614eeb11 +M = 617b5d0d4047bfc5d9dfc875c6eb66b26119e94d + +ModInv = -1 +A = -968c94d379859583fe85cf83bb6613a473e33c401f3246990843be097c5fb25b017b88ed06cd646b4be4b10bed763e972c8dfc34863e2d9b4baf2c7ade779c7cd30f1c2cdba687f8d1843faab949587c5d51c278405798d75b3a76e6a04ed6ac729ba94a39f4382dfa5424a3dacfbaa110c584ddcae5a351756d7249eb7ded293c7ef1ce3921e1083af546c5658b46a1888b967c1c396fbe344c9c0afe9cb5088fefd38a2b3c4812a8e4901ae3cb4f7c541140915275b9040735cb5c8da0a39c84edd0ee01deacc552756e7f9e7618dab04d06f18eceab4a0198d848af62c20fe0076fdf628369adbbd095b03e5e6769295c23dbdb674b2dff +M = be03e1235d355254 + +ModInv = -1 +A = b4760d34cc8d4461d0b7a49187914a0b797fcde45368ae83617b4483155593ad5731737c5f976d66c38c02ee2998cf43e904ff58d07777aa40b0dcd3d73a7a9038660874545fc94a531f3d346e703603aa1fdcedc20b61156eb2723422f7698431eb05ee568fbba2487d1c994377e93689d0a2be2675824f7a2dab07ad2513a6df930ffb960b8fab2442165d4d3425caa407b0b2b5da8d16fd652d254ff9b12feb8f12e954d03b2fec623878b527b3d2d476163f6112213eda14e1ed98f7607331cb7694f2f7854564bfbd729a4f045aceda33ab9f2cf03fff8102c32f4bea6258a6c55d78377f1f82f5264c3bd5467911e9f6e5011b6cc602d +M = ffd724aabbff43 + +ModInv = -1 +A = fc55066a141e1af9043c2deb778826081b2074fd19c48b0023c82f98148193b3f7944ab64995dd4bce865c1a6103c8e35f15d93a9748c5c82ead4b9dfacd23083c678d2789daa41eeb13b713cbd24fafa7ec283ac3ce94b23344c45f68ade2efa62162114cfd4c6c082701039264cc15391f40393e39c607c8aa609345fd4a5a7ef944e5a86b986b9ed422d7205842167f03bc6bf0f59275660d804a88a6bb1f9af4939fdbca826c455c184c3e7a3d35c17fe2928266e97d30c1df6d36e365e7e0ce0337fdb0a6c341a9f9c8fc32dbabf931a9aedd16f8a1726c825a7024644b8bf214f9a27047a53a8602eb743f03fd7c954258e4482eff239fc725 +M = 239414d1f6 + +ModInv = -1 +A = -73c3ac417e4d253a32129cf724606129b2a02be60004218bf65147e0546d156733329331dfe15cddbf9170cb1a4c6d6aa908a80726a8e0ef2ec5e86924d39b3e7fdc514557f9f092599bbde910446f1ad33e3084678fd2f856a0f9a1c0baf692a014fbdaf55095aadab5f90c31ecadf3ee73f433947efc1dcd2b24ab903d30cfba35533f5359d3bbc635fb09c15261f79827adc2a22272bf4c4c9cea461841cd917919f7c7ea3bd2887c9df1adf9d76ffb125621462092dddd4bf475acd10bf3d514fbbd8cb4299691eeb1316bf48fd32faed002e1e292877641aa9fa9d526ca59e01656388d727223e4727acefb7c236072de2f0add2835f2bce8a791 +M = 18cea336 + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +ModInv = -1 +A = -fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + diff --git a/test/recipes/99-test_fuzz_echconfiglist_parser.t b/test/recipes/11-test_fn.t similarity index 55% rename from test/recipes/99-test_fuzz_echconfiglist_parser.t rename to test/recipes/11-test_fn.t index 09e115caa6..d7a4b99fc0 100644 --- a/test/recipes/99-test_fuzz_echconfiglist_parser.t +++ b/test/recipes/11-test_fn.t @@ -1,4 +1,4 @@ -#!/usr/bin/env perl +#! /usr/bin/env perl # Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use @@ -10,16 +10,13 @@ use strict; use warnings; use OpenSSL::Test qw/:DEFAULT srctop_file/; -use OpenSSL::Test::Utils; +setup("test_fn"); -my $fuzzer = "echconfiglist_parser"; -setup("test_fuzz_${fuzzer}"); +my @files = qw( bnmul.txt bnshift.txt bnsum.txt bnmod.txt ); -plan skip_all => "This test requires ech support" - if disabled("ech"); +plan tests => scalar(@files); -plan tests => 2; # one more due to below require_ok(...) - -require_ok(srctop_file('test','recipes','fuzz.pl')); - -fuzz_ok($fuzzer); +foreach my $f (@files) { + ok(run(test(["fntest", srctop_file("test", "recipes", "10-test_bn_data", $f)])), + "running fntest $f"); +} diff --git a/test/recipes/03-test_sha3_x4_internal.t b/test/recipes/11-test_fn_api.t similarity index 56% rename from test/recipes/03-test_sha3_x4_internal.t rename to test/recipes/11-test_fn_api.t index 9e5793aaf3..293cd64822 100644 --- a/test/recipes/03-test_sha3_x4_internal.t +++ b/test/recipes/11-test_fn_api.t @@ -1,6 +1,5 @@ #! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# Copyright (c) 2026 Intel Corporation. All Rights Reserved. +# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -8,9 +7,8 @@ # https://www.openssl.org/source/license.html use strict; -use OpenSSL::Test; +use OpenSSL::Test; # get 'plan' use OpenSSL::Test::Simple; +setup("test_fn_api"); -setup("test_sha3_x4_internal"); - -simple_test("test_sha3_x4_internal", "sha3_x4_internal_test"); +simple_test("test_fn_api", "fn_api_test"); diff --git a/test/recipes/15-test_dsa.t b/test/recipes/15-test_dsa.t index c30cbfbbe3..b2747e3d46 100644 --- a/test/recipes/15-test_dsa.t +++ b/test/recipes/15-test_dsa.t @@ -17,7 +17,7 @@ use OpenSSL::Test::Utils; setup("test_dsa"); plan skip_all => 'DSA is not supported in this build' if disabled('dsa'); -plan tests => 11; +plan tests => 7; require_ok(srctop_file('test','recipes','tconversion.pl')); @@ -45,99 +45,3 @@ subtest "dsa conversions using 'openssl pkey' -- public key" => sub { -in => srctop_file("test","testdsapub.pem"), -args => ["pkey", "-pubin", "-pubout"] ); }; - -SKIP: { - skip "Skipping PVK conversion test", 1 - if disabled("rc4") || disabled("legacy") || disabled("pvkkdf"); - - subtest "dsa conversions using 'openssl dsa' -- PVK" => sub { - tconversion( -type => 'pvk', -prefix => 'dsa-pvk', - -in => srctop_file("test", "testdsa.pem"), - -args => ["dsa", "-passin", "pass:testpass", - "-passout", "pass:testpass", - "-provider", "default", - "-provider", "legacy"] ); - }; -} - -subtest "dsa -modulus prints the DSA public value" => sub { - plan tests => 2; - - # The public value (y) of the committed testdsa.pem / testdsapub.pem - # keypair, i.e. the "pub:" field of 'openssl pkey -text'. - my $expected = "Public Key=CC99A07D9817BFF03BB09B183E9B19EB77ABECF192" - . "C3A9FBA833DBE69EDB719A8E9777BB82736CEC6A8E4E2FAD0693ACC3D1456" - . "5D62710B95B02CC6A5CF091EEF9C22F20193EBE114C45A0B5E54A645037E8" - . "787FE01B3871508A25BDBF7C6B81428F89858F133FDB858C390C2EF7BCF7E" - . "41D7C66578F792A2488C787EF7C7D41"; - - my @priv = run(app(['openssl', 'dsa', '-modulus', '-noout', - '-in', srctop_file("test", "testdsa.pem")], - stderr => undef), - capture => 1); - chomp @priv; - ok(grep(/^\Q$expected\E$/, @priv), - "-modulus prints the expected public value for a private key"); - - my @pub = run(app(['openssl', 'dsa', '-pubin', '-modulus', '-noout', - '-in', srctop_file("test", "testdsapub.pem")], - stderr => undef), - capture => 1); - chomp @pub; - ok(grep(/^\Q$expected\E$/, @pub), - "-modulus prints the expected public value for a public key"); -}; - -subtest "dsa -text prints the key in text form" => sub { - plan tests => 6; - - # The private (x) and public (y) values of the committed testdsa.pem / - # testdsapub.pem keypair. -text prints them as colon-separated hex; we - # strip the formatting and compare against the known values so the actual - # key material, not just the labels, is verified. - my $priv_hex = "BF71D497B89755D0C5E41285D81F9577CC3DF8C2"; - my $pub_hex = "CC99A07D9817BFF03BB09B183E9B19EB77ABECF192C3A9FBA833DBE" - . "69EDB719A8E9777BB82736CEC6A8E4E2FAD0693ACC3D14565D62710B95B02CC" - . "6A5CF091EEF9C22F20193EBE114C45A0B5E54A645037E8787FE01B3871508A2" - . "5BDBF7C6B81428F89858F133FDB858C390C2EF7BCF7E41D7C66578F792A2488" - . "C787EF7C7D41"; - - my @priv = run(app(['openssl', 'dsa', '-text', '-noout', - '-in', srctop_file("test", "testdsa.pem")], - stderr => undef), - capture => 1); - chomp @priv; - my $priv_blob = uc join('', @priv); - $priv_blob =~ s/[^0-9A-F]//g; - ok(grep(/^Private-Key: \(1024 bit\)$/, @priv), - "-text prints the private key header"); - ok(index($priv_blob, $priv_hex) >= 0, - "-text prints the expected private value"); - ok(index($priv_blob, $pub_hex) >= 0, - "-text prints the expected public value for a private key"); - - my @pub = run(app(['openssl', 'dsa', '-pubin', '-text', '-noout', - '-in', srctop_file("test", "testdsapub.pem")], - stderr => undef), - capture => 1); - chomp @pub; - my $pub_blob = uc join('', @pub); - $pub_blob =~ s/[^0-9A-F]//g; - ok(grep(/^Public-Key: \(1024 bit\)$/, @pub), - "-text prints the public key header"); - ok(index($pub_blob, $pub_hex) >= 0, - "-text prints the expected public value for a public key"); - ok(!grep(/^priv:/, @pub), - "-text does not print a private component for a public key"); -}; - -subtest "dsa PVK output is rejected for public key input" => sub { - plan tests => 1; - - # Note: -noout would short-circuit before the format check, so request - # an actual encoding to reach the PVK-with-public-key rejection. - ok(!run(app(['openssl', 'dsa', '-pubin', '-outform', 'PVK', - '-in', srctop_file("test", "testdsapub.pem"), - '-out', 'dsa-pubin.pvk'])), - "-outform PVK with -pubin is rejected"); -}; diff --git a/test/recipes/15-test_dsaparam.t b/test/recipes/15-test_dsaparam.t index fe7a52d836..8f7d2af175 100644 --- a/test/recipes/15-test_dsaparam.t +++ b/test/recipes/15-test_dsaparam.t @@ -68,7 +68,7 @@ plan skip_all => "DSA isn't supported in this build" my @valid = glob(data_file("valid", "*.pem")); my @invalid = glob(data_file("invalid", "*.pem")); -my $num_tests = scalar @valid + scalar @invalid + 4; +my $num_tests = scalar @valid + scalar @invalid + 2; plan tests => $num_tests; foreach (@valid) { @@ -85,32 +85,3 @@ copy($input, $inout); ok(run(app(['openssl', 'dsaparam', '-in', $inout, '-out', $inout])), "identical infile and outfile"); ok(!compare_text($input, $inout), "converted file $inout did not change"); - -# Cover the DER (ASN.1) output paths of the dsaparam app. -my $srcparams = data_file("valid", "p1024_q160_t1862.pem"); -my $params_der = "dsaparam.der"; -my $key_der = "dsakey.der"; - -subtest "dsaparam DER parameter output" => sub { - plan tests => 2; - - # Exercises i2d_KeyParams_bio(). - ok(run(app(['openssl', 'dsaparam', '-in', $srcparams, - '-outform', 'DER', '-out', $params_der])), - "write DSA parameters in DER form"); - ok(run(app(['openssl', 'dsaparam', '-inform', 'DER', '-in', $params_der, - '-noout'])), - "read the DER DSA parameters back"); -}; - -subtest "dsaparam DER private key output with -genkey" => sub { - plan tests => 2; - - # Exercises i2d_PrivateKey_bio(). - ok(run(app(['openssl', 'dsaparam', '-in', $srcparams, '-genkey', - '-outform', 'DER', '-out', $key_der])), - "generate a DSA key and write it in DER form"); - ok(run(app(['openssl', 'pkey', '-inform', 'DER', '-in', $key_der, - '-noout', '-check'])), - "read the DER DSA private key back"); -}; diff --git a/test/recipes/15-test_ec.t b/test/recipes/15-test_ec.t index e3d18a8849..9bf946e81b 100644 --- a/test/recipes/15-test_ec.t +++ b/test/recipes/15-test_ec.t @@ -11,15 +11,14 @@ use strict; use warnings; use File::Spec; -use File::Compare qw(compare); -use OpenSSL::Test qw/:DEFAULT srctop_file data_file/; +use OpenSSL::Test qw/:DEFAULT srctop_file/; use OpenSSL::Test::Utils; setup("test_ec"); plan skip_all => 'EC is not supported in this build' if disabled('ec'); -plan tests => 19; +plan tests => 16; my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); @@ -103,104 +102,6 @@ SKIP: { }; } -subtest 'EC point conversion form (-conv_form)' => sub { - plan tests => 6; - - my $key = srctop_file("test", "testec-p256.pem"); - - ok(run(app(['openssl', 'ec', '-in', $key, '-pubout', - '-outform', 'DER', '-out', 'ec-conv-unc.der'])), - "writing public key with default (uncompressed) conversion form"); - ok(run(app(['openssl', 'ec', '-in', $key, '-pubout', - '-conv_form', 'compressed', - '-outform', 'DER', '-out', 'ec-conv-comp.der'])), - "writing public key with compressed conversion form"); - ok((-s 'ec-conv-comp.der') < (-s 'ec-conv-unc.der'), - "compressed point encoding is smaller than uncompressed"); - # The encodings are deterministic for a fixed key, so compare them - # against the checked-in reference files. - is(compare('ec-conv-unc.der', data_file('ec-conv-unc.der')), 0, - "uncompressed encoding matches the reference file"); - is(compare('ec-conv-comp.der', data_file('ec-conv-comp.der')), 0, - "compressed encoding matches the reference file"); - ok(!run(app(['openssl', 'ec', '-in', $key, '-noout', - '-conv_form', 'bogus'])), - "an invalid conversion form is rejected"); -}; - -subtest 'EC parameter encoding (-param_enc)' => sub { - plan tests => 6; - - my $key = srctop_file("test", "testec-p256.pem"); - - ok(run(app(['openssl', 'ec', '-in', $key, '-pubout', '-param_enc', - 'named_curve', '-outform', 'DER', '-out', 'ec-param-named.der'])), - "writing public key with named_curve parameter encoding"); - ok(run(app(['openssl', 'ec', '-in', $key, '-pubout', '-param_enc', - 'explicit', '-outform', 'DER', '-out', 'ec-param-explicit.der'])), - "writing public key with explicit parameter encoding"); - ok((-s 'ec-param-named.der') < (-s 'ec-param-explicit.der'), - "named_curve encoding is smaller than explicit"); - # The encodings are deterministic for a fixed key, so compare them - # against the checked-in reference files. - is(compare('ec-param-named.der', data_file('ec-param-named.der')), 0, - "named_curve encoding matches the reference file"); - is(compare('ec-param-explicit.der', data_file('ec-param-explicit.der')), 0, - "explicit encoding matches the reference file"); - ok(!run(app(['openssl', 'ec', '-in', $key, '-noout', - '-param_enc', 'bogus'])), - "an invalid parameter encoding is rejected"); -}; - -subtest 'ec -text prints the key in text form' => sub { - plan tests => 7; - - my $priv_key = srctop_file("test", "testec-p256.pem"); - my $pub_key = srctop_file("test", "testecpub-p256.pem"); - - # The private (priv) and public (pub) values of the committed - # testec-p256.pem / testecpub-p256.pem keypair. -text prints them as - # colon-separated hex; we strip the formatting and compare against the - # known values so the actual key material, not just the labels, is checked. - my $priv_hex = "36045F6C909612570C8C0113071FC809F6788084289C6AB003C60A" - . "17B2D5ADAD"; - my $pub_hex = "04257C007484E23C571252C6912369E5CD33519FEFAAE85DFC5EB1FC" - . "9BCB1FDBC0D0FB63A86F9494CEF823552D1EEF4A48A87E9B4970E03DCF262AD" - . "4ACF598B6E9"; - - # ec -text on the private key. - my @priv = run(app(['openssl', 'ec', '-text', '-noout', '-in', $priv_key], - stderr => undef), - capture => 1); - chomp @priv; - my $priv_blob = uc join('', @priv); - $priv_blob =~ s/[^0-9A-F]//g; - ok(grep(/^Private-Key: \(256 bit field, 128 bit security level\)$/, @priv), - "ec -text prints the private key header"); - ok(index($priv_blob, $priv_hex) >= 0, - "ec -text prints the expected private value"); - ok(index($priv_blob, $pub_hex) >= 0, - "ec -text prints the expected public value"); - ok(grep(/^ASN1 OID: prime256v1$/, @priv) - && grep(/^NIST CURVE: P-256$/, @priv), - "ec -text prints the curve identification"); - - # ec -text on the public key. - my @pub = run(app(['openssl', 'ec', '-pubin', '-text', '-noout', - '-in', $pub_key], - stderr => undef), - capture => 1); - chomp @pub; - my $pub_blob = uc join('', @pub); - $pub_blob =~ s/[^0-9A-F]//g; - ok(grep(/^Public-Key: \(256 bit field, 128 bit security level\)$/, @pub), - "ec -text prints the public key header"); - ok(index($pub_blob, $pub_hex) >= 0, - "ec -text prints the expected public value for a public key"); - ok(!grep(/^priv:/, @pub), - "ec -text does not print a private component for a public key"); -}; - subtest 'Check loading of fips and non-fips keys' => sub { plan skip_all => "FIPS is disabled" if $no_fips; diff --git a/test/recipes/15-test_ec_data/ec-conv-comp.der b/test/recipes/15-test_ec_data/ec-conv-comp.der deleted file mode 100644 index cdae088783..0000000000 Binary files a/test/recipes/15-test_ec_data/ec-conv-comp.der and /dev/null differ diff --git a/test/recipes/15-test_ec_data/ec-conv-unc.der b/test/recipes/15-test_ec_data/ec-conv-unc.der deleted file mode 100644 index 7a75bb5cf8..0000000000 Binary files a/test/recipes/15-test_ec_data/ec-conv-unc.der and /dev/null differ diff --git a/test/recipes/15-test_ec_data/ec-param-explicit.der b/test/recipes/15-test_ec_data/ec-param-explicit.der deleted file mode 100644 index e29a3a7208..0000000000 Binary files a/test/recipes/15-test_ec_data/ec-param-explicit.der and /dev/null differ diff --git a/test/recipes/15-test_ec_data/ec-param-named.der b/test/recipes/15-test_ec_data/ec-param-named.der deleted file mode 100644 index 7a75bb5cf8..0000000000 Binary files a/test/recipes/15-test_ec_data/ec-param-named.der and /dev/null differ diff --git a/test/recipes/15-test_ecparam.t b/test/recipes/15-test_ecparam.t index 169814b4e5..0d72154745 100644 --- a/test/recipes/15-test_ecparam.t +++ b/test/recipes/15-test_ecparam.t @@ -30,7 +30,7 @@ if (disabled("sm2")) { @valid = grep { !/sm2-.*\.pem/} @valid; } -plan tests => 16; +plan tests => 14; sub checkload { my $files = shift; # List of files @@ -199,62 +199,4 @@ subtest "Check loading of fips and non-fips params" => sub { $ENV{OPENSSL_CONF} = $defaultconf; }; -subtest "Check ecparam -param_enc converts between named and explicit" => sub { - plan tests => 3; - - my $named = data_file('valid', 'secp384r1-named.pem'); - my $explicit = data_file('valid', 'secp384r1-explicit.pem'); - - # The encodings are canonical, so re-encoding a named curve as explicit - # (and vice versa) must reproduce the matching reference file byte for byte. - my $to_explicit = 'param-explicit.tst'; - ok(run(app(['openssl', 'ecparam', '-in', $named, '-param_enc', 'explicit', - '-out', $to_explicit])) - && !compare($to_explicit, $explicit), - "named_curve params re-encoded as explicit match the reference file"); - - my $to_named = 'param-named.tst'; - ok(run(app(['openssl', 'ecparam', '-in', $explicit, '-param_enc', - 'named_curve', '-out', $to_named])) - && !compare($to_named, $named), - "explicit params re-encoded as named_curve match the reference file"); - - ok(!run(app(['openssl', 'ecparam', '-in', $named, '-noout', - '-param_enc', 'bogus'])), - "an invalid parameter encoding is rejected"); -}; - -subtest "Check ecparam -text prints the parameters in text form" => sub { - plan tests => 6; - - my $named = data_file('valid', 'secp384r1-named.pem'); - my $explicit = data_file('valid', 'secp384r1-explicit.pem'); - - # Named parameters print the curve identification. - my @named = run(app(['openssl', 'ecparam', '-text', '-noout', '-in', $named], - stderr => undef), - capture => 1); - chomp @named; - ok(grep(/^EC-Parameters: \(384 bit field, 192 bit security level\)$/, @named), - "named parameters print the EC-Parameters header"); - ok(grep(/^ASN1 OID: secp384r1$/, @named), - "named parameters print the expected curve OID"); - ok(grep(/^NIST CURVE: P-384$/, @named), - "named parameters print the expected NIST curve name"); - - # Explicit parameters print the field parameters instead of the curve name. - my @explicit = run(app(['openssl', 'ecparam', '-text', '-noout', - '-in', $explicit], - stderr => undef), - capture => 1); - chomp @explicit; - ok(grep(/^EC-Parameters: \(384 bit field, 192 bit security level\)$/, @explicit), - "explicit parameters print the EC-Parameters header"); - ok(grep(/^Field Type: prime-field$/, @explicit) - && grep(/^Cofactor:/, @explicit), - "explicit parameters print the field parameters"); - ok(!grep(/^ASN1 OID:/, @explicit), - "explicit parameters do not print a curve OID"); -}; - ok(run(app(['openssl', 'ecparam', '-list_curves'])), "Test -list_curves"); diff --git a/test/recipes/15-test_genpkey.t b/test/recipes/15-test_genpkey.t index ddef803ff1..b918f73f9f 100644 --- a/test/recipes/15-test_genpkey.t +++ b/test/recipes/15-test_genpkey.t @@ -9,7 +9,7 @@ use strict; use warnings; -use OpenSSL::Test qw/:DEFAULT with/; +use OpenSSL::Test qw/:DEFAULT/; use OpenSSL::Test::Utils; setup("test_genpkey"); @@ -22,7 +22,7 @@ push @algs, qw(EC) unless disabled("ec"); push @algs, qw(X25519 X448) unless disabled("ecx"); push @algs, qw(SM2) unless disabled("sm2"); -plan tests => scalar(@algs) + 2; +plan tests => scalar(@algs); foreach (@algs) { my $alg = $_; @@ -30,40 +30,3 @@ foreach (@algs) { ok(run(app([ 'openssl', 'genpkey', '-algorithm', $alg, '-help'])), "show genpkey pkeyopt values for $alg"); } - -SKIP: { - skip "RSA is not supported by this OpenSSL build", 1 if disabled("rsa"); - - subtest "genpkey with a cipher encrypts the private key" => sub { - plan tests => 3; - - my $key = "genpkey_enc.pem"; - - ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA', - '-pkeyopt', 'rsa_keygen_bits:512', - '-aes256', '-pass', 'pass:secret', '-out', $key])), - "Generate an AES-256 encrypted RSA key"); - ok(run(app(['openssl', 'pkey', '-in', $key, - '-passin', 'pass:secret', '-noout'])), - "Read the encrypted key back with the correct passphrase"); - # A wrong passphrase must not decrypt the key. - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'pkey', '-in', $key, - '-passin', 'pass:wrong', '-noout'])), - "Reading with a wrong passphrase fails"); - }); - }; -} - -SKIP: { - skip "DSA is not supported by this OpenSSL build", 1 if disabled("dsa"); - - # A cipher only encrypts a private key, so it is rejected with -genparam. - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'genpkey', '-genparam', '-algorithm', 'DSA', - '-pkeyopt', 'dsa_paramgen_bits:512', '-aes256'])), - "Cannot use a cipher with -genparam"); - }); -} diff --git a/test/recipes/15-test_ml_dsa_codecs.t b/test/recipes/15-test_ml_dsa_codecs.t index 16fc5c3021..f5b5134c8a 100644 --- a/test/recipes/15-test_ml_dsa_codecs.t +++ b/test/recipes/15-test_ml_dsa_codecs.t @@ -26,7 +26,7 @@ my @formats = qw(seed-priv priv-only seed-only oqskeypair bare-seed bare-priv); plan skip_all => "ML-DSA isn't supported in this build" if disabled("ml-dsa"); -plan tests => @algs * (27 + 13 * @formats); +plan tests => @algs * (26 + 10 * @formats); my $seed = join ("", map {sprintf "%02x", $_} (0..31)); my $weed = join ("", map {sprintf "%02x", $_} (1..32)); my $ikme = join ("", map {sprintf "%02x", $_} (0..31)); @@ -45,12 +45,6 @@ foreach my $alg (@algs) { my $der0 = sprintf("pub-%s.%d.der", $alg, $i++); ok(run(app(['openssl', 'pkey', '-pubin', '-in', $in0, '-outform', 'DER', '-out', $der0]))); - - # Default encoding (no -encopt) is seed-priv; used as a control below. - my $plain = sprintf("prv-%s.plain.pem", $alg); - ok(run(app(['openssl', 'pkey', '-in', data_file($formats{'seed-priv'}), - '-out', $plain])), - sprintf("pkey default re-encode: %s", $alg)); foreach my $f (keys %formats) { my $kf = $formats{$f}; my %pruned = %formats; @@ -77,20 +71,6 @@ foreach my $alg (@algs) { '-provparam', "ml-dsa.input_formats=$f"]))); ok(!run(app(['openssl', 'pkey', '-in', $in, '-noout', '-provparam', "ml-dsa.input_formats=$rest"]))); - - # Re-encode the seed-priv key into format $f via 'pkey -encopt' and - # check it matches the reference; the control asserts the match is due - # to -encopt, i.e. it differs from the default for every non-seed-priv - # format (and equals it for seed-priv). - my $enc = sprintf("prv-%s-%s.enc.pem", $alg, $f); - ok(run(app(['openssl', 'pkey', '-in', data_file($formats{'seed-priv'}), - '-encopt', "output_formats:$f", '-out', $enc])), - sprintf("pkey -encopt re-encode: %s, %s", $alg, $f)); - ok(!compare_text($in, $enc), - sprintf("pkey -encopt output_formats match: %s, %s", $alg, $f)); - ok($f eq 'seed-priv' ? compare_text($plain, $enc) == 0 - : compare_text($plain, $enc) != 0, - sprintf("pkey -encopt changed the encoding: %s, %s", $alg, $f)); } # (1 + 2 * @formats) tests diff --git a/test/recipes/15-test_pkey.t b/test/recipes/15-test_pkey.t index fa4363f057..c61b0548a3 100644 --- a/test/recipes/15-test_pkey.t +++ b/test/recipes/15-test_pkey.t @@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; setup("test_pkey"); -plan tests => 7; +plan tests => 6; my @app = ('openssl', 'pkey'); @@ -112,32 +112,20 @@ subtest "=== pkey handling of DER encoding ===" => sub { "Same file contents after converting to DER and back"); }; -subtest "=== pkey text and text_pub output ===" => sub { - plan tests => 6; +subtest "=== pkey text output ===" => sub { + plan tests => 3; ok((grep /BEGIN PRIVATE KEY/, run(app([@app, '-in', $in_key, '-text']), capture => 1)), "pkey text output contains PEM header"); ok(!(grep /BEGIN PRIVATE KEY/, - run(app([@app, '-in', $in_key, '-text', '-noout']), capture => 1)), - "pkey text output with -noout does not contain PEM header"); + run(app([@app, '-in', $in_key, '-text', '-noout']), capture => 1)), + "pkey text output with -noout does not contain PEM header"); ok((grep /Private-Key:/, run(app([@app, '-in', $in_key, '-text', '-noout']), capture => 1)), "pkey text output (even with -noout) contains \"Private-Key:\""); - - ok(!(grep /Private-Key:/, - run(app([@app, '-in', $in_key, '-text_pub', '-noout']), capture => 1)), - "-text_pub does not print private key components"); - - ok((grep /Public-Key:/, - run(app([@app, '-in', $in_key, '-text_pub', '-noout']), capture => 1)), - "-text_pub prints public key components"); - - ok(!run(app([@app, '-in', $in_key, '-text', '-outform', 'DER', - '-out', 'text_der.tmp'])), - "-text combined with DER output is rejected"); }; subtest "=== pkey EC point conversion form ===" => sub { @@ -183,37 +171,3 @@ subtest "=== pkey EC point conversion form ===" => sub { ok(!run(app([@app, '-in', $in_key, '-ec_conv_form', 'compressed', '-noout'])), "-ec_conv_form on a non-EC key fails"); }; - -subtest "=== pkey EC parameter encoding ===" => sub { - plan skip_all => "EC not supported in this build" if disabled("ec"); - plan tests => 6; - - my $ec_key = 'ec_p256_enc.pem'; - ok(run(app(['openssl', 'genpkey', '-algorithm', 'EC', - '-pkeyopt', 'ec_paramgen_curve:P-256', '-out', $ec_key])), - "generate P-256 EC key"); - - # A named_curve encoding identifies the group by its OID (prime256v1), - # whereas an explicit encoding inlines the full curve parameters, which - # asn1parse shows via the field-type OID (prime-field). - my $named = 'pub_named.der'; - ok(run(app([@app, '-in', $ec_key, '-pubout', '-ec_param_enc', 'named_curve', - '-outform', 'DER', '-out', $named])), - "write public key with named_curve parameters"); - ok((grep /prime256v1/, - run(app(['openssl', 'asn1parse', '-in', $named, '-inform', 'DER']), - capture => 1)), - "named_curve encoding references the curve by OID"); - - my $explicit = 'pub_explicit.der'; - ok(run(app([@app, '-in', $ec_key, '-pubout', '-ec_param_enc', 'explicit', - '-outform', 'DER', '-out', $explicit])), - "write public key with explicit parameters"); - ok((grep /prime-field/, - run(app(['openssl', 'asn1parse', '-in', $explicit, '-inform', 'DER']), - capture => 1)), - "explicit encoding inlines the curve parameters"); - - ok(!run(app([@app, '-in', $in_key, '-ec_param_enc', 'explicit', '-noout'])), - "-ec_param_enc on a non-EC key fails"); -}; diff --git a/test/recipes/15-test_rsa.t b/test/recipes/15-test_rsa.t index c7eafbfb1c..851814e8af 100644 --- a/test/recipes/15-test_rsa.t +++ b/test/recipes/15-test_rsa.t @@ -11,13 +11,12 @@ use strict; use warnings; use File::Spec; -use File::Compare qw/compare/; use OpenSSL::Test qw/:DEFAULT srctop_file/; use OpenSSL::Test::Utils; setup("test_rsa"); -plan tests => 17; +plan tests => 14; require_ok(srctop_file('test', 'recipes', 'tconversion.pl')); @@ -27,53 +26,6 @@ run_rsa_tests("pkey"); run_rsa_tests("rsa"); -SKIP: { - skip "RSA is not supported in this build", 1 if disabled("rsa"); - - subtest "rsa -text prints the key in text form" => sub { - plan tests => 6; - - # The modulus (n) and private exponent (d) of the committed - # testrsa.pem keypair. -text prints them as colon-separated hex; we - # strip the formatting and compare against the known values so the - # actual key material, not just the labels, is verified. - my $modulus = "AADB7AA92E464F15711996166B4FF8BBE2301DFEE9D8B3596DC3" - . "C1A7DFCE7C87180170509FC84EFD17B5BB02CA5DD0A3228686B380CB746F" - . "3CAE4CDFC8AE5D3D"; - my $priv_exp = "677727CDA1D733F6F119A479091D51AC3D6A1410157E840588E1" - . "FDB8F26031AA00BA84048AC3C755C64329C3AFE30120EBF4C89C02170671" - . "2282DAAF473BB2A1"; - - my @priv = run(app(['openssl', 'rsa', '-text', '-noout', - '-in', srctop_file("test", "testrsa.pem")], - stderr => undef), - capture => 1); - chomp @priv; - my $priv_blob = uc join('', @priv); - $priv_blob =~ s/[^0-9A-F]//g; - ok(grep(/^Private-Key: \(512 bit, 2 primes\)$/, @priv), - "-text prints the private key header"); - ok(index($priv_blob, $modulus) >= 0, - "-text prints the expected modulus for a private key"); - ok(index($priv_blob, $priv_exp) >= 0, - "-text prints the expected private exponent"); - - my @pub = run(app(['openssl', 'rsa', '-pubin', '-text', '-noout', - '-in', srctop_file("test", "testrsapub.pem")], - stderr => undef), - capture => 1); - chomp @pub; - my $pub_blob = uc join('', @pub); - $pub_blob =~ s/[^0-9A-F]//g; - ok(grep(/^Public-Key: \(512 bit\)$/, @pub), - "-text prints the public key header"); - ok(index($pub_blob, $modulus) >= 0, - "-text prints the expected modulus for a public key"); - ok(!grep(/privateExponent/, @pub), - "-text does not print a private exponent for a public key"); - }; -} - sub run_rsa_tests { my $cmd = shift; @@ -102,7 +54,7 @@ sub run_rsa_tests { SKIP: { skip "Skipping msblob conversion test", 1 - if disabled("rsa") || $cmd eq 'pkey'; + if disabled($cmd) || $cmd eq 'pkey'; subtest "$cmd conversions -- public key" => sub { tconversion( -type => 'msb', -prefix => "$cmd-msb-pub", @@ -112,7 +64,7 @@ sub run_rsa_tests { } SKIP: { skip "Skipping PVK conversion test", 1 - if disabled("rsa") || $cmd eq 'pkey' || disabled("rc4") + if disabled($cmd) || $cmd eq 'pkey' || disabled("rc4") || disabled ("legacy") || disabled("pvkkdf"); subtest "$cmd conversions -- private key" => sub { @@ -124,59 +76,4 @@ sub run_rsa_tests { "-provider", "legacy"] ); }; } - - SKIP: { - # -RSAPublicKey_in/-RSAPublicKey_out are specific to the rsa app and - # select the PKCS#1 RSAPublicKey structure instead of the - # SubjectPublicKeyInfo used by -pubin/-pubout. - skip "Skipping RSAPublicKey conversion test", 1 - if disabled("rsa") || $cmd eq 'pkey'; - - subtest "$cmd conversions -- RSAPublicKey (PKCS#1) public key" => sub { - plan tests => 9; - - my $priv = srctop_file("test", "testrsa.pem"); - my $pub = srctop_file("test", "testrsapub.pem"); - - my $rsapub = "$cmd-rsapub.pem"; - ok(run(app(['openssl', 'rsa', '-in', $priv, '-RSAPublicKey_out', - '-out', $rsapub])), - "RSAPublicKey_out writes a public key"); - open(my $fh, '<', $rsapub); - my @rsapub_pem = <$fh>; - close($fh); - ok(grep(/BEGIN RSA PUBLIC KEY/, @rsapub_pem), - "RSAPublicKey_out uses the PKCS#1 RSA PUBLIC KEY header"); - - # Re-encoding an RSAPublicKey input as RSAPublicKey is stable. - my $rsapub2 = "$cmd-rsapub2.pem"; - ok(run(app(['openssl', 'rsa', '-in', $rsapub, '-RSAPublicKey_in', - '-RSAPublicKey_out', '-out', $rsapub2])), - "RSAPublicKey_in reads an RSAPublicKey"); - is(compare($rsapub, $rsapub2), 0, - "RSAPublicKey_in round-trips to an identical RSAPublicKey"); - - # RSAPublicKey input re-encoded as SubjectPublicKeyInfo matches the - # canonical SubjectPublicKeyInfo public key. - my $spki1 = "$cmd-spki1.pem"; - my $spki2 = "$cmd-spki2.pem"; - ok(run(app(['openssl', 'rsa', '-in', $rsapub, '-RSAPublicKey_in', - '-pubout', '-out', $spki1])), - "RSAPublicKey_in can be written as SubjectPublicKeyInfo"); - ok(run(app(['openssl', 'rsa', '-in', $pub, '-pubin', '-pubout', - '-out', $spki2])), - "canonical SubjectPublicKeyInfo public key written"); - is(compare($spki1, $spki2), 0, - "RSAPublicKey_in -pubout matches the SubjectPublicKeyInfo key"); - - # Conversely, a SubjectPublicKeyInfo input written as RSAPublicKey - # matches the RSAPublicKey extracted from the private key. - my $rsapub3 = "$cmd-rsapub3.pem"; - ok(run(app(['openssl', 'rsa', '-in', $pub, '-pubin', - '-RSAPublicKey_out', '-out', $rsapub3])), - "SubjectPublicKeyInfo input can be written as RSAPublicKey"); - is(compare($rsapub, $rsapub3), 0, - "pubin -RSAPublicKey_out matches the extracted RSAPublicKey"); - }; - } } diff --git a/test/recipes/20-test_app_s_client_msg.t b/test/recipes/20-test_app_s_client_msg.t deleted file mode 100644 index 75d388efe8..0000000000 --- a/test/recipes/20-test_app_s_client_msg.t +++ /dev/null @@ -1,110 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use strict; -use warnings; - -use IPC::Open3; -use OpenSSL::Test qw/:DEFAULT result_dir srctop_file bldtop_file/; -use OpenSSL::Test::Utils; - -my $test_name = "test_app_s_client_msg"; -setup($test_name); - -plan skip_all => "$test_name needs sock enabled" - if disabled("sock"); -plan skip_all => "$test_name is not available on Windows or VMS" - if $^O =~ /^(VMS|MSWin32|msys)$/; - -my $shlib_wrap = bldtop_file("util", "wrap.pl"); -my $apps_openssl = bldtop_file("apps", "openssl"); -my $server_pem = srctop_file("test", "certs", "servercert.pem"); -my $server_key = srctop_file("test", "certs", "serverkey.pem"); -my $resultdir = result_dir(); - -# Each case exercises the s_client message callback (-msg) over a different -# protocol version. Every record must be decoded; before the DTLSv1.2 fix such -# records were logged as "Not TLS data or unknown version". -my @cases = ( - { name => "TLSv1.2", flag => "-tls1_2", disabled => "tls1_2" }, - { name => "TLSv1.3", flag => "-tls1_3", disabled => "tls1_3" }, - { name => "DTLSv1.2", flag => "-dtls1_2", disabled => "dtls1_2" }, -); -@cases = grep { !disabled($_->{disabled}) } @cases; - -plan tests => scalar @cases; - -# Run one s_server/s_client handshake logging protocol messages via -msgfile. -# Returns the number of decoded and undecoded records seen in the log. -sub run_case -{ - my $case = shift; - my $msgfile = "$resultdir/s_client-msg-$case->{disabled}.txt"; - my ($records, $unknown) = (0, 0); - - eval { - local $SIG{ALRM} = sub { die "timeout\n" }; - alarm 60; - - # Start a server speaking just this protocol version - my @s_server_cmd = ("s_server", $case->{flag}, "-accept", "0", - "-naccept", "1", "-cert", $server_pem, - "-key", $server_key); - my $s_server_pid = open3(my $s_server_i, my $s_server_o, my $s_server_e, - $shlib_wrap, $apps_openssl, @s_server_cmd); - - # Figure out what port it is listening on - my $server_port = "0"; - while (<$s_server_o>) { - print($_); - chomp; - if (/^ACCEPT \S+?:(\d+)/) { - $server_port = $1; - last; - } elsif (/^Using default/) { - ; - } else { - last; - } - } - - # Connect a client that logs the protocol messages to a file. -msgfile - # sets the log destination but selects SSL_trace; the trailing -msg - # switches the callback back to msg_cb (the code under test) while - # keeping the file destination. - my @s_client_cmd = ("s_client", $case->{flag}, "-msgfile", $msgfile, - "-msg", "-connect", "localhost:$server_port"); - my $s_client_pid = open3(my $s_client_i, my $s_client_o, my $s_client_e, - $shlib_wrap, $apps_openssl, @s_client_cmd); - - # Quit the client once connected, then reap both processes - print $s_client_i "Q\n"; - waitpid($s_client_pid, 0); - kill 'HUP', $s_server_pid if kill 0, $s_server_pid; - waitpid($s_server_pid, 0); - - alarm 0; - }; - die $@ if $@ && $@ ne "timeout\n"; - print("TIMEOUT: $case->{name} timed out\n") if $@; - - if (open(my $fh, '<', $msgfile)) { - while (<$fh>) { - $records++ if /^(?:>>>|<<<)/; - $unknown++ if /Not TLS data or unknown version/; - } - close($fh); - } - return ($records, $unknown); -} - -foreach my $case (@cases) { - my ($records, $unknown) = run_case($case); - ok($records > 0 && $unknown == 0, - "s_client -msg decodes all $case->{name} records"); -} diff --git a/test/recipes/20-test_dgst.t b/test/recipes/20-test_dgst.t index 00af8cfff2..e287bd32ff 100644 --- a/test/recipes/20-test_dgst.t +++ b/test/recipes/20-test_dgst.t @@ -18,7 +18,7 @@ use Cwd qw(abs_path); setup("test_dgst"); -plan tests => 27; +plan tests => 25; sub tsignverify { my $testtext = shift; @@ -424,53 +424,6 @@ subtest "signing with xoflen is not supported `dgst` CLI" => sub { "Generating signature with xoflen should fail"); }; -subtest "Listing supported digests with `dgst` CLI" => sub { - plan tests => 3; - - my @listdata = run(app(['openssl', 'dgst', '-list']), capture => 1); - chomp(@listdata); - my $listing = join("\n", @listdata); - - ok($listing =~ /Supported digests:/, "LIST: Check header is printed"); - # Only check digests that are always present, each printed as "-" - ok($listing =~ /-sha256\b/, "LIST: Check sha256 is listed"); - ok($listing =~ /-sha512\b/, "LIST: Check sha512 is listed"); -}; - -subtest "signing and verifying with DER `-keyform` `dgst` CLI" => sub { - if (disabled("rsa")) { - plan tests => 1; - ok(1, "Skipped (RSA not supported)"); - return; - } - plan tests => 4; - - my $data_to_sign = srctop_file('test', 'data.bin'); - my $privkey_pem = srctop_file("test", "testrsa.pem"); - my $pubkey_pem = srctop_file("test", "testrsapub.pem"); - my $privkey_der = "testrsa-keyform.der"; - my $pubkey_der = "testrsapub-keyform.der"; - my $sigfile = "testrsa-keyform.sig"; - - # Convert the keys to DER so the `-keyform DER` code path can be exercised. - ok(run(app(['openssl', 'pkey', '-in', $privkey_pem, - '-outform', 'DER', '-out', $privkey_der])), - "Convert private key to DER"); - ok(run(app(['openssl', 'pkey', '-in', $pubkey_pem, '-pubin', - '-outform', 'DER', '-pubout', '-out', $pubkey_der])), - "Convert public key to DER"); - - ok(run(app(['openssl', 'dgst', '-sign', $privkey_der, '-keyform', 'DER', - '-out', $sigfile, - $data_to_sign])), - "Generating signature with DER private key via -keyform"); - - ok(run(app(['openssl', 'dgst', '-verify', $pubkey_der, '-keyform', 'DER', - '-signature', $sigfile, - $data_to_sign])), - "Verify signature with DER public key via -keyform"); -}; - subtest "signing using the nonce-type sigopt" => sub { if (disabled("ec")) { plan tests => 1; diff --git a/test/recipes/20-test_kdf.t b/test/recipes/20-test_kdf.t index 8d926d68b3..55767871d6 100755 --- a/test/recipes/20-test_kdf.t +++ b/test/recipes/20-test_kdf.t @@ -75,26 +75,12 @@ my @sskdf_tests = ( desc => 'SSKDF HMAC SHA256'}, ); -my @krb5kdf_tests = ( - { cmd => [qw{openssl kdf -keylen 16 -cipher AES-128-CBC -kdfopt hexkey:42263C6E89F4FC28B8DF68EE09799F15 -kdfopt hexconstant:0000000299 KRB5KDF}], - expected => '34:28:0A:38:2B:C9:27:69:B2:DA:2F:9E:F0:66:85:4B', - desc => 'KRB5KDF AES-128-CBC'}, - { cmd => [qw{openssl kdf -keylen 32 -cipher AES-256-CBC -kdfopt hexkey:FE697B52BC0D3CE14432BA036A92E65BBB52280990A2FA27883998D72AF30161 -kdfopt hexconstant:0000000299 KRB5KDF}], - expected => 'BF:AB:38:8B:DC:B2:38:E9:F9:C9:8D:6A:87:83:04:F0:4D:30:C8:25:56:37:5A:C5:07:A7:A8:52:79:0F:46:74', - desc => 'KRB5KDF AES-256-CBC'}, - # Using the -kdfopt cipher: option instead of -cipher - { cmd => [qw{openssl kdf -keylen 16 -kdfopt cipher:AES-128-CBC -kdfopt hexkey:42263C6E89F4FC28B8DF68EE09799F15 -kdfopt hexconstant:0000000299 KRB5KDF}], - expected => '34:28:0A:38:2B:C9:27:69:B2:DA:2F:9E:F0:66:85:4B', - desc => 'KRB5KDF AES-128-CBC'}, -); - my @scrypt_tests = ( { cmd => [qw{openssl kdf -keylen 64 -kdfopt pass:password -kdfopt salt:NaCl -kdfopt n:1024 -kdfopt r:8 -kdfopt p:16 -kdfopt maxmem_bytes:10485760 id-scrypt}], expected => 'fd:ba:be:1c:9d:34:72:00:78:56:e7:19:0d:01:e9:fe:7c:6a:d7:cb:c8:23:78:30:e7:73:76:63:4b:37:31:62:2e:af:30:d9:2e:22:a3:88:6f:f1:09:27:9d:98:30:da:c7:27:af:b9:4a:83:ee:6d:83:60:cb:df:a2:cc:06:40', desc => 'SCRYPT' }, ); -push @kdf_tests, @krb5kdf_tests unless disabled("krb5kdf"); push @kdf_tests, @scrypt_tests unless disabled("scrypt"); push @kdf_tests, @sshkdf_tests unless disabled("sshkdf"); push @kdf_tests, @sskdf_tests unless disabled("sskdf"); diff --git a/test/recipes/20-test_pkeyutl.t b/test/recipes/20-test_pkeyutl.t index dec9b4b183..09797eb321 100644 --- a/test/recipes/20-test_pkeyutl.t +++ b/test/recipes/20-test_pkeyutl.t @@ -17,7 +17,7 @@ use File::Compare qw/compare_text compare/; setup("test_pkeyutl"); -plan tests => 33; +plan tests => 30; # For the tests below we use the cert itself as the TBS file @@ -187,42 +187,6 @@ SKIP: { "-pkeyopt", "rsa_padding_mode:pss"); }; - subtest "pkeyutl -rev reverses the input buffer" => sub { - plan tests => 4; - - my $key = srctop_file("test", "testrsa.pem"); - my $in = "rev_in.bin"; - my $in_rev = "rev_in_reversed.bin"; - - # A non-palindromic input, short enough to be signed as a raw digest. - my $data = "0123456789abcdefghijklmnopqrstuv"; - open(my $fh, '>:raw', $in) or die "cannot create $in: $!"; - print $fh $data; - close($fh); - open($fh, '>:raw', $in_rev) or die "cannot create $in_rev: $!"; - print $fh scalar reverse $data; - close($fh); - - # RSA signing is deterministic, so signing with -rev must match signing - # the manually reversed input. - ok(run(app(['openssl', 'pkeyutl', '-sign', '-inkey', $key, - '-rev', '-in', $in, '-out', 'rev.sig'])), - "Sign with -rev"); - ok(run(app(['openssl', 'pkeyutl', '-sign', '-inkey', $key, - '-in', $in_rev, '-out', 'rev_manual.sig'])), - "Sign the manually reversed input"); - is(compare('rev.sig', 'rev_manual.sig'), 0, - "-rev signature matches signing the reversed input"); - - # -rev is rejected together with raw input. - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'pkeyutl', '-sign', '-inkey', $key, - '-rawin', '-digest', 'sha256', '-rev', '-in', $in])), - "-rev cannot be used with -rawin"); - }); - }; - } SKIP: { @@ -250,7 +214,7 @@ SKIP: { } SKIP: { - skip "EdDSA is not supported by this OpenSSL build", 7 + skip "EdDSA is not supported by this OpenSSL build", 6 if disabled("ecx"); subtest "pkeyutl -rawin oneshot with file input (mmap or buffer path)" => sub { @@ -309,42 +273,7 @@ SKIP: { unlink($stderr_file) if -f $stderr_file; }; - subtest "pkeyutl -rawin oneshot with empty file (buffer path, filesize 0)" => sub { - my $ed25519_key = srctop_file("test", "tested25519.pem"); - my $ed25519_pub = srctop_file("test", "tested25519pub.pem"); - my $empty = "pkeyutl_empty.bin"; - my $sigfile = "rawin_empty_ed25519.sig"; - # Ed25519 is deterministic, so signing the empty message with - # tested25519.pem always yields this exact signature. - my $expected_sig = - "42a443bd375c962f571dbf7402654219655b30c395dee06e" . - "d2a4a41342686da620889e374807266a3aab535345985c96" . - "cbb7475c8b0df47968d29fbf3d352e0c"; - - plan tests => 3; - - # create a zero-length input file - open(my $fh, '>', $empty) or die "cannot create $empty: $!"; - close($fh); - - ok(run(app(['openssl', 'pkeyutl', '-sign', '-rawin', '-inkey', $ed25519_key, - '-in', $empty, '-out', $sigfile])), - "Ed25519 -rawin sign from empty file (filesize 0 buffer path)"); - ok(run(app(['openssl', 'pkeyutl', '-verify', '-rawin', '-pubin', '-inkey', $ed25519_pub, - '-sigfile', $sigfile, '-in', $empty])), - "Ed25519 -rawin verify from empty file"); - - # check the produced signature matches the known reference value - open(my $sfh, '<:raw', $sigfile) or die "cannot open $sigfile: $!"; - read($sfh, my $sig, -s $sigfile); - close($sfh); - is(unpack("H*", $sig), $expected_sig, - "Ed25519 -rawin empty file signature matches the reference value"); - - unlink($empty); - }; - - subtest "Ed25519 CLI signature generation and verification" => sub { + subtest "Ed2559 CLI signature generation and verification" => sub { tsignverify("Ed25519", srctop_file("test","tested25519.pem"), srctop_file("test","tested25519pub.pem"), @@ -358,7 +287,7 @@ SKIP: { "-rawin"); }; - subtest "Ed25519 CLI signature generation and verification, no -rawin" => sub { + subtest "Ed2559 CLI signature generation and verification, no -rawin" => sub { tsignverify("Ed25519", srctop_file("test","tested25519.pem"), srctop_file("test","tested25519pub.pem")); @@ -441,52 +370,3 @@ subtest "pkeyutl -pkeyopt_passin" => sub { "Fail on unknown pkey option via passin"); }); }; - -SKIP: { - skip "EC is not supported by this OpenSSL build", 1 - if disabled("ec"); - - subtest "pkeyutl -derive peer key setup" => sub { - my $eckey = srctop_file("test", "testec-p256.pem"); - my $ecpub = srctop_file("test", "testecpub-p256.pem"); - my $rsapub = srctop_file("test", "testrsapub.pem"); - - plan tests => 5; - - # ECDH derive against a matching peer public key - ok(run(app(['openssl', 'pkeyutl', '-derive', - '-inkey', $eckey, '-peerkey', $ecpub, - '-out', 'derive_secret.bin'])), - "Derive shared secret with matching peer key"); - - # setup_peer: peer key file cannot be loaded - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'pkeyutl', '-derive', - '-inkey', $eckey, '-peerkey', 'no_such_peer.pem'])), - "Fail when the peer key cannot be read"); - }); - - # setup_peer: peer key type does not match the private key type - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'pkeyutl', '-derive', - '-inkey', $eckey, '-peerkey', $rsapub])), - "Fail when peer key type does not match private key"); - }); - - # main: -derive requires -peerkey - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'pkeyutl', '-derive', '-inkey', $eckey])), - "Fail when -derive is given without -peerkey"); - }); - - # main: -peerkey is only valid with -derive - with({ exit_checker => sub { return shift == 1; } }, - sub { - ok(run(app(['openssl', 'pkeyutl', '-inkey', $eckey, '-peerkey', $ecpub])), - "Fail when -peerkey is given without -derive"); - }); - }; -} diff --git a/test/recipes/20-test_skeyutl.t b/test/recipes/20-test_skeyutl.t deleted file mode 100644 index 1c69935cac..0000000000 --- a/test/recipes/20-test_skeyutl.t +++ /dev/null @@ -1,99 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use strict; -use warnings; - -use OpenSSL::Test qw/:DEFAULT bldtop_dir with/; -use OpenSSL::Test::Utils; - -setup("test_skeyutl"); - -# The success path needs the loadable fake-cipher provider, which is only built -# when module support is enabled. -my $fake_cipher = !disabled('module'); - -plan tests => 14 + ($fake_cipher ? 2 : 0); - -# Helper: run skeyutl expecting a non-zero (failure) exit code, and optionally -# check that stderr matches a regular expression. -sub skeyutl_fails { - my ($testtext, $re, @args) = @_; - - my $stderr_file = "skeyutl_err.txt"; - my $err = ''; - - with({ exit_checker => sub { return shift != 0; } }, - sub { - ok(run(app(['openssl', 'skeyutl', @args], stderr => $stderr_file)), - $testtext); - }); - - if (defined $re) { - if (open(my $fh, '<', $stderr_file)) { - $err = do { local $/; <$fh> }; - close($fh); - } - ok($err =~ $re, "$testtext: stderr matches"); - } - unlink($stderr_file) if -f $stderr_file; -} - -# -help exits successfully -ok(run(app(['openssl', 'skeyutl', '-help'])), - "skeyutl -help succeeds"); - -# Neither -cipher nor -skeymgmt is given -skeyutl_fails("skeyutl without -cipher or -skeymgmt fails", - qr/Either -skeymgmt -or -cipher option should be specified/); - -# -genkey but neither -cipher nor -skeymgmt is given: same early check -skeyutl_fails("skeyutl -genkey without -cipher or -skeymgmt fails", - qr/Either -skeymgmt -or -cipher option should be specified/, - '-genkey'); - -# A cipher is given but -genkey is not: generation is the only operation -skeyutl_fails("skeyutl without -genkey reports unsupported operation", - qr/Key generation is the only supported operation/, - '-cipher', 'AES-128-CBC'); - -# -genkey with a valid skey management name: reaches the generation path -# (no built-in provider supports opaque key generation yet) -skeyutl_fails("skeyutl -genkey with valid -skeymgmt reaches generation", - qr/Error creating opaque key for skeymgmt AES/, - '-genkey', '-skeymgmt', 'AES'); - -# -genkey with an unknown skey management name: fetch fails -skeyutl_fails("skeyutl -genkey with unknown -skeymgmt fails", - undef, - '-genkey', '-skeymgmt', 'NoSuchSkeyMgmt'); - -# An unknown cipher name is rejected by option parsing -skeyutl_fails("skeyutl with an unknown cipher fails", - qr/Unknown option or cipher/, - '-genkey', '-cipher', 'NoSuchCipher'); - -# An unknown option is rejected -skeyutl_fails("skeyutl with an unknown option fails", - qr/Unknown option/, - '-not-an-option'); - -# Success path: load the fake-cipher provider, which implements opaque key -# generation, and generate a key with it. -if ($fake_cipher) { - $ENV{OPENSSL_MODULES} = bldtop_dir("test"); - my @prov = ('-provider-path', bldtop_dir("test"), '-provider', 'fake-cipher'); - - my $status; - my @out = run(app(['openssl', 'skeyutl', @prov, - '-genkey', '-skeymgmt', 'fake_cipher']), - capture => 1, statusvar => \$status); - ok($status, "skeyutl -genkey with fake-cipher provider succeeds"); - ok(grep(/opaque key/, @out), - "skeyutl -genkey reports the generated opaque key"); -} diff --git a/test/recipes/25-test_crl.t b/test/recipes/25-test_crl.t index a65b2c6ce8..92101e8d94 100644 --- a/test/recipes/25-test_crl.t +++ b/test/recipes/25-test_crl.t @@ -11,12 +11,11 @@ use strict; use warnings; use File::Spec; -use File::Copy; use OpenSSL::Test qw/:DEFAULT srctop_file/; setup("test_crl"); -plan tests => 12; +plan tests => 10; require_ok(srctop_file('test','recipes','tconversion.pl')); @@ -52,106 +51,6 @@ ok(run(app(["openssl", "crl", "-text", "-in", $pem, "-inform", "PEM", is(cmp_text($out, srctop_file("test/certs", "cyrillic_crl.utf8")), 0, 'Comparing utf8 output'); -# Verify a CRL's signature against its issuer certificate, supplied via -# -CAfile, -CAstore and -CApath. -subtest 'crl signature verification' => sub { - plan tests => 4; - - my $crl = srctop_file("test/certs", "delta-crl-as-complete-delta.pem"); - my $cacert = srctop_file("test/certs", "delta-crl-as-complete-ca.pem"); - - ok(run(app(["openssl", "crl", "-noout", "-in", $crl, - "-CAfile", $cacert])), - "verify CRL signature with -CAfile"); - - ok(run(app(["openssl", "crl", "-noout", "-in", $crl, - "-CAstore", $cacert])), - "verify CRL signature with -CAstore"); - - # -CApath needs a rehashed directory, which relies on the rehash command - # (not available on platforms without symlink support, e.g. Windows). - SKIP: { - skip "rehash is not available on this platform", 2 - unless run(app(["openssl", "rehash", "-help"])); - - my $capath = "crl_capath"; - mkdir $capath; - copy($cacert, File::Spec->catfile($capath, "ca.pem")); - ok(run(app(["openssl", "rehash", $capath])), - "rehash the -CApath directory"); - ok(run(app(["openssl", "crl", "-noout", "-in", $crl, - "-CApath", $capath])), - "verify CRL signature with -CApath"); - } -}; - -# Cover -gendelta (delta CRL generation), which is the only code path in the -# crl app using the -key and -keyform options. -subtest 'crl delta generation with -gendelta, -key and -keyform' => sub { - plan tests => 5; - - # copy the CA cert and key in locally so the config uses plain paths - my $cacert = "gendelta-ca-cert.pem"; - my $cakey = "gendelta-ca-key.pem"; - copy(srctop_file("test", "certs", "ca-cert.pem"), $cacert); - copy(srctop_file("test", "certs", "ca-key.pem"), $cakey); - - open my $cfg, '>', "gencrl.cnf" or die "Could not create gencrl.cnf: $!"; - print $cfg <<"EOF"; -[ca] -default_ca = CA_default -[CA_default] -database = index.txt -certificate = $cacert -private_key = $cakey -crlnumber = crlnumber -default_md = sha256 -default_crl_days = 30 -EOF - close $cfg; - open my $db, '>', "index.txt" or die "Could not create index.txt: $!"; - close $db; # empty CA database - open my $num, '>', "crlnumber" or die "Could not create crlnumber: $!"; - print $num "1000\n"; - close $num; - - run(app(["openssl", "ca", "-gencrl", "-config", "gencrl.cnf", - "-out", "delta-base.crl"])); - run(app(["openssl", "ca", "-gencrl", "-config", "gencrl.cnf", - "-out", "delta-newer.crl"])); - - # -gendelta with a PEM signing key (the default -keyform) - ok(run(app(["openssl", "crl", "-in", "delta-base.crl", - "-gendelta", "delta-newer.crl", - "-key", $cakey, "-out", "delta.crl"])), - "generate delta CRL with -gendelta and a PEM -key"); - - run(app(["openssl", "crl", "-in", "delta.crl", "-noout", "-text", - "-out", "delta.txt"])); - test_file_contains("delta CRL", "delta.txt", "Delta CRL Indicator", 1); - - # The same, loading the signing key from DER via -keyform DER - run(app(["openssl", "pkey", "-in", $cakey, "-outform", "DER", - "-out", "ca-key.der"])); - ok(run(app(["openssl", "crl", "-in", "delta-base.crl", - "-gendelta", "delta-newer.crl", - "-key", "ca-key.der", "-keyform", "DER", - "-out", "delta-der.crl"])), - "generate delta CRL with a DER -key and -keyform DER"); - - # -keyform must match the key encoding: a DER key read as PEM fails. - ok(!run(app(["openssl", "crl", "-in", "delta-base.crl", - "-gendelta", "delta-newer.crl", - "-key", "ca-key.der", "-keyform", "PEM", - "-out", "delta-bad.crl"])), - "wrong -keyform for the signing key makes -gendelta fail"); - - # -gendelta requires a signing key. - ok(!run(app(["openssl", "crl", "-in", "delta-base.crl", - "-gendelta", "delta-newer.crl", "-out", "delta-nokey.crl"])), - "-gendelta without -key fails"); -}; - sub compare1stline { my ($cmdarray, $str) = @_; my @lines = run(app($cmdarray), capture => 1); diff --git a/test/recipes/25-test_pkcs7.t b/test/recipes/25-test_pkcs7.t index 3801c4b106..23f1c8a764 100644 --- a/test/recipes/25-test_pkcs7.t +++ b/test/recipes/25-test_pkcs7.t @@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file data_file/; setup("test_pkcs7"); -plan tests => 10; +plan tests => 7; require_ok(srctop_file('test','recipes','tconversion.pl')); @@ -43,16 +43,3 @@ is(cmp_text($out, data_file('grfc.out')), my $malformed = data_file('malformed.pkcs7'); ok(run(app(["openssl", "pkcs7", "-in", $malformed]))); - -# Test that -print_certs prints CRLs contained in a PKCS#7 structure -my $crlp7 = "testcrl.p7"; -ok(run(app(["openssl", "crl2pkcs7", - "-in", srctop_file("test", "testcrl.pem"), - "-out", $crlp7])), - "create a PKCS#7 structure containing a CRL"); -my @crlout = run(app(["openssl", "pkcs7", "-print_certs", "-in", $crlp7]), - capture => 1); -ok(grep(/Certificate Revocation List \(CRL\):/, @crlout) == 1, - "print_certs shows the CRL contents"); -ok(grep(/-----BEGIN X509 CRL-----/, @crlout) == 1, - "print_certs outputs the CRL in PEM form"); diff --git a/test/recipes/25-test_pkcs8.t b/test/recipes/25-test_pkcs8.t index bd7224459b..50cb01a407 100644 --- a/test/recipes/25-test_pkcs8.t +++ b/test/recipes/25-test_pkcs8.t @@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips is_nofips/; setup("test_pkcs8"); -plan tests => 19; +plan tests => 18; my $pc5_key = srctop_file('test', 'certs', 'pc5-key.pem'); @@ -128,38 +128,6 @@ ok(run(app(([ 'openssl', 'asn1parse', "Check the size of the PBKDF2 PARAM 'salt length' is 8"); -subtest 'PKCS#8 DER inform/outform round trip' => sub { - plan tests => 6; - - # PEM -> DER, unencrypted PKCS#8 (exercises -outform DER) - ok(run(app(['openssl', 'pkcs8', '-topk8', '-nocrypt', - '-in', $pc5_key, '-outform', 'DER', - '-out', 'p8-nocrypt.der'])), - "write unencrypted PKCS#8 in DER form"); - # DER -> PEM (exercises -inform DER) - ok(run(app(['openssl', 'pkcs8', '-nocrypt', - '-inform', 'DER', '-in', 'p8-nocrypt.der', - '-out', 'p8-roundtrip.pem'])), - "read unencrypted PKCS#8 from DER form"); - # PEM -> DER again, the result must match the original DER output - ok(run(app(['openssl', 'pkcs8', '-topk8', '-nocrypt', - '-in', 'p8-roundtrip.pem', '-outform', 'DER', - '-out', 'p8-roundtrip.der'])), - "re-encode the round-tripped key to DER"); - is(compare('p8-nocrypt.der', 'p8-roundtrip.der'), 0, - "DER output is identical after a PEM/DER round trip"); - - # The same for an encrypted PKCS#8 structure - ok(run(app(['openssl', 'pkcs8', '-topk8', - '-in', $pc5_key, '-outform', 'DER', - '-out', 'p8-enc.der', '-passout', 'pass:password'])), - "write encrypted PKCS#8 in DER form"); - ok(run(app(['openssl', 'pkcs8', - '-inform', 'DER', '-in', 'p8-enc.der', - '-out', 'p8-dec.pem', '-passin', 'pass:password'])), - "read encrypted PKCS#8 from DER form"); -}; - SKIP: { skip "SM2, SM3 or SM4 is not supported by this OpenSSL build", 3 if disabled("sm2") || disabled("sm3") || disabled("sm4"); diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t index a37686736f..869ac4c3b7 100644 --- a/test/recipes/25-test_req.t +++ b/test/recipes/25-test_req.t @@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; setup("test_req"); -plan tests => 131; +plan tests => 129; require_ok(srctop_file('test', 'recipes', 'tconversion.pl')); @@ -501,55 +501,6 @@ subtest "generating certificate requests with SLH-DSA" => sub { } }; -subtest "generating certificate with -set_serial" => sub { - plan tests => 3; - - my $cert = "self-signed_set_serial.pem"; - ok(run(app(["openssl", "req", "-x509", "-new", "-days", "365", - "-config", srctop_file("test", "test.cnf"), - "-key", srctop_file("test", "testrsa.pem"), - "-set_serial", "12345", - "-out", $cert])), - "Generating self-signed cert with -set_serial"); - - cert_contains($cert, "Serial Number: 12345", 1); - - ok(!run(app(["openssl", "req", "-x509", "-new", "-days", "365", - "-config", srctop_file("test", "test.cnf"), - "-key", srctop_file("test", "testrsa.pem"), - "-set_serial", "12345", "-set_serial", "67890", - "-out", $cert])), - "Supplying -set_serial twice fails"); -}; - -subtest "generating certificate requests with -pkeyopt" => sub { - plan tests => 3; - - SKIP: { - skip "EC is not supported by this OpenSSL build", 3 if disabled("ec"); - - my $key = "testreq-pkeyopt-key.pem"; - my $req = "testreq-pkeyopt.pem"; - my $text = "testreq-pkeyopt.txt"; - - ok(run(app(["openssl", "req", "-new", - "-config", srctop_file("test", "test.cnf"), - "-newkey", "ec", "-pkeyopt", "ec_paramgen_curve:P-384", - "-nodes", "-keyout", $key, "-out", $req])), - "Generating request with -pkeyopt ec_paramgen_curve:P-384"); - - run(app(["openssl", "req", "-in", $req, "-noout", "-text", - "-out", $text])); - test_file_contains("request", $text, "ASN1 OID: secp384r1", 1); - - ok(!run(app(["openssl", "req", "-new", - "-config", srctop_file("test", "test.cnf"), - "-newkey", "ec", "-pkeyopt", "bogus_opt:1", - "-nodes", "-keyout", $key, "-out", $req])), - "Supplying an unknown -pkeyopt fails"); - } -}; - my @openssl_args = ("req", "-config", srctop_file("apps", "openssl.cnf")); run_conversion('req conversions', diff --git a/test/recipes/25-test_statem_clnt.t b/test/recipes/25-test_statem_clnt.t deleted file mode 100644 index 4352029eed..0000000000 --- a/test/recipes/25-test_statem_clnt.t +++ /dev/null @@ -1,19 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use OpenSSL::Test; -use OpenSSL::Test::Utils; - -setup("test_statem_clnt"); - -plan skip_all => "No TLS protocol enabled in this build" - if disabled("tls1_2") && disabled("tls1_3"); - -plan tests => 1; - -ok(run(test(["statem_clnt_construct_test"])), "statem_clnt construct functions"); diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t index 6efe24087a..9564e78153 100644 --- a/test/recipes/25-test_verify.t +++ b/test/recipes/25-test_verify.t @@ -30,7 +30,7 @@ sub verify { run(app([@args])); } -plan tests => 221; +plan tests => 219; # Canonical success ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), @@ -362,17 +362,6 @@ SKIP: { ok(verify("ee-cert-ec-sha3-512", "", ["root-cert"], ["ca-cert-ec-named"], ), "accept cert generated with EC and SHA3-512"); } - -# DSA chains using id-dsa-with-sha384 / id-dsa-with-sha512 (GitHub issue #30432) -SKIP: { - skip "DSA is not supported by this OpenSSL build", 2 - if disabled("dsa"); - - ok(verify("ee-cert-dsa-sha384", "", ["root-cert-dsa-sha384"], [], ), - "accept DSA cert chain with SHA-384 signatures"); - ok(verify("ee-cert-dsa-sha512", "", ["root-cert-dsa-sha512"], [], ), - "accept DSA cert chain with SHA-512 signatures"); -} # Same as above but with base provider used for decoding SKIP: { my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); diff --git a/test/recipes/25-test_verify_store.t b/test/recipes/25-test_verify_store.t index bfac17c7f4..6338b862b5 100644 --- a/test/recipes/25-test_verify_store.t +++ b/test/recipes/25-test_verify_store.t @@ -72,11 +72,9 @@ SKIP: { -CAstore => $CAcert, $CAcert ); - # Put a pubkey and DH params to the store to test - # that other things in the store are just ignored open(my $out, '>', $CAobjects) or die $!; - my @pubkey = run(app([qw(openssl x509 -pubkey -noout -in), $CAcert]), capture => 1); - print $out @pubkey; + my $pubkey = qx(openssl x509 -pubkey -noout -in $CAcert); + print $out $pubkey; my @files; push @files, srctop_file("test", "certs", "dhp2048.pem") unless disabled("dh"); diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t index 736d185de4..d438de0fe2 100644 --- a/test/recipes/25-test_x509.t +++ b/test/recipes/25-test_x509.t @@ -17,7 +17,7 @@ use File::Compare qw/compare_text/; setup("test_x509"); -plan tests => 153; +plan tests => 151; # Prevent MSys2 filename munging for arguments that look like file paths but # aren't @@ -569,61 +569,6 @@ has_version($b_cert, 3); has_SKID($b_cert, 1); has_AKID($b_cert, 1); -subtest "signing with -sigopt and verifying a CSR with -vfyopt" => sub { - plan tests => 6; - - # -sigopt is passed to the signature algorithm; force RSA-PSS padding - # and check it ends up in the issued certificate. - my $pss_cert = "sigopt-pss.pem"; - ok(run(app(["openssl", "x509", "-req", "-CAcreateserial", - "-CA", $ca_cert, "-CAkey", $ca_key, - "-sigopt", "rsa_padding_mode:pss", - "-in", $b_csr, "-out", $pss_cert])), - "sign cert from CSR with -sigopt rsa_padding_mode:pss"); - cert_contains($pss_cert, "Signature Algorithm: rsassaPss", 1, - "issued cert is signed with PSS as selected via -sigopt"); - - # An unknown -sigopt must abort signing. - ok(!run(app(["openssl", "x509", "-req", "-CAcreateserial", - "-CA", $ca_cert, "-CAkey", $ca_key, - "-sigopt", "bogus:1", - "-in", $b_csr, "-out", "sigopt-bogus.pem"])), - "an unknown -sigopt makes signing fail"); - - # An unknown -vfyopt must abort CSR verification. - ok(!run(app(["openssl", "x509", "-req", "-CAcreateserial", - "-CA", $ca_cert, "-CAkey", $ca_key, - "-vfyopt", "bogus:1", - "-in", $b_csr, "-out", "vfyopt-bogus.pem"])), - "an unknown -vfyopt makes CSR verification fail"); - - SKIP: { - skip "SM2 is not supported by this OpenSSL build", 2 if disabled("sm2"); - - # -vfyopt is used to verify the CSR self-signature. Sign an SM2 CSR - # with a non-default distinguishing id so that the id must be supplied - # via -vfyopt for verification to succeed. - my $sm2_key = "sm2-vfyopt-key.pem"; - my $sm2_csr = "sm2-vfyopt.csr"; - my $distid = "0102030405060708"; - run(app(["openssl", "req", "-new", "-newkey", "sm2", - "-keyout", $sm2_key, "-out", $sm2_csr, "-nodes", - "-config", $cnf, "-subj", "/CN=SM2", - "-sigopt", "distid:$distid"])); - - ok(run(app(["openssl", "x509", "-req", "-CAcreateserial", - "-CA", $ca_cert, "-CAkey", $ca_key, - "-vfyopt", "distid:$distid", - "-in", $sm2_csr, "-out", "sm2-vfyopt.pem"])), - "SM2 CSR verifies when its distid is given via -vfyopt"); - - ok(!run(app(["openssl", "x509", "-req", "-CAcreateserial", - "-CA", $ca_cert, "-CAkey", $ca_key, - "-in", $sm2_csr, "-out", "sm2-novfyopt.pem"])), - "SM2 CSR fails to verify without the matching -vfyopt distid"); - } -}; - # Tests for https://github.com/openssl/openssl/issues/10442 (fixed in 1.1.1a) # (incorrect default `-CAcreateserial` if `-CA` path has a dot in it) my $folder_with_dot = "test_x509.folder"; @@ -764,42 +709,3 @@ ok(!run(app(["openssl", "x509", "-multi", "-checkend", # Bad parse still returns non-zero ok(!run(app(["openssl", "x509", "-checkend", "60", "-in", $c_key])), "Bad parse with -checkend returns non-zero"); - -# Signing using DER-encoded key and CA cert/key inputs, -# exercising -keyform, -CAform and -CAkeyform -subtest 'x509 signing with DER -keyform, -CAform and -CAkeyform' => sub { - plan tests => 6; - - my $csr = srctop_file(@certs, "x509-check.csr"); - my $signkey_der = "x509-check-key.der"; - my $cacert_der = "ca-cert.der"; - my $cakey_der = "ca-key.der"; - - # self-sign the CSR with a DER-encoded signing key - ok(run(app(["openssl", "pkey", - "-in", srctop_file(@certs, "x509-check-key.pem"), - "-outform", "DER", "-out", $signkey_der])), - "convert signing key to DER"); - ok(run(app(["openssl", "x509", "-req", "-in", $csr, - "-signkey", $signkey_der, "-keyform", "DER", - "-out", "x509-self-der.pem"])), - "self-sign CSR with -keyform DER"); - - # sign the CSR with a DER-encoded CA cert and CA key - ok(run(app(["openssl", "x509", - "-in", srctop_file(@certs, "ca-cert.pem"), - "-outform", "DER", "-out", $cacert_der])), - "convert CA cert to DER"); - ok(run(app(["openssl", "pkey", - "-in", srctop_file(@certs, "ca-key.pem"), - "-outform", "DER", "-out", $cakey_der])), - "convert CA key to DER"); - my $caout = "ca-issued-der.pem"; - ok(run(app(["openssl", "x509", "-req", "-in", $csr, - "-CA", $cacert_der, "-CAform", "DER", - "-CAkey", $cakey_der, "-CAkeyform", "DER", - "-CAcreateserial", "-text", "-out", $caout])), - "sign CSR with -CAform DER and -CAkeyform DER"); - ok(get_issuer($caout) =~ /CN=CA/, - "issuer of CA-signed cert matches DER CA cert"); -}; diff --git a/test/recipes/30-test_evp_list_noncache.t b/test/recipes/30-test_evp_list_noncache.t deleted file mode 100644 index 511bcec628..0000000000 --- a/test/recipes/30-test_evp_list_noncache.t +++ /dev/null @@ -1,34 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use strict; -use warnings; - - -use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir bldtop_dir/; -use OpenSSL::Test::Utils; - -setup("test_noncaching_evp_fetch"); - -plan skip_all => "This test requires provider module support" - if disabled("module"); - -plan tests => 1; - -# This tells the p_ossltest provider to request no caching of algs -$ENV{OSSL_TEST_PROVIDER_NO_CACHE} = "yes"; - -my $provdir = bldtop_dir("test"); - -# list all algorithms in p_ossltest, this exercises the EVP_*do_all_provided paths when algorithms -# are not being cached -# -ok(run(app(["openssl", "list", "-provider-path", $provdir, "-provider", "p_ossltest", "-all-algorithms"])), - "list provided algs when provider requests no caching"); - - diff --git a/test/recipes/30-test_pairwise_fail.t b/test/recipes/30-test_pairwise_fail.t index ca2d1f96e4..eaf0dbbb42 100644 --- a/test/recipes/30-test_pairwise_fail.t +++ b/test/recipes/30-test_pairwise_fail.t @@ -22,7 +22,7 @@ use lib bldtop_dir('.'); plan skip_all => "These tests are unsupported in a non fips build" if disabled("fips"); -plan tests => 8; +plan tests => 9; my $provconf = srctop_file("test", "fips-and-base.cnf"); run(test(["fips_version_test", "-config", $provconf, ">=3.1.0"]), @@ -37,11 +37,17 @@ SKIP: { } SKIP: { - skip "Skip EC test because of no ec in this build", 1 + skip "Skip EC test because of no ec in this build", 2 if disabled("ec"); ok(run(test(["pairwise_fail_test", "-config", $provconf, "-pairwise", "ec"])), "fips provider ec keygen pairwise failure test"); + + skip "FIPS provider version is too old", 1 + if !$fips_exit; + ok(run(test(["pairwise_fail_test", "-config", $provconf, + "-pairwise", "eckat"])), + "fips provider ec keygen kat failure test"); } SKIP: { diff --git a/test/recipes/60-test_x509_load_cert_file.t b/test/recipes/60-test_x509_load_cert_file.t index 15e9908ce1..e329d7675c 100644 --- a/test/recipes/60-test_x509_load_cert_file.t +++ b/test/recipes/60-test_x509_load_cert_file.t @@ -8,8 +8,6 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; -$ENV{ASAN_OPTIONS} = "detect_leaks=1"; - setup("test_load_cert_file"); plan tests => 1; diff --git a/test/recipes/70-test_ec_point_formats.t b/test/recipes/70-test_ec_point_formats.t deleted file mode 100644 index 4c86b66c9a..0000000000 --- a/test/recipes/70-test_ec_point_formats.t +++ /dev/null @@ -1,183 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use strict; - -use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/; -use OpenSSL::Test::Utils; -use TLSProxy::Proxy; -use Cwd qw(abs_path); - -my $test_name = "test_ec_point_formats"; -setup($test_name); - -$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("test")); - -plan skip_all => "TLSProxy isn't usable on $^O" - if $^O =~ /^(VMS)$/; - -plan skip_all => "$test_name needs the module feature enabled" - if disabled("module"); - -plan skip_all => "$test_name needs the sock feature enabled" - if disabled("sock"); - -plan skip_all => "$test_name needs TLS 1.2 enabled" - if disabled("tls1_2"); - -plan skip_all => "$test_name needs EC enabled" - if disabled("ec"); - -# RFC 4492 section 5.1.2 requires the peer's ec_point_formats list to -# contain "uncompressed", but only when an EC cipher suite is actually -# negotiated at TLS 1.2 or below. The peer's list is irrelevant at TLS -# 1.3 (the extension itself is) and at TLS 1.2 with a non-ECC cipher -# suite. We mangle the list to contain only "compressed" (0x01) and -# verify the four corner cases: both sides reject in an ECC TLS 1.2 -# handshake; both sides tolerate the missing "uncompressed" when TLS 1.3 -# or a non-ECC cipher suite is in play. - -# Wire format for ec_point_formats: 1-byte length prefix, then the -# ECPointFormat bytes. "\x01\x01" advertises a list of one format, -# the value 1 = ansiX962_compressed_prime; 0 (uncompressed) is absent. -my $only_compressed = "\x01\x01"; - -my $fatal_alert = 0; - -my $proxy = TLSProxy::Proxy->new( - \&mangle_ec_point_formats_clienthello, - cmdstr(app(["openssl"]), display => 1), - srctop_file("apps", "server.pem"), - (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}), -); - -# Test 1: a non-conforming list in the ClientHello -- the server -# must abort with illegal_parameter. ECDHE-RSA suffices to -# trigger the check (client supports at least one ECDHE group and -# cipher, so sends the extension), no EC cert required from either -# side. -$proxy->clientflags("-tls1_2"); -$proxy->serverflags("-tls1_2"); -$proxy->cipherc("ECDHE-RSA-AES128-SHA256"); -$proxy->ciphers("ECDHE-RSA-AES128-SHA256"); -$proxy->start() or plan skip_all => "Unable to start up proxy for tests"; -plan tests => 4; -ok($fatal_alert, - "Server rejects ClientHello whose ec_point_formats omits uncompressed"); - -# Test 2: a non-conforming list in the ServerHello -- the client must -# abort with the same error. -$fatal_alert = 0; -$proxy->clear(); -$proxy->filter(\&mangle_ec_point_formats_serverhello); -$proxy->clientflags("-tls1_2"); -$proxy->serverflags("-tls1_2"); -$proxy->cipherc("ECDHE-RSA-AES128-SHA256"); -$proxy->ciphers("ECDHE-RSA-AES128-SHA256"); -$proxy->start(); -ok($fatal_alert, - "Client rejects ServerHello whose ec_point_formats omits uncompressed"); - -# Mutating a ClientHello on the wire breaks the handshake transcript -# (the client and server compute different transcript hashes), so a -# tolerance test can't wait for the handshake to complete -- the -# Finished MAC will fail later regardless of whether the construct -# hook rejected. Instead, the proxy is allowed to run to whatever -# end it finds and we look at $proxy->message_list afterwards: if the -# server sent a ServerHello in response to the mangled ClientHello, -# it accepted the extension; if it rejected, the only server-side -# message in the list will be the fatal alert. -sub server_sent_hello { - my $proxy = shift; - foreach my $msg (@{$proxy->message_list}) { - return 1 if $msg->mt == TLSProxy::Message::MT_SERVER_HELLO; - } - return 0; -} - -# Test 3: TLS 1.3 ignores the ec_point_formats extension entirely. The -# server doesn't emit one in its TLS 1.3 ServerHello, and the -# construct-hook 5.1.2 check requires an ECC TLS <= 1.2 ciphersuite -# to fire. A mangled ClientHello list must therefore leave the server -# willing to send its ServerHello. -SKIP: { - skip "TLS 1.3 disabled", 1 if disabled("tls1_3"); - - $fatal_alert = 0; - $proxy->clear(); - $proxy->filter(\&mangle_ec_point_formats_clienthello); - $proxy->clientflags("-tls1_3"); - $proxy->serverflags("-tls1_3"); - $proxy->start(); - ok(server_sent_hello($proxy), - "TLS 1.3 server tolerates ec_point_formats missing uncompressed"); -} - -# Test 4: At TLS 1.2 with a non-ECC cipher suite, the construct hook -# returns NOT_SENT without inspecting the peer's list. Offer ECDHE-RSA -# alongside DHE-RSA on the client -- the ECDHE entry is enough for the -# client to advertise ec_point_formats -- pin the server to DHE-RSA, -# and confirm a mangled list is tolerated. -SKIP: { - skip "DH disabled", 1 if disabled("dh"); - - $fatal_alert = 0; - $proxy->clear(); - $proxy->filter(\&mangle_ec_point_formats_clienthello); - $proxy->clientflags("-tls1_2"); - $proxy->serverflags("-tls1_2"); - $proxy->cipherc("ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-GCM-SHA256"); - $proxy->ciphers("DHE-RSA-AES128-GCM-SHA256"); - $proxy->start(); - ok(server_sent_hello($proxy), - "TLS 1.2 non-ECC server tolerates ec_point_formats missing uncompressed"); -} - -sub mangle_ec_point_formats_clienthello -{ - my $proxy = shift; - - if ($proxy->flight == 0) { - foreach my $message (@{$proxy->message_list}) { - if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) { - $message->set_extension( - TLSProxy::Message::EXT_EC_POINT_FORMATS, - $only_compressed); - $message->repack(); - } - } - return; - } - - my $last_record = @{$proxy->{record_list}}[-1]; - $fatal_alert = 1 - if defined $last_record && $last_record->is_fatal_alert(1); -} - -sub mangle_ec_point_formats_serverhello -{ - my $proxy = shift; - - if ($proxy->flight == 0) { - return; - } elsif ($proxy->flight == 1) { - foreach my $message (@{$proxy->message_list}) { - if ($message->mt == TLSProxy::Message::MT_SERVER_HELLO) { - $message->set_extension( - TLSProxy::Message::EXT_EC_POINT_FORMATS, - $only_compressed); - $message->repack(); - } - } - return; - } - - my $last_record = @{$proxy->{record_list}}[-1]; - $fatal_alert = 1 - if defined $last_record && $last_record->is_fatal_alert(0); -} diff --git a/test/recipes/70-test_rio_notifier.t b/test/recipes/70-test_rio_notifier.t index 016cc01216..a0224f8a88 100644 --- a/test/recipes/70-test_rio_notifier.t +++ b/test/recipes/70-test_rio_notifier.t @@ -14,6 +14,9 @@ setup("test_rio_notifier"); plan skip_all => "RIO notifier tests require QUIC" if disabled("quic"); +plan skip_all => "RIO notifier WSA tests are only available on Windows" + if config("target") !~ /^(?:VC-|mingw|BC-)/i; + plan tests => 1; ok(run(test(["rio_notifier_test"]))); diff --git a/test/recipes/70-test_sslextension.t b/test/recipes/70-test_sslextension.t index 89b241efee..3327df474e 100644 --- a/test/recipes/70-test_sslextension.t +++ b/test/recipes/70-test_sslextension.t @@ -38,8 +38,7 @@ use constant { UNSOLICITED_SERVER_NAME => 0, UNSOLICITED_SERVER_NAME_TLS13 => 1, UNSOLICITED_SCT => 2, - NONCOMPLIANT_SUPPORTED_GROUPS => 3, - UNKNOWN_SERVER_HELLO_TLS13 => 4 + NONCOMPLIANT_SUPPORTED_GROUPS => 3 }; my $testtype; @@ -147,8 +146,7 @@ sub inject_unsolicited_extension if ($proxy->flight != 1) { if ($sent_unsolisited_extension) { my $last_record = @{$proxy->record_list}[-1]; - my $alert = $last_record->is_fatal_alert(0); - $fatal_alert = $alert if $alert; + $fatal_alert = 1 if $last_record->is_fatal_alert(0); } return; } @@ -174,8 +172,6 @@ sub inject_unsolicited_extension $type = TLSProxy::Message::EXT_SCT; } elsif ($testtype == NONCOMPLIANT_SUPPORTED_GROUPS) { $type = TLSProxy::Message::EXT_SUPPORTED_GROUPS; - } elsif ($testtype == UNKNOWN_SERVER_HELLO_TLS13) { - $type = TLSProxy::Message::EXT_UNKNOWN; } $message->set_extension($type, $ext); $message->repack(); @@ -198,7 +194,7 @@ sub inject_cryptopro_extension # Test 1-2: Sending a duplicate extension should fail. $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; -plan tests => 9; +plan tests => 8; ok($fatal_alert, "Duplicate ClientHello extension"); SKIP: { @@ -265,7 +261,7 @@ SKIP: { } SKIP: { - skip "TLS 1.3 disabled", 2 + skip "TLS 1.3 disabled", 1 if disabled("tls1_3") || (disabled("ec") && disabled("dh")); #Test 8: Inject an unsolicited extension (TLSv1.3) $fatal_alert = 0; @@ -275,14 +271,4 @@ SKIP: { $proxy->clientflags("-noservername"); $proxy->start(); ok($fatal_alert, "Unsolicited server name extension (TLSv1.3)"); - - #Test 9: Inject an unknown extension in ServerHello (TLSv1.3) - $fatal_alert = 0; - $proxy->clear(); - $proxy->filter(\&inject_unsolicited_extension); - $testtype = UNKNOWN_SERVER_HELLO_TLS13; - $proxy->clientflags(""); - $proxy->start(); - ok($fatal_alert == TLSProxy::Message::AL_DESC_UNSUPPORTED_EXTENSION, - "Unknown ServerHello extension (TLSv1.3)"); } diff --git a/test/recipes/70-test_sslrecords.t b/test/recipes/70-test_sslrecords.t index a49e3a256c..a09a818efe 100644 --- a/test/recipes/70-test_sslrecords.t +++ b/test/recipes/70-test_sslrecords.t @@ -146,12 +146,7 @@ sub run_tests $proxy_start_success = $proxy->start(); if ($run_test_as_dtls == 1) { - # DTLS alerts are best-effort (RFC 6347 section 4.2.7): the client's - # fatal alert may be lost, so we cannot rely on observing it. What we - # verify is that the client rejected the connection, i.e. exited with a - # failure. Whether we happened to see the alert is only diagnostic. - ok($proxy->clientexit != 0, "Unrecognised record type in DTLS1.2"); - note("client fatal alert observed") if $fatal_alert; + ok($proxy_start_success == 0, "Unrecognised record type in DTLS1.2"); } else { ok($fatal_alert, "Unrecognised record type in TLS1.2"); } @@ -171,8 +166,7 @@ sub run_tests $proxy->ciphers("AES128-SHA:\@SECLEVEL=0"); $proxy_start_success = $proxy->start(); if ($run_test_as_dtls == 1) { - ok($proxy->clientexit != 0, "Unrecognised record type in DTLSv1"); - note("client fatal alert observed") if $fatal_alert; + ok($proxy_start_success == 0, "Unrecognised record type in DTLSv1"); } else { ok($fatal_alert, "Unrecognised record type in TLSv1.1"); } diff --git a/test/recipes/70-test_tls13messages.t b/test/recipes/70-test_tls13messages.t index b2e356763c..f3a3f4789f 100644 --- a/test/recipes/70-test_tls13messages.t +++ b/test/recipes/70-test_tls13messages.t @@ -211,9 +211,6 @@ my $proxy = TLSProxy::Proxy->new( (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}), have_IPv6() ); -my $fatal_alert = 0; -my $hello_request_added = 0; -my $hello_request_after_server_hello = 0; #Test 1: Check we get all the right messages for a default handshake (undef, my $session) = tempfile(); @@ -222,7 +219,7 @@ $proxy->cipherc("DEFAULT:\@SECLEVEL=2"); $proxy->clientflags("-no_rx_cert_comp -sess_out ".$session); $proxy->sessionfile($session); $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; -plan tests => 19; +plan tests => 17; checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, checkhandshake::DEFAULT_EXTENSIONS, "Default handshake test"); @@ -422,90 +419,4 @@ checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, | checkhandshake::SUPPORTED_GROUPS_SRV_EXTENSION, "Acceptable but non preferred key_share"); -#Test 18: HelloRequest is reserved in TLSv1.3 -$proxy->clear(); -$fatal_alert = 0; -$hello_request_added = 0; -$hello_request_after_server_hello = 0; -$proxy->filter(\&inject_hello_request); -$proxy->cipherc("DEFAULT:\@SECLEVEL=2"); -$proxy->clientflags("-no_rx_cert_comp"); -$proxy->start(); -ok($fatal_alert, "HelloRequest rejected in TLSv1.3"); - -#Test 19: A HelloRequest received after selecting TLSv1.2 in the initial -# handshake is still ignored, confirming the legacy skip path is -# preserved even when TLSv1.3 was initially enabled. -SKIP: { - skip "TLSv1.2 disabled", 1 if disabled("tls1_2"); - - $proxy->clear(); - $fatal_alert = 0; - $hello_request_added = 0; - $hello_request_after_server_hello = 1; - $proxy->filter(\&inject_hello_request); - $proxy->cipherc("DEFAULT:\@SECLEVEL=2"); - $proxy->clientflags("-no_rx_cert_comp"); - $proxy->serverflags("-no_tls1_3"); - $proxy->start(); - ok(TLSProxy::Message->success() && !$fatal_alert, - "HelloRequest ignored in TLSv1.2"); -} - unlink $session; - -sub inject_hello_request -{ - my $proxy = shift; - my $records = $proxy->record_list; - my $hello_request; - my $record; - my $server_hello_record; - my $i; - - if ($hello_request_added) { - $fatal_alert = 1 - if @{$records}[-1]->is_fatal_alert(0) - == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE; - return; - } - - return if $proxy->flight != 1; - - $hello_request = pack("C4", TLSProxy::Message::MT_HELLO_REQUEST, - 0, 0, 0); - $record = TLSProxy::Record->new( - 1, - TLSProxy::Record::RT_HANDSHAKE, - TLSProxy::Record::VERS_TLS_1_2, - length($hello_request), - length($hello_request), - length($hello_request), - $hello_request, - $hello_request - ); - - if ($hello_request_after_server_hello) { - foreach my $message (@{$proxy->message_list}) { - next if $message->mt != TLSProxy::Message::MT_SERVER_HELLO - || ${$message->records}[0]->flight != 1; - - $server_hello_record = @{$message->records}[-1]; - last; - } - - return if !defined $server_hello_record; - - for ($i = 0; $i < @{$records}; $i++) { - last if ${$records}[$i] == $server_hello_record; - } - $i++; - } else { - for ($i = 0; ${$records}[$i]->flight() < 1; $i++) { - next; - } - } - - splice @{$records}, $i, 0, $record; - $hello_request_added = 1; -} diff --git a/test/recipes/70-test_tls_groups_list.t b/test/recipes/70-test_tls_groups_list.t deleted file mode 100644 index e200a63d0c..0000000000 --- a/test/recipes/70-test_tls_groups_list.t +++ /dev/null @@ -1,17 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use OpenSSL::Test::Simple; -use OpenSSL::Test qw/:DEFAULT/; -use OpenSSL::Test::Utils qw(disabled); - -setup("test_tls_groups_list"); - -plan skip_all => "needs EC and ECX enabled" if disabled("ecx"); - -simple_test("test_tls_groups_list", "tls_groups_list_test"); diff --git a/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt b/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt index 1bce022109..bd8d4c2f6c 100644 --- a/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt +++ b/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt @@ -55,18 +55,6 @@ Header: rsa_pkcs1_sha256 (0x0401) rsa_pkcs1_sha384 (0x0501) rsa_pkcs1_sha512 (0x0601) - slhdsa_sha2_128s (0x0911) - slhdsa_sha2_128f (0x0912) - slhdsa_sha2_192s (0x0913) - slhdsa_sha2_192f (0x0914) - slhdsa_sha2_256s (0x0915) - slhdsa_sha2_256f (0x0916) - slhdsa_shake_128s (0x0917) - slhdsa_shake_128f (0x0918) - slhdsa_shake_192s (0x0919) - slhdsa_shake_192f (0x091a) - slhdsa_shake_256s (0x091b) - slhdsa_shake_256f (0x091c) sm2sig_sm3 (0x0708) extension_type=supported_versions(43), length=3 TLS 1.3 (772) diff --git a/test/recipes/75-test_quicapi_data/ssltraceref.txt b/test/recipes/75-test_quicapi_data/ssltraceref.txt index 300b4ca456..c453344987 100644 --- a/test/recipes/75-test_quicapi_data/ssltraceref.txt +++ b/test/recipes/75-test_quicapi_data/ssltraceref.txt @@ -55,18 +55,6 @@ Header: rsa_pkcs1_sha256 (0x0401) rsa_pkcs1_sha384 (0x0501) rsa_pkcs1_sha512 (0x0601) - slhdsa_sha2_128s (0x0911) - slhdsa_sha2_128f (0x0912) - slhdsa_sha2_192s (0x0913) - slhdsa_sha2_192f (0x0914) - slhdsa_sha2_256s (0x0915) - slhdsa_sha2_256f (0x0916) - slhdsa_shake_128s (0x0917) - slhdsa_shake_128f (0x0918) - slhdsa_shake_192s (0x0919) - slhdsa_shake_192f (0x091a) - slhdsa_shake_256s (0x091b) - slhdsa_shake_256f (0x091c) sm2sig_sm3 (0x0708) extension_type=supported_versions(43), length=3 TLS 1.3 (772) diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index 7516cf024e..34b5fc4171 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -56,7 +56,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) $no_rc2 = 1 if disabled("legacy"); -plan tests => 40; +plan tests => 39; ok(run(test(["pkcs7_test"])), "test pkcs7"); @@ -121,16 +121,6 @@ my @smime_pkcs7_tests = ( \&final_compare ], - [ "signed content DER format, two RSA signers with explicit -inkey", - [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach", - "-signer", catfile($smdir, "smrsa3-cert.pem"), - "-inkey", catfile($smdir, "smrsa3-key.pem"), - "-signer", $smrsa1, "-out", "{output}.cms" ], - [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], - [ "signed content DER format, DSA key", [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach", "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ], @@ -822,18 +812,6 @@ sub zero_compare { return (-e "$opts{output}.txt" && -z "$opts{output}.txt"); } -sub read_file_text { - my ($file) = @_; - open(my $fh, "<", $file) or return undef; - binmode $fh; - local $/; - my $data = <$fh>; - close($fh); - # Normalise line endings as -out is written in text mode on Windows. - $data =~ s/\r\n/\n/g if defined $data; - return $data; -} - subtest "CMS => PKCS#7 compatibility tests\n" => sub { plan tests => scalar @smime_pkcs7_tests; @@ -1042,33 +1020,6 @@ subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub { } }; -subtest "CMS decrypt authEnvelopedData with authenticated attributes\n" => sub { - plan tests => 4; - - # BouncyCastle AES-128-GCM authEnvelopedData (KEK) carrying authAttrs; - # a clean decrypt confirms the authAttrs are verified as the AEAD AAD. - 1 while unlink "authattrs.txt"; - ok(run(app(["openssl", "cms", @defaultprov, "-decrypt", "-inform", "PEM", - "-secretkey", "000102030405060708090A0B0C0D0E0F", - "-secretkeyid", "C0FEE0", - "-in", catfile($datadir, "authenveloped_attrs.pem"), - "-out", "authattrs.txt" ])), - "decrypt authEnvelopedData with authAttrs"); - is(read_file_text("authattrs.txt"), "Hello AuthEnvelopedData world\n", - "decrypted authEnvelopedData plaintext matches expected"); - - # A flipped authAttrs byte must fail the tag check and leave -out empty. - 1 while unlink "bad_authattrs.txt"; - ok(!run(app(["openssl", "cms", @defaultprov, "-decrypt", "-inform", "PEM", - "-secretkey", "000102030405060708090A0B0C0D0E0F", - "-secretkeyid", "C0FEE0", - "-in", catfile($datadir, "bad_authenveloped_attrs.pem"), - "-out", "bad_authattrs.txt" ])), - "reject authEnvelopedData with tampered authAttrs"); - ok(!-s "bad_authattrs.txt", - "tampered authEnvelopedData leaks no plaintext to -out"); -}; - subtest "CAdES <=> CAdES consistency tests\n" => sub { plan tests => (scalar @smime_cms_cades_tests); diff --git a/test/recipes/80-test_cms_data/authenveloped_attrs.pem b/test/recipes/80-test_cms_data/authenveloped_attrs.pem deleted file mode 100644 index 75c8eab00b..0000000000 --- a/test/recipes/80-test_cms_data/authenveloped_attrs.pem +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN CMS----- -MIAGCyqGSIb3DQEJEAEXoIAwgAIBADEzojECAQQwBQQDwP7gMAsGCWCGSAFlAwQB -BQQYknpV85muZoLZSPkwi5Ll1Z1HwzAeZThVMIAGCSqGSIb3DQEHATAeBglghkgB -ZQMEAQYwEQQMkCQb305essfGO2nqAgEQoIAEHvYjM7EK9qZAHgoohdcbSHXe0lGJ -/Hjk3nkK5VsHxgAAAAChFjAUBgkrBgEEAYaNHwExBwwFaGVsbG8EENeGq4IXAd1O -iv8hMl+lHZOiFjAUBgkrBgEEAYaNHwIxBwwFd29ybGQAAAAAAAA= ------END CMS----- diff --git a/test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem b/test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem deleted file mode 100644 index e14946c96d..0000000000 --- a/test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN CMS----- -MIAGCyqGSIb3DQEJEAEXoIAwgAIBADEzojECAQQwBQQDwP7gMAsGCWCGSAFlAwQB -BQQYknpV85muZoLZSPkwi5Ll1Z1HwzAeZThVMIAGCSqGSIb3DQEHATAeBglghkgB -ZQMEAQYwEQQMkCQb305essfGO2nqAgEQoIAEHvYjM7EK9qZAHgoohdcbSHXe0lGJ -/Hjk3nkK5VsHxgAAAAChFjAUBgkrBgEEAYaNHwExBwwFaWVsbG8EENeGq4IXAd1O -iv8hMl+lHZOiFjAUBgkrBgEEAYaNHwIxBwwFd29ybGQAAAAAAAA= ------END CMS----- diff --git a/test/recipes/80-test_ocsp.t b/test/recipes/80-test_ocsp.t index 3f9255b530..3e12a0b23e 100644 --- a/test/recipes/80-test_ocsp.t +++ b/test/recipes/80-test_ocsp.t @@ -54,7 +54,7 @@ sub test_ocsp { $title); }); } -plan tests => 15; +plan tests => 13; subtest "=== VALID OCSP RESPONSES ===" => sub { plan tests => 7; @@ -232,12 +232,6 @@ subtest "=== OCSP API TESTS===" => sub { "running ocspapitest"); }; -subtest "=== OCSP VERIFICATION TESTS ===" => sub { - plan tests => 1; - - ok(run(test(["ocsptest"])), "running ocsptest"); -}; - subtest "=== UNTRUSTED ISSUER HINTS ===" => sub { plan tests => 1; @@ -263,44 +257,3 @@ subtest "=== OCSP handling of identical input and output files ===" => sub { ok(run(app(['openssl', 'ocsp', '-respin', $inout2, '-respout', $inout2, '-noverify']))); ok(!compare($inout2, $backup2), "copied response $inout2 did not change"); }; - -subtest "=== OCSP offline request/responder/verify round-trip ===" => sub { - plan tests => 6; - - # Offline round-trip: build a request, answer it with the built-in - # responder using a static index, then verify the response. - my $issuer = catfile($ocspdir, "intermediate-cert.pem"); - my $ee = catfile($ocspdir, "server-cert.pem"); - my $index = catfile($ocspdir, "index.txt"); - my $rsigner = catfile($ocspdir, "ocsp.pem"); - my $root = catfile($ocspdir, "root-cert.pem"); - - # The serial of server-cert.pem is listed as valid in index.txt, so its - # status is "good"; a serial absent from the index yields "unknown". - my $roundtrip = sub { - my ($title, $reqargs, $status) = @_; - my $req = "rt-req.der"; - my $resp = "rt-resp.der"; - - ok(run(app(['openssl', 'ocsp', '-issuer', $issuer, @$reqargs, - '-reqout', $req])), - "$title: produce request"); - ok(run(app(['openssl', 'ocsp', '-index', $index, '-rsigner', $rsigner, - '-CA', $issuer, '-reqin', $req, '-respout', $resp])), - "$title: responder produces response"); - # Passing the request again lets print_ocsp_summary report the status. - ok(run(app(['openssl', 'ocsp', '-issuer', $issuer, @$reqargs, - '-no_nonce', '-respin', $resp, '-CAfile', $root, - '-verify_other', $rsigner, - '-no-CApath', '-no-CAstore'])), - "$title: verify self-generated response ($status)"); - }; - - SKIP: { - # The responder certificates use EC keys. - skip "EC is not supported by this OpenSSL build", 6 if disabled("ec"); - - $roundtrip->("GOOD (by cert)", ['-cert', $ee], "good"); - $roundtrip->("UNKNOWN (by serial)", ['-serial', '0x1234'], "unknown"); - } -}; diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t index 5e9838d107..a1dc539311 100644 --- a/test/recipes/80-test_pkcs12.t +++ b/test/recipes/80-test_pkcs12.t @@ -56,7 +56,7 @@ $ENV{OPENSSL_WIN32_UTF8}=1; my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); -plan tests => 64 + ($no_fips ? 0 : 5); +plan tests => 61 + ($no_fips ? 0 : 5); # Test different PKCS#12 formats ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); @@ -176,29 +176,6 @@ ok(grep(/Trusted key usage (Oracle)/, @pkcs12info) == 0, ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr6_empty"); } -# Test dumping a PKCS#12 file whose private key is stored in an unencrypted -# keyBag (created with -keypbe NONE) rather than a shrouded keyBag. -{ - my $keybag = "keybag.p12"; - ok(run(app(["openssl", "pkcs12", "-export", "-keypbe", "NONE", - "-certpbe", "NONE", "-nomac", - "-inkey", srctop_file(@path, "cert-key-cert.pem"), - "-in", srctop_file(@path, "cert-key-cert.pem"), - "-passout", "pass:", "-out", $keybag])), - "export PKCS#12 with an unencrypted key bag"); - - # -nodes so the dumped key isn't re-encrypted (which would prompt). - my @info = run(app(["openssl", "pkcs12", "-in", $keybag, "-info", "-nodes", - "-passin", "pass:"], stderr => "keybag_info.txt"), - capture => 1); - open DATA, "keybag_info.txt"; - my @match = grep /Key bag/, ; - close DATA; - ok(scalar @match > 0 ? 1 : 0, "test unencrypted key bag is reported"); - ok(grep(/-----BEGIN PRIVATE KEY-----/, @info) == 1, - "test private key from key bag is output"); -} - my %pbmac1_tests = ( pbmac1_defaults => {args => [], lookup => "hmacWithSHA256"}, pbmac1_nondefaults => {args => ["-pbmac1_pbkdf2_md", "sha512", "-macalg", "sha384"], lookup => "hmacWithSHA512"}, diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 8516652f97..a2d69e3c47 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -42,7 +42,7 @@ if (defined $ENV{SSL_TESTS}) { @conf_srcs = glob(srctop_file("test", "ssl-tests", "*.cnf.in")); # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. - plan tests => 32; + plan tests => 31; } map { s/;.*// } @conf_srcs if $^O eq "VMS"; my @conf_files = map { basename($_, ".in") } @conf_srcs; @@ -100,7 +100,6 @@ my %conf_dependent_tests = ( "28-seclevel.cnf" => disabled("tls1_2") || $no_ecx, "30-extended-master-secret.cnf" => disabled("tls1_2"), "32-compressed-certificate.cnf" => disabled("comp") || disabled("tls1_3"), - "33-compressed-spki.cnf" => disabled("tls1_2") || disabled("tls1_3") || $no_ec, ); # Add your test here if it should be skipped for some compile-time @@ -136,7 +135,6 @@ my %skip = ( "26-tls13_client_auth.cnf" => disabled("tls1_3") || ($no_ec && $no_dh), "29-dtls-sctp-label-bug.cnf" => disabled("sctp") || disabled("sock"), "32-compressed-certificate.cnf" => disabled("comp") || disabled("tls1_3"), - "33-compressed-spki.cnf" => disabled("tls1_2") || disabled("tls1_3") || $no_ec, ); foreach my $conf (@conf_files) { diff --git a/test/recipes/90-test_dtls12_psk.t b/test/recipes/90-test_dtls12_psk.t deleted file mode 100644 index c7ed9759fc..0000000000 --- a/test/recipes/90-test_dtls12_psk.t +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use OpenSSL::Test; -use OpenSSL::Test::Utils; - -my $test_name = "test_dtls12psk"; -setup($test_name); - -plan skip_all => "$test_name is not supported in this build" - if disabled("dtls1_2") || disabled("psk"); - -plan tests => 1; - -ok(run(test(["dtls12psk_test"])), "running dtls12psk_test"); diff --git a/test/recipes/90-test_memfail.t b/test/recipes/90-test_memfail.t index fefc2771b6..f89b1b9e1e 100644 --- a/test/recipes/90-test_memfail.t +++ b/test/recipes/90-test_memfail.t @@ -35,6 +35,8 @@ run(test(["x509-memfail", "count", srctop_file("test", "certs", "servercert.pem" run(test(["load_key_certs_crls_memfail", "count", srctop_file("test", "certs", "servercert.pem")], stderr => "$resultdir/load_key_certs_crls_countinfo.txt")); +run(test(["property-memfail", "count"], stderr => "$resultdir/propertycountinfo.txt")); + sub get_count_info { my ($infile) = @_; my ($skipcount, $malloccount) = (0, 0); @@ -61,8 +63,10 @@ my ($x509skipcount, $x509malloccount) = get_count_info("$resultdir/x509countinfo my ($load_key_certs_crls_skipcount, $load_key_certs_crls_malloccount) = get_count_info("$resultdir/load_key_certs_crls_countinfo.txt"); +my (undef, $propertymalloccount) = get_count_info("$resultdir/propertycountinfo.txt"); + my $total_malloccount = $hsmalloccount + $x509malloccount - + $load_key_certs_crls_malloccount; + + $load_key_certs_crls_malloccount + $propertymalloccount; plan skip_all => "could not get malloc counts (one or more count runs failed or output format changed)" if $total_malloccount == 0; @@ -97,3 +101,7 @@ run_memfail_test($hsskipcount, $hsmalloccount, ["handshake-memfail", "run", srct run_memfail_test($x509skipcount, $x509malloccount, ["x509-memfail", "run", srctop_file("test", "certs", "servercert.pem")]); run_memfail_test($load_key_certs_crls_skipcount, $load_key_certs_crls_malloccount, ["load_key_certs_crls_memfail", "run", srctop_file("test", "certs", "servercert.pem")]); + +for my $idx (1..$propertymalloccount) { + ok(run(test(["property-memfail", "run", $idx]))); +} diff --git a/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt b/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt index e6c193fa82..68d46c8b38 100644 --- a/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt +++ b/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt @@ -48,18 +48,6 @@ Header: rsa_pkcs1_sha256 (0x0401) rsa_pkcs1_sha384 (0x0501) rsa_pkcs1_sha512 (0x0601) - slhdsa_sha2_128s (0x0911) - slhdsa_sha2_128f (0x0912) - slhdsa_sha2_192s (0x0913) - slhdsa_sha2_192f (0x0914) - slhdsa_sha2_256s (0x0915) - slhdsa_sha2_256f (0x0916) - slhdsa_shake_128s (0x0917) - slhdsa_shake_128f (0x0918) - slhdsa_shake_192s (0x0919) - slhdsa_shake_192f (0x091a) - slhdsa_shake_256s (0x091b) - slhdsa_shake_256f (0x091c) sm2sig_sm3 (0x0708) extension_type=supported_versions(43), length=3 TLS 1.3 (772) diff --git a/test/recipes/90-test_sslapi_data/ssltraceref.txt b/test/recipes/90-test_sslapi_data/ssltraceref.txt index b5d8931e3d..d84d0e02fb 100644 --- a/test/recipes/90-test_sslapi_data/ssltraceref.txt +++ b/test/recipes/90-test_sslapi_data/ssltraceref.txt @@ -48,18 +48,6 @@ Header: rsa_pkcs1_sha256 (0x0401) rsa_pkcs1_sha384 (0x0501) rsa_pkcs1_sha512 (0x0601) - slhdsa_sha2_128s (0x0911) - slhdsa_sha2_128f (0x0912) - slhdsa_sha2_192s (0x0913) - slhdsa_sha2_192f (0x0914) - slhdsa_sha2_256s (0x0915) - slhdsa_sha2_256f (0x0916) - slhdsa_shake_128s (0x0917) - slhdsa_shake_128f (0x0918) - slhdsa_shake_192s (0x0919) - slhdsa_shake_192f (0x091a) - slhdsa_shake_256s (0x091b) - slhdsa_shake_256f (0x091c) sm2sig_sm3 (0x0708) extension_type=supported_versions(43), length=3 TLS 1.3 (772) diff --git a/test/recipes/95-test_external_pkcs11_provider_data/patches/0002-Temporarily-disable-the-pem-encoder.patch b/test/recipes/95-test_external_pkcs11_provider_data/patches/0002-Temporarily-disable-the-pem-encoder.patch deleted file mode 100644 index 2498938a69..0000000000 --- a/test/recipes/95-test_external_pkcs11_provider_data/patches/0002-Temporarily-disable-the-pem-encoder.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 891c0d9a615ce37506969875792afdb6defe9b79 Mon Sep 17 00:00:00 2001 -From: Bob Beck -Date: Wed, 10 Jun 2026 16:40:37 -0600 -Subject: [PATCH] Temporarily disable the pem encoder - -This appears to have some sort of internal error fetching ec keys -from the softhsm. (and appears to also be disabled for -similar reasons on some linux distros) ---- - tests/meson.build | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/tests/meson.build b/tests/meson.build -index 6050fe5..24520d1 100644 ---- a/tests/meson.build -+++ b/tests/meson.build -@@ -155,7 +155,6 @@ tests = { - 'oaepsha2': {'suites': ['softokn', 'kryoptic', 'kryoptic.nss']}, - 'hkdf': {'suites': ['softokn', 'kryoptic', 'kryoptic.nss']}, - 'imported' : {'suites': ['softokn', 'kryoptic', 'kryoptic.nss']}, -- 'pem_encoder': {'suites': all_suites}, - 'rsa': {'suites': all_suites}, - 'rsapss': {'suites': all_suites}, - 'rsapssam': {'suites': ['softhsm', 'kryoptic']}, --- -2.53.0 - diff --git a/test/recipes/95-test_external_pkcs11_provider_data/pkcs11-provider.sh b/test/recipes/95-test_external_pkcs11_provider_data/pkcs11-provider.sh index f75f1260a0..1b49ca933f 100755 --- a/test/recipes/95-test_external_pkcs11_provider_data/pkcs11-provider.sh +++ b/test/recipes/95-test_external_pkcs11_provider_data/pkcs11-provider.sh @@ -85,10 +85,13 @@ echo "Running tests" echo "------------------------------------------------------------------" # For maintenance reasons and simplicity we only run test with kryoptic token -meson test -C $PKCS11_PROVIDER_BUILDDIR --print-errorlogs --suite=kryoptic +meson test -C $PKCS11_PROVIDER_BUILDDIR --suite=kryoptic -RESULT=$? +if [ $? -ne 0 ]; then + cat $PKCS11_PROVIDER_BUILDDIR/meson-logs/testlog.txt + exit 1 +fi rm -rf $PKCS11_PROVIDER_BUILDDIR -exit $RESULT +exit 0 diff --git a/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in b/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in index e22ffd2641..2ed47253b8 100644 --- a/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in +++ b/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in @@ -12,12 +12,12 @@ {"name" : "test-tls13-certificate-verify.py", "arguments" : ["-k", "tests/clientX509Key.pem", "-c", "tests/clientX509Cert.pem", - "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 9+17 9+18 9+19 9+20 9+21 9+22 9+23 9+24 9+25 9+26 9+27 9+28 7+8", + "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 7+8", "-p", "@PORT@"]}, {"name" : "test-tls13-ecdsa-in-certificate-verify.py", "arguments" : ["-k", "tests/serverECKey.pem", "-c", "tests/serverECCert.pem", - "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 9+17 9+18 9+19 9+20 9+21 9+22 9+23 9+24 9+25 9+26 9+27 9+28 7+8", + "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 7+8", "-p", "@PORT@"]} ] }, diff --git a/test/recipes/fuzz.pl b/test/recipes/fuzz.pl index e5182a362c..3f03eef4f7 100644 --- a/test/recipes/fuzz.pl +++ b/test/recipes/fuzz.pl @@ -1,4 +1,4 @@ -# Copyright 2016-2026 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -8,295 +8,18 @@ use strict; use warnings; -use Cwd qw/abs_path/; - use OpenSSL::Glob; -use OpenSSL::Test qw/:DEFAULT srctop_dir bldtop_file result_file/; - -# print logs -sub fuzz_dump_log { - my ($log) = @_; - return unless $ENV{HARNESS_VERBOSE} && open(my $fh, '<', $log); - print STDERR <$fh>; - close $fh; -} - -# execute test and print backtrace -sub fuzz_print_backtrace { - my ($f, $path, $point) = @_; - my $bt_log = result_file("$f-backtrace.stderr.log"); - local $ENV{OPENSSL_TEST_MFAIL_BACKTRACE} = 1; - local $ENV{OPENSSL_TEST_MFAIL_POINT} = $point if defined $point; - run(fuzz(["$f-test", $path], stderr => $bt_log)); - - diag("- backtrace at injection point:"); - if (open(my $fh, '<', $bt_log)) { - while (my $line = <$fh>) { - chomp $line; - diag(" $line"); - } - close $fh; - } -} - -# check fuzz test logs -sub fuzz_check_log { - my ($f, $log, $exit_ok, $silent_leak) = @_; - - my $has_leaks = 0; - my $corpus_time = 0; - my @tail; - my ($last_path, $last_point); - - # collect info from the executed fuzz log - if (open(my $fh, '<', $log)) { - while (my $line = <$fh>) { - chomp $line; - if ($line =~ /^#\s/) { - $corpus_time = $1 - if $line =~ /^#\s*corpus_time:\s*([\d.]+)/; - $last_path = $1 if $line =~ /\bpath=(.+?)\s*$/; - $last_point = $1 if $line =~ /\bpoint=(\d+)\//; - @tail = ($line); - } else { - push @tail, $line; - $has_leaks = 1 - if $line =~ /^(?:Direct|Indirect) leak of \d+ byte/; - } - } - close $fh; - } - - # return if the test passed and there is no leak - return (1, 0, $corpus_time) if $exit_ok && !$has_leaks; - # return if there is a leak but it's silent (should not be reported) - return (0, $has_leaks, $corpus_time) if $has_leaks && $silent_leak; - - # log leak info - my $why = !$exit_ok ? "non-zero exit" : "leaks (clean exit)"; - diag("fuzz $f failed: $why"); - diag("- full stderr: $log"); - if (defined $last_path) { - my $bin = abs_path(bldtop_file('fuzz', "$f-test")); - my $path = abs_path($last_path); - my $env = defined $last_point - ? "OPENSSL_TEST_MFAIL_POINT=$last_point " : ""; - diag("- reproduce: $env$bin $path"); - } - diag($_) for @tail; - fuzz_print_backtrace($f, $last_path, $last_point) - if defined $last_path && !$has_leaks; - return (0, $has_leaks, $corpus_time); -} - -# run fuzz test and dump logs -sub fuzz_run { - my ($f, $d, $log_name, $silent_leak) = @_; - my $log = result_file($log_name); - my $exit_ok = run(fuzz(["$f-test", $d], stderr => $log)); - fuzz_dump_log($log); - my ($passed, $leaks, $corpus_time) = fuzz_check_log($f, $log, $exit_ok, - $silent_leak); - return ($passed, $leaks, $corpus_time, $log); -} - -# run fuzz test in counting mode and no fail run -sub fuzz_run_count_only { - my ($f, $d) = @_; - my $log = result_file("$f-count.stderr.log"); - local $ENV{OPENSSL_TEST_MFAIL_COUNT_ONLY} = 1; - my $exit_ok = run(fuzz(["$f-test", $d], stderr => $log)); - fuzz_dump_log($log); - - my ($corpus_time, $cur, @allocs) = (0, undef); - if (open(my $fh, '<', $log)) { - while (my $line = <$fh>) { - $corpus_time = $1 if $line =~ /^#\s*corpus_time:\s*([\d.]+)/; - $cur = $1 if $line =~ /^#\s*CORPUS_FILE\s+file_idx=(\d+)/; - push @allocs, $1 + 0 if defined $cur - && $line =~ /:\s*(\d+)\s+allocations\s*$/; - } - close $fh; - } - return ($exit_ok, $corpus_time, \@allocs); -} - -# find path and point of the reported leak for easy recreation -sub fuzz_mfail_bisect { - my ($f, $log) = @_; - - # collect all paths and executed points from the output - my (%path, %points); - if (open(my $fh, '<', $log)) { - while (my $line = <$fh>) { - $path{$1} = $2 - if $line =~ - /CORPUS_FILE\s+file_idx=(\d+)\s+size=\d+\s+path=(\S+)/; - push @{$points{$1}}, $2 - if $line =~ /MFAIL_BEGIN\s+file_idx=(\d+)\s+point=(\d+)\/\d+/; - } - close $fh; - } - - # reset current envs so they don't get used in bisect run - delete local $ENV{OPENSSL_TEST_MFAIL_COUNT}; - delete local $ENV{OPENSSL_TEST_MFAIL_START}; - delete local $ENV{OPENSSL_TEST_MFAIL_POINT}; - - diag("bisecting mfail leak across isolated point reruns"); - - # go through all executed corpus files - for my $idx (sort { $a <=> $b } keys %path) { - # go trhout all executed points in path - for my $p (@{$points{$idx} || []}) { - local $ENV{OPENSSL_TEST_MFAIL_POINT} = $p; - my $plog = result_file("$f-bisect-$idx-$p.stderr.log"); - my $exit_ok = run(fuzz(["$f-test", $path{$idx}], stderr => $plog), - quiet => 1); - # silently skip runs without a leak - my (undef, $leaks) = fuzz_check_log($f, $plog, $exit_ok, 1); - next unless $leaks; - # report exact leak location - my $bin = abs_path(bldtop_file('fuzz', "$f-test")); - my $abs = abs_path($path{$idx}); - diag("isolated leak: file_idx=$idx point=$p path=$path{$idx}"); - diag("- log: $plog"); - diag("- reproduce: OPENSSL_TEST_MFAIL_POINT=$p $bin $abs"); - fuzz_print_backtrace($f, $path{$idx}, $p); - return; - } - } - diag("bisection did not reproduce the leak"); -} - -# get all test_fuzz tests calling this -sub fuzz_test_names { - my @names; - for my $p (glob(srctop_dir('test', 'recipes') . '/[0-9][0-9]-test_fuzz_*.t')) { - # push the actual name of the test used in TESTS filtering - push @names, $1 if $p =~ m{/\d+-(test_fuzz_\S+)\.t$}; - } - return @names; -} - -# match a test name against TESTS env filter (test/run_tests.pl semantics) -sub fuzz_match_tests_filter { - my ($name, $filter) = @_; - return 1 unless defined $filter && $filter ne ''; - - my @pats = grep { length } split /\s+/, $filter; - return 1 unless @pats; - - # a leading negative implies a starting "alltests" - my $included = $pats[0] =~ /^-/ ? 1 : 0; - - for my $pat (@pats) { - # alltests resets the set to all, ignoring everything before - if ($pat eq 'alltests') { - $included = 1; - next; - } - - my $neg = $pat =~ s/^-//; - - # glob -> regex - (my $re = quotemeta $pat) =~ s/\\\*/.*/g; - $re =~ s/\\\?/./g; - next unless $name =~ /\A$re\z/; - - $included = $neg ? 0 : 1; - } - - return $included; -} - -# get budget per test -sub fuzz_per_test_budget { - my $budget = $ENV{OSSL_FUZZ_TEST_BUDGET} or return 0; - my $jobs = $ENV{OSSL_FUZZ_TEST_JOBS} || 1; - my $filter = $ENV{TESTS}; - - my @active = grep { fuzz_match_tests_filter($_, $filter) } fuzz_test_names(); - my $count = scalar(@active) || 1; - - # we don't need all jobs if there are less tests - $jobs = $count if $jobs > $count; - - my $per_test = $budget * $jobs / $count; - diag(sprintf("budget=%ss jobs=%d active=%d -> per-test=%.3fs", - $budget, $jobs, $count, $per_test)); - return $per_test; -} +use OpenSSL::Test qw/:DEFAULT srctop_dir/; sub fuzz_ok { - my ($f, %opts) = @_; + die "Only one argument accepted" if scalar @_ != 1; + + my $f = $_[0]; my $d = srctop_dir('fuzz', 'corpora', $f); SKIP: { skip "No directory $d", 1 unless -d $d; - - my $per_test = fuzz_per_test_budget(); - my $safety = 0.8; - my $target = $per_test * $safety; - - # no budget configured, just run the corpus - unless ($per_test > 0) { - ok(run(fuzz(["$f-test", $d])), "Fuzzing $f"); - return; - } - - # baseline run to measure the corpus run time - my ($ok, $corpus_time, $allocs) = fuzz_run_count_only($f, $d); - unless ($ok) { - ok(0, "Fuzzing $f (count-only)"); - return; - } - - # get the maximum allocations in instance and count total - my $total_allocs = 0; - my $max_k = 0; - for (@$allocs) { - $total_allocs += $_; - $max_k = $_ if $_ > $max_k; - } - my $num_files = scalar @$allocs; - diag(sprintf("%s: count-only %.3fs, allocs=%d, files=%d, max=%d", - $f, $corpus_time, $total_allocs, $num_files, $max_k)); - - # baseline alone consumed the budget, nothing left for mfail - if ($corpus_time <= 0 || $corpus_time >= $target) { - ok(1, "Fuzzing $f (no mfail budget; " - . "corpus=${corpus_time}s, target=${target}s)"); - return; - } - - # no allocations counted, can't size the mfail run - if ($total_allocs <= 0 || $num_files <= 0) { - ok(1, "Fuzzing $f (no allocations counted)"); - return; - } - - # number of mfail iterations that fit alongside the baseline: - # ~corpus_time * (1 + count / 2) <= target - my $count = int(2 * ($target - $corpus_time) / $corpus_time); - # never exceed max(K_i); injections beyond that are wasted - $count = $max_k if $count > $max_k; - if ($count <= 0) { - ok(1, "Fuzzing $f (budget too small for mfail)"); - return; - } - diag("$f: running mfail with count=$count"); - - local $ENV{OPENSSL_TEST_MFAIL_COUNT} = $count; - my $main_log = "$f-mfail.stderr.log"; - my ($passed, $leaks, undef, $log) = fuzz_run($f, $d, $main_log, 1); - - unless ($passed) { - fuzz_mfail_bisect($f, $log) if $leaks; - ok(0, "Fuzzing $f (mfail count=$count, per-test=${per_test}s)"); - return; - } - ok(1, "Fuzzing $f (mfail count=$count, per-test=${per_test}s)"); + ok(run(fuzz(["$f-test", $d])), "Fuzzing $f"); } } diff --git a/test/rsa_test.c b/test/rsa_test.c index de2966b2a2..2150a3cb6d 100644 --- a/test/rsa_test.c +++ b/test/rsa_test.c @@ -757,8 +757,13 @@ int setup_tests(void) { ADD_ALL_TESTS(test_rsa_pkcs1, 3); ADD_ALL_TESTS(test_rsa_oaep, 3); +#if defined(_MSC_VER) || defined(OPENSSL_NO_CACHED_FETCH) + ADD_MFAIL_ALL_NO_CHECK_TESTS(test_rsa_pkcs1_mfail, 3); + ADD_MFAIL_ALL_NO_CHECK_TESTS(test_rsa_oaep_mfail, 3); +#else ADD_MFAIL_ALL_TESTS(test_rsa_pkcs1_mfail, 3); ADD_MFAIL_ALL_TESTS(test_rsa_oaep_mfail, 3); +#endif ADD_ALL_TESTS(test_rsa_security_bit, OSSL_NELEM(rsa_security_bits_cases)); ADD_TEST(test_rsa_saos); ADD_TEST(test_EVP_rsa_legacy_key); diff --git a/test/run_tests.pl b/test/run_tests.pl index f31c181a3d..f9b2d2d2c0 100644 --- a/test/run_tests.pl +++ b/test/run_tests.pl @@ -128,7 +128,6 @@ open $openssl_args{'tap_copy'}, ">$outfilename" my @alltests = find_matching_tests("*"); my %tests = (); -my $has_nonexistent_test = 0; sub reorder { my $key = pop; @@ -153,7 +152,6 @@ foreach my $arg (@ARGV ? @ARGV : ('alltests')) { warn "'alltests' encountered, ignoring everything before that...\n" unless $initial_arg; %tests = map { $_ => 1 } @alltests; - $has_nonexistent_test = 0; } elsif ($arg =~ m/^(-?)(.*)/) { my $sign = $1; my $test = $2; @@ -164,12 +162,10 @@ foreach my $arg (@ARGV ? @ARGV : ('alltests')) { %tests = map { $_ => 1 } @alltests; } - # Flag non-existent test so we can return an error if (scalar @matches == 0) { warn "Test $test found no match, skipping ", ($sign eq '-' ? "removal" : "addition"), "...\n"; - $has_nonexistent_test = 1 unless $sign eq '-'; } else { foreach $test (@matches) { if ($sign eq '-') { @@ -395,10 +391,9 @@ if (ref($ret) ne "TAP::Parser::Aggregator" || !$ret->has_errors) { # If this is a TAP::Parser::Aggregator, $ret->has_errors is the count of # tests that failed. We don't bother with that exact number, just exit -# with an appropriate exit code when it isn't zero. We also return an error -# if attempting to run a non-existent test. +# with an appropriate exit code when it isn't zero. if (ref($ret) eq "TAP::Parser::Aggregator") { - exit 0 unless $ret->has_errors || $has_nonexistent_test; + exit 0 unless $ret->has_errors; exit 1 unless $^O eq 'VMS'; # On VMS, perl converts an exit 1 to SS$_ABORT (%SYSTEM-F-ABORT), which # is a bit harsh. As per perl recommendations, we explicitly use the @@ -414,6 +409,4 @@ if (ref($ret) eq "TAP::Parser::Aggregator") { # If this isn't a TAP::Parser::Aggregator, it's the pre-TAP test harness, # which simply dies at the end if any test failed, so we don't need to bother -# with any exit code in that case. The only exception is if we have a -# non-existent test). -exit 1 if $has_nonexistent_test; +# with any exit code in that case. diff --git a/test/sha3_x4_internal_test.c b/test/sha3_x4_internal_test.c deleted file mode 100644 index aa6a452db6..0000000000 --- a/test/sha3_x4_internal_test.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2026 Intel Corporation. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Internal cross-validation tests for the SHAKE x4 multi-buffer API. - * - * Each test computes SHAKE-128 or SHAKE-256 on four independent inputs - * using the x4 (AVX-512VL) path and compares every lane's output to the - * equivalent result produced by the scalar ossl_sha3_* API. - * - * Tests cover: - * - Single-call (ossl_sha3_shake{128,256}_x4_avx512vl) for many (inlen, outlen) pairs - * - Incremental init/absorb/squeeze for the same (inlen, outlen) pairs - * - Multi-absorb: input split at every possible block boundary - * - Multi-squeeze: output produced in two successive squeeze calls - */ - -#include -#include "testutil.h" - -/* - * KECCAK1600_ASM is only added to the library compilation flags by the build - * system, not to test binaries. Since the x4 declarations in internal/sha3.h - * are guarded by that macro, we define it here before the include so that the - * KECCAK1600_X4_AVX512VL_CTX type and function prototypes are visible. - * The symbols themselves live in libcrypto and are always present. - * We additionally gate all x4 code on x86_64 (GCC/Clang: __x86_64__, - * MSVC: _M_AMD64/_M_X64) and !OPENSSL_NO_ASM so that the test still - * compiles on other platforms or in no-asm builds. - */ -#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \ - && !defined(OPENSSL_NO_ASM) -#ifndef KECCAK1600_ASM -#define KECCAK1600_ASM -#endif -#endif -#include "internal/sha3.h" - -/* - * A single deterministic 1024-byte message. Each of the four lanes receives - * a different slice of this buffer, with lane base pointers spaced 64 bytes - * apart, so their inputs are distinct yet entirely self-contained. - */ -#define MSG_BUF_SIZE 1024 -#define LANE_STRIDE 64 /* byte offset between lane base pointers */ -#define NUM_LANES 4 - -static unsigned char msg[MSG_BUF_SIZE]; - -/* Maximum output length used in this file – must fit chunk1 + chunk2. */ -#define MAX_OUT 640 - -#if defined(KECCAK1600_ASM) \ - && (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \ - && !defined(OPENSSL_NO_ASM) - -/* - * Input lengths exercising: empty, tiny, sub-block, block boundary ±1, - * multiple blocks and a longer message for SHAKE-128 (rate=168) and - * SHAKE-256 (rate=136). - */ -static const size_t input_sizes[] = { - 0, 1, 17, 100, 135, 136, 137, 168, 169, 200, 400 -}; -#define NUM_INPUT_SIZES (sizeof(input_sizes) / sizeof(input_sizes[0])) - -/* Output lengths chosen to straddle rate boundaries for both variants. */ -static const size_t output_sizes[] = { - 16, 32, 64, 136, 168, 256, 512 -}; -#define NUM_OUTPUT_SIZES (sizeof(output_sizes) / sizeof(output_sizes[0])) - -/* Helpers functions */ - -/* - * Compute a scalar SHAKE-128 or SHAKE-256 digest. - * bitlen: 128 or 256. Returns 1 on success, 0 on failure. - */ -static int scalar_shake(const unsigned int bitlen, - const unsigned char *in, const size_t inlen, - unsigned char *out, const size_t outlen) -{ - KECCAK1600_CTX ctx; - - if (!ossl_sha3_init(&ctx, 0x1f, bitlen)) - return 0; - /* ossl_sha3_init does not populate the method vtable; do it here. */ - ctx.meth.absorb = ossl_sha3_absorb_default; - ctx.meth.final = ossl_sha3_final_default; - ctx.meth.squeeze = ossl_shake_squeeze_default; - return ossl_sha3_absorb(&ctx, in, inlen) - && ossl_sha3_squeeze(&ctx, out, outlen); -} - -/* - * Encode (inlen_idx, outlen_idx) into a single test index and back. - * test index n = inlen_idx * NUM_OUTPUT_SIZES + outlen_idx - */ -static void decode_idx(const int n, size_t *inlen, size_t *outlen) -{ - *inlen = input_sizes[n / (int)NUM_OUTPUT_SIZES]; - *outlen = output_sizes[n % (int)NUM_OUTPUT_SIZES]; -} - -/* One-shot tests */ - -static int test_shake_x4_oneshot(const unsigned int bitlen, const int n) -{ - size_t inlen, outlen; - const unsigned char *in[NUM_LANES]; - unsigned char x4_out[NUM_LANES][MAX_OUT]; - unsigned char ref_out[NUM_LANES][MAX_OUT]; - int i; - - decode_idx(n, &inlen, &outlen); - - for (i = 0; i < NUM_LANES; i++) - in[i] = msg + i * LANE_STRIDE; - - /* Ensure the lane inputs fit within the message buffer. */ - if (!TEST_size_t_le(inlen + (NUM_LANES - 1) * LANE_STRIDE, MSG_BUF_SIZE)) - return 0; - if (!TEST_size_t_le(outlen, MAX_OUT)) - return 0; - - /* x4 single-call */ - if (bitlen == 128) - ossl_sha3_shake128_x4_avx512vl(x4_out[0], x4_out[1], x4_out[2], x4_out[3], - outlen, - in[0], in[1], in[2], in[3], inlen); - else - ossl_sha3_shake256_x4_avx512vl(x4_out[0], x4_out[1], x4_out[2], x4_out[3], - outlen, - in[0], in[1], in[2], in[3], inlen); - - /* scalar reference */ - for (i = 0; i < NUM_LANES; i++) - if (!TEST_true(scalar_shake(bitlen, in[i], inlen, ref_out[i], outlen))) - return 0; - - /* compare */ - for (i = 0; i < NUM_LANES; i++) { - if (!TEST_mem_eq(x4_out[i], outlen, ref_out[i], outlen)) { - TEST_info("SHAKE-%u x4 oneshot lane %d: inlen=%zu outlen=%zu", - bitlen, i, inlen, outlen); - return 0; - } - } - return 1; -} - -static int test_shake128_x4_oneshot(const int n) -{ - return test_shake_x4_oneshot(128, n); -} - -static int test_shake256_x4_oneshot(const int n) -{ - return test_shake_x4_oneshot(256, n); -} - -/* Incremental (init / absorb / finalize / squeeze) tests */ - -static int test_shake_x4_incremental(const unsigned int bitlen, const int n) -{ - size_t inlen, outlen; - const unsigned char *in[NUM_LANES]; - unsigned char x4_out[NUM_LANES][MAX_OUT]; - unsigned char ref_out[NUM_LANES][MAX_OUT]; - KECCAK1600_X4_AVX512VL_CTX ctx; - int i; - - decode_idx(n, &inlen, &outlen); - - for (i = 0; i < NUM_LANES; i++) - in[i] = msg + i * LANE_STRIDE; - - if (!TEST_size_t_le(inlen + (NUM_LANES - 1) * LANE_STRIDE, MSG_BUF_SIZE)) - return 0; - - /* x4 incremental */ - if (bitlen == 128) { - ossl_sha3_shake128_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake128_x4_inc_absorb_avx512vl(&ctx, in[0], in[1], in[2], in[3], - inlen); - ossl_sha3_shake128_x4_inc_squeeze_avx512vl(x4_out[0], x4_out[1], - x4_out[2], x4_out[3], outlen, &ctx); - } else { - ossl_sha3_shake256_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake256_x4_inc_absorb_avx512vl(&ctx, in[0], in[1], in[2], in[3], - inlen); - ossl_sha3_shake256_x4_inc_squeeze_avx512vl(x4_out[0], x4_out[1], - x4_out[2], x4_out[3], outlen, &ctx); - } - - /* scalar reference */ - for (i = 0; i < NUM_LANES; i++) - if (!TEST_true(scalar_shake(bitlen, in[i], inlen, ref_out[i], outlen))) - return 0; - - for (i = 0; i < NUM_LANES; i++) { - if (!TEST_mem_eq(x4_out[i], outlen, ref_out[i], outlen)) { - TEST_info("SHAKE-%u x4 incremental lane %d: inlen=%zu outlen=%zu", - bitlen, i, inlen, outlen); - return 0; - } - } - return 1; -} - -static int test_shake128_x4_incremental(const int n) -{ - return test_shake_x4_incremental(128, n); -} - -static int test_shake256_x4_incremental(const int n) -{ - return test_shake_x4_incremental(256, n); -} - -/* Multi-absorb tests */ - -/* - * Split the input at every tested input size, absorbing the two halves - * in separate calls. The split length is chosen as input_sizes[n] so that - * we exercise sub-block, at-block and multi-block split points. - * - * Full message length is fixed at the largest tested input size so that - * every split index is meaningful. - */ -static int test_shake_x4_multi_absorb(const unsigned int bitlen, const int n) -{ - const size_t total = input_sizes[NUM_INPUT_SIZES - 1]; - const size_t split = input_sizes[n]; - const size_t outlen = 64; /* fixed output length for this sub-test */ - const unsigned char *in[NUM_LANES]; - unsigned char x4_out[NUM_LANES][MAX_OUT]; - unsigned char ref_out[NUM_LANES][MAX_OUT]; - KECCAK1600_X4_AVX512VL_CTX ctx; - int i; - - if (split > total) - return 1; /* nothing to test */ - - for (i = 0; i < NUM_LANES; i++) - in[i] = msg + i * LANE_STRIDE; - - if (!TEST_size_t_le(total + (NUM_LANES - 1) * LANE_STRIDE, MSG_BUF_SIZE)) - return 0; - - /* x4 split absorb */ - if (bitlen == 128) { - ossl_sha3_shake128_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake128_x4_inc_absorb_avx512vl(&ctx, - in[0], in[1], in[2], in[3], split); - ossl_sha3_shake128_x4_inc_absorb_avx512vl(&ctx, - in[0] + split, in[1] + split, in[2] + split, in[3] + split, - total - split); - ossl_sha3_shake128_x4_inc_squeeze_avx512vl(x4_out[0], x4_out[1], - x4_out[2], x4_out[3], outlen, &ctx); - } else { - ossl_sha3_shake256_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake256_x4_inc_absorb_avx512vl(&ctx, - in[0], in[1], in[2], in[3], split); - ossl_sha3_shake256_x4_inc_absorb_avx512vl(&ctx, - in[0] + split, in[1] + split, in[2] + split, in[3] + split, - total - split); - ossl_sha3_shake256_x4_inc_squeeze_avx512vl(x4_out[0], x4_out[1], - x4_out[2], x4_out[3], outlen, &ctx); - } - - /* scalar reference (single absorb of full message) */ - for (i = 0; i < NUM_LANES; i++) - if (!TEST_true(scalar_shake(bitlen, in[i], total, ref_out[i], outlen))) - return 0; - - for (i = 0; i < NUM_LANES; i++) { - if (!TEST_mem_eq(x4_out[i], outlen, ref_out[i], outlen)) { - TEST_info("SHAKE-%u x4 multi-absorb lane %d: total=%zu split=%zu", - bitlen, i, total, split); - return 0; - } - } - return 1; -} - -static int test_shake128_x4_multi_absorb(const int n) -{ - return test_shake_x4_multi_absorb(128, n); -} - -static int test_shake256_x4_multi_absorb(const int n) -{ - return test_shake_x4_multi_absorb(256, n); -} - -/* Multi-squeeze tests */ - -/* - * Squeeze in two successive calls and verify that the concatenated output - * matches a single scalar squeeze of the same total length. - * Parameterized over output_sizes[] for the first chunk; the second chunk - * is always 64 bytes so the total length varies. - */ -static int test_shake_x4_multi_squeeze(const unsigned int bitlen, const int n) -{ - const size_t inlen = 200; /* fixed input length */ - const size_t chunk1 = output_sizes[n]; - const size_t chunk2 = 64; - const size_t total = chunk1 + chunk2; - const unsigned char *in[NUM_LANES]; - unsigned char x4_a[NUM_LANES][MAX_OUT]; /* first chunk */ - unsigned char x4_b[NUM_LANES][MAX_OUT]; /* second chunk */ - unsigned char ref_out[NUM_LANES][MAX_OUT]; - KECCAK1600_X4_AVX512VL_CTX ctx; - int i; - - if (!TEST_size_t_le(total, MAX_OUT)) - return 0; - if (!TEST_size_t_le(inlen + (NUM_LANES - 1) * LANE_STRIDE, MSG_BUF_SIZE)) - return 0; - - for (i = 0; i < NUM_LANES; i++) - in[i] = msg + i * LANE_STRIDE; - - /* x4 two-shot squeeze */ - if (bitlen == 128) { - ossl_sha3_shake128_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake128_x4_inc_absorb_avx512vl(&ctx, in[0], in[1], in[2], in[3], - inlen); - /* first squeeze */ - ossl_sha3_shake128_x4_inc_squeeze_avx512vl(x4_a[0], x4_a[1], x4_a[2], x4_a[3], - chunk1, &ctx); - /* second squeeze – context carries state from previous call */ - ossl_sha3_shake128_x4_inc_squeeze_avx512vl(x4_b[0], x4_b[1], x4_b[2], x4_b[3], - chunk2, &ctx); - } else { - ossl_sha3_shake256_x4_inc_init_avx512vl(&ctx); - ossl_sha3_shake256_x4_inc_absorb_avx512vl(&ctx, in[0], in[1], in[2], in[3], - inlen); - ossl_sha3_shake256_x4_inc_squeeze_avx512vl(x4_a[0], x4_a[1], x4_a[2], x4_a[3], - chunk1, &ctx); - ossl_sha3_shake256_x4_inc_squeeze_avx512vl(x4_b[0], x4_b[1], x4_b[2], x4_b[3], - chunk2, &ctx); - } - - /* scalar reference – squeeze the full total in one call */ - for (i = 0; i < NUM_LANES; i++) - if (!TEST_true(scalar_shake(bitlen, in[i], inlen, ref_out[i], total))) - return 0; - - /* check first chunk, then second chunk */ - for (i = 0; i < NUM_LANES; i++) { - if (!TEST_mem_eq(x4_a[i], chunk1, ref_out[i], chunk1)) { - TEST_info("SHAKE-%u x4 multi-squeeze lane %d chunk1: " - "inlen=%zu chunk1=%zu chunk2=%zu", - bitlen, i, inlen, chunk1, chunk2); - return 0; - } - if (!TEST_mem_eq(x4_b[i], chunk2, ref_out[i] + chunk1, chunk2)) { - TEST_info("SHAKE-%u x4 multi-squeeze lane %d chunk2: " - "inlen=%zu chunk1=%zu chunk2=%zu", - bitlen, i, inlen, chunk1, chunk2); - return 0; - } - } - return 1; -} - -static int test_shake128_x4_multi_squeeze(const int n) -{ - return test_shake_x4_multi_squeeze(128, n); -} - -static int test_shake256_x4_multi_squeeze(const int n) -{ - return test_shake_x4_multi_squeeze(256, n); -} - -#endif /* KECCAK1600_ASM && x86_64 && !OPENSSL_NO_ASM */ - -/* Test entry point */ - -int setup_tests(void) -{ - size_t i; - - /* Fill the message buffer with a deterministic non-zero pattern. */ - for (i = 0; i < MSG_BUF_SIZE; i++) - msg[i] = (unsigned char)(251 * i + 17); - -#ifdef OPENSSL_CPUID_OBJ - OPENSSL_cpuid_setup(); -#endif - -#if !defined(KECCAK1600_ASM) \ - || !(defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \ - || defined(OPENSSL_NO_ASM) - return TEST_skip("SHAKE x4 API not available in this build"); -#else - if (!SHA3_avx512vl_capable()) { - return TEST_skip("AVX-512VL not available; skipping SHAKE x4 tests"); - } - - ADD_ALL_TESTS(test_shake128_x4_oneshot, - (int)(NUM_INPUT_SIZES * NUM_OUTPUT_SIZES)); - ADD_ALL_TESTS(test_shake256_x4_oneshot, - (int)(NUM_INPUT_SIZES * NUM_OUTPUT_SIZES)); - - ADD_ALL_TESTS(test_shake128_x4_incremental, - (int)(NUM_INPUT_SIZES * NUM_OUTPUT_SIZES)); - ADD_ALL_TESTS(test_shake256_x4_incremental, - (int)(NUM_INPUT_SIZES * NUM_OUTPUT_SIZES)); - - ADD_ALL_TESTS(test_shake128_x4_multi_absorb, (int)NUM_INPUT_SIZES); - ADD_ALL_TESTS(test_shake256_x4_multi_absorb, (int)NUM_INPUT_SIZES); - - ADD_ALL_TESTS(test_shake128_x4_multi_squeeze, (int)NUM_OUTPUT_SIZES); - ADD_ALL_TESTS(test_shake256_x4_multi_squeeze, (int)NUM_OUTPUT_SIZES); -#endif - - return 1; -} diff --git a/test/srptest.c b/test/srptest.c index d7620f95f9..0fceadd24b 100644 --- a/test/srptest.c +++ b/test/srptest.c @@ -149,10 +149,11 @@ static int run_srp_kat(void) /* use builtin 1024-bit params */ const SRP_gN *GN; - if (!TEST_ptr(GN = SRP_get_default_gN("1024")) - || !TEST_true(BN_hex2bn(&s, "BEB25379D1A8581EB5A727673A2441EE")) - /* Set up server's password entry */ - || !TEST_true(SRP_create_verifier_BN("alice", "password123", &s, &v, GN->N, + if (!TEST_ptr(GN = SRP_get_default_gN("1024"))) + goto err; + BN_hex2bn(&s, "BEB25379D1A8581EB5A727673A2441EE"); + /* Set up server's password entry */ + if (!TEST_true(SRP_create_verifier_BN("alice", "password123", &s, &v, GN->N, GN->g))) goto err; @@ -167,9 +168,8 @@ static int run_srp_kat(void) TEST_note(" okay"); /* Server random */ - if (!TEST_true(BN_hex2bn(&b, "E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" - "05284D20"))) - goto err; + BN_hex2bn(&b, "E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" + "05284D20"); /* Server's first message */ Bpub = SRP_Calc_B(b, GN->N, GN->g, v); @@ -187,9 +187,8 @@ static int run_srp_kat(void) TEST_note(" okay"); /* Client random */ - if (!TEST_true(BN_hex2bn(&a, "60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" - "DA2D4393"))) - goto err; + BN_hex2bn(&a, "60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" + "DA2D4393"); /* Client's response */ Apub = SRP_Calc_A(a, GN->N, GN->g); diff --git a/test/ssl-tests/33-compressed-spki.cnf b/test/ssl-tests/33-compressed-spki.cnf deleted file mode 100644 index fd9816a27e..0000000000 --- a/test/ssl-tests/33-compressed-spki.cnf +++ /dev/null @@ -1,76 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 2 - -test-0 = 0-tls12-compressed-spki -test-1 = 1-tls13-compressed-spki -# =========================================================== - -[0-tls12-compressed-spki] -ssl_conf = 0-tls12-compressed-spki-ssl - -[0-tls12-compressed-spki-ssl] -server = 0-tls12-compressed-spki-server -client = 0-tls12-compressed-spki-client - -[0-tls12-compressed-spki-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem -CipherString = DEFAULT -ClientCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem -VerifyMode = Require - -[0-tls12-compressed-spki-client] -Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem -CipherString = ECDHE-ECDSA-AES128-GCM-SHA256 -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem -VerifyMode = Peer - -[test-0] -ExpectedClientCertType = P-256 -ExpectedProtocol = TLSv1.2 -ExpectedResult = Success -ExpectedServerCertType = P-256 - - -# =========================================================== - -[1-tls13-compressed-spki] -ssl_conf = 1-tls13-compressed-spki-ssl - -[1-tls13-compressed-spki-ssl] -server = 1-tls13-compressed-spki-server -client = 1-tls13-compressed-spki-client - -[1-tls13-compressed-spki-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem -CipherString = DEFAULT -ClientCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem -MaxProtocol = TLSv1.3 -MinProtocol = TLSv1.3 -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem -VerifyMode = Require - -[1-tls13-compressed-spki-client] -Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem -CipherString = DEFAULT -MaxProtocol = TLSv1.3 -MinProtocol = TLSv1.3 -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem -VerifyMode = Peer - -[test-1] -ExpectedClientCertType = P-256 -ExpectedProtocol = TLSv1.3 -ExpectedResult = Success -ExpectedServerCertType = P-256 - - diff --git a/test/ssl-tests/33-compressed-spki.cnf.in b/test/ssl-tests/33-compressed-spki.cnf.in deleted file mode 100644 index 06302a46a9..0000000000 --- a/test/ssl-tests/33-compressed-spki.cnf.in +++ /dev/null @@ -1,81 +0,0 @@ -# -*- mode: perl; -*- -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - - -## End-to-end check that compressed-form EC leaf certificates -## (server-ec-compressed-cert.pem, P-256 named curve, SPKI bit-string -## leading byte 0x02 or 0x03, anchored to the P-384 EC root) work at -## both TLS 1.2 and TLS 1.3 in both directions: the client presents -## the same compressed leaf to a server that requires client -## authentication, exercising X.509 acceptance of compressed point -## form on both sides simultaneously. The ec_point_formats extension -## no longer affects X.509 cert selection or acceptance, so neither -## peer opts into LegacyECPointFormats; the default ec_point_formats -## lists ('uncompressed' only) and the compressed leaves coexist. - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = (); - -unless (disabled("ec") || disabled("tls1_2") || disabled("tls1_3")) { -@tests = ( - { - name => "tls12-compressed-spki", - server => { - "Certificate" => test_pem("server-ec-compressed-cert.pem"), - "PrivateKey" => test_pem("server-ec-compressed-key.pem"), - "VerifyCAFile" => test_pem("p384-root.pem"), - "ClientCAFile" => test_pem("p384-root.pem"), - "VerifyMode" => "Require", - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - }, - client => { - "Certificate" => test_pem("server-ec-compressed-cert.pem"), - "PrivateKey" => test_pem("server-ec-compressed-key.pem"), - "VerifyCAFile" => test_pem("p384-root.pem"), - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - "CipherString" => "ECDHE-ECDSA-AES128-GCM-SHA256", - }, - test => { - "ExpectedResult" => "Success", - "ExpectedProtocol" => "TLSv1.2", - "ExpectedServerCertType" => "P-256", - "ExpectedClientCertType" => "P-256", - }, - }, - - { - name => "tls13-compressed-spki", - server => { - "Certificate" => test_pem("server-ec-compressed-cert.pem"), - "PrivateKey" => test_pem("server-ec-compressed-key.pem"), - "VerifyCAFile" => test_pem("p384-root.pem"), - "ClientCAFile" => test_pem("p384-root.pem"), - "VerifyMode" => "Require", - "MinProtocol" => "TLSv1.3", - "MaxProtocol" => "TLSv1.3", - }, - client => { - "Certificate" => test_pem("server-ec-compressed-cert.pem"), - "PrivateKey" => test_pem("server-ec-compressed-key.pem"), - "VerifyCAFile" => test_pem("p384-root.pem"), - "MinProtocol" => "TLSv1.3", - "MaxProtocol" => "TLSv1.3", - }, - test => { - "ExpectedResult" => "Success", - "ExpectedProtocol" => "TLSv1.3", - "ExpectedServerCertType" => "P-256", - "ExpectedClientCertType" => "P-256", - }, - }, -); -} diff --git a/test/ssl_old_test.c b/test/ssl_old_test.c index 40df6536e3..8a3c7b5fb0 100644 --- a/test/ssl_old_test.c +++ b/test/ssl_old_test.c @@ -1284,7 +1284,7 @@ int main(int argc, char *argv[]) no_protocol = 0; /* - * Testing was requested for a compiled-out protocol (e.g. TLSv1, etc.). + * Testing was requested for a compiled-out protocol (e.g. SSLv3). * Ideally, we would error out, but the generic test wrapper can't know * when to expect failure. So we do nothing and return success. */ diff --git a/test/sslapitest.c b/test/sslapitest.c index 6fc18a0dc0..c1e15c1933 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -136,7 +136,6 @@ static const char *ocsp_signer_cert = "subinterCA.pem"; && defined(OPENSSL_NO_BROTLI) && defined(OPENSSL_NO_ZSTD) \ && !defined(OPENSSL_NO_ECX) && !defined(OPENSSL_NO_DH) \ && !defined(OPENSSL_NO_ML_DSA) && !defined(OPENSSL_NO_ML_KEM) \ - && !defined(OPENSSL_NO_SLH_DSA) \ && !defined(OPENSSL_NO_TLS1_3) && !defined(OPENSSL_NO_SM2) #define DO_SSL_TRACE_TEST #endif @@ -3030,58 +3029,6 @@ static int test_session_with_both_cache(void) #endif } -/* - * Test that remove_session_cb is not invoked while ctx->lock is held. - * The callback calls SSL_CTX_flush_sessions_ex(), which itself tries to - * acquire ctx->lock; if the lock is already held when the callback fires, - * the nested acquisition deadlocks immediately. t = 1 (Unix epoch + 1s) is - * used so that no current sessions are flushed and the callback is not - * re-entered. - */ -static void remove_session_lock_test_cb(SSL_CTX *ctx, SSL_SESSION *sess) -{ - SSL_CTX_flush_sessions_ex(ctx, 1); -} - -static int test_remove_session_cb_not_under_lock(void) -{ - SSL_CTX *ctx = NULL; - SSL_SESSION *sess1 = NULL, *sess2 = NULL; - static const unsigned char sid1[] = { 1 }; - static const unsigned char sid2[] = { 2 }; - int testresult = 0; - - if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method()))) - goto end; - - SSL_CTX_sess_set_cache_size(ctx, 1); - SSL_CTX_sess_set_remove_cb(ctx, remove_session_lock_test_cb); - - if (!TEST_ptr(sess1 = SSL_SESSION_new()) - || !TEST_true(SSL_SESSION_set1_id(sess1, sid1, sizeof(sid1))) - || !TEST_true(SSL_CTX_add_session(ctx, sess1))) - goto end; - - if (!TEST_ptr(sess2 = SSL_SESSION_new()) - || !TEST_true(SSL_SESSION_set1_id(sess2, sid2, sizeof(sid2)))) - goto end; - - /* - * Adding sess2 evicts sess1 (cache is full), firing remove_session_cb. - * If the callback is invoked while holding ctx->lock the flush call - * inside it will deadlock. - */ - if (!TEST_true(SSL_CTX_add_session(ctx, sess2))) - goto end; - - testresult = 1; -end: - SSL_SESSION_free(sess1); - SSL_SESSION_free(sess2); - SSL_CTX_free(ctx); - return testresult; -} - static int test_session_wo_ca_names(void) { #ifndef OSSL_NO_USABLE_TLS1_3 @@ -6546,165 +6493,6 @@ end: return testresult; } -/* - * A server with SSL_VERIFY_PEER set but no session ID context configured - * must still accept a TLS 1.3 external PSK connection: the session was - * just resolved via the application's own callback for this identity, not - * read back out of a shared cache, so the sid_ctx check that guards - * against cross-context cache reuse does not apply to it. - */ -static int test_tls13_psk_verify_peer_no_sid_ctx(void) -{ - SSL_CTX *sctx = NULL, *cctx = NULL; - SSL *serverssl = NULL, *clientssl = NULL; - int testresult = 0; - - if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), - TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, NULL, NULL)) - || !TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_128_GCM_SHA256"))) - goto end; - - SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL); - - SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb); - SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb); - srvid = pskid; - use_session_cb_cnt = 0; - find_session_cb_cnt = 0; - - if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL))) - goto end; - - clientpsk = create_a_psk(clientssl, SHA256_DIGEST_LENGTH); - if (!TEST_ptr(clientpsk) || !TEST_true(SSL_SESSION_up_ref(clientpsk))) - goto end; - serverpsk = clientpsk; - - if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) - || !TEST_true(SSL_session_reused(clientssl)) - || !TEST_true(SSL_session_reused(serverssl))) - goto end; - - testresult = 1; -end: - SSL_SESSION_free(clientpsk); - SSL_SESSION_free(serverpsk); - clientpsk = serverpsk = NULL; - SSL_free(serverssl); - SSL_free(clientssl); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - return testresult; -} - -/* - * A server with SSL_VERIFY_PEER set but no session ID context configured - * must not issue a session ticket after a full (non-PSK) handshake: any - * such ticket would be a poison pill, since resuming it would hit exactly - * the sid_ctx check that a fresh external PSK is exempted from above. - */ -static int test_tls13_psk_verify_peer_no_ticket(void) -{ - SSL_CTX *sctx = NULL, *cctx = NULL; - SSL *serverssl = NULL, *clientssl = NULL; - SSL_SESSION *sess = NULL; - int testresult = 0; - - if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), - TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) - goto end; - - SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL); - - if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL)) - || !TEST_true(create_ssl_connection(serverssl, clientssl, - SSL_ERROR_NONE))) - goto end; - - sess = SSL_get1_session(clientssl); - if (!TEST_ptr(sess) || !TEST_false(SSL_SESSION_has_ticket(sess))) - goto end; - - testresult = 1; -end: - SSL_SESSION_free(sess); - SSL_free(serverssl); - SSL_free(clientssl); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - return testresult; -} - -/* - * A client with its own session ID context configured must still be able - * to resume a TLS 1.3 external PSK obtained via the legacy - * psk_use_session_cb()/psk_client_callback() callbacks. s->psksession is - * never routed through ssl_get_new_session(), so, unlike an ordinary - * session, it was never stamped with the client's own sid_ctx; without - * that stamp tls_process_server_hello()'s own sid_ctx self-consistency - * check fatally rejects marking it reused. - * - * Test 0: new style callback (psk_use_session_cb()/psk_find_session_cb()). - * Test 1: old style callback (psk_client_callback()/psk_server_callback()). - */ -static int test_tls13_psk_client_sid_ctx(int idx) -{ - SSL_CTX *sctx = NULL, *cctx = NULL; - SSL *serverssl = NULL, *clientssl = NULL; - int sess_id_ctx = 1; - int testresult = 0; - - if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), - TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, NULL, NULL)) - || !TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_128_GCM_SHA256")) - || !TEST_true(SSL_CTX_set_session_id_context(cctx, - (void *)&sess_id_ctx, sizeof(sess_id_ctx)))) - goto end; - - srvid = pskid; - if (idx == 0) { - SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb); - SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb); - use_session_cb_cnt = 0; - find_session_cb_cnt = 0; - } -#ifndef OPENSSL_NO_PSK - else { - SSL_CTX_set_psk_client_callback(cctx, psk_client_cb); - SSL_CTX_set_psk_server_callback(sctx, psk_server_cb); - psk_client_cb_cnt = 0; - psk_server_cb_cnt = 0; - } -#endif - - if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL))) - goto end; - - clientpsk = create_a_psk(clientssl, SHA256_DIGEST_LENGTH); - if (!TEST_ptr(clientpsk) || !TEST_true(SSL_SESSION_up_ref(clientpsk))) - goto end; - serverpsk = clientpsk; - - if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) - || !TEST_true(SSL_session_reused(clientssl)) - || !TEST_true(SSL_session_reused(serverssl))) - goto end; - - testresult = 1; -end: - SSL_SESSION_free(clientpsk); - SSL_SESSION_free(serverpsk); - clientpsk = serverpsk = NULL; - SSL_free(serverssl); - SSL_free(clientssl); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - return testresult; -} - #ifndef OSSL_NO_USABLE_TLS1_3 /* * Test TLS1.3 connection establishment succeeds with various configurations of @@ -10812,8 +10600,7 @@ static int test_session_cache_overflow(int idx) SSL *serverssl = NULL, *clientssl = NULL; int testresult = 0; SSL_SESSION *sess = NULL; - - get_sess_val = NULL; + int references; #ifdef OSSL_NO_USABLE_TLS1_3 /* If no TLSv1.3 available then do nothing in this case */ @@ -10884,9 +10671,18 @@ static int test_session_cache_overflow(int idx) * The session we just negotiated may have been already removed from the * internal cache - but we will return it anyway from our external cache. */ - get_sess_val = SSL_get1_session(serverssl); + get_sess_val = SSL_get_session(serverssl); if (!TEST_ptr(get_sess_val)) goto end; + /* + * Normally the session is also stored in the cache, thus we have more than + * one reference, but due to an out-of-memory error it can happen that this + * is the only reference, and in that case the SSL_free(serverssl) below + * would free the get_sess_val, causing a use-after-free error. + */ + if (!TEST_true(CRYPTO_GET_REF(&get_sess_val->references, &references)) + || !TEST_int_ge(references, 2)) + goto end; sess = SSL_get1_session(clientssl); if (!TEST_ptr(sess)) goto end; @@ -10910,8 +10706,6 @@ static int test_session_cache_overflow(int idx) testresult = 1; end: - SSL_SESSION_free(get_sess_val); - get_sess_val = NULL; SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); @@ -12598,7 +12392,7 @@ static int test_legacy_ec_point_formats(void) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; - const unsigned char *pformats = NULL; + const char *pformats = NULL; int nformats; int testresult = 0; @@ -13079,51 +12873,6 @@ end: SSL_CTX_free(cctx); return testresult; } - -static int un_ext_add_cb(SSL *s, unsigned int ext_type, - unsigned int context, const unsigned char **out, size_t *outlen, X509 *x, - size_t chainidx, int *al, void *add_arg) -{ - static const unsigned char data[] = { 0xaa }; - *out = data; - *outlen = sizeof(data); - return 1; -} - -static int un_ext_parse_cb(SSL *s, unsigned int ext_type, - unsigned int context, const unsigned char *in, size_t inlen, X509 *x, - size_t chainidx, int *al, void *parse_arg) -{ - return 1; -} - -/* - * Test that a handshake succeeds when the peer sends an extension type we do - * not recognise. The client registers a custom extension in its ClientHello - * that the server knows nothing about, so on the server tls_collect_extensions() - * takes the "unknown extension" branch. - */ -static int test_tls13_unknown_extension(void) -{ - SSL_CTX *s = NULL, *c = NULL; - SSL *s_ssl = NULL, *c_ssl = NULL; - int test; - - test = TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), - TLS_client_method(), TLS1_3_VERSION, TLS1_3_VERSION, &s, &c, cert, privkey)) - && TEST_true(SSL_CTX_add_custom_ext(c, 0xfefe, SSL_EXT_CLIENT_HELLO, - un_ext_add_cb, NULL, NULL, un_ext_parse_cb, NULL)) - && TEST_true(create_ssl_objects(s, c, &s_ssl, &c_ssl, NULL, NULL)) - /* The server must tolerate the unknown extension and complete. */ - && TEST_true(create_ssl_connection(s_ssl, c_ssl, SSL_ERROR_NONE)); - - SSL_free(s_ssl); - SSL_free(c_ssl); - SSL_CTX_free(s); - SSL_CTX_free(c); - return test; -} - #endif /* OSSL_NO_USABLE_TLS1_3 */ static int check_version_string(SSL *s, int version) @@ -15430,7 +15179,6 @@ int setup_tests(void) ADD_TEST(test_session_with_only_int_cache); ADD_TEST(test_session_with_only_ext_cache); ADD_TEST(test_session_with_both_cache); - ADD_TEST(test_remove_session_cb_not_under_lock); ADD_TEST(test_session_wo_ca_names); #ifndef OSSL_NO_USABLE_TLS1_3 ADD_ALL_TESTS(test_stateful_tickets, 3); @@ -15484,13 +15232,9 @@ int setup_tests(void) ADD_ALL_TESTS(test_tls13_ciphersuite, 4); #ifdef OPENSSL_NO_PSK ADD_ALL_TESTS(test_tls13_psk, 1); - ADD_ALL_TESTS(test_tls13_psk_client_sid_ctx, 1); #else ADD_ALL_TESTS(test_tls13_psk, 4); - ADD_ALL_TESTS(test_tls13_psk_client_sid_ctx, 2); #endif /* OPENSSL_NO_PSK */ - ADD_TEST(test_tls13_psk_verify_peer_no_sid_ctx); - ADD_TEST(test_tls13_psk_verify_peer_no_ticket); #ifndef OSSL_NO_USABLE_TLS1_3 ADD_ALL_TESTS(test_tls13_no_dhe_kex, 8); #endif /* OSSL_NO_USABLE_TLS1_3 */ @@ -15588,7 +15332,6 @@ int setup_tests(void) #ifndef OSSL_NO_USABLE_TLS1_3 ADD_TEST(test_read_ahead_key_change); ADD_ALL_TESTS(test_tls13_record_padding, 6); - ADD_TEST(test_tls13_unknown_extension); #endif #if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3) ADD_ALL_TESTS(test_serverinfo_custom, 4); diff --git a/test/sslbuffertest.c b/test/sslbuffertest.c index 13b6f6b404..c7bcbe66e9 100644 --- a/test/sslbuffertest.c +++ b/test/sslbuffertest.c @@ -177,7 +177,7 @@ end: * Test 1: Attempt to free buffers after only a partial record header has been * received * Test 2: Attempt to free buffers after a full record header but no record body - * Test 3: Attempt to free buffers after a full record header and partial record + * Test 3: Attempt to free buffers after a full record hedaer and partial record * body */ static int test_free_buffers(int test) diff --git a/test/stack_test.c b/test/stack_test.c index c2ed731f44..848c843931 100644 --- a/test/stack_test.c +++ b/test/stack_test.c @@ -255,15 +255,6 @@ static int test_uchar_stack(int reserve) goto end; sk_uchar_sort(r); sk_uchar_sort(q); - for (i = 0; i < n; i++) { - int idx = sk_uchar_find(q, v + i); - - if (!TEST_int_ge(idx, 0) - || !TEST_uchar_eq(*sk_uchar_value(q, idx), v[i])) { - TEST_info("uchar sorted find %d", i); - goto end; - } - } /* pop */ for (i = 0; i < n; i++) { @@ -353,35 +344,11 @@ static char *string_copy(const char *p) return OPENSSL_strdup(p); } -static int string_cmp(const char *const *a, const char *const *b) -{ - return strcmp(*a, *b); -} - static void string_free(char *p) { OPENSSL_free(p); } -static int push_string(STACK_OF(OPENSSL_STRING) *s, const char *str) -{ - char *p = OPENSSL_strdup(str); - int expected = sk_OPENSSL_STRING_num(s) + 1; - int pushed; - - if (!TEST_ptr(p)) - return 0; - - pushed = sk_OPENSSL_STRING_push(s, p); - if (!TEST_int_eq(pushed, expected)) { - if (pushed <= 0) - OPENSSL_free(p); - return 0; - } - - return 1; -} - static int test_SS_stack(void) { STACK_OF(TST_SS) *s = sk_TST_SS_new_null(); @@ -541,88 +508,11 @@ end: return testresult; } -static int test_STRING_STACK_stack_ubsan(int idx) -{ - STACK_OF(OPENSSL_STRING) *s = NULL; - STACK_OF(OPENSSL_STRING) *t = NULL; - STACK_OF(OPENSSL_STRING) *u = NULL; - int testresult = 0; - - switch (idx) { - case 0: - s = sk_OPENSSL_STRING_new_null(); - break; - case 1: - s = sk_OPENSSL_STRING_new(string_cmp); - break; - case 2: - s = sk_OPENSSL_STRING_new_reserve(string_cmp, 2); - break; - case 3: - s = sk_OPENSSL_STRING_deep_copy(NULL, string_copy, string_free); - break; - case 4: - t = sk_OPENSSL_STRING_new(string_cmp); - if (!TEST_ptr(t)) - goto end; - if (!push_string(t, "b") - || !push_string(t, "a")) - goto end; - s = sk_OPENSSL_STRING_dup(t); - if (s != NULL) { - sk_OPENSSL_STRING_free(t); - t = NULL; - } - break; - case 5: - t = sk_OPENSSL_STRING_deep_copy(NULL, string_copy, string_free); - if (!TEST_ptr(t)) - goto end; - if (!push_string(t, "b") - || !push_string(t, "a")) - goto end; - s = sk_OPENSSL_STRING_deep_copy(t, string_copy, string_free); - break; - default: - goto end; - } - if (!TEST_ptr(s)) - goto end; - - if (idx < 4) { - if (!push_string(s, "b") - || !push_string(s, "a")) - goto end; - } - - sk_OPENSSL_STRING_set_cmp_func(s, string_cmp); - sk_OPENSSL_STRING_sort(s); - if (!TEST_str_eq(sk_OPENSSL_STRING_value(s, 0), "a") - || !TEST_int_eq(sk_OPENSSL_STRING_find(s, "b"), 1)) - goto end; - - u = sk_OPENSSL_STRING_deep_copy(s, string_copy, string_free); - if (!TEST_ptr(u) - || !TEST_int_eq(sk_OPENSSL_STRING_num(u), 2) - || !TEST_ptr_ne(sk_OPENSSL_STRING_value(u, 0), - sk_OPENSSL_STRING_value(s, 0)) - || !TEST_str_eq(sk_OPENSSL_STRING_value(u, 0), "a")) - goto end; - - testresult = 1; -end: - sk_OPENSSL_STRING_pop_free(u, string_free); - sk_OPENSSL_STRING_pop_free(s, string_free); - sk_OPENSSL_STRING_pop_free(t, string_free); - return testresult; -} - int setup_tests(void) { ADD_ALL_TESTS(test_int_stack, 4); ADD_ALL_TESTS(test_uchar_stack, 4); ADD_TEST(test_SS_stack); - ADD_ALL_TESTS(test_STRING_STACK_stack_ubsan, 6); ADD_TEST(test_SU_stack); ADD_MFAIL_TEST(test_OPENSSL_STRING_deep_copy_mfail); return 1; diff --git a/test/statem_clnt_construct_test.c b/test/statem_clnt_construct_test.c deleted file mode 100644 index 350e59ce2f..0000000000 --- a/test/statem_clnt_construct_test.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Direct tests for the client state-machine construct functions in - * statem_clnt.c: prime a client SSL_CONNECTION enough to call a construct - * function without a full handshake, then check the result structurally and, - * where useful, by round-tripping it through the server parser. OOM branches - * are covered with mfail tests. - */ - -#include -#ifndef OPENSSL_NO_ECH -#include -#include -#endif - -#include "internal/ssl_unwrap.h" -#include "../ssl/ssl_local.h" -#include "../ssl/statem/statem_local.h" -#include "testutil.h" - -/* - * TLS 1.3 needs a key-share group, so it is unusable when both EC and DH are - * disabled even though the protocol itself is compiled in (e.g. no-bulk). - */ -#if defined(OPENSSL_NO_TLS1_3) \ - || (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH)) -#define OSSL_NO_USABLE_TLS1_3 -#endif - -/* ECH needs a curve (EC/ECX) for its default suite and usable TLS 1.3. */ -#if defined(OPENSSL_NO_ECH) || defined(OPENSSL_NO_EC) \ - || defined(OPENSSL_NO_ECX) || defined(OSSL_NO_USABLE_TLS1_3) -#define OSSL_NO_USABLE_ECH -#endif - -/* - * Helpers down to finish_msg() are generic and reusable by tests for any - * statem_clnt construct function; the per-message code follows. - */ - -/* Connection configuration shared by the construct tests. */ -typedef struct { - int is_dtls; - int min_ver; /* 0 for library default */ - int max_ver; /* 0 for library default */ - int clear_midbox; /* clear SSL_OP_ENABLE_MIDDLEBOX_COMPAT */ -} CH_CONFIG; - -static const SSL_METHOD *client_method(const CH_CONFIG *cfg) -{ - return cfg->is_dtls ? DTLS_client_method() : TLS_client_method(); -} - -/* Handshake message header length (msg precedes the ClientHello body). */ -static size_t hdr_len(const CH_CONFIG *cfg) -{ - return cfg->is_dtls ? DTLS1_HM_HEADER_LENGTH : SSL3_HM_HEADER_LENGTH; -} - -static const SSL_METHOD *server_method(const CH_CONFIG *cfg) -{ - return cfg->is_dtls ? DTLS_server_method() : TLS_server_method(); -} - -static SSL_CTX *new_ctx(const CH_CONFIG *cfg, const SSL_METHOD *meth) -{ - SSL_CTX *ctx = SSL_CTX_new(meth); - - if (ctx == NULL) - return NULL; - if ((cfg->min_ver != 0 - && !SSL_CTX_set_min_proto_version(ctx, cfg->min_ver)) - || (cfg->max_ver != 0 - && !SSL_CTX_set_max_proto_version(ctx, cfg->max_ver))) { - SSL_CTX_free(ctx); - return NULL; - } - return ctx; -} - -/* - * Set up the init_buf and handshake state the write state machine would have - * established before calling a construct function. For the client a WPACKET - * with the handshake header for message type mt is emitted into init_buf. - * initbuf_len of 0 means full size; a small value exercises WPACKET failures. - */ -static int prime_ssl(SSL *ssl, int is_client, size_t initbuf_len, WPACKET *pkt, - int mt) -{ - SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL(ssl); - - if (!TEST_ptr(s)) - return 0; - - if (is_client) - SSL_set_connect_state(ssl); - else - SSL_set_accept_state(ssl); - - if (initbuf_len == 0) - initbuf_len = SSL3_RT_MAX_PLAIN_LENGTH; - - if (!TEST_ptr(s->init_buf = BUF_MEM_new()) - || !TEST_true(BUF_MEM_grow(s->init_buf, initbuf_len))) - return 0; - - if (!TEST_true(tls_setup_handshake(s))) - return 0; - - if (pkt != NULL - && (!TEST_true(WPACKET_init(pkt, s->init_buf)) - || !TEST_true(ssl_set_handshake_header(s, pkt, mt)))) - return 0; - - return 1; -} - -/* Finalize a constructed message and return its bytes (header + body). */ -static int finish_msg(SSL *ssl, WPACKET *pkt, int mt, unsigned char **msg, - size_t *msglen) -{ - SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL(ssl); - - if (!TEST_ptr(s) - || !TEST_true(ssl_close_construct_packet(s, pkt, mt)) - || !TEST_true(WPACKET_get_total_written(pkt, msglen)) - || !TEST_true(WPACKET_finish(pkt))) - return 0; - - *msg = (unsigned char *)s->init_buf->data; - return 1; -} - -/* - * =========================================================================== - * tls_construct_client_hello - * =========================================================================== - */ - -/* Recover the session_id length, the main branching difference in construct. */ -static int get_ch_sessid_len(const CH_CONFIG *cfg, const unsigned char *msg, - size_t msglen, size_t *sidlen) -{ - PACKET pkt = { 0 }, sessid = { 0 }, cookie = { 0 }; - PACKET ciphers = { 0 }, comp = { 0 }; - unsigned int legacy_version; - size_t hl = hdr_len(cfg); - - if (!TEST_size_t_gt(msglen, hl) - || !TEST_true(PACKET_buf_init(&pkt, msg + hl, msglen - hl))) - return 0; - - if (!TEST_true(PACKET_get_net_2(&pkt, &legacy_version)) - || !TEST_true(PACKET_forward(&pkt, SSL3_RANDOM_SIZE)) - || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &sessid))) - return 0; - - if (cfg->is_dtls - && !TEST_true(PACKET_get_length_prefixed_1(&pkt, &cookie))) - return 0; - - /* Sanity: cipher list non-empty, compression present and contains NULL. */ - if (!TEST_true(PACKET_get_length_prefixed_2(&pkt, &ciphers)) - || !TEST_size_t_gt(PACKET_remaining(&ciphers), 0) - || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &comp)) - || !TEST_size_t_gt(PACKET_remaining(&comp), 0)) - return 0; - - *sidlen = PACKET_remaining(&sessid); - return 1; -} - -/* Run the produced ClientHello body through the server-side parser. */ -static int roundtrip_process_ch(const CH_CONFIG *cfg, const unsigned char *msg, - size_t msglen) -{ - SSL_CTX *sctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - PACKET pkt; - int ret = 0; - - if (!TEST_ptr(sctx = new_ctx(cfg, server_method(cfg))) - || !TEST_ptr(ssl = SSL_new(sctx))) - goto err; - - if (!prime_ssl(ssl, 0, 0, NULL, SSL3_MT_CLIENT_HELLO)) - goto err; - s = SSL_CONNECTION_FROM_SSL(ssl); - - if (!TEST_true(PACKET_buf_init(&pkt, msg + hdr_len(cfg), - msglen - hdr_len(cfg)))) - goto err; - - if (!TEST_int_eq(tls_process_client_hello(s, &pkt), - MSG_PROCESS_CONTINUE_PROCESSING)) - goto err; - - ret = 1; -err: - SSL_free(ssl); - SSL_CTX_free(sctx); - return ret; -} - -/* - * Construct a ClientHello, assert its session_id length and optionally - * round-trip it. prep injects extra state just before construct; - * expect_random asserts the produced client random (to check reuse). - * Both may be NULL. - */ -static int do_construct_ch(const CH_CONFIG *cfg, - int (*prep)(SSL_CONNECTION *s), size_t expect_sidlen, int roundtrip, - const unsigned char *expect_random) -{ - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - unsigned char *msg = NULL; - size_t msglen = 0, sidlen = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(cfg, client_method(cfg))) - || !TEST_ptr(ssl = SSL_new(cctx))) - goto err; - if (cfg->clear_midbox) - SSL_clear_options(ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); - - if (!prime_ssl(ssl, 1, 0, &pkt, SSL3_MT_CLIENT_HELLO)) - goto err; - s = SSL_CONNECTION_FROM_SSL(ssl); - - if (prep != NULL && !prep(s)) { - WPACKET_cleanup(&pkt); - goto err; - } - - if (!TEST_int_eq(tls_construct_client_hello(s, &pkt), CON_FUNC_SUCCESS)) { - WPACKET_cleanup(&pkt); - goto err; - } - if (!finish_msg(ssl, &pkt, SSL3_MT_CLIENT_HELLO, &msg, &msglen)) - goto err; - - if (!get_ch_sessid_len(cfg, msg, msglen, &sidlen) - || !TEST_size_t_eq(sidlen, expect_sidlen)) - goto err; - - /* The client random follows the 2-byte legacy_version in the body. */ - if (expect_random != NULL - && !TEST_mem_eq(msg + hdr_len(cfg) + 2, SSL3_RANDOM_SIZE, - expect_random, SSL3_RANDOM_SIZE)) - goto err; - - if (roundtrip && !roundtrip_process_ch(cfg, msg, msglen)) - goto err; - - ret = 1; -err: - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -/* Expect tls_construct_client_hello() to fail (CON_FUNC_ERROR). */ -static int do_construct_ch_expect_fail(const CH_CONFIG *cfg, - int (*prep)(SSL_CONNECTION *s), - size_t initbuf_len, int empty_ciphers) -{ - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - int have_pkt = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(cfg, client_method(cfg))) - || !TEST_ptr(ssl = SSL_new(cctx))) - goto err; - - if (empty_ciphers) { - /* Leave no usable cipher: aNULL is disabled at default sec level. */ - int r1 = SSL_set_ciphersuites(ssl, ""); - int r2 = SSL_set_cipher_list(ssl, "aNULL"); - - (void)r1; - (void)r2; - } - - if (!prime_ssl(ssl, 1, initbuf_len, &pkt, SSL3_MT_CLIENT_HELLO)) - goto err; - have_pkt = 1; - s = SSL_CONNECTION_FROM_SSL(ssl); - - if (prep != NULL && !prep(s)) - goto err; - - if (!TEST_int_eq(tls_construct_client_hello(s, &pkt), CON_FUNC_ERROR)) - goto err; - - ret = 1; -err: - if (have_pkt) - WPACKET_cleanup(&pkt); - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -/* TLS 1.2 happy-path / session tests */ - -#ifndef OPENSSL_NO_TLS1_2 -static int test_construct_ch_tls12(void) -{ - CH_CONFIG cfg = { 0, TLS1_2_VERSION, TLS1_2_VERSION, 0 }; - - /* Fresh (non-resumable) TLS 1.2 session: empty session id. */ - return do_construct_ch(&cfg, NULL, 0, 1, NULL); -} - -/* Resumable non-TLS1.3 session: construct reuses its session id. */ -static int prep_resume(SSL_CONNECTION *s) -{ - SSL *ssl = SSL_CONNECTION_GET_SSL(s); - SSL_SESSION *sess = SSL_SESSION_new(); - int ret = 0; - - if (!TEST_ptr(sess)) - goto err; - sess->ssl_version = TLS1_2_VERSION; - sess->session_id_length = sizeof(sess->session_id); - memset(sess->session_id, 0x5A, sess->session_id_length); - sess->cipher = sk_SSL_CIPHER_value(SSL_get_ciphers(ssl), 0); - if (!TEST_ptr(sess->cipher) || !TEST_true(SSL_set_session(ssl, sess))) - goto err; - ret = 1; -err: - SSL_SESSION_free(sess); - return ret; -} - -static int test_construct_ch_resume(void) -{ - CH_CONFIG cfg = { 0, TLS1_2_VERSION, TLS1_2_VERSION, 0 }; - - /* Resumed session: the pre-loaded 32-byte session id is sent. */ - return do_construct_ch(&cfg, prep_resume, SSL_MAX_SSL_SESSION_ID_LENGTH, 1, - NULL); -} -#endif /* OPENSSL_NO_TLS1_2 */ - -/* TLS 1.3 happy-path / HRR tests */ - -#ifndef OSSL_NO_USABLE_TLS1_3 -static int test_construct_ch_tls13(void) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 0 }; - - /* Middlebox compat is on by default: a random 32-byte session id. */ - return do_construct_ch(&cfg, NULL, SSL_MAX_SSL_SESSION_ID_LENGTH, 1, NULL); -} - -static int test_construct_ch_tls13_no_middlebox(void) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 1 }; - - /* No middlebox compat: empty session id. */ - return do_construct_ch(&cfg, NULL, 0, 1, NULL); -} - -static int prep_hrr(SSL_CONNECTION *s) -{ - SSL *ssl = SSL_CONNECTION_GET_SSL(s); - SSL_SESSION *sess = SSL_SESSION_new(); - int ret = 0; - - /* Under HRR construct skips ssl_get_new_session(), so a session must - * already exist (created for the first ClientHello). */ - if (!TEST_ptr(sess)) - goto err; - sess->ssl_version = TLS1_3_VERSION; - sess->cipher = sk_SSL_CIPHER_value(SSL_get_ciphers(ssl), 0); - if (!TEST_ptr(sess->cipher) || !TEST_true(SSL_set_session(ssl, sess))) - goto err; - s->hello_retry_request = SSL_HRR_COMPLETE; - ret = 1; -err: - SSL_SESSION_free(sess); - return ret; -} - -static int test_construct_ch_hrr(void) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 0 }; - - /* TLS 1.3 + middlebox compat still emits a 32-byte session id under HRR. */ - return do_construct_ch(&cfg, prep_hrr, SSL_MAX_SSL_SESSION_ID_LENGTH, 1, - NULL); -} -#endif /* OSSL_NO_USABLE_TLS1_3 */ - -/* DTLS happy-path / cookie / random-reuse tests */ - -#if !defined(OPENSSL_NO_DTLS) && !defined(OPENSSL_NO_DTLS1_2) -static int test_construct_ch_dtls(void) -{ - CH_CONFIG cfg = { 1, 0, 0, 0 }; - - /* DTLS uses a different server parser path; skip the roundtrip. */ - return do_construct_ch(&cfg, NULL, 0, 0, NULL); -} - -static int prep_dtls_cookie(SSL_CONNECTION *s) -{ - /* A HelloVerifyRequest cookie is echoed in the ClientHello. */ - static const unsigned char cookie[16] = { - 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, - 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xc0, 0x08 - }; - - memcpy(s->d1->cookie, cookie, sizeof(cookie)); - s->d1->cookie_len = sizeof(cookie); - return 1; -} - -static int test_construct_ch_dtls_cookie(void) -{ - CH_CONFIG cfg = { 1, 0, 0, 0 }; - - return do_construct_ch(&cfg, prep_dtls_cookie, 0, 0, NULL); -} - -/* A recognizable, all-non-zero client random to detect reuse. */ -static const unsigned char reused_random[SSL3_RANDOM_SIZE] = { - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf -}; - -static int prep_dtls_client_random(SSL_CONNECTION *s) -{ - /* DTLS reuses an already-set client random (HelloVerifyRequest reply). */ - memcpy(s->s3.client_random, reused_random, sizeof(reused_random)); - return 1; -} - -static int test_construct_ch_dtls_client_random(void) -{ - CH_CONFIG cfg = { 1, 0, 0, 0 }; - - return do_construct_ch(&cfg, prep_dtls_client_random, 0, 0, reused_random); -} -#endif /* OPENSSL_NO_DTLS */ - -/* Deterministic error-branch tests */ - -static int test_construct_ch_small_buf(void) -{ - /* Default version: the overflow is version-independent. */ - CH_CONFIG cfg = { 0, 0, 0, 0 }; - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - /* - * Fixed, non-growable buffer that overflows part-way through the body (a - * BUF_MEM-backed WPACKET would just grow), hitting a WPACKET write failure. - */ - unsigned char buf[40]; - int have_pkt = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(ssl = SSL_new(cctx))) - goto err; - SSL_set_connect_state(ssl); - s = SSL_CONNECTION_FROM_SSL(ssl); - if (!TEST_ptr(s) - || !TEST_ptr(s->init_buf = BUF_MEM_new()) - || !TEST_true(BUF_MEM_grow(s->init_buf, SSL3_RT_MAX_PLAIN_LENGTH)) - || !TEST_true(tls_setup_handshake(s))) - goto err; - - if (!TEST_true(WPACKET_init_static_len(&pkt, buf, sizeof(buf), 0))) - goto err; - have_pkt = 1; - if (!TEST_true(ssl_set_handshake_header(s, &pkt, SSL3_MT_CLIENT_HELLO))) - goto err; - - if (!TEST_int_eq(tls_construct_client_hello(s, &pkt), CON_FUNC_ERROR)) - goto err; - - ret = 1; -err: - if (have_pkt) - WPACKET_cleanup(&pkt); - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -static int test_construct_ch_no_ciphers(void) -{ - CH_CONFIG cfg = { 0, 0, 0, 0 }; - - return do_construct_ch_expect_fail(&cfg, NULL, 0, 1); -} - -/* Allocation-failure (mfail) tests */ - -/* Compiled when any mfail caller below (TLS 1.2, TLS 1.3 or ECH) is. */ -#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) -static int mfail_construct_ch_common(const CH_CONFIG *cfg, - int (*prep)(SSL_CONNECTION *s)) -{ - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - int ok = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(cfg, client_method(cfg))) - || !TEST_ptr(ssl = SSL_new(cctx))) - goto err; - if (cfg->clear_midbox) - SSL_clear_options(ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); - - if (!prime_ssl(ssl, 1, 0, &pkt, SSL3_MT_CLIENT_HELLO)) - goto err; - s = SSL_CONNECTION_FROM_SSL(ssl); - - if (prep != NULL && !prep(s)) { - WPACKET_cleanup(&pkt); - goto err; - } - - MFAIL_start(); - ok = (tls_construct_client_hello(s, &pkt) == CON_FUNC_SUCCESS); - MFAIL_end(); - - WPACKET_cleanup(&pkt); - - /* 1 on clean success, 0 on an injected allocation failure. */ - ret = ok ? 1 : 0; -err: - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} -#endif - -#ifndef OSSL_NO_USABLE_TLS1_3 -static int mfail_construct_ch_tls13(void) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 0 }; - - return mfail_construct_ch_common(&cfg, NULL); -} -#endif - -#ifndef OPENSSL_NO_TLS1_2 -static int mfail_construct_ch_tls12(void) -{ - CH_CONFIG cfg = { 0, TLS1_2_VERSION, TLS1_2_VERSION, 0 }; - - return mfail_construct_ch_common(&cfg, NULL); -} -#endif - -#ifndef OSSL_NO_USABLE_ECH -/* ECH path tests */ - -/* Attach an ECH config so construct takes the ECH wrapper path. */ -static int prep_ech(SSL_CONNECTION *s) -{ - SSL *ssl = SSL_CONNECTION_GET_SSL(s); - OSSL_ECHSTORE *es = NULL; - OSSL_HPKE_SUITE suite = OSSL_HPKE_SUITE_DEFAULT; - int ret = 0; - - if (!TEST_ptr(es = OSSL_ECHSTORE_new(NULL, NULL)) - || !TEST_true(OSSL_ECHSTORE_new_config(es, OSSL_ECH_CURRENT_VERSION, 0, - "example.com", suite)) - || !TEST_true(SSL_set1_echstore(ssl, es))) - goto err; - ret = 1; -err: - OSSL_ECHSTORE_free(es); - return ret; -} - -/* - * ECH happy path: the server reuses the client's store, which holds the private - * key needed to decrypt the inner ClientHello, so the round-trip can succeed. - */ -static int test_construct_ch_ech(void) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 0 }; - SSL_CTX *cctx = NULL, *sctx = NULL; - SSL *cssl = NULL, *sssl = NULL; - SSL_CONNECTION *cs, *ss; - OSSL_ECHSTORE *es = NULL; - OSSL_HPKE_SUITE suite = OSSL_HPKE_SUITE_DEFAULT; - WPACKET pkt; - PACKET rpkt; - unsigned char *msg = NULL; - size_t msglen = 0, sidlen = 0; - int ret = 0; - - if (!TEST_ptr(es = OSSL_ECHSTORE_new(NULL, NULL)) - || !TEST_true(OSSL_ECHSTORE_new_config(es, OSSL_ECH_CURRENT_VERSION, 0, - "example.com", suite))) - goto err; - - /* Client: construct the outer ClientHello with ECH. */ - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(cssl = SSL_new(cctx)) - || !TEST_true(SSL_set1_echstore(cssl, es)) - || !prime_ssl(cssl, 1, 0, &pkt, SSL3_MT_CLIENT_HELLO)) - goto err; - cs = SSL_CONNECTION_FROM_SSL(cssl); - if (!TEST_int_eq(tls_construct_client_hello(cs, &pkt), CON_FUNC_SUCCESS)) { - WPACKET_cleanup(&pkt); - goto err; - } - if (!finish_msg(cssl, &pkt, SSL3_MT_CLIENT_HELLO, &msg, &msglen) - || !get_ch_sessid_len(&cfg, msg, msglen, &sidlen) - || !TEST_size_t_eq(sidlen, SSL_MAX_SSL_SESSION_ID_LENGTH)) - goto err; - - /* Server: decrypt and process the outer using the same store. */ - if (!TEST_ptr(sctx = new_ctx(&cfg, server_method(&cfg))) - || !TEST_ptr(sssl = SSL_new(sctx)) - || !TEST_true(SSL_set1_echstore(sssl, es)) - || !prime_ssl(sssl, 0, 0, NULL, SSL3_MT_CLIENT_HELLO)) - goto err; - ss = SSL_CONNECTION_FROM_SSL(sssl); - if (!TEST_true(PACKET_buf_init(&rpkt, msg + hdr_len(&cfg), - msglen - hdr_len(&cfg))) - || !TEST_int_eq(tls_process_client_hello(ss, &rpkt), - MSG_PROCESS_CONTINUE_PROCESSING)) - goto err; - - ret = 1; -err: - OSSL_ECHSTORE_free(es); - SSL_free(cssl); - SSL_free(sssl); - SSL_CTX_free(cctx); - SSL_CTX_free(sctx); - return ret; -} - -#ifndef OPENSSL_NO_TLS1_2 -static int test_construct_ch_ech_tls12(void) -{ - CH_CONFIG cfg = { 0, TLS1_2_VERSION, TLS1_2_VERSION, 0 }; - - /* ECH requires TLS 1.3: the inner construct fails the version check. */ - return do_construct_ch_expect_fail(&cfg, prep_ech, 0, 0); -} -#endif /* OPENSSL_NO_TLS1_2 */ - -static int mfail_construct_ch_ech(void) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 0 }; - - return mfail_construct_ch_common(&cfg, prep_ech); -} -#endif /* OSSL_NO_USABLE_ECH */ - -/* - * =========================================================================== - * tls_construct_end_of_early_data - * =========================================================================== - */ - -#ifndef OSSL_NO_USABLE_TLS1_3 -/* - * EndOfEarlyData carries no body and only advances early_data_state; it is - * valid only from the WRITE_RETRY/FINISHED_WRITING states. - */ -static int do_construct_eoed(int state, CON_FUNC_RETURN expect) -{ - CH_CONFIG cfg = { 0, TLS1_3_VERSION, TLS1_3_VERSION, 0 }; - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - unsigned char *msg = NULL; - size_t msglen = 0; - int have_pkt = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(ssl = SSL_new(cctx)) - || !prime_ssl(ssl, 1, 0, &pkt, SSL3_MT_END_OF_EARLY_DATA)) - goto err; - have_pkt = 1; - s = SSL_CONNECTION_FROM_SSL(ssl); - s->early_data_state = state; - - if (!TEST_int_eq(tls_construct_end_of_early_data(s, &pkt), expect)) - goto err; - - if (expect == CON_FUNC_SUCCESS) { - /* State advances and the body is empty (only the header is written). */ - if (!TEST_int_eq(s->early_data_state, SSL_EARLY_DATA_FINISHED_WRITING) - || !finish_msg(ssl, &pkt, SSL3_MT_END_OF_EARLY_DATA, &msg, &msglen)) - goto err; - have_pkt = 0; - if (!TEST_size_t_eq(msglen, hdr_len(&cfg))) - goto err; - } - - ret = 1; -err: - if (have_pkt) - WPACKET_cleanup(&pkt); - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -static int test_construct_eoed(void) -{ - return do_construct_eoed(SSL_EARLY_DATA_WRITE_RETRY, CON_FUNC_SUCCESS); -} - -static int test_construct_eoed_bad_state(void) -{ - /* Called from an unexpected state: CON_FUNC_ERROR, nothing written. */ - return do_construct_eoed(SSL_EARLY_DATA_NONE, CON_FUNC_ERROR); -} -#endif /* OSSL_NO_USABLE_TLS1_3 */ - -/* - * =========================================================================== - * tls_construct_client_certificate - * =========================================================================== - */ - -#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) -/* Self-signed client cert + signing-capable key; regenerate with the - * statem_clnt_construct_test ossl-test-tools subcommand. */ -static const char *kClientCert[] = { - "-----BEGIN CERTIFICATE-----\n", - "MIIDvzCCAqegAwIBAgICAQAwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVT\n", - "MRAwDgYDVQQIDAdXeW9taW5nMREwDwYDVQQHDAhDaGV5ZW5uZTEVMBMGA1UECgwM\n", - "T3BlblNTTCBUZXN0MRQwEgYDVQQLDAtzdGF0ZW1fY2xudDEgMB4GA1UEAwwXc3Rh\n", - "dGVtX2NsbnQgdGVzdCBjbGllbnQwHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAw\n", - "MDAwWjCBgTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB1d5b21pbmcxETAPBgNVBAcM\n", - "CENoZXllbm5lMRUwEwYDVQQKDAxPcGVuU1NMIFRlc3QxFDASBgNVBAsMC3N0YXRl\n", - "bV9jbG50MSAwHgYDVQQDDBdzdGF0ZW1fY2xudCB0ZXN0IGNsaWVudDCCASIwDQYJ\n", - "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMnUvJvluB2ZUoQNQlW4wgv0qceITB5X\n", - "cHQe60H1CMTapaRi32dpwEzoEMnMjULcrZshcTAkdke6J1ubJ6qviGp7n1kVYH18\n", - "rGYYk6VT+GPb/SZnjMX3+e5WEpH+53UEGVvBPHl/med0AzklOOf/0hDlMFzMBejA\n", - "z+T++88QIT19BoIwfilcMDZxE0uXbq3QLpugADGd93zLSCwM1vxd9Vi0EwyMpy7Q\n", - "Ot9eIR/+ML0HESXZ1AvVcLjvuhqm+xkNiR9qil68zqgJk+dUpK5hCpLBi7cfBpk7\n", - "jLultF09up6G3Y5KiXd8wS9upwJZXA9+9OKHTf05w4xWAA/kpp9gt0MCAwEAAaM/\n", - "MD0wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFM9Nespo\n", - "NSyfQO8jPjRl4JfH5kOsMA0GCSqGSIb3DQEBCwUAA4IBAQBtTgy5ePCHR+iu3Ign\n", - "wlJzL5+zkWOkQsbAzJsbWrvzqwx2shXr1adM7OJy7tCkmDgwHsXjTTO2qAZrlmYQ\n", - "ktGA/UAtttIqgiiYcyGdrZas2vXUWLUps5YzMm4YdY8YNTvqQl3LCziUhO5YREDP\n", - "teXy4FF6ijGUDe84CYsmKvtbIn34LtZ2Vo3gsiRHvdiaxHavH30UqED9k4NjKnFx\n", - "XM6eMw+bs0Yl1vi/Dz5tHPRaAnsGvnKcEveSAdAoSWmodw8n8W5t8ZvPoPCoKz88\n", - "DOGzUvLma/kVL+3HLiSn6XFiQ2NLfO9ceUgDsSzcRo76XZHJnfGsK6Iewgje3NrB\n", - "WnZs\n", - "-----END CERTIFICATE-----\n", - NULL -}; - -static const char *kClientKey[] = { - "-----BEGIN RSA PRIVATE KEY-----\n", - "MIIEowIBAAKCAQEAydS8m+W4HZlShA1CVbjCC/Spx4hMHldwdB7rQfUIxNqlpGLf\n", - "Z2nATOgQycyNQtytmyFxMCR2R7onW5snqq+IanufWRVgfXysZhiTpVP4Y9v9JmeM\n", - "xff57lYSkf7ndQQZW8E8eX+Z53QDOSU45//SEOUwXMwF6MDP5P77zxAhPX0GgjB+\n", - "KVwwNnETS5durdAum6AAMZ33fMtILAzW/F31WLQTDIynLtA6314hH/4wvQcRJdnU\n", - "C9VwuO+6Gqb7GQ2JH2qKXrzOqAmT51SkrmEKksGLtx8GmTuMu6W0XT26nobdjkqJ\n", - "d3zBL26nAllcD3704odN/TnDjFYAD+Smn2C3QwIDAQABAoIBAGAjkzIJczG6MmmP\n", - "bU0q5FfQk7zlaii7yuetQK/a2fH3GpbauALpBz46/qA5bQJv3sw52lIt1B+nhw7m\n", - "MbdmxKrANy+2dI9hvzckttO2U2exxvyvr4kvbWB/pHnhu3vsV23y9m0DgJqVEuH6\n", - "Hoi4PWZp3aceUiRED+NLKERCMSs5lPSSWR7sUkzHku4x5fZXZppcQW4leo+Z/kNC\n", - "I36CGF4pI9FJXwcuRhbv3NsFMVl/Ng4hWgzgu7zwJEPw2OSKyhdwHV53qGQWyMnJ\n", - "7SawyQfyspKlMZnjWxplFZ5tgaV6O63zZZPEOC2mZNeiZKWC9Lut/wyriLs+W4w7\n", - "9BBX3q0CgYEA94sgemr3rGY2R+9kiPV/TC08IUflMJ7kt0epDDRnojWqobinJzQG\n", - "Nq25i5vZHbjn9g7l2hNmOcHVZZmCYZitmjwWr4ibthftU7+H6WkvcBvH6b6EmHQm\n", - "5IGtOxYPmtf2Ghnj1uQmsBe9vRYcqx7B8/anqRi3lQhebykkII0MLR8CgYEA0LnV\n", - "vXaFAwLOta4Kn43mXC6sVRRMt316d70zRpVRsSQ64TdhtwArmKq3RUmLH2r3ysRL\n", - "6+mxEGJriL7JERH3Jlm0YGsUUQvQWxCddccuTQRc16+UVt7+xzfhzJZNTD4+t0aA\n", - "jsVLpPQHzXI8Yqzh1p83oC4XV4hCYZNLlfleTV0CgYBWIG/yZ9k4gG+OY7pk9JWP\n", - "2YU8Rxl06zPEmQg2GN2d0HJHxklSGIW47ITMEDNgZf8+2zwZvfopSkmHCfwVHNv5\n", - "98Ik3LDgkD6gjtko2tIIfYH2z7SunmsRwhSVpD1VsKINvshI8iSLzBbV/SWIXDE7\n", - "Qqxe5xyom7rPjk7ljG2aHQKBgB36oxV8YWxmSdRUdBgopG6XEY+Cw+YS8rUiCqxX\n", - "pA0iXAafErzbHGfoFTyxbHcNwRtxiEoRHapxyGoypOR7xRjQB5VVq+xcGwgJYeRZ\n", - "wG+1cbRU9qRnkQaCIz9kUyPhSNbAHJTlB5Fgr4I1pzCxDhrqcW3jUNz0qDwlkNSw\n", - "pXfNAoGBAKlFbbPEzFonlkHVtdUuk6Chsi5k/ddrWsGxwUw5F5BSu0UaseolVls5\n", - "TyDVa8FEfDnUZRxl8HSfC/Qp/kAdveGKyhNaex22L5G8m20rXjsQBMFHMOy2Mho1\n", - "hgs0/emKuVyCs+wnYOqJlWZ8Vf/qGcUtDF3r4aEZ1JUDhUBAVEpo\n", - "-----END RSA PRIVATE KEY-----\n", - NULL -}; - -static int load_cert_and_key(SSL *ssl) -{ - X509 *cert = NULL; - EVP_PKEY *pkey = NULL; - int ret = 0; - - if (!TEST_ptr(cert = X509_from_strings(kClientCert)) - || !TEST_ptr(pkey = PKEY_from_strings(kClientKey)) - || !TEST_int_eq(SSL_use_certificate(ssl, cert), 1) - || !TEST_int_eq(SSL_use_PrivateKey(ssl, pkey), 1)) - goto err; - ret = 1; -err: - X509_free(cert); - EVP_PKEY_free(pkey); - return ret; -} - -/* - * Run tls_construct_client_certificate() under mfail; prep installs the cert - * material. For TLS 1.3 the method is swapped in (IS_TLS13 keys off it) and - * middlebox compat cleared to skip the write-key change. - */ -static int mfail_construct_cert(int is_tls13, int (*prep)(SSL_CONNECTION *s)) -{ - CH_CONFIG cfg = { 0, 0, 0, 0 }; - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - int ok = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(ssl = SSL_new(cctx))) - goto err; - if (is_tls13) - SSL_clear_options(ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); - if (!prime_ssl(ssl, 1, 0, &pkt, SSL3_MT_CERTIFICATE)) - goto err; - s = SSL_CONNECTION_FROM_SSL(ssl); -#ifndef OSSL_NO_USABLE_TLS1_3 - if (is_tls13) - ssl->method = tlsv1_3_client_method(); -#endif - - if (prep != NULL && !prep(s)) { - WPACKET_cleanup(&pkt); - goto err; - } - - MFAIL_start(); - ok = (tls_construct_client_certificate(s, &pkt) == CON_FUNC_SUCCESS); - MFAIL_end(); - - WPACKET_cleanup(&pkt); - - ret = ok ? 1 : 0; -err: - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} -#endif /* TLS 1.2 or usable TLS 1.3 */ - -#ifndef OSSL_NO_USABLE_TLS1_3 -/* x509 over TLS 1.3; NO_AUTO_CHAIN avoids best-effort verify swallowing OOM. */ -static int prep_cert_x509(SSL_CONNECTION *s) -{ - SSL *ssl = SSL_CONNECTION_GET_SSL(s); - - SSL_set_mode(ssl, SSL_MODE_NO_AUTO_CHAIN); - return load_cert_and_key(ssl); -} - -static int mfail_construct_cert_x509(void) -{ - return mfail_construct_cert(1, prep_cert_x509); -} -#endif /* OSSL_NO_USABLE_TLS1_3 */ - -#ifndef OPENSSL_NO_TLS1_2 -/* RPK derived from the certificate public key over TLS 1.2 (tls_output_rpk). */ -static int prep_cert_rpk(SSL_CONNECTION *s) -{ - if (!load_cert_and_key(SSL_CONNECTION_GET_SSL(s))) - return 0; - s->ext.client_cert_type = TLSEXT_cert_type_rpk; - return 1; -} - -static int mfail_construct_cert_rpk(void) -{ - return mfail_construct_cert(0, prep_cert_rpk); -} -#endif /* OPENSSL_NO_TLS1_2 */ - -/* Deterministic error branches that mfail (allocation-only) cannot reach. */ - -/* An unrecognized certificate type is rejected. */ -static int test_construct_cert_bad_type(void) -{ - CH_CONFIG cfg = { 0, 0, 0, 0 }; - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - int have_pkt = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(ssl = SSL_new(cctx)) - || !prime_ssl(ssl, 1, 0, &pkt, SSL3_MT_CERTIFICATE)) - goto err; - have_pkt = 1; - s = SSL_CONNECTION_FROM_SSL(ssl); - s->ext.client_cert_type = 0xff; - - if (!TEST_int_eq(tls_construct_client_certificate(s, &pkt), CON_FUNC_ERROR)) - goto err; - - ret = 1; -err: - if (have_pkt) - WPACKET_cleanup(&pkt); - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -#ifndef OSSL_NO_USABLE_TLS1_3 -/* - * With middlebox compat on, the TLS 1.3 path changes the write keys; without a - * negotiated cipher that fails rather than succeeding. - */ -static int test_construct_cert_change_cipher_fail(void) -{ - CH_CONFIG cfg = { 0, 0, 0, 0 }; - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - int have_pkt = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(ssl = SSL_new(cctx)) - || !prime_ssl(ssl, 1, 0, &pkt, SSL3_MT_CERTIFICATE)) - goto err; - have_pkt = 1; - s = SSL_CONNECTION_FROM_SSL(ssl); - ssl->method = tlsv1_3_client_method(); - - if (!TEST_int_eq(tls_construct_client_certificate(s, &pkt), CON_FUNC_ERROR)) - goto err; - - ret = 1; -err: - if (have_pkt) - WPACKET_cleanup(&pkt); - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -/* - * A WPACKET failure while writing the TLS 1.3 certificate_request_context - * yields CON_FUNC_ERROR. with_pha exercises the non-empty-context branch. - */ -static int do_construct_cert_ctx_small_buf(int with_pha) -{ - CH_CONFIG cfg = { 0, 0, 0, 0 }; - SSL_CTX *cctx = NULL; - SSL *ssl = NULL; - SSL_CONNECTION *s; - WPACKET pkt; - unsigned char buf[16]; - int have_pkt = 0; - int ret = 0; - - if (!TEST_ptr(cctx = new_ctx(&cfg, client_method(&cfg))) - || !TEST_ptr(ssl = SSL_new(cctx))) - goto err; - SSL_set_connect_state(ssl); - s = SSL_CONNECTION_FROM_SSL(ssl); - if (!TEST_ptr(s) - || !TEST_ptr(s->init_buf = BUF_MEM_new()) - || !TEST_true(BUF_MEM_grow(s->init_buf, SSL3_RT_MAX_PLAIN_LENGTH)) - || !TEST_true(tls_setup_handshake(s))) - goto err; - ssl->method = tlsv1_3_client_method(); - - if (with_pha) { - if (!TEST_ptr(s->pha_context = OPENSSL_malloc(4))) - goto err; - s->pha_context_len = 4; - } - - /* Only the handshake header fits, so the context write overflows. */ - if (!TEST_true(WPACKET_init_static_len(&pkt, buf, hdr_len(&cfg), 0))) - goto err; - have_pkt = 1; - if (!TEST_true(ssl_set_handshake_header(s, &pkt, SSL3_MT_CERTIFICATE))) - goto err; - - if (!TEST_int_eq(tls_construct_client_certificate(s, &pkt), CON_FUNC_ERROR)) - goto err; - - ret = 1; -err: - if (have_pkt) - WPACKET_cleanup(&pkt); - SSL_free(ssl); - SSL_CTX_free(cctx); - return ret; -} - -static int test_construct_cert_ctx_small_buf(void) -{ - return do_construct_cert_ctx_small_buf(0); -} - -static int test_construct_cert_pha_ctx_small_buf(void) -{ - return do_construct_cert_ctx_small_buf(1); -} -#endif /* OSSL_NO_USABLE_TLS1_3 */ - -int setup_tests(void) -{ - ADD_TEST(test_construct_ch_small_buf); - ADD_TEST(test_construct_ch_no_ciphers); - -#ifndef OPENSSL_NO_TLS1_2 - ADD_TEST(test_construct_ch_tls12); - ADD_TEST(test_construct_ch_resume); - ADD_MFAIL_TEST(mfail_construct_ch_tls12); -#endif - -#ifndef OSSL_NO_USABLE_TLS1_3 - ADD_TEST(test_construct_ch_tls13); - ADD_TEST(test_construct_ch_tls13_no_middlebox); - ADD_TEST(test_construct_ch_hrr); - ADD_TEST(test_construct_eoed); - ADD_TEST(test_construct_eoed_bad_state); -#if defined(OPENSSL_NO_ECX) - /* - * Without ECX the key_share falls back to EC keygen, which makes a - * best-effort param-cache allocation whose failure does not propagate; - * only crash/leak checking is meaningful then. - * - * No caching also needs no check. - */ - ADD_MFAIL_NO_CHECK_TEST(mfail_construct_ch_tls13); -#else - ADD_MFAIL_TEST(mfail_construct_ch_tls13); -#endif /* OPENSSL_NO_ECX */ -#endif /* OSSL_NO_USABLE_TLS1_3 */ - -#if !defined(OPENSSL_NO_DTLS) && !defined(OPENSSL_NO_DTLS1_2) - ADD_TEST(test_construct_ch_dtls); - ADD_TEST(test_construct_ch_dtls_cookie); - ADD_TEST(test_construct_ch_dtls_client_random); -#endif - -#ifndef OSSL_NO_USABLE_ECH - ADD_TEST(test_construct_ch_ech); -#ifndef OPENSSL_NO_TLS1_2 - ADD_TEST(test_construct_ch_ech_tls12); -#endif - ADD_MFAIL_TEST(mfail_construct_ch_ech); -#endif /* OSSL_NO_USABLE_ECH */ - - /* tls_construct_client_certificate: OOM coverage of the output functions. */ -#ifndef OSSL_NO_USABLE_TLS1_3 - ADD_MFAIL_TEST(mfail_construct_cert_x509); -#endif -#ifndef OPENSSL_NO_TLS1_2 - ADD_MFAIL_TEST(mfail_construct_cert_rpk); -#endif - ADD_TEST(test_construct_cert_bad_type); -#ifndef OSSL_NO_USABLE_TLS1_3 - ADD_TEST(test_construct_cert_change_cipher_fail); - ADD_TEST(test_construct_cert_ctx_small_buf); - ADD_TEST(test_construct_cert_pha_ctx_small_buf); -#endif - return 1; -} diff --git a/test/testutil.h b/test/testutil.h index 7e23f53827..b38791b287 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -73,32 +73,17 @@ /* Per-test flags for add_mfail_test() */ #define MFAIL_TEST_NO_CHECK (1 << 0) -#define MFAIL_TEST_SAMPLED (1 << 1) #define ADD_MFAIL_TEST(test_fn) \ - add_mfail_test(#test_fn, test_fn, 0, 0) + add_mfail_test(#test_fn, test_fn, 0) #define ADD_MFAIL_NO_CHECK_TEST(test_fn) \ - add_mfail_test(#test_fn, test_fn, MFAIL_TEST_NO_CHECK, 0) - -/* Caps injection at |cnt| points (exhaustive when allocations <= cnt) */ -#define ADD_MFAIL_SAMPLED_TEST(test_fn, cnt) \ - add_mfail_test(#test_fn, test_fn, MFAIL_TEST_SAMPLED, cnt) -#define ADD_MFAIL_SAMPLED_NO_CHECK_TEST(test_fn, cnt) \ - add_mfail_test(#test_fn, test_fn, \ - MFAIL_TEST_NO_CHECK | MFAIL_TEST_SAMPLED, cnt) + add_mfail_test(#test_fn, test_fn, MFAIL_TEST_NO_CHECK) /* Runs the exhaustive mfail cycle for each 0 <= idx < num */ #define ADD_MFAIL_ALL_TESTS(test_fn, num) \ - add_mfail_all_tests(#test_fn, test_fn, num, 0, 0) + add_mfail_all_tests(#test_fn, test_fn, num, 0) #define ADD_MFAIL_ALL_NO_CHECK_TESTS(test_fn, num) \ - add_mfail_all_tests(#test_fn, test_fn, num, MFAIL_TEST_NO_CHECK, 0) - -/* Sampled variants of the above */ -#define ADD_MFAIL_SAMPLED_ALL_TESTS(test_fn, num, cnt) \ - add_mfail_all_tests(#test_fn, test_fn, num, MFAIL_TEST_SAMPLED, cnt) -#define ADD_MFAIL_SAMPLED_ALL_NO_CHECK_TESTS(test_fn, num, cnt) \ - add_mfail_all_tests(#test_fn, test_fn, num, \ - MFAIL_TEST_NO_CHECK | MFAIL_TEST_SAMPLED, cnt) + add_mfail_all_tests(#test_fn, test_fn, num, MFAIL_TEST_NO_CHECK) /* * A variant of the same without TAP output. @@ -271,9 +256,9 @@ void add_test(const char *test_case_name, int (*test_fn)(void)); void add_all_tests(const char *test_case_name, int (*test_fn)(int idx), int num, int subtest); void add_mfail_test(const char *test_case_name, int (*test_fn)(void), - int flags, int sampled); + int flags); void add_mfail_all_tests(const char *test_case_name, int (*test_fn)(int idx), - int num, int flags, int sampled); + int num, int flags); #define MFAIL_start mfail_start #define MFAIL_end mfail_end @@ -337,11 +322,18 @@ const OPTIONS *test_get_options(void); */ #define PRINTF_FORMAT(a, b) -#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__MINGW64__) \ +#if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__MINGW32__) && !defined(__MINGW64__) \ && !defined(__APPLE__) +/* + * Because we support the 'z' modifier, which made its appearance in C99, + * we can't use __attribute__ with pre C99 dialects. + */ +#if __STDC_VERSION__ >= 199901L #undef PRINTF_FORMAT #define PRINTF_FORMAT(a, b) __attribute__((format(printf, a, b))) #endif +#endif #define DECLARE_COMPARISON(type, name, opname) \ int test_##name##_##opname(const char *, int, \ diff --git a/test/testutil/driver.c b/test/testutil/driver.c index bfcb65b7bc..54aa2a061a 100644 --- a/test/testutil/driver.c +++ b/test/testutil/driver.c @@ -39,7 +39,6 @@ typedef struct test_info { unsigned int subtest : 1; unsigned int mfail : 1; int mfail_flags; - int mfail_sampled; } TEST_INFO; static TEST_INFO all_tests[1024]; @@ -85,8 +84,7 @@ void add_all_tests(const char *test_case_name, int (*test_fn)(int idx), num_test_cases += num; } -void add_mfail_test(const char *test_case_name, int (*test_fn)(void), int flags, - int sampled) +void add_mfail_test(const char *test_case_name, int (*test_fn)(void), int flags) { assert(num_tests != OSSL_NELEM(all_tests)); all_tests[num_tests].test_case_name = test_case_name; @@ -94,13 +92,12 @@ void add_mfail_test(const char *test_case_name, int (*test_fn)(void), int flags, all_tests[num_tests].num = -1; all_tests[num_tests].mfail = 1; all_tests[num_tests].mfail_flags = flags; - all_tests[num_tests].mfail_sampled = sampled; ++num_tests; ++num_test_cases; } void add_mfail_all_tests(const char *test_case_name, int (*test_fn)(int idx), - int num, int flags, int sampled) + int num, int flags) { assert(num_tests != OSSL_NELEM(all_tests)); all_tests[num_tests].test_case_name = test_case_name; @@ -109,7 +106,6 @@ void add_mfail_all_tests(const char *test_case_name, int (*test_fn)(int idx), all_tests[num_tests].subtest = 1; all_tests[num_tests].mfail = 1; all_tests[num_tests].mfail_flags = flags; - all_tests[num_tests].mfail_sampled = sampled; ++num_tests; ++num_test_cases; } @@ -325,24 +321,8 @@ static int mfail_run_test(const TEST_INFO *t, int idx) int injections = 0; int allocations = 0; int no_check = (t->mfail_flags & MFAIL_TEST_NO_CHECK) != 0; - int sampled = (t->mfail_flags & MFAIL_TEST_SAMPLED) != 0; - int init_flags = no_check ? MFAIL_FLAG_NO_CHECK : 0; clock_t start = clock(); - if (sampled) - /* cap injection at mfail_sampled points (exhaustive below that) */ - init_flags |= MFAIL_FLAG_COUNT; -#ifdef OPENSSL_NO_CACHED_FETCH - else - /* - * The non-cached does too many allocations, which results in a - * significant slowdown of the tests. It does not provide much value, - * as it also requires NO_CHECK variant, so just run counting - * correctness check and skip the memory failure injection part. - */ - init_flags |= MFAIL_FLAG_COUNT_ONLY; -#endif - level += 4; test_adjust_streams_tap_level(level); test_printf_stdout("Subtest: %s[%d]\n", t->test_case_name, idx); @@ -350,7 +330,7 @@ static int mfail_run_test(const TEST_INFO *t, int idx) test_flush_stdout(); test_flush_tapout(); - mfail_init_ex(idx, init_flags, t->mfail_sampled); + mfail_init(0, no_check ? MFAIL_FLAG_NO_CHECK : 0); while (mfail_has_next()) { int phase = mfail_get_phase(); @@ -403,8 +383,6 @@ static int mfail_run_test(const TEST_INFO *t, int idx) test_verdict(TEST_SKIP_CODE, "2 - injection (mfail not installed)"); else if (mfail_env_skip_all()) test_verdict(TEST_SKIP_CODE, "2 - injection (mfail skip-all set)"); - else if (mfail_is_count_only()) - test_verdict(TEST_SKIP_CODE, "2 - injection (count only)"); else if (mfail_was_slow_skipped()) test_verdict(TEST_SKIP_CODE, "2 - injection (%d allocations exceeds slow threshold %d)", diff --git a/test/testutil/output.h b/test/testutil/output.h index e4f6058ac7..cee3026b11 100644 --- a/test/testutil/output.h +++ b/test/testutil/output.h @@ -13,10 +13,22 @@ #include #define ossl_test__attr__(x) -#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__MINGW64__) \ +#if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__MINGW32__) && !defined(__MINGW64__) \ && !defined(__APPLE__) +/* + * Because we support the 'z' modifier, which made its appearance in C99, + * we can't use __attribute__ with pre C99 dialects. + */ +#if __STDC_VERSION__ >= 199901L #undef ossl_test__attr__ #define ossl_test__attr__ __attribute__ +#if __GNUC__ * 10 + __GNUC_MINOR__ >= 44 +#define ossl_test__printf__ __gnu_printf__ +#else +#define ossl_test__printf__ __printf__ +#endif +#endif #endif /* * The basic I/O functions used internally by the test framework. These @@ -27,13 +39,13 @@ void test_close_streams(void); void test_adjust_streams_tap_level(int level); /* The following ALL return the number of characters written */ int test_vprintf_stdout(const char *fmt, va_list ap) - ossl_test__attr__((__format__(__printf__, 1, 0))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 0))); int test_vprintf_tapout(const char *fmt, va_list ap) - ossl_test__attr__((__format__(__printf__, 1, 0))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 0))); int test_vprintf_stderr(const char *fmt, va_list ap) - ossl_test__attr__((__format__(__printf__, 1, 0))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 0))); int test_vprintf_taperr(const char *fmt, va_list ap) - ossl_test__attr__((__format__(__printf__, 1, 0))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 0))); /* These return failure or success */ int test_flush_stdout(void); int test_flush_tapout(void); @@ -42,14 +54,15 @@ int test_flush_taperr(void); /* Commodity functions. There's no need to override these */ int test_printf_stdout(const char *fmt, ...) - ossl_test__attr__((__format__(__printf__, 1, 2))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 2))); int test_printf_tapout(const char *fmt, ...) - ossl_test__attr__((__format__(__printf__, 1, 2))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 2))); int test_printf_stderr(const char *fmt, ...) - ossl_test__attr__((__format__(__printf__, 1, 2))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 2))); int test_printf_taperr(const char *fmt, ...) - ossl_test__attr__((__format__(__printf__, 1, 2))); + ossl_test__attr__((__format__(ossl_test__printf__, 1, 2))); +#undef ossl_test__printf__ #undef ossl_test__attr__ #endif /* OSSL_TESTUTIL_OUTPUT_H */ diff --git a/test/threadstest.c b/test/threadstest.c index 50a5d90340..6915df3a3e 100644 --- a/test/threadstest.c +++ b/test/threadstest.c @@ -760,7 +760,7 @@ static OSSL_PROVIDER *multi_provider[MAXIMUM_PROVIDERS + 1]; static size_t multi_num_threads; static thread_t multi_threads[MAXIMUM_THREADS]; -static void multi_initialise(void) +static void multi_intialise(void) { multi_success = 1; multi_libctx = NULL; @@ -789,7 +789,7 @@ static void thead_teardown_libctx(void) for (p = multi_provider; *p != NULL; p++) OSSL_PROVIDER_unload(*p); OSSL_LIB_CTX_free(multi_libctx); - multi_initialise(); + multi_intialise(); } static int thread_setup_libctx(int libctx, const char *providers[]) @@ -840,7 +840,7 @@ static int thread_run_test(void (*main_func)(void), { int testresult = 0; - multi_initialise(); + multi_intialise(); if (!thread_setup_libctx(libctx, providers) || !start_threads(num_threads, thread_func)) goto err; @@ -1019,7 +1019,7 @@ static int test_multi_shared_pkey_common(void (*worker)(void)) { int testresult = 0; - multi_initialise(); + multi_intialise(); if (!thread_setup_libctx(1, do_fips ? fips_and_default_providers : default_provider) || !TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx)) || !start_threads(1, &thread_shared_evp_pkey) @@ -1071,7 +1071,7 @@ static int test_multi_shared_pkey_release(void) int testresult = 0; size_t i = 1; - multi_initialise(); + multi_intialise(); shared_evp_pkey = NULL; if (!thread_setup_libctx(1, do_fips ? fips_and_default_providers : default_provider) || !TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx))) @@ -1104,7 +1104,7 @@ static int test_multi_load_unload_provider(void) OSSL_PROVIDER *prov = NULL; int testresult = 0; - multi_initialise(); + multi_intialise(); if (!thread_setup_libctx(1, NULL) || !TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, "default")) || !TEST_ptr(sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL)) diff --git a/test/tls-provider.c b/test/tls-provider.c index 34ea1652a0..51db8b138e 100644 --- a/test/tls-provider.c +++ b/test/tls-provider.c @@ -725,7 +725,7 @@ static int xor_key_up_ref(XORKEY *key) { int refcnt; - if (!CRYPTO_UP_REF(&key->references, &refcnt)) + if (CRYPTO_UP_REF(&key->references, &refcnt) <= 0) return 0; assert(refcnt > 1); @@ -1282,7 +1282,7 @@ static XORKEY *xor_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, plen = 0; } else { p = ASN1_STRING_get0_data(oct); - plen = (int)ASN1_STRING_length_ex(oct); + plen = ASN1_STRING_length(oct); } xork = xor_key_op(palg, p, plen, KEY_OP_PRIVATE, @@ -2598,7 +2598,7 @@ static int xor_get_aid(unsigned char **oidbuf, const char *tls_name) aidlen = i2d_X509_ALGOR(algor, oidbuf); X509_ALGOR_free(algor); - return aidlen; + return (aidlen); } /* diff --git a/test/tls_groups_list_test.c b/test/tls_groups_list_test.c deleted file mode 100644 index 9770393634..0000000000 --- a/test/tls_groups_list_test.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Tests for the TLS supported-groups list parser (tls1_set_groups_list()), - * driven through the public SSL_CTX_set1_groups_list() entry point. - * - * The parser maintains three flat arrays and their bookkeeping in SSL_CTX: - * ctx->ext.supportedgroups[0..supportedgroups_len) - groups, in order - * ctx->ext.tuples[0..tuples_len) - group count per tuple - * ctx->ext.keyshares[0..keyshares_len) - keyshare group IDs - * with the governing invariant that the per-tuple counts sum to the group - * count: sum(tuples) == supportedgroups_len. Those fields are not visible - * through the public API, so we include ssl_local.h and check them directly. - * - * Several of the cases below are regressions for GitHub #31315, where the - * remove-group path could leave tuples/keyshares out of step with the group - * array (manifesting as an out-of-bounds read under a sanitizer). - */ - -#include -#include "internal/nelem.h" -#include "internal/tlsgroups.h" -#include "../ssl/ssl_local.h" -#include "testutil.h" - -#define MAX_GROUPS 8 -#define MAX_TUPLES 8 -#define MAX_KS 8 - -/* - * Sentinel used in ctx->ext.keyshares to mean "a single keyshare from the - * first supported group" (set when no '*' prefix appears anywhere). - */ -#define KS_FIRST 0 - -typedef struct { - const char *desc; - const char *list; /* input passed to set1_groups_list */ - uint16_t groups[MAX_GROUPS]; /* expected groups, in order */ - size_t ngroups; - size_t tuples[MAX_TUPLES]; /* expected per-tuple group counts */ - size_t ntuples; - uint16_t keyshares[MAX_KS]; /* expected keyshares (KS_FIRST == 0) */ - size_t nkeyshares; -} TESTCASE; - -static const TESTCASE cases[] = { - /* --- Well-formed baselines --------------------------------------- */ - { - "single tuple, two groups, implicit keyshare", - "X25519:prime256v1", - { OSSL_TLS_GROUP_ID_x25519, OSSL_TLS_GROUP_ID_secp256r1 }, - 2, - { 2 }, - 1, - { KS_FIRST }, - 1, - }, - { - "two tuples, implicit keyshare", - "X25519/prime256v1", - { OSSL_TLS_GROUP_ID_x25519, OSSL_TLS_GROUP_ID_secp256r1 }, - 2, - { 1, 1 }, - 2, - { KS_FIRST }, - 1, - }, - { - "explicit keyshare prefix", - "*X25519:prime256v1", - { OSSL_TLS_GROUP_ID_x25519, OSSL_TLS_GROUP_ID_secp256r1 }, - 2, - { 2 }, - 1, - { OSSL_TLS_GROUP_ID_x25519 }, - 1, - }, - - /* --- #31315: removal that empties a *closed* tuple --------------- */ - { - /* - * -X25519 empties closed tuple 0; it must be excised and the - * active-tuple counter shifted down (was: "1 group, 0 tuples"). - */ - "remove empties closed tuple (excision)", - "X25519/prime256v1:-X25519", - { OSSL_TLS_GROUP_ID_secp256r1 }, - 1, - { 1 }, - 1, - { KS_FIRST }, - 1, - }, - { - /* - * Removed group carried the keyshare and its tuple empties: the - * keyshare must be dropped, not floated onto another tuple's group - * (was: "1 group, tuples {1,1}", keyshare pointing at prime256v1). - */ - "remove keyshared group empties tuple (drop, not float)", - "*X25519/prime256v1/-X25519", - { OSSL_TLS_GROUP_ID_secp256r1 }, - 1, - { 1 }, - 1, - { KS_FIRST }, - 1, - }, - { - /* - * Two removals, each emptying a distinct closed tuple (was: - * "3 groups but tuple counts summing to 5"). - */ - "two removals empty two closed tuples", - "X25519/secp256r1:secp384r1:secp521r1/*X448:-X25519/-X448", - { OSSL_TLS_GROUP_ID_secp256r1, OSSL_TLS_GROUP_ID_secp384r1, - OSSL_TLS_GROUP_ID_secp521r1 }, - 3, - { 3 }, - 1, - { KS_FIRST }, - 1, - }, - - /* --- Removal from the *active* tuple (no excision) --------------- */ - { - "remove empties the active tuple only", - "X25519:-X25519", - { 0 }, - 0, - { 0 }, - 0, - { 0 }, - 0, - }, - { - "closed tuple intact, active tuple emptied and discarded", - "X25519/prime256v1:-prime256v1", - { OSSL_TLS_GROUP_ID_x25519 }, - 1, - { 1 }, - 1, - { KS_FIRST }, - 1, - }, - { - "keyshared group removed from active tuple", - "X25519/secp384r1/*X448:-X448", - { OSSL_TLS_GROUP_ID_x25519, OSSL_TLS_GROUP_ID_secp384r1 }, - 2, - { 1, 1 }, - 2, - { KS_FIRST }, - 1, - }, - - /* --- Legitimate keyshare retention (tuple not emptied) ----------- */ - { - /* - * Removing the keyshared X25519 from a tuple that still has - * prime256v1: prime256v1's own keyshare is retained. - */ - "remove one of two keyshares, tuple survives", - "*X25519:*prime256v1:-X25519", - { OSSL_TLS_GROUP_ID_secp256r1 }, - 1, - { 1 }, - 1, - { OSSL_TLS_GROUP_ID_secp256r1 }, - 1, - }, - - /* --- Keyshare floats *within* its own (surviving, closed) tuple --- */ - { - /* - * X25519 carried the keyshare in closed tuple 0 {X25519,secp384r1}; - * removing it must float the keyshare to secp384r1 (the remaining - * group of tuple 0), NOT to secp256r1 which is in tuple 1. - */ - "keyshare floats to remaining group of same tuple", - "*X25519:secp384r1/secp256r1:-X25519", - { OSSL_TLS_GROUP_ID_secp384r1, OSSL_TLS_GROUP_ID_secp256r1 }, - 2, - { 1, 1 }, - 2, - { OSSL_TLS_GROUP_ID_secp384r1 }, - 1, - }, - { - /* - * Removed keyshared group is in the middle of tuple 0; its keyshare - * floats to the tuple's first group (X25519), and tuple 1's own - * keyshare (secp256r1) is untouched. A float that escaped tuple 0 - * would corrupt this to a different keyshare set. - */ - "mid-tuple keyshare floats to tuple head, not across tuples", - "X25519:*X448:secp384r1 / *secp256r1:-X448", - { OSSL_TLS_GROUP_ID_x25519, OSSL_TLS_GROUP_ID_secp384r1, - OSSL_TLS_GROUP_ID_secp256r1 }, - 3, - { 2, 1 }, - 2, - { OSSL_TLS_GROUP_ID_x25519, OSSL_TLS_GROUP_ID_secp256r1 }, - 2, - }, -}; - -/* - * Assert every structural invariant the parser must maintain, from the parsed - * state alone (independent of the specific input): - * - * 1. Partition: sum(tuples[0..tuples_len)) == supportedgroups_len. - * 2. No empty tuples survive the final compaction (every count > 0). - * 3. Groups are distinct. - * 4. Keyshares are either the lone "first group" sentinel {0}, or a set of - * distinct non-zero group IDs that appear as an ordered subsequence of - * the supported groups (never the sentinel mixed with real IDs). - * - * These are exactly the properties that were violated by GitHub #31315 (a - * broken partition led to an out-of-bounds read in the remove path). - */ -static int check_invariants(SSL_CTX *ctx) -{ - size_t i, j, sum; - int ok = 1; - - /* 1 + 2: partition, with no zero-count tuple left behind. */ - for (i = 0, sum = 0; i < ctx->ext.tuples_len; i++) { - if (!TEST_size_t_gt(ctx->ext.tuples[i], 0)) { - TEST_error("zero-count tuple at index %zu survived", i); - ok = 0; - } - sum += ctx->ext.tuples[i]; - } - if (!TEST_size_t_eq(sum, ctx->ext.supportedgroups_len)) - ok = 0; - - /* 3: groups distinct. */ - for (i = 0; i < ctx->ext.supportedgroups_len; i++) - for (j = 0; j < i; j++) - if (!TEST_uint_ne(ctx->ext.supportedgroups[i], - ctx->ext.supportedgroups[j])) - ok = 0; - - /* 4: keyshare shape. */ - if (ctx->ext.keyshares_len == 1 && ctx->ext.keyshares[0] == KS_FIRST) { - /* Sentinel form: a single implicit keyshare from the first group. */ - } else { - size_t g = 0; - - for (i = 0; i < ctx->ext.keyshares_len; i++) { - uint16_t ks = ctx->ext.keyshares[i]; - - if (!TEST_uint_ne(ks, KS_FIRST)) { /* sentinel must be alone */ - ok = 0; - continue; - } - for (j = 0; j < i; j++) /* distinct */ - if (!TEST_uint_ne(ks, ctx->ext.keyshares[j])) - ok = 0; - while (g < ctx->ext.supportedgroups_len - && ctx->ext.supportedgroups[g] != ks) - g++; /* ordered subsequence */ - if (!TEST_size_t_lt(g, ctx->ext.supportedgroups_len)) { - TEST_error("keyshare 0x%04X not an in-order group", ks); - ok = 0; - break; - } - g++; - } - } - - return ok; -} - -static int run_case(int idx) -{ - const TESTCASE *tc = &cases[idx]; - SSL_CTX *ctx = NULL; - int ret = 0; - size_t i; - - TEST_info("case %d: %s [\"%s\"]", idx, tc->desc, tc->list); - - if (!TEST_ptr(ctx = SSL_CTX_new(TLS_method()))) - goto end; - - if (!TEST_int_eq(SSL_CTX_set1_groups_list(ctx, tc->list), 1)) - goto end; - - /* Groups: exact contents and order. */ - if (!TEST_size_t_eq(ctx->ext.supportedgroups_len, tc->ngroups)) - goto end; - for (i = 0; i < tc->ngroups; i++) - if (!TEST_uint_eq(ctx->ext.supportedgroups[i], tc->groups[i])) - goto end; - - /* Tuples: exact per-tuple counts. */ - if (!TEST_size_t_eq(ctx->ext.tuples_len, tc->ntuples)) - goto end; - for (i = 0; i < tc->ntuples; i++) - if (!TEST_size_t_eq(ctx->ext.tuples[i], tc->tuples[i])) - goto end; - - /* Keyshares: exact contents (KS_FIRST == 0 sentinel). */ - if (!TEST_size_t_eq(ctx->ext.keyshares_len, tc->nkeyshares)) - goto end; - for (i = 0; i < tc->nkeyshares; i++) - if (!TEST_uint_eq(ctx->ext.keyshares[i], tc->keyshares[i])) - goto end; - - if (!check_invariants(ctx)) - goto end; - - ret = 1; -end: - SSL_CTX_free(ctx); - return ret; -} - -/* - * Synthetic edge-case forms. We do not spell out the exact parsed result for - * these (that would just re-derive the parser); instead we assert the parse - * succeeds or fails as expected and, on success, that all invariants hold. - * These deliberately stress the corners of the remove/dedup/keyshare paths. - */ -typedef struct { - const char *list; - int expect_ok; /* 1: parse succeeds; 0: syntax/parse error */ -} EDGECASE; - -static const EDGECASE edgecases[] = { - /* --- valid, invariant-preserving corner cases --- */ - { "X25519", 1 }, - { "X25519:secp256r1:secp384r1:secp521r1:X448", 1 }, /* one full tuple */ - { "X25519/secp256r1/secp384r1/secp521r1/X448", 1 }, /* many tuples */ - { "*X25519:secp256r1", 1 }, - { "X25519:X25519", 1 }, /* dup within tuple */ - { "X25519/X25519", 1 }, /* dup across tuples */ - { "X25519:-secp384r1", 1 }, /* remove absent: no-op */ - { "X25519:-X25519", 1 }, /* empty the active tuple */ - { "X25519/secp256r1:-X25519", 1 }, /* excise closed tuple */ - { "X25519/secp256r1/secp384r1:-secp256r1", 1 }, /* excise middle tuple */ - { "X25519:secp256r1/secp384r1:-secp384r1", 1 }, /* empty active, discard */ - { "*X25519/prime256v1/-X25519", 1 }, /* #31315: drop, not float */ - { "X25519/secp256r1:secp384r1:secp521r1/*X448:-X25519/-X448", 1 }, /* #31315 */ - { "*X25519:*secp256r1:-X25519", 1 }, /* keyshare survives sibling */ - { "X25519/secp256r1:-X25519:secp384r1", 1 }, /* excise then refill */ - { "X25519:secp256r1:X448:-X25519:-X448", 1 }, /* multiple removals */ - { "?*BOGUS:X25519 / *secp256r1", 1 }, /* stacked prefix, unknown */ - { "X25519:?BOGUS:secp256r1", 1 }, /* ignore unknown mid-tuple */ - { "*X25519:DEFAULT:-secp256r1:-X448", 1 }, /* DEFAULT + removals */ - { "DEFAULT:-X25519:-?curveSM2:-?ffdhe2048:-?ffdhe3072", 1 }, - { "secp256r1:DEFAULT", 1 }, /* prepend then DEFAULT */ - - /* --- expected syntax / parse errors --- */ - { "X25519//secp256r1", 0 }, /* empty tuple */ - { "X25519::secp256r1", 0 }, /* empty group */ - { ":X25519", 0 }, - { "X25519:", 0 }, - { "/X25519", 0 }, - { "X25519/", 0 }, - { "**X25519", 0 }, /* double keyshare prefix */ - { "??X25519", 0 }, - { "--X25519", 0 }, - { "X25519:NOTAREALGROUP", 0 }, /* unknown w/o '?' */ - { "-DEFAULT", 0 }, /* prefix on pseudo-group */ - { "?DEFAULT", 0 }, -}; - -static int run_edge(int idx) -{ - const EDGECASE *tc = &edgecases[idx]; - SSL_CTX *ctx = NULL; - int ret = 0, r; - - TEST_info("edge %d: [\"%s\"] expect %s", idx, tc->list, - tc->expect_ok ? "ok" : "error"); - - if (!TEST_ptr(ctx = SSL_CTX_new(TLS_method()))) - goto end; - - r = SSL_CTX_set1_groups_list(ctx, tc->list); - if (tc->expect_ok) { - if (!TEST_int_eq(r, 1) || !check_invariants(ctx)) - goto end; - } else { - if (!TEST_int_eq(r, 0)) - goto end; - } - - ret = 1; -end: - SSL_CTX_free(ctx); - return ret; -} - -int setup_tests(void) -{ - ADD_ALL_TESTS(run_case, (int)OSSL_NELEM(cases)); - ADD_ALL_TESTS(run_edge, (int)OSSL_NELEM(edgecases)); - return 1; -} diff --git a/test/unit/.gitignore b/test/unit/.gitignore deleted file mode 100644 index 2576bf0319..0000000000 --- a/test/unit/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -* -!*/ -!*.c -!*.h -!*.inc -!*.pl -!*.t -!*.txt -!*.cnf -!*.pem -!build.info -!.gitignore -!README* diff --git a/test/unit/README.md b/test/unit/README.md deleted file mode 100644 index b945b438ab..0000000000 --- a/test/unit/README.md +++ /dev/null @@ -1,564 +0,0 @@ -OpenSSL Unit Tests -================== - -This directory holds the OpenSSL *unit* tests. Their purpose is to test a -single function, or a small group of related functions, in isolation by -replacing the other functions it calls with mocks. This makes it possible to -test logic that is otherwise hard to reach: error and failure paths of -dependencies, branches that depend on the exact arguments passed to a -collaborator, or code whose real dependencies would require network access, -specific hardware, or elaborate setup. Each test can then drive the function -under test through a precise, fully controlled sequence of calls and return -values, and assert on exactly how it interacts with its surroundings. - -Unit tests are not meant to replace the broader, integration-style testing that -makes up most of `test/`, and they are not the right tool for everything. They -are used for selected, self-contained pieces of the library where the mocking -boundary is clean and the payoff is high, the BIO layer being the main example. -Most code continues to be tested through the ordinary recipes (typically built -on `testutil`, and generally without mocking). - -Requirements ------------- - -The tests are built on [cmocka], a lightweight C unit-testing framework, and -rely on the GNU/BSD linker's `--wrap` option to intercept calls into the -function under test's dependencies. Because `--wrap` is required, unit tests -are only built on platforms that support it (Linux and BSD only at present), -and only when the build is configured with `enable-unit-tests`. - -[cmocka]: https://cmocka.org/ - -Tests must build and run against cmocka 1.1.5, as that is still the version -shipped by some currently supported enterprise and LTS distributions. Do not -rely on APIs introduced in cmocka 2.x, since a test that needs them cannot be -built on those systems; when in doubt, check against the 1.1.5 headers rather -than the latest online documentation. - -Building and Running --------------------- - -Unit tests are disabled by default. To build them, configure with -`enable-unit-tests` and make sure the cmocka development files are installed -on the system: - -```console -$ sudo apt-get install libcmocka-dev # Debian/Ubuntu -$ ./config enable-unit-tests -$ make -``` - -If cmocka is installed in a non-standard location, point the build at it with: - -```console -$ ./config enable-unit-tests \ - --with-cmocka-include=/path/to/include \ - --with-cmocka-lib=/path/to/lib -``` - -On a platform without `--wrap` support, `enable-unit-tests` is silently turned -off during configuration; the rest of the build proceeds normally. - -The whole unit-test suite runs as part of the normal test target: - -```console -$ make test -``` - -It is gathered under a single recipe, so it can also be run on its own: - -```console -$ make test TESTS=test_unit -``` - -The recipe discovers every executable named `test_*` under the build's -`test/unit` tree and runs each one, so a newly added test binary is picked up -automatically once it builds. Each binary reports its results in TAP, which the -harness consumes directly. - -Because each test is an ordinary standalone executable, it can also be run -directly, which is convenient when debugging a single failure under a debugger: - -```console -$ gdb test/unit/crypto/foo/test_bar -``` - -Running the binary on its own prints its TAP output to the terminal and makes -it straightforward to set breakpoints in a specific test, mock, or in the -function under test. - -For debugging it is worth configuring the build with `--debug` as well, e.g. -`./config enable-unit-tests --debug`. A normal build is optimized, which makes -stepping through code and inspecting variables awkward; `--debug` lowers the -optimization level and adds debug information, giving a much more predictable -experience under gdb. - -Anatomy of a Unit Test ----------------------- - -A unit test is a single C source file laid out under `test/unit/` in a path -that mirrors the location of the code it exercises. For example, code that -lives in `crypto/foo/bar.c` is tested by `test/unit/crypto/foo/test_bar.c`. The -file is self-contained: it provides its own `main()`, registers a list of test -cases, and runs them as a cmocka group. - -The body of a test file is organised into a few clearly separated sections, -conventionally introduced by short comments, in this order: - - * the `__wrap_*` mock implementations (`/* wraps */`), - * thin `expect_*` helpers that program each mock (`/* expectations */`), - * any shared helpers (fake methods, accessors, reset routines), - * the `setup`/`teardown` fixtures, - * the test functions themselves, and - * `main()`, which builds the `CMUnitTest` array and runs it. - -Keeping these sections in this order and clearly labelled makes a test file -predictable to read and easy to extend. - -### main() and the test list - -`main()` declares a `struct CMUnitTest` array, selects TAP output, and runs the -group: - -```c -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_something_simple), - cmocka_unit_test_setup_teardown(test_with_fixture, setup, teardown), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} -``` - -Always select `CM_OUTPUT_TAP` so the harness can parse the results. Use -`cmocka_unit_test()` for tests that need no per-test fixture, and -`cmocka_unit_test_setup_teardown()` when a test needs a fresh object built -before it and cleaned up after. The last two arguments to -`cmocka_run_group_tests()` are an optional group-level setup and teardown, run -once before and after the whole group; pass `NULL` when they are not needed. - -It is common to wrap the registration macros in a short local macro when most -tests share the same fixture, e.g. - -```c -#define MY_TEST(name) \ - cmocka_unit_test_setup_teardown(name, setup, teardown) -``` - -### A test function - -Each test is a function with the signature `void (void **state)`. The `state` -argument carries whatever a `setup` fixture stored there; tests that do not use -it should cast it to `void` to silence warnings: - -```c -static void test_addr_family(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_INET; - assert_int_equal(BIO_ADDR_family(&ap), AF_INET); -} -``` - -Assertions come from cmocka: `assert_int_equal`, `assert_ptr_equal`, -`assert_true`, `assert_false`, `assert_null`, `assert_non_null`, -`assert_string_equal`, `assert_memory_equal`, and friends. A failing assertion -aborts the current test and marks it failed without disturbing the others. - -How the Expectation Mechanism Works ------------------------------------ - -Before writing mocks it helps to understand what cmocka is actually doing, -because the model is simple once stated plainly and it makes the rest of the -API obvious. - -For each `(function, parameter)` pair cmocka keeps an internal queue. The -`expect_*()` macros, called from the test, push values onto these queues. The -`check_expected()` macro, called from inside the mock, pops the next value and -compares it against the argument the mock actually received; a mismatch fails -the test. Return values work the same way: `will_return()` pushes a value from -the test, and `mock_type()`/`mock_ptr_type()` pops it inside the mock to use as -the return value. Call accounting is analogous: `expect_function_call()` pushes -an expected call and `function_called()` consumes one. - -So a test programs, in order, the calls it expects the function under test to -make, and the mocks consume those programmed entries as the calls actually -happen. Entries are consumed in the order they were queued, which is why the -`expect_*`/`will_return` calls in a test must be written in the same order the -function under test will call its dependencies. At the end of the test cmocka -fails if any queued entry was never consumed, or if a mock is called with -nothing queued for it. This is what turns the expected interaction sequence -into a checked specification rather than a loose suggestion. - -Because each entry covers a single call, a function that is expected to be -called more than once is programmed by pushing the entries that many times, in -the order the calls will occur: - -```c -/* the SUT is expected to call BIO_socket twice */ -expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, INVALID_SOCKET); -expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); -``` - -cmocka also offers `_count` variants (such as `will_return_count()`, -`expect_value_count()` and `expect_function_calls()`) that program one entry -for a given number of calls in a single statement. These are not just a -shorthand for repeating the macro: they carry a different ordering semantics. -Repeating `expect_function_call()` pins each call's position in the overall -sequence, so any other expected call programmed between two of them must -actually occur between them. `expect_function_calls(f, 2)`, by contrast, only -requires that `f` is called twice somewhere; other calls may fall before, -after, or in between without failing the test. Prefer repeating the plain -macros when the interleaving matters (which is the common case), and reach for -the count variants only when a function is genuinely called many times and its -position relative to the others is not what the test is checking. - -Two consequences are worth keeping in mind: - - * **cmocka has nothing to do with `--wrap`.** The expectation machinery is - just these queues plus the `check_expected`/`mock`/`function_called` - macros. It works in any function whose body calls them. `--wrap` is merely - the linker trick OpenSSL uses to *substitute* a dependency with a mock; the - two are independent. The same `expect_*` style is used below for purpose- - built fake objects that are never wrapped at all (see Fixtures). - - * Because matching is per parameter and in order, a mock must call - `check_expected()` for exactly the parameters the test programs with - `expect_*()`, and the `will_return`/`mock_type` counts must balance. - -Mocking Dependencies with --wrap --------------------------------- - -The core technique is link-time function interception. When a binary is linked -with `-Wl,--wrap=foo`, every call to `foo` is redirected to a function named -`__wrap_foo`, and the original is still reachable as `__real_foo`. This lets a -test replace the function under test's dependencies with mocks that record how -they were called and return whatever the test dictates. - -### Declaring the wraps - -The set of wrapped symbols for a test binary is declared in the `build.info` -file (see below). For each wrapped symbol the test file provides a -`__wrap_` function with exactly the same signature as the real one. A -prototype is also needed to satisfy `-Wmissing-prototypes`: - -```c -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options); - -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options) -{ - function_called(); - check_expected(domain); - check_expected(socktype); - check_expected(protocol); - check_expected(options); - return mock_type(int); -} -``` - -A typical mock does three things: - - * `function_called()` records that the function was invoked, balanced against - the test's `expect_function_call()`. - * `check_expected(param)` (or `check_expected_ptr(param)` for pointers) - verifies the argument against the value the test queued. Use the `_ptr` - variant for pointer parameters. - * `mock_type(T)` (or `mock_ptr_type(T)` for pointers) returns the value the - test queued for this call. A `void` mock omits this. - -Mocks may also have deliberate side effects when the real function would -produce one that the code under test depends on. For example, a function that -fills a caller-supplied buffer should have its mock write into that buffer, and -a fatal-error reporter that the code expects to flip a state flag should do so: - -```c -int __wrap_ssl_fill_hello_random(SSL_CONNECTION *s, int server, - unsigned char *field, size_t len, DOWNGRADE dgrd) -{ - function_called(); - check_expected_ptr(s); - check_expected(server); - check_expected_ptr(field); - check_expected(len); - check_expected(dgrd); - - if (field != NULL) - memset(field, 0xAB, len); - - return mock_type(int); -} -``` - -Keep these side effects minimal and confined to what the function under test -genuinely observes; the goal is to reproduce the contract of the real function, -not to re-implement it. - -### Programming the mocks: expectations - -Rather than scatter `expect_function_call`/`expect_value`/`will_return` calls -through every test, wrap each mock in a small `expect_` helper that takes -the expected arguments and the return value. This keeps the tests readable and, -crucially, gives a single place to update when a function's signature or call -contract changes: - -```c -static void expect_BIO_socket(int domain, int socktype, int protocol, - int options, int rc) -{ - expect_function_call(__wrap_BIO_socket); - expect_value(__wrap_BIO_socket, domain, domain); - expect_value(__wrap_BIO_socket, socktype, socktype); - expect_value(__wrap_BIO_socket, protocol, protocol); - expect_value(__wrap_BIO_socket, options, options); - will_return(__wrap_BIO_socket, rc); -} -``` - -The most useful cmocka primitives here are: - - * `expect_function_call(f)`: expect one call to `f`. Pair every - `function_called()` in a mock with one of these. - * `expect_value(f, param, value)`: the argument must equal `value`. This is - consumed by `check_expected(param)`. - * `expect_any(f, param)`: the argument may be anything; still consumed by - `check_expected(param)`, so it must be present whenever the mock checks - that parameter. - * `will_return(f, value)`: queue a return value for the next call, - retrieved by `mock_type`/`mock_ptr_type`. Queue several in order if the - mock pulls more than one value (e.g. a return code followed by an - out-parameter payload). - -When a mock conditionally retrieves a second value, the matching expectation -must queue it under the same condition, so the queues stay aligned: - -```c -static void expect_BIO_lookup(BIO_ADDRINFO *res, int rc) -{ - expect_function_call(__wrap_BIO_lookup); - expect_any(__wrap_BIO_lookup, host); - expect_any(__wrap_BIO_lookup, service); - expect_value(__wrap_BIO_lookup, lookup_type, BIO_LOOKUP_SERVER); - expect_any(__wrap_BIO_lookup, family); - expect_any(__wrap_BIO_lookup, socktype); - will_return(__wrap_BIO_lookup, rc); - if (rc == 1) - will_return(__wrap_BIO_lookup, res); -} -``` - -### Writing a test against the mocks - -With the helpers in place, a test reads as: arrange the object, declare the -expected sequence of calls, invoke the function under test, and assert on the -result and any observable state. - -```c -static void test_socket_then_listen_fails(void **state) -{ - BIO *bio = *state; - - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); - expect_BIO_listen(FAKE_SOCKET, &expected_addr, 0, 0); - expect_BIO_closesocket(FAKE_SOCKET, 0); - - assert_true(BIO_do_accept(bio) <= 0); -} -``` - -If the function under test makes a call that was not programmed, or fails to -make one that was, or passes an argument that does not match, cmocka fails the -test and reports the mismatch. - -Fixtures and Real Fake Objects ------------------------------- - -A `setup` function allocates or initialises whatever object the test needs and -stores it through `*state`; the matching `teardown` releases it. Returning -non-zero from either aborts the test as an error. - -```c -static int setup(void **state) -{ - BIO *bio = BIO_new(BIO_s_accept()); - - assert_non_null(bio); - *state = bio; - return 0; -} - -static int teardown(void **state) -{ - if (*state != NULL) - BIO_free(*state); - return 0; -} -``` - -A group-level setup/teardown (the last two arguments to -`cmocka_run_group_tests`) is the place for one-time work shared by every test, -such as initialising static fixtures used across the file. - -Two practical cautions apply when fixtures interact with wrapped functions: - - * Teardown can itself trigger wrapped calls. If freeing the object under test - would invoke a wrapped function (for instance, closing a socket), reset the - relevant fields to safe sentinels before the free so no *unexpected* mock - call is made, or program the expectation for it. A common pattern is a - small `reset_for_teardown()` helper called at the end of any test that left - such state behind. - - * It is often cleaner to drive an object through its public interface with a - *real* minimal fake than to mock everything. For example, building a small - fake `BIO_METHOD` whose read/write callbacks are themselves cmocka mocks - (using the same `function_called`/`check_expected`/`mock_type` machinery, - even though nothing is wrapped) lets a test exercise the forwarding logic - of the object under test without wrapping low-level syscalls. Choose - whichever boundary keeps the test focused on the function actually under - examination. - -Conditional Compilation ------------------------- - -Mirror the `#ifdef`/`#ifndef` guards of the code under test. If a function only -exists under a build option, guard both the test function and its registration -in `main()` with the same condition, so the suite still builds in every -configuration: - -```c -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_addr_make_unix(void **state) -{ - ... -} -#endif - -int main(void) -{ - const struct CMUnitTest tests[] = { -#ifndef OPENSSL_NO_UNIX_SOCK - cmocka_unit_test(test_addr_make_unix), -#endif - ... - }; - ... -} -``` - -When an entire test file only makes sense under some option, guard the whole -body and provide a trivial `main()` for the disabled case so the binary still -links and the recipe still finds something to run: - -```c -#ifndef OPENSSL_NO_SOCK - -/* ... the tests ... */ - -#else - -int main(void) -{ - return 0; -} - -#endif -``` - -Wiring a New Test into the Build --------------------------------- - -Test binaries are declared in `test/unit/build.info`. A unit test that wraps no -symbols would not be linked against cmocka, so **every** unit test must declare -at least one `WRAP[]` entry: this is what causes both the `--wrap` link flags -and `-lcmocka` to be added for that binary. The directives needed per test are -`PROGRAMS`, `SOURCE`, `INCLUDE`, `DEPEND`, and `WRAP`: - -```text -PROGRAMS{noinst}=crypto/foo/test_bar -SOURCE[crypto/foo/test_bar]=crypto/foo/test_bar.c -INCLUDE[crypto/foo/test_bar]=../../include ../../include/internal \ - ../../crypto/foo -DEPEND[crypto/foo/test_bar]=../../libcrypto.a -WRAP[crypto/foo/test_bar]=BIO_socket BIO_listen BIO_closesocket -``` - -Notes: - - * `PROGRAMS{noinst}` marks the binary as not installed. - * `INCLUDE[]` lists the directories needed to reach the headers the test - uses, including any internal directory that declares the types or the - function under test. The cmocka include path is added automatically to - every target that has a `WRAP[]` entry, so it need not be listed. - * `DEPEND[]` links the appropriate static libraries: `../../libcrypto.a`, - and `../../libssl.a` as well for libssl code. - * `WRAP[]` is the whitespace-separated list of symbols to intercept; it may - be split over several lines with trailing backslashes. List exactly the - dependencies the test mocks. - -Because the recipe discovers binaries by name, no change to the Perl recipe is -needed; building the new `test_*` binary is enough for it to run under -`test_unit`. - -Generating Mock Stubs with mkwraps.pl -------------------------------------- - -Writing the `__wrap_*` and `expect_*` boilerplate by hand for a long `WRAP[]` -list is tedious and error-prone, so the helper script `util/mkwraps.pl` -generates a first draft from the `build.info` declaration. It reads the -`WRAP[]` list, searches the headers under the target's `INCLUDE[]` -directories for each function's prototype, and emits matching wrap functions -and expectation helpers. Functions not found there (typically libc/POSIX -functions such as `read` or `socket`) are looked up under the compiler's -default system include paths, and emitted with angle-bracket includes. - -```console -$ ./util/mkwraps.pl --build-info test/unit/build.info \ - --target crypto/foo/test_bar -``` - -Useful options: - - * `--mode wraps|expects|both`: emit only the `__wrap_*` functions, only the - `expect_*` helpers, or both (the default). - * `--include DIR`: add an extra header search directory beyond those in - `INCLUDE[]`. Cumulative. - * `--cc NAME`: C compiler queried for the system include paths (default - `$CC` or `cc`). - * `--no-system`: do not fall back to the compiler's system include - directories for functions missing from the project headers. - * `--output FILE`: write to a file instead of standard output. - * `--verbose`: report progress and where each prototype was found. - -The output is a *starting point*, not a finished test. The generated mocks call -`function_called()`, check every parameter, and return a `mock_type` value, but -any real behaviour still has to be added by hand: side effects on -out-parameters, variadic forwarding, conditional `will_return` payloads, and -the use of internal headers for opaque types. Generated `#include` lines and -parameter checks frequently need adjusting. Treat the script as a way to skip -the mechanical typing, then review and edit every generated function. - -Conventions ------------ - -Unit tests follow the usual OpenSSL C coding style (enforced via -clang-format), so it is not repeated here. A few conventions specific to unit -tests keep them consistent and maintainable: - - * Order the file as wraps, expectations, helpers, fixtures, tests, then - `main()`, with the short section-header comments shown above. - * Name test functions `test__` so the suite reads as a list - of behaviours, and add a brief comment on any test whose setup or expected - sequence is not obvious from the name. - * Give every mock a matching `expect_` helper and route all programming - of that mock through it rather than inlining `expect_value`/`will_return` - in the tests, so a change to a function's contract is fixed in one place. - * Keep each test focused on one behaviour, and prefer several small tests - over one test with many branches. - * Always emit TAP output, and always reset fixture state that would otherwise - cause an unexpected wrapped call during teardown. diff --git a/test/unit/build.info b/test/unit/build.info deleted file mode 100644 index ac04787457..0000000000 --- a/test/unit/build.info +++ /dev/null @@ -1,67 +0,0 @@ -IF[{- $config{target} =~ /^(?:linux|BSD)/ -}] - PROGRAMS{noinst}=crypto/bio/test_bio_addr - SOURCE[crypto/bio/test_bio_addr]=crypto/bio/test_bio_addr.c - INCLUDE[crypto/bio/test_bio_addr]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bio_addr]=../../libcrypto.a - WRAP[crypto/bio/test_bio_addr]=BIO_sock_init getnameinfo freeaddrinfo - - PROGRAMS{noinst}=crypto/bio/test_bio_sock - SOURCE[crypto/bio/test_bio_sock]=crypto/bio/test_bio_sock.c - INCLUDE[crypto/bio/test_bio_sock]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bio_sock]=../../libcrypto.a - WRAP[crypto/bio/test_bio_sock]=getsockopt setsockopt getsockname ioctl poll \ - gethostbyname BIO_lookup BIO_socket BIO_listen BIO_closesocket \ - BIO_ADDRINFO_free BIO_accept_ex BIO_sock_should_retry \ - BIO_ADDR_hostname_string BIO_ADDR_service_string - - PROGRAMS{noinst}=crypto/bio/test_bio_sock2 - SOURCE[crypto/bio/test_bio_sock2]=crypto/bio/test_bio_sock2.c - INCLUDE[crypto/bio/test_bio_sock2]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bio_sock2]=../../libcrypto.a - WRAP[crypto/bio/test_bio_sock2]=socket connect bind listen accept close \ - getsockopt setsockopt BIO_socket_nbio BIO_sock_should_retry - - PROGRAMS{noinst}=crypto/bio/test_bss_acpt - SOURCE[crypto/bio/test_bss_acpt]=crypto/bio/test_bss_acpt.c - WRAP[crypto/bio/test_bss_acpt]=BIO_lookup BIO_socket BIO_listen \ - BIO_accept_ex BIO_sock_info BIO_sock_should_retry BIO_closesocket \ - BIO_ADDR_hostname_string BIO_ADDR_service_string - INCLUDE[crypto/bio/test_bss_acpt]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bss_acpt]=../../libcrypto.a - - PROGRAMS{noinst}=crypto/bio/test_bss_conn - SOURCE[crypto/bio/test_bss_conn]=crypto/bio/test_bss_conn.c - WRAP[crypto/bio/test_bss_conn]=BIO_lookup BIO_socket BIO_connect \ - BIO_sock_should_retry BIO_closesocket BIO_socket_wait BIO_sock_error \ - read write - INCLUDE[crypto/bio/test_bss_conn]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bss_conn]=../../libcrypto.a - - PROGRAMS{noinst}=crypto/bio/test_bss_dgram - SOURCE[crypto/bio/test_bss_dgram]=crypto/bio/test_bss_dgram.c - WRAP[crypto/bio/test_bss_dgram]=recvfrom sendto write getsockname \ - getpeername BIO_closesocket BIO_socket_nbio - INCLUDE[crypto/bio/test_bss_dgram]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bss_dgram]=../../libcrypto.a - - PROGRAMS{noinst}=crypto/bio/test_bss_fd - SOURCE[crypto/bio/test_bss_fd]=crypto/bio/test_bss_fd.c - INCLUDE[crypto/bio/test_bss_fd]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bss_fd]=../../libcrypto.a - WRAP[crypto/bio/test_bss_fd]=read write lseek close - - PROGRAMS{noinst}=crypto/bio/test_bss_sock - SOURCE[crypto/bio/test_bss_sock]=crypto/bio/test_bss_sock.c - WRAP[crypto/bio/test_bss_sock]=read write BIO_closesocket - INCLUDE[crypto/bio/test_bss_sock]=../../include ../../crypto/bio - DEPEND[crypto/bio/test_bss_sock]=../../libcrypto.a -ENDIF - -IF[{- $config{target} =~ /^VC-/ -}] - PROGRAMS{noinst}=crypto/bio/test_bss_dgram_win - SOURCE[crypto/bio/test_bss_dgram_win]=crypto/bio/test_bss_dgram_win.c - UNIT_TEST[crypto/bio/test_bss_dgram_win]=cmocka detours - INCLUDE[crypto/bio/test_bss_dgram_win]=../../include ../../include/internal \ - ../../crypto/bio - DEPEND[crypto/bio/test_bss_dgram_win]=../../libcrypto -ENDIF diff --git a/test/unit/crypto/bio/test_bio_addr.c b/test/unit/crypto/bio/test_bio_addr.c deleted file mode 100644 index de92d8a0f6..0000000000 --- a/test/unit/crypto/bio/test_bio_addr.c +++ /dev/null @@ -1,1155 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/sockets.h" - -#ifdef OPENSSL_NO_SOCK - -int main(void) -{ - return 0; -} - -#else - -#include -#include -#include -#include -#include - -#include "bio_local.h" - -#include - -/* wraps */ - -int __wrap_BIO_sock_init(void); -#ifdef AI_PASSIVE -int __wrap_getnameinfo(const struct sockaddr *sa, socklen_t salen, - char *host, socklen_t hostlen, - char *serv, socklen_t servlen, int flags); -void __wrap_freeaddrinfo(struct addrinfo *res); -#endif - -int __wrap_BIO_sock_init(void) -{ - function_called(); - return mock_type(int); -} - -#ifdef AI_PASSIVE -int __wrap_getnameinfo(const struct sockaddr *sa, socklen_t salen, - char *host, socklen_t hostlen, - char *serv, socklen_t servlen, int flags) -{ - int rc; - - function_called(); - check_expected_ptr(sa); - check_expected(salen); - check_expected(flags); - rc = mock_type(int); - if (rc == 0) { - if (host != NULL) - strncpy(host, mock_ptr_type(const char *), hostlen - 1); - if (serv != NULL) - strncpy(serv, mock_ptr_type(const char *), servlen - 1); - } - return rc; -} - -void __wrap_freeaddrinfo(struct addrinfo *res) -{ - function_called(); - check_expected_ptr(res); -} -#endif /* AI_PASSIVE */ - -/* expectations */ - -static void expect_sock_init(int rc) -{ - expect_function_call(__wrap_BIO_sock_init); - will_return(__wrap_BIO_sock_init, rc); -} - -#ifdef AI_PASSIVE -static void expect_getnameinfo(const struct sockaddr *sa, socklen_t salen, - int flags, int rc, - const char *host_out, const char *serv_out) -{ - expect_function_call(__wrap_getnameinfo); - expect_value(__wrap_getnameinfo, sa, sa); - expect_value(__wrap_getnameinfo, salen, salen); - expect_value(__wrap_getnameinfo, flags, flags); - will_return(__wrap_getnameinfo, rc); - if (rc == 0) { - will_return(__wrap_getnameinfo, host_out); - will_return(__wrap_getnameinfo, serv_out); - } -} - -static void expect_freeaddrinfo(const struct addrinfo *res) -{ - expect_function_call(__wrap_freeaddrinfo); - expect_value(__wrap_freeaddrinfo, res, res); -} -#endif /* AI_PASSIVE */ - -/* BIO_ADDR_clear */ - -static void test_addr_clear(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0xFF, sizeof(ap)); - BIO_ADDR_clear(&ap); - assert_int_equal(ap.sa.sa_family, AF_UNSPEC); - assert_int_equal(ap.s_in.sin_port, 0); - assert_int_equal(ap.s_in.sin_addr.s_addr, 0); -} - -/* BIO_ADDR_make */ - -static void test_addr_make_ipv4(void **state) -{ - struct sockaddr_in sa4; - BIO_ADDR ap; - - (void)state; - memset(&sa4, 0, sizeof(sa4)); - sa4.sin_family = AF_INET; - sa4.sin_port = htons(443); - sa4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - assert_int_equal(BIO_ADDR_make(&ap, (const struct sockaddr *)&sa4), 1); - assert_int_equal(ap.s_in.sin_family, AF_INET); - assert_int_equal(ap.s_in.sin_port, htons(443)); - assert_int_equal(ap.s_in.sin_addr.s_addr, htonl(INADDR_LOOPBACK)); -} - -#if OPENSSL_USE_IPV6 -static void test_addr_make_ipv6(void **state) -{ - struct sockaddr_in6 sa6; - BIO_ADDR ap; - struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT; - - (void)state; - memset(&sa6, 0, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - sa6.sin6_port = htons(443); - sa6.sin6_addr = loopback; - - assert_int_equal(BIO_ADDR_make(&ap, (const struct sockaddr *)&sa6), 1); - assert_int_equal(ap.s_in6.sin6_family, AF_INET6); - assert_int_equal(ap.s_in6.sin6_port, htons(443)); - assert_memory_equal(&ap.s_in6.sin6_addr, &loopback, sizeof(loopback)); -} -#endif - -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_addr_make_unix(void **state) -{ - struct sockaddr_un sau; - BIO_ADDR ap; - - (void)state; - memset(&sau, 0, sizeof(sau)); - sau.sun_family = AF_UNIX; - strncpy(sau.sun_path, "/tmp/test.sock", sizeof(sau.sun_path) - 1); - - assert_int_equal(BIO_ADDR_make(&ap, (const struct sockaddr *)&sau), 1); - assert_int_equal(ap.s_un.sun_family, AF_UNIX); - assert_string_equal(ap.s_un.sun_path, "/tmp/test.sock"); -} -#endif - -static void test_addr_make_unknown_family(void **state) -{ - struct sockaddr sa; - BIO_ADDR ap; - - (void)state; - memset(&sa, 0, sizeof(sa)); - sa.sa_family = AF_UNSPEC; - assert_int_equal(BIO_ADDR_make(&ap, &sa), 0); -} - -/* BIO_ADDR_rawmake */ - -static void test_rawmake_ipv4(void **state) -{ - struct in_addr addr4; - BIO_ADDR ap; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - assert_int_equal( - BIO_ADDR_rawmake(&ap, AF_INET, &addr4, sizeof(addr4), htons(80)), 1); - assert_int_equal(ap.s_in.sin_family, AF_INET); - assert_int_equal(ap.s_in.sin_port, htons(80)); - assert_int_equal(ap.s_in.sin_addr.s_addr, htonl(INADDR_LOOPBACK)); -} - -static void test_rawmake_ipv4_wrong_len(void **state) -{ - struct in_addr addr4; - BIO_ADDR ap; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - assert_int_equal( - BIO_ADDR_rawmake(&ap, AF_INET, &addr4, sizeof(addr4) - 1, 0), 0); -} - -#if OPENSSL_USE_IPV6 -static void test_rawmake_ipv6(void **state) -{ - struct in6_addr addr6 = IN6ADDR_LOOPBACK_INIT; - BIO_ADDR ap; - - (void)state; - assert_int_equal( - BIO_ADDR_rawmake(&ap, AF_INET6, &addr6, sizeof(addr6), htons(443)), 1); - assert_int_equal(ap.s_in6.sin6_family, AF_INET6); - assert_int_equal(ap.s_in6.sin6_port, htons(443)); - assert_memory_equal(&ap.s_in6.sin6_addr, &addr6, sizeof(addr6)); -} -#endif - -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_rawmake_unix(void **state) -{ - const char *path = "/tmp/test.sock"; - BIO_ADDR ap; - - (void)state; - assert_int_equal( - BIO_ADDR_rawmake(&ap, AF_UNIX, path, strlen(path), 0), 1); - assert_int_equal(ap.s_un.sun_family, AF_UNIX); - assert_string_equal(ap.s_un.sun_path, path); -} - -static void test_rawmake_unix_too_long(void **state) -{ - /* path longer than sun_path must be rejected */ - char path[sizeof(((struct sockaddr_un *)0)->sun_path) + 2]; - BIO_ADDR ap; - - (void)state; - memset(path, 'x', sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - assert_int_equal( - BIO_ADDR_rawmake(&ap, AF_UNIX, path, strlen(path), 0), 0); -} -#endif - -static void test_rawmake_unknown_family(void **state) -{ - char data[4] = { 0 }; - BIO_ADDR ap; - - (void)state; - assert_int_equal(BIO_ADDR_rawmake(&ap, AF_UNSPEC, data, 0, 0), 0); -} - -/* BIO_ADDR_family */ - -static void test_addr_family(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_UNSPEC; - assert_int_equal(BIO_ADDR_family(&ap), AF_UNSPEC); - ap.sa.sa_family = AF_INET; - assert_int_equal(BIO_ADDR_family(&ap), AF_INET); -} - -/* BIO_ADDR_rawport */ - -static void test_rawport_ipv4(void **state) -{ - BIO_ADDR ap; - struct in_addr addr4; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&ap, AF_INET, &addr4, sizeof(addr4), htons(443)); - assert_int_equal(BIO_ADDR_rawport(&ap), htons(443)); -} - -#if OPENSSL_USE_IPV6 -static void test_rawport_ipv6(void **state) -{ - BIO_ADDR ap; - struct in6_addr addr6 = IN6ADDR_LOOPBACK_INIT; - - (void)state; - BIO_ADDR_rawmake(&ap, AF_INET6, &addr6, sizeof(addr6), htons(8080)); - assert_int_equal(BIO_ADDR_rawport(&ap), htons(8080)); -} -#endif - -static void test_rawport_no_port(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_UNSPEC; - assert_int_equal(BIO_ADDR_rawport(&ap), 0); -} - -/* BIO_ADDR_sockaddr and BIO_ADDR_sockaddr_noconst */ - -static void test_sockaddr_pointers(void **state) -{ - BIO_ADDR ap = { 0 }; - - (void)state; - memset(&ap, 0, sizeof(ap)); - assert_ptr_equal(BIO_ADDR_sockaddr(&ap), &ap.sa); - assert_ptr_equal(BIO_ADDR_sockaddr_noconst(&ap), &ap.sa); -} - -/* BIO_ADDR_sockaddr_size */ - -static void test_sockaddr_size_ipv4(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_INET; - assert_int_equal(BIO_ADDR_sockaddr_size(&ap), sizeof(struct sockaddr_in)); -} - -#if OPENSSL_USE_IPV6 -static void test_sockaddr_size_ipv6(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_INET6; - assert_int_equal(BIO_ADDR_sockaddr_size(&ap), sizeof(struct sockaddr_in6)); -} -#endif - -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_sockaddr_size_unix(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_UNIX; - assert_int_equal(BIO_ADDR_sockaddr_size(&ap), sizeof(struct sockaddr_un)); -} -#endif - -static void test_sockaddr_size_default(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_UNSPEC; - assert_int_equal(BIO_ADDR_sockaddr_size(&ap), sizeof(BIO_ADDR)); -} - -/* BIO_ADDR_rawaddress */ - -static void test_rawaddress_unset(void **state) -{ - BIO_ADDR ap; - struct in_addr out; - size_t len; - - (void)state; - memset(&ap, 0, sizeof(ap)); - ap.sa.sa_family = AF_UNSPEC; - assert_int_equal(BIO_ADDR_rawaddress(&ap, &out, &len), 0); -} - -static void test_rawaddress_ipv4(void **state) -{ - BIO_ADDR ap; - struct in_addr expected, out; - size_t len = 0; - - (void)state; - expected.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&ap, AF_INET, &expected, sizeof(expected), htons(80)); - - assert_int_equal(BIO_ADDR_rawaddress(&ap, &out, &len), 1); - assert_int_equal(len, sizeof(struct in_addr)); - assert_memory_equal(&out, &expected, sizeof(expected)); -} - -static void test_rawaddress_ipv4_len_only(void **state) -{ - BIO_ADDR ap; - struct in_addr addr4; - size_t len = 0; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&ap, AF_INET, &addr4, sizeof(addr4), 0); - - assert_int_equal(BIO_ADDR_rawaddress(&ap, NULL, &len), 1); - assert_int_equal(len, sizeof(struct in_addr)); -} - -static void test_rawaddress_ipv4_ptr_only(void **state) -{ - BIO_ADDR ap; - struct in_addr expected, out; - - (void)state; - expected.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&ap, AF_INET, &expected, sizeof(expected), 0); - - assert_int_equal(BIO_ADDR_rawaddress(&ap, &out, NULL), 1); - assert_memory_equal(&out, &expected, sizeof(expected)); -} - -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_rawaddress_unix(void **state) -{ - BIO_ADDR ap; - const char *path = "/tmp/unit.sock"; - char out[64]; - size_t len = 0; - - (void)state; - BIO_ADDR_rawmake(&ap, AF_UNIX, path, strlen(path), 0); - - assert_int_equal(BIO_ADDR_rawaddress(&ap, out, &len), 1); - assert_int_equal(len, strlen(path)); - assert_memory_equal(out, path, strlen(path)); -} -#endif - -/* BIO_ADDR_copy */ - -static void test_addr_copy_null(void **state) -{ - BIO_ADDR ap; - - (void)state; - memset(&ap, 0, sizeof(ap)); - assert_int_equal(BIO_ADDR_copy(NULL, NULL), 0); - assert_int_equal(BIO_ADDR_copy(NULL, &ap), 0); - assert_int_equal(BIO_ADDR_copy(&ap, NULL), 0); -} - -static void test_addr_copy_unspec(void **state) -{ - BIO_ADDR src, dst; - - (void)state; - memset(&src, 0, sizeof(src)); - src.sa.sa_family = AF_UNSPEC; - memset(&dst, 0xFF, sizeof(dst)); - - assert_int_equal(BIO_ADDR_copy(&dst, &src), 1); - assert_int_equal(dst.sa.sa_family, AF_UNSPEC); -} - -static void test_addr_copy_ipv4(void **state) -{ - BIO_ADDR src, dst; - struct in_addr addr4; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&src, AF_INET, &addr4, sizeof(addr4), htons(443)); - memset(&dst, 0, sizeof(dst)); - - assert_int_equal(BIO_ADDR_copy(&dst, &src), 1); - assert_int_equal(dst.s_in.sin_family, AF_INET); - assert_int_equal(dst.s_in.sin_port, htons(443)); - assert_int_equal(dst.s_in.sin_addr.s_addr, htonl(INADDR_LOOPBACK)); -} - -/* BIO_ADDR_new and BIO_ADDR_free */ - -static void test_addr_new_sets_unspec(void **state) -{ - BIO_ADDR *ap; - - (void)state; - ap = BIO_ADDR_new(); - assert_non_null(ap); - assert_int_equal(BIO_ADDR_family(ap), AF_UNSPEC); - BIO_ADDR_free(ap); -} - -/* BIO_ADDR_dup */ - -static void test_addr_dup_null(void **state) -{ - (void)state; - assert_null(BIO_ADDR_dup(NULL)); -} - -static void test_addr_dup_ipv4(void **state) -{ - BIO_ADDR src, *dup; - struct in_addr addr4; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&src, AF_INET, &addr4, sizeof(addr4), htons(8443)); - - dup = BIO_ADDR_dup(&src); - assert_non_null(dup); - assert_int_equal(dup->s_in.sin_family, AF_INET); - assert_int_equal(dup->s_in.sin_port, htons(8443)); - assert_int_equal(dup->s_in.sin_addr.s_addr, htonl(INADDR_LOOPBACK)); - BIO_ADDR_free(dup); -} - -/* BIO_ADDR_path_string */ - -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_path_string_unix(void **state) -{ - BIO_ADDR ap; - char *path; - - (void)state; - BIO_ADDR_rawmake(&ap, AF_UNIX, "/run/unit.sock", 14, 0); - - path = BIO_ADDR_path_string(&ap); - assert_non_null(path); - assert_string_equal(path, "/run/unit.sock"); - OPENSSL_free(path); -} -#endif - -static void test_path_string_non_unix(void **state) -{ - BIO_ADDR ap; - struct in_addr addr4; - - (void)state; - addr4.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(&ap, AF_INET, &addr4, sizeof(addr4), htons(80)); - assert_null(BIO_ADDR_path_string(&ap)); -} - -/* BIO_ADDRINFO accessors */ - -static void test_addrinfo_next_null(void **state) -{ - (void)state; - assert_null(BIO_ADDRINFO_next(NULL)); -} - -static void test_addrinfo_next(void **state) -{ - BIO_ADDRINFO a, b; - - (void)state; - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - a.bai_next = &b; - b.bai_next = NULL; - assert_ptr_equal(BIO_ADDRINFO_next(&a), &b); - assert_null(BIO_ADDRINFO_next(&b)); -} - -static void test_addrinfo_family(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - assert_int_equal(BIO_ADDRINFO_family(NULL), 0); - memset(&bai, 0, sizeof(bai)); - bai.bai_family = AF_INET; - assert_int_equal(BIO_ADDRINFO_family(&bai), AF_INET); -} - -static void test_addrinfo_socktype(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - assert_int_equal(BIO_ADDRINFO_socktype(NULL), 0); - memset(&bai, 0, sizeof(bai)); - bai.bai_socktype = SOCK_STREAM; - assert_int_equal(BIO_ADDRINFO_socktype(&bai), SOCK_STREAM); -} - -/* BIO_ADDRINFO_protocol */ - -static void test_addrinfo_protocol_null(void **state) -{ - (void)state; - assert_int_equal(BIO_ADDRINFO_protocol(NULL), 0); -} - -static void test_addrinfo_protocol_explicit(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - memset(&bai, 0, sizeof(bai)); - bai.bai_protocol = IPPROTO_SCTP; - assert_int_equal(BIO_ADDRINFO_protocol(&bai), IPPROTO_SCTP); -} - -static void test_addrinfo_protocol_stream(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - memset(&bai, 0, sizeof(bai)); - bai.bai_family = AF_INET; - bai.bai_socktype = SOCK_STREAM; - assert_int_equal(BIO_ADDRINFO_protocol(&bai), IPPROTO_TCP); -} - -static void test_addrinfo_protocol_dgram(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - memset(&bai, 0, sizeof(bai)); - bai.bai_family = AF_INET; - bai.bai_socktype = SOCK_DGRAM; - assert_int_equal(BIO_ADDRINFO_protocol(&bai), IPPROTO_UDP); -} - -#ifndef OPENSSL_NO_UNIX_SOCK -static void test_addrinfo_protocol_unix(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - memset(&bai, 0, sizeof(bai)); - bai.bai_family = AF_UNIX; - bai.bai_socktype = SOCK_STREAM; - /* AF_UNIX always returns 0, regardless of socktype */ - assert_int_equal(BIO_ADDRINFO_protocol(&bai), 0); -} -#endif - -static void test_addrinfo_sockaddr_size(void **state) -{ - BIO_ADDRINFO bai; - - (void)state; - assert_int_equal(BIO_ADDRINFO_sockaddr_size(NULL), 0); - memset(&bai, 0, sizeof(bai)); - bai.bai_addrlen = 28; - assert_int_equal(BIO_ADDRINFO_sockaddr_size(&bai), 28); -} - -static void test_addrinfo_sockaddr(void **state) -{ - BIO_ADDRINFO bai; - struct sockaddr sa; - - (void)state; - assert_null(BIO_ADDRINFO_sockaddr(NULL)); - memset(&bai, 0, sizeof(bai)); - bai.bai_addr = &sa; - assert_ptr_equal(BIO_ADDRINFO_sockaddr(&bai), &sa); -} - -static void test_addrinfo_address(void **state) -{ - BIO_ADDRINFO bai; - struct sockaddr sa; - - (void)state; - assert_null(BIO_ADDRINFO_address(NULL)); - memset(&bai, 0, sizeof(bai)); - bai.bai_addr = &sa; - assert_ptr_equal(BIO_ADDRINFO_address(&bai), (BIO_ADDR *)&sa); -} - -/* BIO_ADDRINFO_free */ - -static void test_addrinfo_free_null(void **state) -{ - (void)state; - BIO_ADDRINFO_free(NULL); /* must not crash */ -} - -#ifdef AI_PASSIVE -static void test_addrinfo_free_ip(void **state) -{ - /* AF_INET with AI_PASSIVE: freeaddrinfo is called, not manual free */ - struct addrinfo bai; - - (void)state; - memset(&bai, 0, sizeof(bai)); - bai.ai_family = AF_INET; - - expect_freeaddrinfo(&bai); - BIO_ADDRINFO_free(&bai); -} -#endif - -/* BIO_parse_hostserv */ - -static void test_parse_host_and_service(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("host.example:443", &host, &service, - BIO_PARSE_PRIO_HOST), - 1); - assert_string_equal(host, "host.example"); - assert_string_equal(service, "443"); - OPENSSL_free(host); - OPENSSL_free(service); -} - -static void test_parse_empty_host(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv(":80", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_null(host); - assert_string_equal(service, "80"); - OPENSSL_free(service); -} - -static void test_parse_star_host(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("*:80", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_null(host); - assert_string_equal(service, "80"); - OPENSSL_free(service); -} - -static void test_parse_empty_service(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("host:", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(host, "host"); - assert_null(service); - OPENSSL_free(host); -} - -static void test_parse_star_service(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("host:*", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(host, "host"); - assert_null(service); - OPENSSL_free(host); -} - -static void test_parse_no_colon_host_prio(void **state) -{ - /* no colon + HOST prio: host set, service untouched */ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("myhost", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(host, "myhost"); - assert_null(service); - OPENSSL_free(host); -} - -static void test_parse_no_colon_serv_prio(void **state) -{ - /* no colon + SERV prio: service set, host untouched */ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("https", &host, &service, BIO_PARSE_PRIO_SERV), 1); - assert_null(host); - assert_string_equal(service, "https"); - OPENSSL_free(service); -} - -static void test_parse_bracket_host_and_service(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("[::1]:443", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(host, "::1"); - assert_string_equal(service, "443"); - OPENSSL_free(host); - OPENSSL_free(service); -} - -static void test_parse_bracket_no_service(void **state) -{ - /* "[host]" with no trailing colon: service left untouched */ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("[::1]", &host, &service, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(host, "::1"); - assert_null(service); - OPENSSL_free(host); -} - -static void test_parse_bracket_unclosed(void **state) -{ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("[::1", &host, &service, BIO_PARSE_PRIO_HOST), 0); -} - -static void test_parse_bracket_bad_suffix(void **state) -{ - /* ']' not followed by ':' or '\0' */ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("[::1]X", &host, &service, BIO_PARSE_PRIO_HOST), 0); -} - -static void test_parse_bracket_service_with_colon(void **state) -{ - /* service part contains a colon */ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("[host]:a:b", &host, &service, BIO_PARSE_PRIO_HOST), 0); -} - -static void test_parse_ambiguous(void **state) -{ - /* multiple colons without brackets */ - char *host = NULL, *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("host:port:extra", &host, &service, - BIO_PARSE_PRIO_HOST), - 0); -} - -static void test_parse_null_host_param(void **state) -{ - /* host output param NULL */ - char *service = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("host:443", NULL, &service, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(service, "443"); - OPENSSL_free(service); -} - -static void test_parse_null_service_param(void **state) -{ - /* service output param NULL */ - char *host = NULL; - - (void)state; - assert_int_equal( - BIO_parse_hostserv("host:443", &host, NULL, BIO_PARSE_PRIO_HOST), 1); - assert_string_equal(host, "host"); - OPENSSL_free(host); -} - -/* BIO_ADDR_hostname_string and BIO_ADDR_service_string (addr_strings) */ - -static void make_ipv4_addr(BIO_ADDR *ap, unsigned short port) -{ - struct in_addr addr4; - - addr4.s_addr = htonl(INADDR_LOOPBACK); - BIO_ADDR_rawmake(ap, AF_INET, &addr4, sizeof(addr4), htons(port)); -} - -static void test_hostname_string_sock_init_fail(void **state) -{ - BIO_ADDR ap; - - (void)state; - make_ipv4_addr(&ap, 80); - - expect_sock_init(0); - assert_null(BIO_ADDR_hostname_string(&ap, 1)); -} - -static void test_service_string_sock_init_fail(void **state) -{ - BIO_ADDR ap; - - (void)state; - make_ipv4_addr(&ap, 443); - - expect_sock_init(0); - assert_null(BIO_ADDR_service_string(&ap, 1)); -} - -#ifdef AI_PASSIVE -static void test_hostname_string_getnameinfo_fail(void **state) -{ - BIO_ADDR ap; - - (void)state; - make_ipv4_addr(&ap, 80); - - expect_sock_init(1); - expect_getnameinfo(BIO_ADDR_sockaddr(&ap), - BIO_ADDR_sockaddr_size(&ap), - NI_NUMERICHOST | NI_NUMERICSERV, - EAI_AGAIN, NULL, NULL); - assert_null(BIO_ADDR_hostname_string(&ap, 1)); -} - -static void test_hostname_string_numeric(void **state) -{ - BIO_ADDR ap; - char *result; - - (void)state; - make_ipv4_addr(&ap, 80); - - expect_sock_init(1); - expect_getnameinfo(BIO_ADDR_sockaddr(&ap), - BIO_ADDR_sockaddr_size(&ap), - NI_NUMERICHOST | NI_NUMERICSERV, - 0, "127.0.0.1", "80"); - result = BIO_ADDR_hostname_string(&ap, 1); - assert_non_null(result); - assert_string_equal(result, "127.0.0.1"); - OPENSSL_free(result); -} - -static void test_hostname_string_non_numeric(void **state) -{ - BIO_ADDR ap; - char *result; - - (void)state; - make_ipv4_addr(&ap, 80); - - expect_sock_init(1); - expect_getnameinfo(BIO_ADDR_sockaddr(&ap), - BIO_ADDR_sockaddr_size(&ap), - 0, /* flags = 0 for non-numeric lookup */ - 0, "localhost", "http"); - result = BIO_ADDR_hostname_string(&ap, 0); - assert_non_null(result); - assert_string_equal(result, "localhost"); - OPENSSL_free(result); -} - -static void test_service_string_numeric(void **state) -{ - BIO_ADDR ap; - char *result; - - (void)state; - make_ipv4_addr(&ap, 443); - - expect_sock_init(1); - expect_getnameinfo(BIO_ADDR_sockaddr(&ap), - BIO_ADDR_sockaddr_size(&ap), - NI_NUMERICHOST | NI_NUMERICSERV, - 0, "127.0.0.1", "443"); - result = BIO_ADDR_service_string(&ap, 1); - assert_non_null(result); - assert_string_equal(result, "443"); - OPENSSL_free(result); -} -#else - -/* inet_ntoa path: no getnameinfo, result is deterministic from the address */ -static void test_hostname_string_fallback(void **state) -{ - BIO_ADDR ap; - char *result; - - (void)state; - make_ipv4_addr(&ap, 80); - - expect_sock_init(1); - result = BIO_ADDR_hostname_string(&ap, 1); - assert_non_null(result); - assert_string_equal(result, "127.0.0.1"); - OPENSSL_free(result); -} - -static void test_service_string_fallback(void **state) -{ - BIO_ADDR ap; - char *result; - - (void)state; - make_ipv4_addr(&ap, 443); - - expect_sock_init(1); - result = BIO_ADDR_service_string(&ap, 1); - assert_non_null(result); - assert_string_equal(result, "443"); - OPENSSL_free(result); -} - -#endif /* AI_PASSIVE */ - -/* main */ - -#define ADDR_TEST(name) cmocka_unit_test(name) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* BIO_ADDR_clear */ - ADDR_TEST(test_addr_clear), - /* BIO_ADDR_make */ - ADDR_TEST(test_addr_make_ipv4), -#if OPENSSL_USE_IPV6 - ADDR_TEST(test_addr_make_ipv6), -#endif -#ifndef OPENSSL_NO_UNIX_SOCK - ADDR_TEST(test_addr_make_unix), -#endif - ADDR_TEST(test_addr_make_unknown_family), - /* BIO_ADDR_rawmake */ - ADDR_TEST(test_rawmake_ipv4), - ADDR_TEST(test_rawmake_ipv4_wrong_len), -#if OPENSSL_USE_IPV6 - ADDR_TEST(test_rawmake_ipv6), -#endif -#ifndef OPENSSL_NO_UNIX_SOCK - ADDR_TEST(test_rawmake_unix), - ADDR_TEST(test_rawmake_unix_too_long), -#endif - ADDR_TEST(test_rawmake_unknown_family), - /* BIO_ADDR_family */ - ADDR_TEST(test_addr_family), - /* BIO_ADDR_rawport */ - ADDR_TEST(test_rawport_ipv4), -#if OPENSSL_USE_IPV6 - ADDR_TEST(test_rawport_ipv6), -#endif - ADDR_TEST(test_rawport_no_port), - /* BIO_ADDR_sockaddr / BIO_ADDR_sockaddr_noconst */ - ADDR_TEST(test_sockaddr_pointers), - /* BIO_ADDR_sockaddr_size */ - ADDR_TEST(test_sockaddr_size_ipv4), -#if OPENSSL_USE_IPV6 - ADDR_TEST(test_sockaddr_size_ipv6), -#endif -#ifndef OPENSSL_NO_UNIX_SOCK - ADDR_TEST(test_sockaddr_size_unix), -#endif - ADDR_TEST(test_sockaddr_size_default), - /* BIO_ADDR_rawaddress */ - ADDR_TEST(test_rawaddress_unset), - ADDR_TEST(test_rawaddress_ipv4), - ADDR_TEST(test_rawaddress_ipv4_len_only), - ADDR_TEST(test_rawaddress_ipv4_ptr_only), -#ifndef OPENSSL_NO_UNIX_SOCK - ADDR_TEST(test_rawaddress_unix), -#endif - /* BIO_ADDR_copy */ - ADDR_TEST(test_addr_copy_null), - ADDR_TEST(test_addr_copy_unspec), - ADDR_TEST(test_addr_copy_ipv4), - /* BIO_ADDR_new and BIO_ADDR_free */ - ADDR_TEST(test_addr_new_sets_unspec), - /* BIO_ADDR_dup */ - ADDR_TEST(test_addr_dup_null), - ADDR_TEST(test_addr_dup_ipv4), - /* BIO_ADDR_path_string */ -#ifndef OPENSSL_NO_UNIX_SOCK - ADDR_TEST(test_path_string_unix), -#endif - ADDR_TEST(test_path_string_non_unix), - /* BIO_ADDRINFO accessors */ - ADDR_TEST(test_addrinfo_next_null), - ADDR_TEST(test_addrinfo_next), - ADDR_TEST(test_addrinfo_family), - ADDR_TEST(test_addrinfo_socktype), - ADDR_TEST(test_addrinfo_protocol_null), - ADDR_TEST(test_addrinfo_protocol_explicit), - ADDR_TEST(test_addrinfo_protocol_stream), - ADDR_TEST(test_addrinfo_protocol_dgram), -#ifndef OPENSSL_NO_UNIX_SOCK - ADDR_TEST(test_addrinfo_protocol_unix), -#endif - ADDR_TEST(test_addrinfo_sockaddr_size), - ADDR_TEST(test_addrinfo_sockaddr), - ADDR_TEST(test_addrinfo_address), - /* BIO_ADDRINFO_free */ - ADDR_TEST(test_addrinfo_free_null), -#ifdef AI_PASSIVE - ADDR_TEST(test_addrinfo_free_ip), -#endif - /* BIO_parse_hostserv */ - ADDR_TEST(test_parse_host_and_service), - ADDR_TEST(test_parse_empty_host), - ADDR_TEST(test_parse_star_host), - ADDR_TEST(test_parse_empty_service), - ADDR_TEST(test_parse_star_service), - ADDR_TEST(test_parse_no_colon_host_prio), - ADDR_TEST(test_parse_no_colon_serv_prio), - ADDR_TEST(test_parse_bracket_host_and_service), - ADDR_TEST(test_parse_bracket_no_service), - ADDR_TEST(test_parse_bracket_unclosed), - ADDR_TEST(test_parse_bracket_bad_suffix), - ADDR_TEST(test_parse_bracket_service_with_colon), - ADDR_TEST(test_parse_ambiguous), - ADDR_TEST(test_parse_null_host_param), - ADDR_TEST(test_parse_null_service_param), - /* BIO_ADDR_hostname_string / BIO_ADDR_service_string */ - ADDR_TEST(test_hostname_string_sock_init_fail), - ADDR_TEST(test_service_string_sock_init_fail), -#ifdef AI_PASSIVE - ADDR_TEST(test_hostname_string_getnameinfo_fail), - ADDR_TEST(test_hostname_string_numeric), - ADDR_TEST(test_hostname_string_non_numeric), - ADDR_TEST(test_service_string_numeric), -#else - ADDR_TEST(test_hostname_string_fallback), - ADDR_TEST(test_service_string_fallback), -#endif - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/test/unit/crypto/bio/test_bio_sock.c b/test/unit/crypto/bio/test_bio_sock.c deleted file mode 100644 index b41f9ed011..0000000000 --- a/test/unit/crypto/bio/test_bio_sock.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/sockets.h" - -#ifndef OPENSSL_NO_SOCK - -#include -#include -#include -#include - -#include "bio_local.h" -#include - -#define FAKE_SOCKET 42 - -#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) -#ifdef SOL_TCP -#define TEST_TCP_LEVEL SOL_TCP -#else -#define TEST_TCP_LEVEL IPPROTO_TCP -#endif -#endif - -/* prototypes for __wrap_* (required by -Wmissing-prototypes) */ -int __wrap_getsockopt(int fd, int level, int optname, void *optval, - socklen_t *optlen); -int __wrap_setsockopt(int fd, int level, int optname, const void *optval, - socklen_t optlen); -int __wrap_getsockname(int fd, struct sockaddr *addr, socklen_t *slen); -int __wrap_ioctl(int fd, unsigned long request, void *arg); -int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout); -struct hostent *__wrap_gethostbyname(const char *name); -int __wrap_BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, int family, int socktype, - BIO_ADDRINFO **res); -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options); -int __wrap_BIO_listen(int sock, const BIO_ADDR *ba, int options); -int __wrap_BIO_closesocket(int sock); -void __wrap_BIO_ADDRINFO_free(BIO_ADDRINFO *bai); -int __wrap_BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options); -int __wrap_BIO_sock_should_retry(int i); -char *__wrap_BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric); -char *__wrap_BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric); - -/* wraps */ - -int __wrap_getsockopt(int fd, int level, int optname, void *optval, - socklen_t *optlen) -{ - int rc; - - function_called(); - check_expected(fd); - check_expected(level); - check_expected(optname); - (void)optlen; - rc = mock_type(int); - if (rc == 0) { - if (optval != NULL) - *(int *)optval = mock_type(int); - } else { - errno = mock_type(int); - } - return rc; -} - -int __wrap_setsockopt(int fd, int level, int optname, const void *optval, - socklen_t optlen) -{ - int on = (optval != NULL) ? *(const int *)optval : 0; - - function_called(); - check_expected(fd); - check_expected(level); - check_expected(optname); - check_expected(on); - (void)optlen; - return mock_type(int); -} - -int __wrap_getsockname(int fd, struct sockaddr *addr, socklen_t *slen) -{ - int rc; - - function_called(); - check_expected(fd); - (void)addr; - rc = mock_type(int); - if (rc == 0 && slen != NULL) - *slen = (socklen_t)mock_type(int); - return rc; -} - -int __wrap_ioctl(int fd, unsigned long request, void *arg) -{ - function_called(); - check_expected(fd); - check_expected(request); - (void)arg; - return mock_type(int); -} - -int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) -{ - int pfd = fds[0].fd; - int events = fds[0].events; - - function_called(); - check_expected(pfd); - check_expected(events); - (void)nfds; - (void)timeout; - return mock_type(int); -} - -struct hostent *__wrap_gethostbyname(const char *name) -{ - function_called(); - check_expected_ptr(name); - return mock_ptr_type(struct hostent *); -} - -int __wrap_BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, int family, int socktype, - BIO_ADDRINFO **res) -{ - int rc; - - function_called(); - check_expected(family); - check_expected(socktype); - check_expected(lookup_type); - (void)host; - (void)service; - rc = mock_type(int); - if (rc == 1) { - BIO_ADDRINFO *r = mock_ptr_type(BIO_ADDRINFO *); - - if (res != NULL) - *res = r; - } - return rc; -} - -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options) -{ - function_called(); - check_expected(domain); - check_expected(socktype); - check_expected(protocol); - (void)options; - return mock_type(int); -} - -int __wrap_BIO_listen(int sock, const BIO_ADDR *ba, int options) -{ - function_called(); - check_expected(sock); - check_expected(options); - (void)ba; - return mock_type(int); -} - -int __wrap_BIO_closesocket(int sock) -{ - function_called(); - check_expected(sock); - return mock_type(int); -} - -/* the fake addrinfo handed back by BIO_lookup is static; nothing to release */ -void __wrap_BIO_ADDRINFO_free(BIO_ADDRINFO *bai) -{ - (void)bai; -} - -int __wrap_BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options) -{ - function_called(); - check_expected(accept_sock); - check_expected(options); - (void)addr; - return mock_type(int); -} - -int __wrap_BIO_sock_should_retry(int i) -{ - function_called(); - check_expected(i); - return mock_type(int); -} - -char *__wrap_BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric) -{ - function_called(); - check_expected(numeric); - (void)ap; - return mock_ptr_type(char *); -} - -char *__wrap_BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric) -{ - function_called(); - check_expected(numeric); - (void)ap; - return mock_ptr_type(char *); -} - -/* expectations */ - -static void expect_getsockopt(int fd, int rc, int value) -{ - expect_function_call(__wrap_getsockopt); - expect_value(__wrap_getsockopt, fd, fd); - expect_value(__wrap_getsockopt, level, SOL_SOCKET); - expect_value(__wrap_getsockopt, optname, SO_ERROR); - will_return(__wrap_getsockopt, rc); - will_return(__wrap_getsockopt, value); -} - -#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) -static void expect_setsockopt(int fd, int on, int rc) -{ - expect_function_call(__wrap_setsockopt); - expect_value(__wrap_setsockopt, fd, fd); - expect_value(__wrap_setsockopt, level, TEST_TCP_LEVEL); - expect_value(__wrap_setsockopt, optname, TCP_NODELAY); - expect_value(__wrap_setsockopt, on, on); - will_return(__wrap_setsockopt, rc); -} -#endif - -static void expect_getsockname(int fd, int rc, socklen_t outlen) -{ - expect_function_call(__wrap_getsockname); - expect_value(__wrap_getsockname, fd, fd); - will_return(__wrap_getsockname, rc); - if (rc == 0) - will_return(__wrap_getsockname, (int)outlen); -} - -#ifdef FIONBIO -static void expect_ioctl(int fd, unsigned long request, int rc) -{ - expect_function_call(__wrap_ioctl); - expect_value(__wrap_ioctl, fd, fd); - expect_value(__wrap_ioctl, request, request); - will_return(__wrap_ioctl, rc); -} -#endif - -static void expect_poll(int fd, int events, int rc) -{ - expect_function_call(__wrap_poll); - expect_value(__wrap_poll, pfd, fd); - expect_value(__wrap_poll, events, events); - will_return(__wrap_poll, rc); -} - -/* setup */ - -/* BIO_sock_init / bio_sock_cleanup_int */ - -static void test_sock_init(void **state) -{ - (void)state; - assert_int_equal(BIO_sock_init(), 1); -} - -static void test_sock_cleanup(void **state) -{ - (void)state; - /* no-op on non-Windows; exercised for coverage */ - bio_sock_cleanup_int(); -} - -/* BIO_sock_error */ - -static void test_sock_error_value(void **state) -{ - /* getsockopt succeeds: SO_ERROR value is returned verbatim */ - (void)state; - expect_getsockopt(FAKE_SOCKET, 0, ECONNREFUSED); - assert_int_equal(BIO_sock_error(FAKE_SOCKET), ECONNREFUSED); -} - -static void test_sock_error_getsockopt_fails(void **state) -{ - /* getsockopt fails: the last socket error (errno) is returned */ - (void)state; - expect_getsockopt(FAKE_SOCKET, -1, EBADF); - assert_int_equal(BIO_sock_error(FAKE_SOCKET), EBADF); -} - -/* BIO_socket_ioctl */ - -#ifdef FIONBIO -static void test_socket_ioctl_success(void **state) -{ - int arg = 1; - - (void)state; - expect_ioctl(FAKE_SOCKET, FIONBIO, 0); - assert_int_equal(BIO_socket_ioctl(FAKE_SOCKET, FIONBIO, &arg), 0); -} - -static void test_socket_ioctl_error(void **state) -{ - int arg = 1; - - (void)state; - expect_ioctl(FAKE_SOCKET, FIONBIO, -1); - assert_int_equal(BIO_socket_ioctl(FAKE_SOCKET, FIONBIO, &arg), -1); -} -#endif - -/* BIO_set_tcp_ndelay */ - -#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) -static void test_set_tcp_ndelay_on(void **state) -{ - (void)state; - expect_setsockopt(FAKE_SOCKET, 1, 0); - assert_int_equal(BIO_set_tcp_ndelay(FAKE_SOCKET, 1), 1); -} - -static void test_set_tcp_ndelay_off(void **state) -{ - (void)state; - expect_setsockopt(FAKE_SOCKET, 0, 0); - assert_int_equal(BIO_set_tcp_ndelay(FAKE_SOCKET, 0), 1); -} - -static void test_set_tcp_ndelay_fails(void **state) -{ - (void)state; - expect_setsockopt(FAKE_SOCKET, 1, -1); - assert_int_equal(BIO_set_tcp_ndelay(FAKE_SOCKET, 1), 0); -} -#endif - -/* BIO_socket_nbio */ - -#ifdef FIONBIO -static void test_socket_nbio_enable(void **state) -{ - (void)state; - expect_ioctl(FAKE_SOCKET, FIONBIO, 0); - assert_int_equal(BIO_socket_nbio(FAKE_SOCKET, 1), 1); -} - -static void test_socket_nbio_disable(void **state) -{ - (void)state; - expect_ioctl(FAKE_SOCKET, FIONBIO, 0); - assert_int_equal(BIO_socket_nbio(FAKE_SOCKET, 0), 1); -} - -static void test_socket_nbio_fails(void **state) -{ - (void)state; - expect_ioctl(FAKE_SOCKET, FIONBIO, -1); - assert_int_equal(BIO_socket_nbio(FAKE_SOCKET, 1), 0); -} -#endif - -/* BIO_sock_info */ - -static void test_sock_info_success(void **state) -{ - union BIO_sock_info_u info; - BIO_ADDR addr; - - (void)state; - memset(&addr, 0, sizeof(addr)); - info.addr = &addr; - expect_getsockname(FAKE_SOCKET, 0, (socklen_t)sizeof(struct sockaddr_in)); - assert_int_equal( - BIO_sock_info(FAKE_SOCKET, BIO_SOCK_INFO_ADDRESS, &info), 1); -} - -static void test_sock_info_getsockname_fails(void **state) -{ - union BIO_sock_info_u info; - BIO_ADDR addr; - - (void)state; - memset(&addr, 0, sizeof(addr)); - info.addr = &addr; - expect_getsockname(FAKE_SOCKET, -1, 0); - assert_int_equal( - BIO_sock_info(FAKE_SOCKET, BIO_SOCK_INFO_ADDRESS, &info), 0); -} - -static void test_sock_info_truncated(void **state) -{ - /* getsockname reports an address larger than the BIO_ADDR storage */ - union BIO_sock_info_u info; - BIO_ADDR addr; - - (void)state; - memset(&addr, 0, sizeof(addr)); - info.addr = &addr; - expect_getsockname(FAKE_SOCKET, 0, (socklen_t)(sizeof(BIO_ADDR) + 1)); - assert_int_equal( - BIO_sock_info(FAKE_SOCKET, BIO_SOCK_INFO_ADDRESS, &info), 0); -} - -static void test_sock_info_unknown_type(void **state) -{ - union BIO_sock_info_u info; - BIO_ADDR addr; - - (void)state; - memset(&addr, 0, sizeof(addr)); - info.addr = &addr; - assert_int_equal( - BIO_sock_info(FAKE_SOCKET, (enum BIO_sock_info_type)999, &info), 0); -} - -/* BIO_socket_wait */ - -static void test_socket_wait_immediate(void **state) -{ - /* max_time == 0 returns immediately without polling */ - (void)state; - assert_int_equal(BIO_socket_wait(FAKE_SOCKET, 1, 0), 1); -} - -static void test_socket_wait_bad_fd(void **state) -{ - (void)state; - assert_int_equal(BIO_socket_wait(-1, 1, time(NULL) + 100), -1); -} - -static void test_socket_wait_past(void **state) -{ - /* deadline already elapsed: timeout without polling */ - (void)state; - assert_int_equal(BIO_socket_wait(FAKE_SOCKET, 1, (time_t)1), 0); -} - -static void test_socket_wait_read_ready(void **state) -{ - (void)state; - expect_poll(FAKE_SOCKET, POLLIN, 1); - assert_int_equal(BIO_socket_wait(FAKE_SOCKET, 1, time(NULL) + 100), 1); -} - -static void test_socket_wait_write_ready(void **state) -{ - (void)state; - expect_poll(FAKE_SOCKET, POLLOUT, 1); - assert_int_equal(BIO_socket_wait(FAKE_SOCKET, 0, time(NULL) + 100), 1); -} - -static void test_socket_wait_timeout(void **state) -{ - (void)state; - expect_poll(FAKE_SOCKET, POLLIN, 0); - assert_int_equal(BIO_socket_wait(FAKE_SOCKET, 1, time(NULL) + 100), 0); -} - -static void test_socket_wait_error(void **state) -{ - (void)state; - expect_poll(FAKE_SOCKET, POLLIN, -1); - assert_int_equal(BIO_socket_wait(FAKE_SOCKET, 1, time(NULL) + 100), -1); -} - -/* main */ - -#define SOCK_TEST(name) cmocka_unit_test(name) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* BIO_sock_init / cleanup */ - SOCK_TEST(test_sock_init), - SOCK_TEST(test_sock_cleanup), - /* BIO_sock_error */ - SOCK_TEST(test_sock_error_value), - SOCK_TEST(test_sock_error_getsockopt_fails), -#ifdef FIONBIO - /* BIO_socket_ioctl */ - SOCK_TEST(test_socket_ioctl_success), - SOCK_TEST(test_socket_ioctl_error), -#endif - /* BIO_set_tcp_ndelay */ -#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) - SOCK_TEST(test_set_tcp_ndelay_on), - SOCK_TEST(test_set_tcp_ndelay_off), - SOCK_TEST(test_set_tcp_ndelay_fails), -#endif - /* BIO_socket_nbio */ -#ifdef FIONBIO - SOCK_TEST(test_socket_nbio_enable), - SOCK_TEST(test_socket_nbio_disable), - SOCK_TEST(test_socket_nbio_fails), -#endif - /* BIO_sock_info */ - SOCK_TEST(test_sock_info_success), - SOCK_TEST(test_sock_info_getsockname_fails), - SOCK_TEST(test_sock_info_truncated), - SOCK_TEST(test_sock_info_unknown_type), - /* BIO_socket_wait */ - SOCK_TEST(test_socket_wait_immediate), - SOCK_TEST(test_socket_wait_bad_fd), - SOCK_TEST(test_socket_wait_past), - SOCK_TEST(test_socket_wait_read_ready), - SOCK_TEST(test_socket_wait_write_ready), - SOCK_TEST(test_socket_wait_timeout), - SOCK_TEST(test_socket_wait_error), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#else - -int main(void) -{ - return 0; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/test/unit/crypto/bio/test_bio_sock2.c b/test/unit/crypto/bio/test_bio_sock2.c deleted file mode 100644 index 96f63e59cf..0000000000 --- a/test/unit/crypto/bio/test_bio_sock2.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/sockets.h" - -#ifndef OPENSSL_NO_SOCK - -#include -#include -#include -#include - -#include "bio_local.h" -#include "internal/bio_tfo.h" -#include - -#define FAKE_SOCKET 42 -#define ACCEPTED_SOCKET 7 - -/* prototypes for __wrap_* (required by -Wmissing-prototypes) */ -int __wrap_socket(int domain, int type, int protocol); -int __wrap_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); -int __wrap_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); -int __wrap_listen(int fd, int backlog); -int __wrap_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); -int __wrap_close(int fd); -int __wrap_getsockopt(int fd, int level, int optname, void *optval, - socklen_t *optlen); -int __wrap_setsockopt(int fd, int level, int optname, const void *optval, - socklen_t optlen); -int __wrap_BIO_socket_nbio(int fd, int mode); -int __wrap_BIO_sock_should_retry(int i); - -/* wraps */ - -int __wrap_socket(int domain, int type, int protocol) -{ - function_called(); - check_expected(domain); - check_expected(type); - check_expected(protocol); - return mock_type(int); -} - -int __wrap_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) -{ - function_called(); - check_expected(fd); - (void)addr; - (void)addrlen; - return mock_type(int); -} - -int __wrap_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) -{ - function_called(); - check_expected(fd); - (void)addr; - (void)addrlen; - return mock_type(int); -} - -int __wrap_listen(int fd, int backlog) -{ - function_called(); - check_expected(fd); - (void)backlog; - return mock_type(int); -} - -int __wrap_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) -{ - function_called(); - check_expected(fd); - (void)addr; - (void)addrlen; - return mock_type(int); -} - -int __wrap_close(int fd) -{ - function_called(); - check_expected(fd); - return mock_type(int); -} - -int __wrap_getsockopt(int fd, int level, int optname, void *optval, - socklen_t *optlen) -{ - int rc; - - function_called(); - check_expected(fd); - check_expected(level); - check_expected(optname); - rc = mock_type(int); - if (rc == 0) { - if (optval != NULL) - *(int *)optval = mock_type(int); - if (optlen != NULL) - *optlen = (socklen_t)mock_type(int); - } - return rc; -} - -int __wrap_setsockopt(int fd, int level, int optname, const void *optval, - socklen_t optlen) -{ - int on = (optval != NULL) ? *(const int *)optval : 0; - - function_called(); - check_expected(fd); - check_expected(level); - check_expected(optname); - check_expected(on); - (void)optlen; - return mock_type(int); -} - -int __wrap_BIO_socket_nbio(int fd, int mode) -{ - function_called(); - check_expected(fd); - check_expected(mode); - return mock_type(int); -} - -int __wrap_BIO_sock_should_retry(int i) -{ - function_called(); - check_expected(i); - return mock_type(int); -} - -/* expectations */ - -static void expect_socket(int domain, int type, int protocol, int rc) -{ - expect_function_call(__wrap_socket); - expect_value(__wrap_socket, domain, domain); - expect_value(__wrap_socket, type, type); - expect_value(__wrap_socket, protocol, protocol); - will_return(__wrap_socket, rc); -} - -static void expect_connect(int fd, int rc) -{ - expect_function_call(__wrap_connect); - expect_value(__wrap_connect, fd, fd); - will_return(__wrap_connect, rc); -} - -static void expect_bind(int fd, int rc) -{ - expect_function_call(__wrap_bind); - expect_value(__wrap_bind, fd, fd); - will_return(__wrap_bind, rc); -} - -static void expect_listen(int fd, int rc) -{ - expect_function_call(__wrap_listen); - expect_value(__wrap_listen, fd, fd); - will_return(__wrap_listen, rc); -} - -static void expect_accept(int fd, int rc) -{ - expect_function_call(__wrap_accept); - expect_value(__wrap_accept, fd, fd); - will_return(__wrap_accept, rc); -} - -static void expect_close(int fd, int rc) -{ - expect_function_call(__wrap_close); - expect_value(__wrap_close, fd, fd); - will_return(__wrap_close, rc); -} - -static void expect_getsockopt(int fd, int level, int optname, int rc, - int value, socklen_t outlen) -{ - expect_function_call(__wrap_getsockopt); - expect_value(__wrap_getsockopt, fd, fd); - expect_value(__wrap_getsockopt, level, level); - expect_value(__wrap_getsockopt, optname, optname); - will_return(__wrap_getsockopt, rc); - if (rc == 0) { - will_return(__wrap_getsockopt, value); - will_return(__wrap_getsockopt, (int)outlen); - } -} - -static void expect_setsockopt(int fd, int level, int optname, int on, int rc) -{ - expect_function_call(__wrap_setsockopt); - expect_value(__wrap_setsockopt, fd, fd); - expect_value(__wrap_setsockopt, level, level); - expect_value(__wrap_setsockopt, optname, optname); - expect_value(__wrap_setsockopt, on, on); - will_return(__wrap_setsockopt, rc); -} - -static void expect_nbio(int fd, int mode, int rc) -{ - expect_function_call(__wrap_BIO_socket_nbio); - expect_value(__wrap_BIO_socket_nbio, fd, fd); - expect_value(__wrap_BIO_socket_nbio, mode, mode); - will_return(__wrap_BIO_socket_nbio, rc); -} - -static void expect_should_retry(int i, int rc) -{ - expect_function_call(__wrap_BIO_sock_should_retry); - expect_value(__wrap_BIO_sock_should_retry, i, i); - will_return(__wrap_BIO_sock_should_retry, rc); -} - -/* helpers */ - -static void make_addr(BIO_ADDR *a, int family) -{ - memset(a, 0, sizeof(*a)); - a->sa.sa_family = family; -} - -/* BIO_socket */ - -static void test_socket_success(void **state) -{ - (void)state; - expect_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, FAKE_SOCKET); - assert_int_equal( - BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0), FAKE_SOCKET); -} - -static void test_socket_fails(void **state) -{ - (void)state; - expect_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, -1); - assert_int_equal( - BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0), (int)INVALID_SOCKET); -} - -/* BIO_connect */ - -static void test_connect_invalid_sock(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - assert_int_equal(BIO_connect(-1, &a, 0), 0); -} - -static void test_connect_nbio_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 0); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, 0), 0); -} - -static void test_connect_success(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_connect(FAKE_SOCKET, 0); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, 0), 1); -} - -static void test_connect_nonblock(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 1, 1); - expect_connect(FAKE_SOCKET, 0); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, BIO_SOCK_NONBLOCK), 1); -} - -static void test_connect_keepalive(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_KEEPALIVE, 1, 0); - expect_connect(FAKE_SOCKET, 0); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, BIO_SOCK_KEEPALIVE), 1); -} - -static void test_connect_keepalive_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_KEEPALIVE, 1, -1); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, BIO_SOCK_KEEPALIVE), 0); -} - -static void test_connect_nodelay(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, IPPROTO_TCP, TCP_NODELAY, 1, 0); - expect_connect(FAKE_SOCKET, 0); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, BIO_SOCK_NODELAY), 1); -} - -static void test_connect_nodelay_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, IPPROTO_TCP, TCP_NODELAY, 1, -1); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, BIO_SOCK_NODELAY), 0); -} - -static void test_connect_fails_retry(void **state) -{ - /* connect() failing retryably returns 0 without raising a fatal error */ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_connect(FAKE_SOCKET, -1); - expect_should_retry(-1, 1); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, 0), 0); -} - -static void test_connect_fails_error(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_connect(FAKE_SOCKET, -1); - expect_should_retry(-1, 0); - assert_int_equal(BIO_connect(FAKE_SOCKET, &a, 0), 0); -} - -/* BIO_bind */ - -static void test_bind_invalid_sock(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - assert_int_equal(BIO_bind(-1, &a, 0), 0); -} - -static void test_bind_success(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_bind(FAKE_SOCKET, 0); - assert_int_equal(BIO_bind(FAKE_SOCKET, &a, 0), 1); -} - -static void test_bind_reuseaddr(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_REUSEADDR, 1, 0); - expect_bind(FAKE_SOCKET, 0); - assert_int_equal(BIO_bind(FAKE_SOCKET, &a, BIO_SOCK_REUSEADDR), 1); -} - -static void test_bind_reuseaddr_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_REUSEADDR, 1, -1); - assert_int_equal(BIO_bind(FAKE_SOCKET, &a, BIO_SOCK_REUSEADDR), 0); -} - -static void test_bind_bind_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_bind(FAKE_SOCKET, -1); - assert_int_equal(BIO_bind(FAKE_SOCKET, &a, 0), 0); -} - -/* BIO_listen */ - -static void test_listen_success(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 1); -} - -static void test_listen_invalid_sock(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - assert_int_equal(BIO_listen(-1, &a, 0), 0); -} - -static void test_listen_getsockopt_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, -1, 0, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 0); -} - -static void test_listen_socktype_len_mismatch(void **state) -{ - /* a short socktype_len is rejected even when getsockopt succeeds */ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - (socklen_t)(sizeof(int) - 1)); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 0); -} - -static void test_listen_nbio_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 0); -} - -static void test_listen_keepalive(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_KEEPALIVE, 1, 0); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, BIO_SOCK_KEEPALIVE), 1); -} - -static void test_listen_keepalive_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_KEEPALIVE, 1, -1); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, BIO_SOCK_KEEPALIVE), 0); -} - -static void test_listen_nodelay(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, IPPROTO_TCP, TCP_NODELAY, 1, 0); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, BIO_SOCK_NODELAY), 1); -} - -static void test_listen_reuseaddr(void **state) -{ - /* REUSEADDR is honoured inside the real (unwrappable) BIO_bind */ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, SOL_SOCKET, SO_REUSEADDR, 1, 0); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, BIO_SOCK_REUSEADDR), 1); -} - -static void test_listen_bind_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_bind(FAKE_SOCKET, -1); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 0); -} - -static void test_listen_dgram(void **state) -{ - /* datagram sockets are bound but never put into listen() */ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_DGRAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_bind(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 1); -} - -static void test_listen_listen_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, -1); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 0); -} - -#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) -static void test_listen_v6only(void **state) -{ - /* an AF_INET6 socket always gets IPV6_V6ONLY set, here to 1 */ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET6); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, IPPROTO_IPV6, IPV6_V6ONLY, 1, 0); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, BIO_SOCK_V6_ONLY), 1); -} - -static void test_listen_v6only_off(void **state) -{ - /* without BIO_SOCK_V6_ONLY the option is still set, to 0 */ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET6); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, IPPROTO_IPV6, IPV6_V6ONLY, 0, 0); - expect_bind(FAKE_SOCKET, 0); - expect_listen(FAKE_SOCKET, 0); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, 0), 1); -} - -static void test_listen_v6only_fails(void **state) -{ - BIO_ADDR a; - - (void)state; - make_addr(&a, AF_INET6); - expect_getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, 0, SOCK_STREAM, - sizeof(int)); - expect_nbio(FAKE_SOCKET, 0, 1); - expect_setsockopt(FAKE_SOCKET, IPPROTO_IPV6, IPV6_V6ONLY, 1, -1); - assert_int_equal(BIO_listen(FAKE_SOCKET, &a, BIO_SOCK_V6_ONLY), 0); -} -#endif - -/* BIO_accept_ex */ - -static void test_accept_ex_success(void **state) -{ - BIO_ADDR a; - - (void)state; - memset(&a, 0, sizeof(a)); - expect_accept(FAKE_SOCKET, ACCEPTED_SOCKET); - expect_nbio(ACCEPTED_SOCKET, 0, 1); - assert_int_equal(BIO_accept_ex(FAKE_SOCKET, &a, 0), ACCEPTED_SOCKET); -} - -static void test_accept_ex_null_addr(void **state) -{ - /* a NULL addr is accepted into an internal local BIO_ADDR */ - (void)state; - expect_accept(FAKE_SOCKET, ACCEPTED_SOCKET); - expect_nbio(ACCEPTED_SOCKET, 0, 1); - assert_int_equal(BIO_accept_ex(FAKE_SOCKET, NULL, 0), ACCEPTED_SOCKET); -} - -static void test_accept_ex_nonblock(void **state) -{ - BIO_ADDR a; - - (void)state; - memset(&a, 0, sizeof(a)); - expect_accept(FAKE_SOCKET, ACCEPTED_SOCKET); - expect_nbio(ACCEPTED_SOCKET, 1, 1); - assert_int_equal( - BIO_accept_ex(FAKE_SOCKET, &a, BIO_SOCK_NONBLOCK), ACCEPTED_SOCKET); -} - -static void test_accept_ex_retry(void **state) -{ - BIO_ADDR a; - - (void)state; - memset(&a, 0, sizeof(a)); - expect_accept(FAKE_SOCKET, -1); - expect_should_retry(-1, 1); - assert_int_equal(BIO_accept_ex(FAKE_SOCKET, &a, 0), (int)INVALID_SOCKET); -} - -static void test_accept_ex_error(void **state) -{ - BIO_ADDR a; - - (void)state; - memset(&a, 0, sizeof(a)); - expect_accept(FAKE_SOCKET, -1); - expect_should_retry(-1, 0); - assert_int_equal(BIO_accept_ex(FAKE_SOCKET, &a, 0), (int)INVALID_SOCKET); -} - -static void test_accept_ex_nbio_fails(void **state) -{ - /* a non-blocking failure on the accepted socket closes it again */ - BIO_ADDR a; - - (void)state; - memset(&a, 0, sizeof(a)); - expect_accept(FAKE_SOCKET, ACCEPTED_SOCKET); - expect_nbio(ACCEPTED_SOCKET, 0, 0); - expect_close(ACCEPTED_SOCKET, 0); - assert_int_equal(BIO_accept_ex(FAKE_SOCKET, &a, 0), (int)INVALID_SOCKET); -} - -/* BIO_closesocket */ - -static void test_closesocket_success(void **state) -{ - (void)state; - expect_close(FAKE_SOCKET, 0); - assert_int_equal(BIO_closesocket(FAKE_SOCKET), 1); -} - -static void test_closesocket_negative(void **state) -{ - /* a negative fd short-circuits before any close() */ - (void)state; - assert_int_equal(BIO_closesocket(-1), 0); -} - -static void test_closesocket_fails(void **state) -{ - (void)state; - expect_close(FAKE_SOCKET, -1); - assert_int_equal(BIO_closesocket(FAKE_SOCKET), 0); -} - -/* main */ - -#define SOCK_TEST(name) cmocka_unit_test(name) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* BIO_socket */ - SOCK_TEST(test_socket_success), - SOCK_TEST(test_socket_fails), - /* BIO_connect */ - SOCK_TEST(test_connect_invalid_sock), - SOCK_TEST(test_connect_nbio_fails), - SOCK_TEST(test_connect_success), - SOCK_TEST(test_connect_nonblock), - SOCK_TEST(test_connect_keepalive), - SOCK_TEST(test_connect_keepalive_fails), - SOCK_TEST(test_connect_nodelay), - SOCK_TEST(test_connect_nodelay_fails), - SOCK_TEST(test_connect_fails_retry), - SOCK_TEST(test_connect_fails_error), - /* BIO_bind */ - SOCK_TEST(test_bind_invalid_sock), - SOCK_TEST(test_bind_success), - SOCK_TEST(test_bind_reuseaddr), - SOCK_TEST(test_bind_reuseaddr_fails), - SOCK_TEST(test_bind_bind_fails), - /* BIO_listen */ - SOCK_TEST(test_listen_success), - SOCK_TEST(test_listen_invalid_sock), - SOCK_TEST(test_listen_getsockopt_fails), - SOCK_TEST(test_listen_socktype_len_mismatch), - SOCK_TEST(test_listen_nbio_fails), - SOCK_TEST(test_listen_keepalive), - SOCK_TEST(test_listen_keepalive_fails), - SOCK_TEST(test_listen_nodelay), - SOCK_TEST(test_listen_reuseaddr), - SOCK_TEST(test_listen_bind_fails), - SOCK_TEST(test_listen_dgram), - SOCK_TEST(test_listen_listen_fails), -#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) - SOCK_TEST(test_listen_v6only), - SOCK_TEST(test_listen_v6only_off), - SOCK_TEST(test_listen_v6only_fails), -#endif - /* BIO_accept_ex */ - SOCK_TEST(test_accept_ex_success), - SOCK_TEST(test_accept_ex_null_addr), - SOCK_TEST(test_accept_ex_nonblock), - SOCK_TEST(test_accept_ex_retry), - SOCK_TEST(test_accept_ex_error), - SOCK_TEST(test_accept_ex_nbio_fails), - /* BIO_closesocket */ - SOCK_TEST(test_closesocket_success), - SOCK_TEST(test_closesocket_negative), - SOCK_TEST(test_closesocket_fails), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#else - -int main(void) -{ - return 0; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/test/unit/crypto/bio/test_bss_acpt.c b/test/unit/crypto/bio/test_bss_acpt.c deleted file mode 100644 index 4a51c27373..0000000000 --- a/test/unit/crypto/bio/test_bss_acpt.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/sockets.h" - -#ifndef OPENSSL_NO_SOCK - -#include -#include -#include -#include -#include -#include -#include -#include -#include "bio_local.h" - -#define FAKE_SOCKET 42 - -/* - * Fake addrinfo used across state machine tests. g_addrinfo1.bai_next is - * NULL by default. Tests needing a second address temporarily set it to - * &g_addrinfo2 and restore it afterwards. - */ -static struct sockaddr_in g_sin; -static BIO_ADDRINFO g_addrinfo1; -static BIO_ADDRINFO g_addrinfo2; - -/* prototypes for __wrap_* (required by -Wmissing-prototypes) */ -int __wrap_BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, - int family, int socktype, BIO_ADDRINFO **res); -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options); -int __wrap_BIO_listen(int sock, const BIO_ADDR *addr, int options); -int __wrap_BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options); -int __wrap_BIO_sock_info(int sock, enum BIO_sock_info_type type, - union BIO_sock_info_u *info); -int __wrap_BIO_sock_should_retry(int i); -int __wrap_BIO_closesocket(int sock); -char *__wrap_BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric); -char *__wrap_BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric); - -/* wraps */ - -int __wrap_BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, - int family, int socktype, BIO_ADDRINFO **res) -{ - int rc; - - function_called(); - check_expected(host); - check_expected(service); - check_expected(lookup_type); - check_expected(family); - check_expected(socktype); - rc = mock_type(int); - if (rc == 1) - *res = mock_ptr_type(BIO_ADDRINFO *); - return rc; -} - -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options) -{ - function_called(); - check_expected(domain); - check_expected(socktype); - check_expected(protocol); - check_expected(options); - return mock_type(int); -} - -int __wrap_BIO_listen(int sock, const BIO_ADDR *addr, int options) -{ - function_called(); - check_expected(sock); - check_expected_ptr(addr); - check_expected(options); - return mock_type(int); -} - -int __wrap_BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options) -{ - function_called(); - check_expected(accept_sock); - check_expected_ptr(addr); - check_expected(options); - return mock_type(int); -} - -int __wrap_BIO_sock_info(int sock, enum BIO_sock_info_type type, - union BIO_sock_info_u *info) -{ - function_called(); - check_expected(sock); - check_expected(type); - (void)info; /* addr field left untouched; cache addr is zeroed already */ - return mock_type(int); -} - -int __wrap_BIO_sock_should_retry(int i) -{ - function_called(); - check_expected(i); - return mock_type(int); -} - -int __wrap_BIO_closesocket(int sock) -{ - function_called(); - check_expected(sock); - return mock_type(int); -} - -/* - * The cache_*_name / cache_*_serv pointers get OPENSSL_free()d in - * BIO_ACCEPT_free and when a new bind starts, so these wraps must return - * heap pointers (or NULL). - */ -char *__wrap_BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric) -{ - function_called(); - (void)ap; - (void)numeric; - return mock_ptr_type(char *); -} - -char *__wrap_BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric) -{ - function_called(); - (void)ap; - (void)numeric; - return mock_ptr_type(char *); -} - -/* - * A minimal fake sink BIO. The accept BIO forwards reads/writes to its - * next_bio once a connection is established, so I/O tests push one of these - * instead of a real socket BIO. This keeps acpt_read/acpt_write under test - * in isolation: no dependency on sock_read/sock_write, on the libc read/write - * syscalls, or on BIO_sock_should_retry. - * - * The fake read/write return mock_type and, on a non-positive result, set - * their own retry flag when asked, so acpt_read/acpt_write's - * BIO_copy_next_retry has a real source-of-truth to propagate upward. - */ - -static int fake_sink_read(BIO *b, char *buf, size_t size, size_t *readbytes); -static int fake_sink_write(BIO *b, const char *buf, size_t size, - size_t *written); -static long fake_sink_ctrl(BIO *b, int cmd, long arg1, void *arg2); - -static int fake_sink_read(BIO *b, char *buf, size_t size, size_t *readbytes) -{ - int ret; - - function_called(); - check_expected_ptr(buf); - check_expected(size); - BIO_clear_retry_flags(b); - ret = mock_type(int); - if (ret > 0) { - *readbytes = (size_t)ret; - return 1; - } - if (mock_type(int)) - BIO_set_retry_read(b); - *readbytes = 0; - return ret; -} - -static int fake_sink_write(BIO *b, const char *buf, size_t size, - size_t *written) -{ - int ret; - - function_called(); - check_expected_ptr(buf); - check_expected(size); - BIO_clear_retry_flags(b); - ret = mock_type(int); - if (ret > 0) { - *written = (size_t)ret; - return 1; - } - if (mock_type(int)) - BIO_set_retry_write(b); - *written = 0; - return ret; -} - -static long fake_sink_ctrl(BIO *b, int cmd, long arg1, void *arg2) -{ - (void)b; - (void)arg1; - (void)arg2; - if (cmd == BIO_CTRL_FLUSH) - return 1; - return 0; -} - -static BIO_METHOD *fake_sink_method = NULL; - -static BIO_METHOD *make_fake_sink_method(void) -{ - BIO_METHOD *m = BIO_meth_new(BIO_TYPE_SOURCE_SINK | 0xff, "fake sink"); - - assert_non_null(m); - assert_true(BIO_meth_set_read_ex(m, fake_sink_read)); - assert_true(BIO_meth_set_write_ex(m, fake_sink_write)); - assert_true(BIO_meth_set_ctrl(m, fake_sink_ctrl)); - return m; -} - -static BIO *make_fake_sink(void) -{ - BIO *b = BIO_new(fake_sink_method); - - assert_non_null(b); - BIO_set_init(b, 1); - return b; -} - -/* expectations */ - -static void expect_BIO_lookup(BIO_ADDRINFO *res, int rc) -{ - expect_function_call(__wrap_BIO_lookup); - expect_any(__wrap_BIO_lookup, host); - expect_any(__wrap_BIO_lookup, service); - expect_value(__wrap_BIO_lookup, lookup_type, BIO_LOOKUP_SERVER); - expect_any(__wrap_BIO_lookup, family); - expect_any(__wrap_BIO_lookup, socktype); - will_return(__wrap_BIO_lookup, rc); - if (rc == 1) - will_return(__wrap_BIO_lookup, res); -} - -/* options is the literal the state machine passes (always 0 here) */ -static void expect_BIO_socket(int domain, int socktype, int protocol, - int options, int rc) -{ - expect_function_call(__wrap_BIO_socket); - expect_value(__wrap_BIO_socket, domain, domain); - expect_value(__wrap_BIO_socket, socktype, socktype); - expect_value(__wrap_BIO_socket, protocol, protocol); - expect_value(__wrap_BIO_socket, options, options); - will_return(__wrap_BIO_socket, rc); -} - -static void expect_BIO_listen(int sock, const BIO_ADDR *addr, int options, - int rc) -{ - expect_function_call(__wrap_BIO_listen); - expect_value(__wrap_BIO_listen, sock, sock); - expect_value(__wrap_BIO_listen, addr, addr); - expect_value(__wrap_BIO_listen, options, options); - will_return(__wrap_BIO_listen, rc); -} - -static void expect_BIO_accept_ex(int sock, int options, int rc) -{ - expect_function_call(__wrap_BIO_accept_ex); - expect_value(__wrap_BIO_accept_ex, accept_sock, sock); - expect_any(__wrap_BIO_accept_ex, addr); - expect_value(__wrap_BIO_accept_ex, options, options); - will_return(__wrap_BIO_accept_ex, rc); -} - -static void expect_BIO_sock_info(int sock, int rc) -{ - expect_function_call(__wrap_BIO_sock_info); - expect_value(__wrap_BIO_sock_info, sock, sock); - expect_value(__wrap_BIO_sock_info, type, BIO_SOCK_INFO_ADDRESS); - will_return(__wrap_BIO_sock_info, rc); -} - -static void expect_BIO_sock_should_retry(int i, int rc) -{ - expect_function_call(__wrap_BIO_sock_should_retry); - expect_value(__wrap_BIO_sock_should_retry, i, i); - will_return(__wrap_BIO_sock_should_retry, rc); -} - -static void expect_BIO_closesocket(int sock, int rc) -{ - expect_function_call(__wrap_BIO_closesocket); - expect_value(__wrap_BIO_closesocket, sock, sock); - will_return(__wrap_BIO_closesocket, rc); -} - -/* The returned pointer is heap allocated; ownership passes to the BIO. */ -static void expect_BIO_ADDR_hostname_string(const char *val) -{ - expect_function_call(__wrap_BIO_ADDR_hostname_string); - will_return(__wrap_BIO_ADDR_hostname_string, - val == NULL ? NULL : OPENSSL_strdup(val)); -} - -static void expect_BIO_ADDR_service_string(const char *val) -{ - expect_function_call(__wrap_BIO_ADDR_service_string); - will_return(__wrap_BIO_ADDR_service_string, - val == NULL ? NULL : OPENSSL_strdup(val)); -} - -/* - * rc is the byte count (>0) or the non-positive result; retry tells the sink - * whether to set its own retry flag when rc <= 0. - */ -static void expect_fake_sink_read(const void *buf, size_t size, int rc, - int retry) -{ - expect_function_call(fake_sink_read); - expect_value(fake_sink_read, buf, buf); - expect_value(fake_sink_read, size, size); - will_return(fake_sink_read, rc); - if (rc <= 0) - will_return(fake_sink_read, retry); -} - -static void expect_fake_sink_write(const void *buf, size_t size, int rc, - int retry) -{ - expect_function_call(fake_sink_write); - expect_value(fake_sink_write, buf, buf); - expect_value(fake_sink_write, size, size); - will_return(fake_sink_write, rc); - if (rc <= 0) - will_return(fake_sink_write, retry); -} - -/* - * The LISTEN state always emits, in order: BIO_listen, BIO_sock_info, then a - * hostname_string + service_string pair for the accepting address cache. - */ -static void expect_listen_sequence(int sock) -{ - expect_BIO_listen(sock, (const BIO_ADDR *)&g_sin, 0, 1); - expect_BIO_sock_info(sock, 1); - expect_BIO_ADDR_hostname_string("127.0.0.1"); - expect_BIO_ADDR_service_string("443"); -} - -/* helpers */ - -static BIO_ACCEPT *get_data(BIO *bio) -{ - return (BIO_ACCEPT *)bio->ptr; -} - -/* - * Reset socket bookkeeping so acpt_close_socket is a no-op during free, and - * clear the address iterators that point at static storage. - */ -static void reset_for_teardown(BIO *bio) -{ - BIO_ACCEPT *data = get_data(bio); - - bio->num = (int)INVALID_SOCKET; - data->accept_sock = (int)INVALID_SOCKET; - data->addr_first = NULL; - data->addr_iter = NULL; - data->state = BIO_ACPT_S_BEFORE; -} - -/* setup / teardown */ - -static int setup(void **state) -{ - BIO *bio = BIO_new(BIO_s_accept()); - - assert_non_null(bio); - *state = bio; - return 0; -} - -static int teardown(void **state) -{ - if (*state != NULL) - BIO_free(*state); - return 0; -} - -/* - * I/O tests pre-establish state=OK and push a fake sink BIO so the state - * machine exits immediately and reads/writes are forwarded to next_bio. - */ -static int setup_io(void **state) -{ - BIO *bio, *sink; - BIO_ACCEPT *data; - - if (setup(state) != 0) - return -1; - bio = *state; - data = get_data(bio); - data->state = BIO_ACPT_S_OK; - data->accept_sock = FAKE_SOCKET; - bio->num = FAKE_SOCKET; - bio->init = 1; - - sink = make_fake_sink(); - assert_non_null(BIO_push(bio, sink)); - return 0; -} - -static int teardown_io(void **state) -{ - if (*state != NULL) { - reset_for_teardown(*state); - /* BIO_free_all to also release the pushed fake sink BIO. */ - BIO_free_all(*state); - *state = NULL; - } - return 0; -} - -static int group_setup(void **state) -{ - (void)state; - - fake_sink_method = make_fake_sink_method(); - - memset(&g_sin, 0, sizeof(g_sin)); - g_sin.sin_family = AF_INET; - g_sin.sin_port = htons(443); - g_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - memset(&g_addrinfo1, 0, sizeof(g_addrinfo1)); - g_addrinfo1.bai_family = AF_INET; - g_addrinfo1.bai_socktype = SOCK_STREAM; - g_addrinfo1.bai_protocol = IPPROTO_TCP; - g_addrinfo1.bai_addrlen = sizeof(g_sin); - g_addrinfo1.bai_addr = (struct sockaddr *)&g_sin; - g_addrinfo1.bai_next = NULL; - - memcpy(&g_addrinfo2, &g_addrinfo1, sizeof(g_addrinfo1)); - g_addrinfo2.bai_next = NULL; - - return 0; -} - -static int group_teardown(void **state) -{ - (void)state; - BIO_meth_free(fake_sink_method); - fake_sink_method = NULL; - return 0; -} - -/* acpt_new */ - -static void test_acpt_new(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - assert_non_null(data); - assert_int_equal(data->state, BIO_ACPT_S_BEFORE); - assert_int_equal(data->accept_family, BIO_FAMILY_IPANY); - assert_int_equal(data->accept_sock, (int)INVALID_SOCKET); - assert_null(data->param_addr); - assert_null(data->param_serv); - assert_null(data->addr_first); - assert_null(data->bio_chain); - assert_int_equal(bio->num, (int)INVALID_SOCKET); - assert_int_equal(bio->init, 0); - assert_int_equal(bio->shutdown, 1); -} - -/* acpt_free */ - -static void test_acpt_free_no_shutdown(void **state) -{ - /* shutdown=0: acpt_close_socket and BIO_ACCEPT_free are both skipped */ - BIO *bio = BIO_new(BIO_s_accept()); - - assert_non_null(bio); - bio->shutdown = BIO_NOCLOSE; - BIO_free(bio); - *state = NULL; -} - -/* acpt_close_socket (via BIO_CTRL_RESET) */ - -static void test_close_socket_none(void **state) -{ - /* accept_sock == INVALID_SOCKET: no closesocket expected */ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_RESET, 0, NULL), 0); - assert_int_equal(get_data(*state)->state, BIO_ACPT_S_BEFORE); -} - -/* acpt_state via BIO_C_DO_STATE_MACHINE (BIO_do_accept) */ - -static void test_acpt_state_no_addr(void **state) -{ - /* BEFORE with no addr and no serv -> error */ - assert_true(BIO_do_accept(*state) <= 0); -} - -static void test_acpt_state_unsupported_family(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->param_serv = OPENSSL_strdup("443"); - data->accept_family = 9999; - - assert_true(BIO_do_accept(bio) <= 0); -} - -static void test_acpt_state_lookup_fails(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->param_serv = OPENSSL_strdup("443"); - - expect_BIO_lookup(NULL, 0); - assert_true(BIO_do_accept(bio) <= 0); -} - -static void test_acpt_state_lookup_empty(void **state) -{ - /* BIO_lookup succeeds but returns no addresses */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->param_serv = OPENSSL_strdup("443"); - - expect_BIO_lookup(NULL, 1); /* rc==1 but res stays NULL */ - assert_true(BIO_do_accept(bio) <= 0); -} - -static void test_acpt_state_socket_fails(void **state) -{ - /* Pre-set CREATE_SOCKET, single address: BIO_socket fails -> error */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->state = BIO_ACPT_S_CREATE_SOCKET; - data->addr_iter = &g_addrinfo1; /* bai_next == NULL */ - - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, - (int)INVALID_SOCKET); - assert_true(BIO_do_accept(bio) <= 0); - - reset_for_teardown(bio); -} - -static void test_acpt_state_socket_next_addr(void **state) -{ - /* - * Two addresses: first BIO_socket fails, iterator advances, second - * BIO_socket also fails -> clean error exit. - */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - g_addrinfo1.bai_next = &g_addrinfo2; - data->state = BIO_ACPT_S_CREATE_SOCKET; - data->addr_iter = &g_addrinfo1; - - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, - (int)INVALID_SOCKET); - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, - (int)INVALID_SOCKET); - assert_true(BIO_do_accept(bio) <= 0); - - g_addrinfo1.bai_next = NULL; - reset_for_teardown(bio); -} - -static void test_acpt_state_listen_fails(void **state) -{ - /* CREATE_SOCKET succeeds, BIO_listen fails -> closesocket, error */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->state = BIO_ACPT_S_CREATE_SOCKET; - data->addr_iter = &g_addrinfo1; - - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); - expect_BIO_listen(FAKE_SOCKET, (const BIO_ADDR *)&g_sin, 0, 0); - expect_BIO_closesocket(FAKE_SOCKET, 0); - - assert_true(BIO_do_accept(bio) <= 0); - assert_int_equal(data->accept_sock, (int)INVALID_SOCKET); - - reset_for_teardown(bio); -} - -static void test_acpt_state_sock_info_fails(void **state) -{ - /* listen ok, BIO_sock_info fails -> closesocket, error */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->state = BIO_ACPT_S_CREATE_SOCKET; - data->addr_iter = &g_addrinfo1; - - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); - expect_BIO_listen(FAKE_SOCKET, (const BIO_ADDR *)&g_sin, 0, 1); - expect_BIO_sock_info(FAKE_SOCKET, 0); - expect_BIO_closesocket(FAKE_SOCKET, 0); - - assert_true(BIO_do_accept(bio) <= 0); - assert_int_equal(data->accept_sock, (int)INVALID_SOCKET); - - reset_for_teardown(bio); -} - -static void test_acpt_state_bind_ok(void **state) -{ - /* - * Full bind path: BEFORE -> GET_ADDR -> CREATE_SOCKET -> LISTEN returns 1 - * and the machine stops at BIO_ACPT_S_ACCEPT (next_bio is NULL). - */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->param_serv = OPENSSL_strdup("443"); - - expect_BIO_lookup(&g_addrinfo1, 1); - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); - expect_listen_sequence(FAKE_SOCKET); - - assert_int_equal(BIO_do_accept(bio), 1); - assert_int_equal(data->state, BIO_ACPT_S_ACCEPT); - assert_int_equal(data->accept_sock, FAKE_SOCKET); - assert_string_equal(data->cache_accepting_name, "127.0.0.1"); - assert_string_equal(data->cache_accepting_serv, "443"); - - reset_for_teardown(bio); -} - -static void test_acpt_state_accept_retry(void **state) -{ - /* Pre-set ACCEPT, no next_bio: BIO_accept_ex retryable -> special flag */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->state = BIO_ACPT_S_ACCEPT; - data->accept_sock = FAKE_SOCKET; - bio->num = FAKE_SOCKET; - - expect_BIO_accept_ex(FAKE_SOCKET, 0, -1); - expect_BIO_sock_should_retry(-1, 1); - - assert_true(BIO_do_accept(bio) <= 0); - assert_true(BIO_should_io_special(bio)); - assert_int_equal(bio->retry_reason, BIO_RR_ACCEPT); - - reset_for_teardown(bio); -} - -static void test_acpt_state_accept_error(void **state) -{ - /* Pre-set ACCEPT: BIO_accept_ex fails, not retryable -> error */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->state = BIO_ACPT_S_ACCEPT; - data->accept_sock = FAKE_SOCKET; - bio->num = FAKE_SOCKET; - - expect_BIO_accept_ex(FAKE_SOCKET, 0, -1); - expect_BIO_sock_should_retry(-1, 0); - - assert_true(BIO_do_accept(bio) <= 0); - - reset_for_teardown(bio); -} - -static void test_acpt_state_already_ok_no_next(void **state) -{ - /* - * State OK but next_bio NULL: machine drops back to ACCEPT and tries to - * accept. We make that accept fail non-retryably for a clean exit. - */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->state = BIO_ACPT_S_OK; - data->accept_sock = FAKE_SOCKET; - bio->num = FAKE_SOCKET; - - expect_BIO_accept_ex(FAKE_SOCKET, 0, -1); - expect_BIO_sock_should_retry(-1, 0); - - assert_true(BIO_do_accept(bio) <= 0); - - reset_for_teardown(bio); -} - -/* acpt_read / acpt_write (state already OK with a pushed fake sink BIO) */ - -static void test_acpt_read_forwards(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_fake_sink_read(buf, 8, 8, 0); - assert_int_equal(BIO_read(bio, buf, 8), 8); - assert_false(BIO_should_retry(bio)); -} - -static void test_acpt_read_forwards_retry(void **state) -{ - /* - * The fake sink returns a retryable read and sets its own retry-read - * flag; acpt_read must propagate it onto the accept BIO via - * BIO_copy_next_retry. - */ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_fake_sink_read(buf, 8, -1, 1); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_true(BIO_should_read(bio)); - assert_true(BIO_should_retry(bio)); -} - -static void test_acpt_write_forwards(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_fake_sink_write(buf, 5, 5, 0); - assert_int_equal(BIO_write(bio, buf, 5), 5); - assert_false(BIO_should_retry(bio)); -} - -static void test_acpt_write_forwards_retry(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_fake_sink_write(buf, 5, -1, 1); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_true(BIO_should_write(bio)); - assert_true(BIO_should_retry(bio)); -} - -static void test_acpt_puts_forwards(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_fake_sink_write(str, 5, 5, 0); - assert_int_equal(BIO_puts(bio, str), 5); -} - -/* acpt_ctrl */ - -static void test_acpt_ctrl_reset_clears_addrs(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - data->addr_first = NULL; /* keep BIO_ADDRINFO_free a no-op */ - data->addr_iter = &g_addrinfo1; - bio->flags = BIO_FLAGS_SHOULD_RETRY; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL), 0); - assert_null(data->addr_first); - assert_null(data->addr_iter); - assert_int_equal(bio->flags, 0); - assert_int_equal(data->state, BIO_ACPT_S_BEFORE); -} - -static void test_acpt_ctrl_set_accept_name(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - assert_true(BIO_set_accept_name(bio, "host.example:443") > 0); - assert_int_equal(bio->init, 1); - assert_string_equal(data->param_addr, "host.example"); - assert_string_equal(data->param_serv, "443"); -} - -static void test_acpt_ctrl_set_accept_port(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - assert_true(BIO_set_accept_port(bio, "8443") > 0); - assert_int_equal(bio->init, 1); - assert_string_equal(data->param_serv, "8443"); -} - -static void test_acpt_ctrl_set_nbio_accept(void **state) -{ - /* toggles BIO_SOCK_NONBLOCK in bind_mode */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - BIO_set_nbio_accept(bio, 1); - assert_true(data->bind_mode & BIO_SOCK_NONBLOCK); - - BIO_set_nbio_accept(bio, 0); - assert_false(data->bind_mode & BIO_SOCK_NONBLOCK); -} - -static void test_acpt_ctrl_set_accept_bios(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - BIO *chain = BIO_new(BIO_s_mem()); - - assert_non_null(chain); - assert_true(BIO_set_accept_bios(bio, chain) > 0); - assert_ptr_equal(data->bio_chain, chain); - /* freed by BIO_ACCEPT_free in teardown */ -} - -static void test_acpt_ctrl_set_accept_ip_family(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - assert_true(BIO_set_accept_ip_family(bio, BIO_FAMILY_IPV4) > 0); - assert_int_equal(data->accept_family, BIO_FAMILY_IPV4); -} - -static void test_acpt_ctrl_set_tfo_accept(void **state) -{ - /* toggles BIO_SOCK_TFO in bind_mode */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - BIO_set_tfo_accept(bio, 1); - assert_true(data->bind_mode & BIO_SOCK_TFO); - - BIO_set_tfo_accept(bio, 0); - assert_false(data->bind_mode & BIO_SOCK_TFO); -} - -static void test_acpt_ctrl_set_nbio(void **state) -{ - /* BIO_C_SET_NBIO: toggles BIO_SOCK_NONBLOCK in accepted_mode */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - BIO_set_nbio(bio, 1); - assert_true(data->accepted_mode & BIO_SOCK_NONBLOCK); - - BIO_set_nbio(bio, 0); - assert_false(data->accepted_mode & BIO_SOCK_NONBLOCK); -} - -static void test_acpt_ctrl_set_fd(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - assert_int_equal(bio->num, FAKE_SOCKET); - assert_int_equal(data->accept_sock, FAKE_SOCKET); - assert_int_equal(data->state, BIO_ACPT_S_ACCEPT); - assert_int_equal(bio->init, 1); - assert_int_equal(bio->shutdown, BIO_NOCLOSE); - - reset_for_teardown(bio); -} - -static void test_acpt_ctrl_get_fd(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - int fd = -1; - - /* init==0 -> -1 */ - assert_int_equal(BIO_get_fd(bio, &fd), -1); - - bio->init = 1; - data->accept_sock = FAKE_SOCKET; - assert_int_equal(BIO_get_fd(bio, &fd), FAKE_SOCKET); - assert_int_equal(fd, FAKE_SOCKET); - - bio->init = 0; - data->accept_sock = (int)INVALID_SOCKET; -} - -static void test_acpt_ctrl_get_accept_names(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - const char *out; - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_ACCEPT, 0, &out), -1); - - bio->init = 1; - data->cache_accepting_name = OPENSSL_strdup("accept.host"); - data->cache_accepting_serv = OPENSSL_strdup("443"); - data->cache_peer_name = OPENSSL_strdup("peer.host"); - data->cache_peer_serv = OPENSSL_strdup("55000"); - - assert_string_equal(BIO_get_accept_name(bio), "accept.host"); - assert_string_equal(BIO_get_accept_port(bio), "443"); - assert_string_equal(BIO_get_peer_name(bio), "peer.host"); - assert_string_equal(BIO_get_peer_port(bio), "55000"); - - bio->init = 0; -} - -static void test_acpt_ctrl_get_accept_family(void **state) -{ - /* AF_INET addr_iter maps to BIO_FAMILY_IPV4 */ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - bio->init = 1; - data->addr_iter = &g_addrinfo1; - assert_int_equal(BIO_get_accept_ip_family(bio), BIO_FAMILY_IPV4); - data->addr_iter = NULL; - bio->init = 0; -} - -static void test_acpt_ctrl_get_set_close(void **state) -{ - BIO *bio = *state; - - bio->shutdown = BIO_NOCLOSE; - assert_int_equal(BIO_get_close(bio), BIO_NOCLOSE); - - assert_int_equal(BIO_set_close(bio, BIO_CLOSE), 1); - assert_int_equal(bio->shutdown, BIO_CLOSE); -} - -static void test_acpt_ctrl_bind_mode(void **state) -{ - BIO *bio = *state; - BIO_ACCEPT *data = get_data(bio); - - BIO_set_bind_mode(bio, BIO_SOCK_REUSEADDR); - assert_int_equal(data->bind_mode, BIO_SOCK_REUSEADDR); - assert_int_equal(BIO_get_bind_mode(bio), BIO_SOCK_REUSEADDR); -} - -static void test_acpt_ctrl_pending_flush(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL), 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL), 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL), 1); -} - -static void test_acpt_ctrl_eof_no_next(void **state) -{ - /* next_bio == NULL -> 0 */ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_EOF, 0, NULL), 0); -} - -static void test_acpt_ctrl_default(void **state) -{ - assert_int_equal(BIO_ctrl(*state, 9999, 0, NULL), 0); -} - -/* BIO_new_accept convenience constructor */ - -static void test_bio_new_accept(void **state) -{ - BIO *bio = BIO_new_accept("localhost:443"); - BIO_ACCEPT *data; - - assert_non_null(bio); - data = (BIO_ACCEPT *)bio->ptr; - assert_string_equal(data->param_addr, "localhost"); - assert_string_equal(data->param_serv, "443"); - BIO_free(bio); - (void)state; -} - -/* main */ - -#define ACPT_TEST(name) \ - cmocka_unit_test_setup_teardown(name, setup, teardown) - -#define ACPT_TEST_IO(name) \ - cmocka_unit_test_setup_teardown(name, setup_io, teardown_io) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* acpt_new */ - ACPT_TEST(test_acpt_new), - /* acpt_free */ - ACPT_TEST(test_acpt_free_no_shutdown), - /* acpt_close_socket */ - ACPT_TEST(test_close_socket_none), - /* acpt_state */ - ACPT_TEST(test_acpt_state_no_addr), - ACPT_TEST(test_acpt_state_unsupported_family), - ACPT_TEST(test_acpt_state_lookup_fails), - ACPT_TEST(test_acpt_state_lookup_empty), - ACPT_TEST(test_acpt_state_socket_fails), - ACPT_TEST(test_acpt_state_socket_next_addr), - ACPT_TEST(test_acpt_state_listen_fails), - ACPT_TEST(test_acpt_state_sock_info_fails), - ACPT_TEST(test_acpt_state_bind_ok), - ACPT_TEST(test_acpt_state_accept_retry), - ACPT_TEST(test_acpt_state_accept_error), - ACPT_TEST(test_acpt_state_already_ok_no_next), - /* acpt_read / acpt_write / acpt_puts */ - ACPT_TEST_IO(test_acpt_read_forwards), - ACPT_TEST_IO(test_acpt_read_forwards_retry), - ACPT_TEST_IO(test_acpt_write_forwards), - ACPT_TEST_IO(test_acpt_write_forwards_retry), - ACPT_TEST_IO(test_acpt_puts_forwards), - /* acpt_ctrl */ - ACPT_TEST(test_acpt_ctrl_reset_clears_addrs), - ACPT_TEST(test_acpt_ctrl_set_accept_name), - ACPT_TEST(test_acpt_ctrl_set_accept_port), - ACPT_TEST(test_acpt_ctrl_set_nbio_accept), - ACPT_TEST(test_acpt_ctrl_set_accept_bios), - ACPT_TEST(test_acpt_ctrl_set_accept_ip_family), - ACPT_TEST(test_acpt_ctrl_set_tfo_accept), - ACPT_TEST(test_acpt_ctrl_set_nbio), - ACPT_TEST(test_acpt_ctrl_set_fd), - ACPT_TEST(test_acpt_ctrl_get_fd), - ACPT_TEST(test_acpt_ctrl_get_accept_names), - ACPT_TEST(test_acpt_ctrl_get_accept_family), - ACPT_TEST(test_acpt_ctrl_get_set_close), - ACPT_TEST(test_acpt_ctrl_bind_mode), - ACPT_TEST(test_acpt_ctrl_pending_flush), - ACPT_TEST(test_acpt_ctrl_eof_no_next), - ACPT_TEST(test_acpt_ctrl_default), - /* BIO_new_accept */ - ACPT_TEST(test_bio_new_accept), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, group_setup, group_teardown); -} - -#else - -int main(void) -{ - return 0; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/test/unit/crypto/bio/test_bss_conn.c b/test/unit/crypto/bio/test_bss_conn.c deleted file mode 100644 index 992a1b781a..0000000000 --- a/test/unit/crypto/bio/test_bss_conn.c +++ /dev/null @@ -1,1590 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/sockets.h" - -#ifndef OPENSSL_NO_SOCK - -#include -#include -#include -#include -#include -#include -#include -#include -#include "bio_local.h" - -#define FAKE_SOCKET 42 - -/* - * Fake addrinfo used across state machine tests. g_addrinfo1.bai_next is - * NULL by default. Tests needing a second address temporarily set it to - * &g_addrinfo2 and restore it afterwards. - */ -static struct sockaddr_in g_sin; -static BIO_ADDRINFO g_addrinfo1; -static BIO_ADDRINFO g_addrinfo2; - -/* prototypes for __wrap_* (required by -Wmissing-prototypes) */ -ssize_t __wrap_read(int fd, void *buf, size_t count); -ssize_t __wrap_write(int fd, const void *buf, size_t count); -int __wrap_BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, - int family, int socktype, BIO_ADDRINFO **res); -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options); -int __wrap_BIO_connect(int sock, const BIO_ADDR *addr, int options); -int __wrap_BIO_sock_should_retry(int i); -int __wrap_BIO_closesocket(int sock); -int __wrap_BIO_socket_wait(int fd, int for_write, time_t max_time); -int __wrap_BIO_sock_error(int sock); - -/* wraps */ - -ssize_t __wrap_read(int fd, void *buf, size_t count) -{ - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - return mock_type(ssize_t); -} - -ssize_t __wrap_write(int fd, const void *buf, size_t count) -{ - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - return mock_type(ssize_t); -} - -int __wrap_BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, - int family, int socktype, BIO_ADDRINFO **res) -{ - int rc; - - function_called(); - check_expected(host); - check_expected(service); - check_expected(lookup_type); - check_expected(family); - check_expected(socktype); - rc = mock_type(int); - if (rc == 1) - *res = mock_ptr_type(BIO_ADDRINFO *); - return rc; -} - -int __wrap_BIO_socket(int domain, int socktype, int protocol, int options) -{ - function_called(); - check_expected(domain); - check_expected(socktype); - check_expected(protocol); - check_expected(options); - return mock_type(int); -} - -int __wrap_BIO_connect(int sock, const BIO_ADDR *addr, int options) -{ - function_called(); - check_expected(sock); - check_expected_ptr(addr); - check_expected(options); - return mock_type(int); -} - -int __wrap_BIO_sock_should_retry(int i) -{ - function_called(); - check_expected(i); - return mock_type(int); -} - -int __wrap_BIO_closesocket(int sock) -{ - function_called(); - check_expected(sock); - return mock_type(int); -} - -int __wrap_BIO_socket_wait(int fd, int for_write, time_t max_time) -{ - function_called(); - check_expected(fd); - check_expected(for_write); - (void)max_time; /* derived from time(NULL): not checked */ - return mock_type(int); -} - -int __wrap_BIO_sock_error(int sock) -{ - function_called(); - check_expected(sock); - return mock_type(int); -} - -/* - * A minimal fake dgram BIO. conn_read/conn_write/conn_sendmmsg/conn_recvmmsg - * delegate to the public BIO_* calls on data->dgram_bio, so the leaf needs - * read/write/sendmmsg/recvmmsg to dispatch. Everything the connect layer - * forwards (the buffer, message array, stride, count and flags) is verified. - */ - -static int fake_dgram_read(BIO *b, char *buf, size_t size, size_t *readbytes); -static int fake_dgram_write(BIO *b, const char *buf, size_t size, - size_t *written); -static long fake_dgram_ctrl(BIO *b, int cmd, long arg1, void *arg2); -static int fake_dgram_sendmmsg(BIO *b, BIO_MSG *m, size_t s, size_t n, - uint64_t f, size_t *mp); -static int fake_dgram_recvmmsg(BIO *b, BIO_MSG *m, size_t s, size_t n, - uint64_t f, size_t *mp); - -static int fake_dgram_read(BIO *b, char *buf, size_t size, size_t *readbytes) -{ - int ret; - - (void)b; - function_called(); - check_expected_ptr(buf); - check_expected(size); - ret = mock_type(int); - if (ret > 0) { - *readbytes = (size_t)ret; - return 1; - } - *readbytes = 0; - return ret; -} - -static int fake_dgram_write(BIO *b, const char *buf, size_t size, - size_t *written) -{ - int ret; - - (void)b; - function_called(); - check_expected_ptr(buf); - check_expected(size); - ret = mock_type(int); - if (ret > 0) { - *written = (size_t)ret; - return 1; - } - *written = 0; - return ret; -} - -static long fake_dgram_ctrl(BIO *b, int cmd, long arg1, void *arg2) -{ - (void)b; - (void)arg1; - (void)arg2; - if (cmd == BIO_CTRL_FLUSH) - return 1; - return 0; -} - -static int fake_dgram_sendmmsg(BIO *b, BIO_MSG *m, size_t s, size_t n, - uint64_t f, size_t *mp) -{ - (void)b; - function_called(); - check_expected_ptr(m); - check_expected(s); - check_expected(n); - check_expected(f); - *mp = mock_type(size_t); - return mock_type(int); -} - -static int fake_dgram_recvmmsg(BIO *b, BIO_MSG *m, size_t s, size_t n, - uint64_t f, size_t *mp) -{ - (void)b; - function_called(); - check_expected_ptr(m); - check_expected(s); - check_expected(n); - check_expected(f); - *mp = mock_type(size_t); - return mock_type(int); -} - -static BIO_METHOD *fake_dgram_method = NULL; - -static BIO_METHOD *make_fake_dgram_method(void) -{ - BIO_METHOD *m = BIO_meth_new(BIO_TYPE_DGRAM | 0xff, "fake dgram"); - - assert_non_null(m); - assert_true(BIO_meth_set_read_ex(m, fake_dgram_read)); - assert_true(BIO_meth_set_write_ex(m, fake_dgram_write)); - assert_true(BIO_meth_set_ctrl(m, fake_dgram_ctrl)); - assert_true(BIO_meth_set_sendmmsg(m, fake_dgram_sendmmsg)); - assert_true(BIO_meth_set_recvmmsg(m, fake_dgram_recvmmsg)); - return m; -} - -static BIO *make_fake_dgram(void) -{ - BIO *d = BIO_new(fake_dgram_method); - - assert_non_null(d); - BIO_set_init(d, 1); - return d; -} - -/* expectations */ - -static void expect_read(int fd, const void *buf, size_t count, ssize_t rc) -{ - expect_function_call(__wrap_read); - expect_value(__wrap_read, fd, fd); - expect_value(__wrap_read, buf, buf); - expect_value(__wrap_read, count, count); - will_return(__wrap_read, rc); -} - -static void expect_write(int fd, const void *buf, size_t count, ssize_t rc) -{ - expect_function_call(__wrap_write); - expect_value(__wrap_write, fd, fd); - expect_value(__wrap_write, buf, buf); - expect_value(__wrap_write, count, count); - will_return(__wrap_write, rc); -} - -static void expect_BIO_lookup(BIO_ADDRINFO *res, int rc) -{ - expect_function_call(__wrap_BIO_lookup); - expect_any(__wrap_BIO_lookup, host); - expect_any(__wrap_BIO_lookup, service); - expect_any(__wrap_BIO_lookup, lookup_type); - expect_any(__wrap_BIO_lookup, family); - expect_any(__wrap_BIO_lookup, socktype); - will_return(__wrap_BIO_lookup, rc); - if (rc == 1) - will_return(__wrap_BIO_lookup, res); -} - -/* options is the literal the state machine passes (always 0 here) */ -static void expect_BIO_socket(int domain, int socktype, int protocol, - int options, int rc) -{ - expect_function_call(__wrap_BIO_socket); - expect_value(__wrap_BIO_socket, domain, domain); - expect_value(__wrap_BIO_socket, socktype, socktype); - expect_value(__wrap_BIO_socket, protocol, protocol); - expect_value(__wrap_BIO_socket, options, options); - will_return(__wrap_BIO_socket, rc); -} - -static void expect_BIO_connect(int sock, const BIO_ADDR *addr, int options, - int rc) -{ - expect_function_call(__wrap_BIO_connect); - expect_value(__wrap_BIO_connect, sock, sock); - expect_value(__wrap_BIO_connect, addr, addr); - expect_value(__wrap_BIO_connect, options, options); - will_return(__wrap_BIO_connect, rc); -} - -static void expect_BIO_sock_should_retry(int i, int rc) -{ - expect_function_call(__wrap_BIO_sock_should_retry); - expect_value(__wrap_BIO_sock_should_retry, i, i); - will_return(__wrap_BIO_sock_should_retry, rc); -} - -static void expect_BIO_closesocket(int sock, int rc) -{ - expect_function_call(__wrap_BIO_closesocket); - expect_value(__wrap_BIO_closesocket, sock, sock); - will_return(__wrap_BIO_closesocket, rc); -} - -static void expect_BIO_socket_wait(int fd, int for_write, int rc) -{ - expect_function_call(__wrap_BIO_socket_wait); - expect_value(__wrap_BIO_socket_wait, fd, fd); - expect_value(__wrap_BIO_socket_wait, for_write, for_write); - will_return(__wrap_BIO_socket_wait, rc); -} - -static void expect_BIO_sock_error(int sock, int rc) -{ - expect_function_call(__wrap_BIO_sock_error); - expect_value(__wrap_BIO_sock_error, sock, sock); - will_return(__wrap_BIO_sock_error, rc); -} - -static void expect_fake_dgram_read(const void *buf, size_t size, int rc) -{ - expect_function_call(fake_dgram_read); - expect_value(fake_dgram_read, buf, buf); - expect_value(fake_dgram_read, size, size); - will_return(fake_dgram_read, rc); -} - -static void expect_fake_dgram_write(const void *buf, size_t size, int rc) -{ - expect_function_call(fake_dgram_write); - expect_value(fake_dgram_write, buf, buf); - expect_value(fake_dgram_write, size, size); - will_return(fake_dgram_write, rc); -} - -static void expect_fake_dgram_sendmmsg(const BIO_MSG *m, size_t s, size_t n, - uint64_t f, size_t processed, int rc) -{ - expect_function_call(fake_dgram_sendmmsg); - expect_value(fake_dgram_sendmmsg, m, m); - expect_value(fake_dgram_sendmmsg, s, s); - expect_value(fake_dgram_sendmmsg, n, n); - expect_value(fake_dgram_sendmmsg, f, f); - will_return(fake_dgram_sendmmsg, processed); - will_return(fake_dgram_sendmmsg, rc); -} - -static void expect_fake_dgram_recvmmsg(const BIO_MSG *m, size_t s, size_t n, - uint64_t f, size_t processed, int rc) -{ - expect_function_call(fake_dgram_recvmmsg); - expect_value(fake_dgram_recvmmsg, m, m); - expect_value(fake_dgram_recvmmsg, s, s); - expect_value(fake_dgram_recvmmsg, n, n); - expect_value(fake_dgram_recvmmsg, f, f); - will_return(fake_dgram_recvmmsg, processed); - will_return(fake_dgram_recvmmsg, rc); -} - -/* helpers */ - -static BIO_CONNECT *get_data(BIO *bio) -{ - return (BIO_CONNECT *)bio->ptr; -} - -/* - * Call at the end of any test that sets bio->num or addr_first to prevent - * unexpected BIO_closesocket or BIO_ADDRINFO_free invocations in teardown. - */ -static void reset_for_teardown(BIO *bio) -{ - BIO_CONNECT *data = get_data(bio); - - bio->num = (int)INVALID_SOCKET; - data->addr_first = NULL; - data->addr_iter = NULL; - data->state = BIO_CONN_S_BEFORE; -} - -/* setup / teardown */ - -static int setup(void **state) -{ - BIO *bio = BIO_new(BIO_s_connect()); - - assert_non_null(bio); - *state = bio; - return 0; -} - -static int teardown(void **state) -{ - if (*state != NULL) - BIO_free(*state); - return 0; -} - -/* I/O tests pre-establish state=OK so the state machine is not entered. */ -static int setup_io(void **state) -{ - BIO *bio; - BIO_CONNECT *data; - - if (setup(state) != 0) - return -1; - bio = *state; - data = get_data(bio); - data->state = BIO_CONN_S_OK; - bio->num = FAKE_SOCKET; - bio->init = 1; - return 0; -} - -static int teardown_io(void **state) -{ - if (*state != NULL) - reset_for_teardown(*state); - return teardown(state); -} - -static int group_setup(void **state) -{ - (void)state; - - fake_dgram_method = make_fake_dgram_method(); - - memset(&g_sin, 0, sizeof(g_sin)); - g_sin.sin_family = AF_INET; - g_sin.sin_port = htons(443); - g_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - memset(&g_addrinfo1, 0, sizeof(g_addrinfo1)); - g_addrinfo1.bai_family = AF_INET; - g_addrinfo1.bai_socktype = SOCK_STREAM; - g_addrinfo1.bai_protocol = IPPROTO_TCP; - g_addrinfo1.bai_addrlen = sizeof(g_sin); - g_addrinfo1.bai_addr = (struct sockaddr *)&g_sin; - g_addrinfo1.bai_next = NULL; - - memcpy(&g_addrinfo2, &g_addrinfo1, sizeof(g_addrinfo1)); - g_addrinfo2.bai_next = NULL; - - return 0; -} - -static int group_teardown(void **state) -{ - (void)state; - BIO_meth_free(fake_dgram_method); - fake_dgram_method = NULL; - return 0; -} - -/* conn_new */ - -static void test_conn_new(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - assert_non_null(data); - assert_int_equal(data->state, BIO_CONN_S_BEFORE); - assert_int_equal(data->connect_family, BIO_FAMILY_IPANY); - assert_int_equal(data->connect_sock_type, SOCK_STREAM); - assert_null(data->param_hostname); - assert_null(data->param_service); - assert_null(data->addr_first); - assert_null(data->dgram_bio); - assert_int_equal(bio->num, (int)INVALID_SOCKET); - assert_int_equal(bio->init, 0); -} - -/* conn_free */ - -static void test_conn_free_no_shutdown(void **state) -{ - /* shutdown=0: conn_close_socket and BIO_CONNECT_free are both skipped */ - BIO *bio = BIO_new(BIO_s_connect()); - - assert_non_null(bio); - bio->shutdown = BIO_NOCLOSE; - BIO_free(bio); - *state = NULL; -} - -/* conn_close_socket (via BIO_CTRL_RESET) */ - -static void test_close_socket_none(void **state) -{ - /* bio->num == INVALID_SOCKET: no calls expected */ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_RESET, 0, NULL), 0); -} - -static void test_close_socket_non_ok_state(void **state) -{ - /* Socket open but state != OK: BIO_closesocket called, no shutdown */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - bio->num = FAKE_SOCKET; - data->state = BIO_CONN_S_BLOCKED_CONNECT; - - expect_BIO_closesocket(FAKE_SOCKET, 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL), 0); - assert_int_equal(bio->num, (int)INVALID_SOCKET); - assert_int_equal(data->state, BIO_CONN_S_BEFORE); -} - -static void test_close_socket_ok_state(void **state) -{ - /* Socket open and state=OK: shutdown first, then BIO_closesocket */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - bio->num = FAKE_SOCKET; - data->state = BIO_CONN_S_OK; - - expect_BIO_closesocket(FAKE_SOCKET, 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL), 0); - assert_int_equal(bio->num, (int)INVALID_SOCKET); - assert_int_equal(data->state, BIO_CONN_S_BEFORE); -} - -/* conn_state (via BIO_C_DO_STATE_MACHINE) */ - -static void test_conn_state_no_hostname(void **state) -{ - /* BEFORE with no hostname and no service */ - assert_true(BIO_ctrl(*state, BIO_C_DO_STATE_MACHINE, 0, NULL) <= 0); -} - -static void test_conn_state_unsupported_family(void **state) -{ - /* BEFORE -> GET_ADDR -> unrecognised connect_family -> error */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - data->connect_family = 9999; - - assert_true(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL) <= 0); -} - -static void test_conn_state_lookup_fails(void **state) -{ - /* BEFORE -> GET_ADDR -> BIO_lookup returns 0 */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - - expect_BIO_lookup(NULL, 0); - assert_true(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL) <= 0); -} - -static void test_conn_state_socket_fails(void **state) -{ - /* Pre-set CREATE_SOCKET: BIO_socket returns INVALID_SOCKET */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->state = BIO_CONN_S_CREATE_SOCKET; - data->addr_iter = &g_addrinfo1; - - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, - (int)INVALID_SOCKET); - assert_true(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL) <= 0); - - data->addr_iter = NULL; - data->state = BIO_CONN_S_BEFORE; -} - -static void test_conn_state_connect_succeeds(void **state) -{ - /* Full happy path: BEFORE -> GET_ADDR -> CREATE_SOCKET -> CONNECT -> OK */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - - expect_BIO_lookup(&g_addrinfo1, 1); - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); - /* STREAM addrinfo adds KEEPALIVE to the default (zero) connect_mode */ - expect_BIO_connect(FAKE_SOCKET, (BIO_ADDR *)&g_sin, BIO_SOCK_KEEPALIVE, 1); - - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 1); - assert_int_equal(data->state, BIO_CONN_S_OK); - - reset_for_teardown(bio); -} - -static void test_conn_state_already_ok(void **state) -{ - /* State already OK: returns 1 with no external calls */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->state = BIO_CONN_S_OK; - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 1); - data->state = BIO_CONN_S_BEFORE; -} - -static void test_conn_state_connect_retry(void **state) -{ - /* Pre-set CONNECT: BIO_connect fails with retry -> BLOCKED_CONNECT */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->state = BIO_CONN_S_CONNECT; - data->addr_iter = &g_addrinfo1; - bio->num = FAKE_SOCKET; - - expect_BIO_connect(FAKE_SOCKET, (BIO_ADDR *)&g_sin, BIO_SOCK_KEEPALIVE, 0); - expect_BIO_sock_should_retry(0, 1); - - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 0); - assert_int_equal(data->state, BIO_CONN_S_BLOCKED_CONNECT); - assert_int_equal(bio->retry_reason, BIO_RR_CONNECT); - - reset_for_teardown(bio); -} - -static void test_conn_state_connect_error(void **state) -{ - /* Pre-set CONNECT: fails, no retry, no more addresses -> CONNECT_ERROR */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->state = BIO_CONN_S_CONNECT; - data->addr_iter = &g_addrinfo1; /* bai_next == NULL */ - bio->num = FAKE_SOCKET; - - expect_BIO_connect(FAKE_SOCKET, (BIO_ADDR *)&g_sin, BIO_SOCK_KEEPALIVE, 0); - expect_BIO_sock_should_retry(0, 0); - /* loop continues to CONNECT_ERROR which exits immediately */ - - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 0); - - reset_for_teardown(bio); -} - -static void test_conn_state_connect_next_addr(void **state) -{ - /* - * Pre-set CONNECT with two addresses: first connect fails, iterator - * advances, second CREATE_SOCKET fails so we get a clean exit. - */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - g_addrinfo1.bai_next = &g_addrinfo2; - data->state = BIO_CONN_S_CONNECT; - data->addr_iter = &g_addrinfo1; - bio->num = FAKE_SOCKET; - - expect_BIO_connect(FAKE_SOCKET, (BIO_ADDR *)&g_sin, BIO_SOCK_KEEPALIVE, 0); - expect_BIO_sock_should_retry(0, 0); - expect_BIO_closesocket(FAKE_SOCKET, 0); - /* CREATE_SOCKET for g_addrinfo2 */ - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, - (int)INVALID_SOCKET); - - assert_true(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL) <= 0); - - g_addrinfo1.bai_next = NULL; - reset_for_teardown(bio); -} - -static void test_conn_state_blocked_ok(void **state) -{ - /* Pre-set BLOCKED_CONNECT: socket becomes writable, no error -> OK */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->state = BIO_CONN_S_BLOCKED_CONNECT; - data->addr_iter = &g_addrinfo1; - bio->num = FAKE_SOCKET; - - expect_BIO_socket_wait(FAKE_SOCKET, 0, 1); - expect_BIO_sock_error(FAKE_SOCKET, 0); - - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 1); - assert_int_equal(data->state, BIO_CONN_S_OK); - - reset_for_teardown(bio); -} - -static void test_conn_state_blocked_error(void **state) -{ - /* Pre-set BLOCKED_CONNECT: socket error, no more addresses -> error */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->state = BIO_CONN_S_BLOCKED_CONNECT; - data->addr_iter = &g_addrinfo1; /* bai_next == NULL */ - bio->num = FAKE_SOCKET; - - expect_BIO_socket_wait(FAKE_SOCKET, 0, 1); - expect_BIO_sock_error(FAKE_SOCKET, ECONNREFUSED); - - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 0); - - reset_for_teardown(bio); -} - -#ifndef OPENSSL_NO_DGRAM -static void test_conn_state_connect_dgram_ok(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->connect_sock_type = SOCK_DGRAM; - data->state = BIO_CONN_S_CONNECT; - data->addr_iter = &g_addrinfo1; - bio->num = FAKE_SOCKET; - - /* DGRAM addrinfo means opts stays at the default connect_mode (0) */ - g_addrinfo1.bai_socktype = SOCK_DGRAM; - - expect_BIO_connect(FAKE_SOCKET, (BIO_ADDR *)&g_sin, 0, 1); - - assert_int_equal(BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL), 1); - assert_int_equal(data->state, BIO_CONN_S_OK); - assert_non_null(data->dgram_bio); - - g_addrinfo1.bai_socktype = SOCK_STREAM; - - assert_int_equal(BIO_set_close(data->dgram_bio, BIO_NOCLOSE), 1); - BIO_free(data->dgram_bio); - data->dgram_bio = NULL; - reset_for_teardown(bio); -} -#endif - -/* conn_read */ - -static void test_conn_read_success(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 8, 8); - assert_int_equal(BIO_read(bio, buf, 8), 8); - assert_false(BIO_should_retry(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_conn_read_eof(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 8, 0); - expect_BIO_sock_should_retry(0, 0); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_true(BIO_eof(bio)); -} - -static void test_conn_read_retry(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 8, -1); - expect_BIO_sock_should_retry(-1, 1); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_true(BIO_should_read(bio)); -} - -static void test_conn_read_error(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 8, -1); - expect_BIO_sock_should_retry(-1, 0); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_false(BIO_should_retry(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_conn_read_enters_state_machine(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - char buf[8] = { 0 }; - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - bio->init = 1; - - expect_BIO_lookup(&g_addrinfo1, 1); - expect_BIO_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, FAKE_SOCKET); - expect_BIO_connect(FAKE_SOCKET, (BIO_ADDR *)&g_sin, BIO_SOCK_KEEPALIVE, 1); - expect_read(FAKE_SOCKET, buf, 8, 8); - - assert_int_equal(BIO_read(bio, buf, 8), 8); - assert_int_equal(data->state, BIO_CONN_S_OK); - - reset_for_teardown(bio); -} - -static void test_conn_read_state_machine_fails(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - char buf[8] = { 0 }; - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - bio->init = 1; - - expect_BIO_lookup(NULL, 0); /* conn_state <= 0, no socket touched */ - - assert_true(BIO_read(bio, buf, 8) <= 0); - - reset_for_teardown(bio); -} - -static void test_conn_read_dgram_delegates(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO *dg = make_fake_dgram(); - char buf[8] = { 0 }; - - data->dgram_bio = dg; - - expect_fake_dgram_read(buf, 8, 4); - assert_int_equal(BIO_read(bio, buf, 8), 4); - - data->dgram_bio = NULL; - BIO_free(dg); -} - -/* conn_write */ - -static void test_conn_write_success(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_SOCKET, buf, 5, 5); - assert_int_equal(BIO_write(bio, buf, 5), 5); - assert_false(BIO_should_retry(bio)); -} - -static void test_conn_write_retry(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_SOCKET, buf, 5, -1); - expect_BIO_sock_should_retry(-1, 1); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_true(BIO_should_write(bio)); -} - -static void test_conn_write_error(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_SOCKET, buf, 5, -1); - expect_BIO_sock_should_retry(-1, 0); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_false(BIO_should_retry(bio)); -} - -static void test_conn_write_dgram_delegates(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO *dg = make_fake_dgram(); - const char buf[] = "hello"; - - data->dgram_bio = dg; - - expect_fake_dgram_write(buf, 5, 5); - assert_int_equal(BIO_write(bio, buf, 5), 5); - - data->dgram_bio = NULL; - BIO_free(dg); -} - -/* conn_gets - * - * conn_gets is non-static (unlike the other method functions) so it is a - * public symbol, but we exercise it via BIO_gets to stay in-interface. - */ - -static void test_conn_gets_null_buf(void **state) -{ - assert_true(BIO_gets(*state, NULL, 8) <= 0); -} - -static void test_conn_gets_zero_size(void **state) -{ - char buf[8] = { 0 }; - - assert_true(BIO_gets(*state, buf, 0) <= 0); -} - -static void test_conn_gets_null_ptr(void **state) -{ - /* bio->ptr == NULL is caught before any field access */ - BIO *bio = *state; - char buf[8] = { 0 }; - void *saved = bio->ptr; - - bio->ptr = NULL; - assert_true(BIO_gets(bio, buf, sizeof(buf)) <= 0); - bio->ptr = saved; -} - -static void test_conn_gets_dgram_bio_set(void **state) -{ - /* dgram_bio present is an error for gets */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - char buf[8] = { 0 }; - BIO fake_dgram; - - data->dgram_bio = &fake_dgram; - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), -1); - data->dgram_bio = NULL; -} - -static void test_conn_gets_newline(void **state) -{ - BIO *bio = *state; - char buf[8] = { 'h', 'i', '\n' }; - - expect_read(FAKE_SOCKET, buf, 1, 1); - expect_read(FAKE_SOCKET, buf + 1, 1, 1); - expect_read(FAKE_SOCKET, buf + 2, 1, 1); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), 3); -} - -static void test_conn_gets_fills_buffer(void **state) -{ - /* size=4 allows at most 3 chars before the terminating NUL */ - BIO *bio = *state; - char buf[4] = { 'a', 'b', 'c' }; - - expect_read(FAKE_SOCKET, buf, 1, 1); - expect_read(FAKE_SOCKET, buf + 1, 1, 1); - expect_read(FAKE_SOCKET, buf + 2, 1, 1); - - assert_int_equal(BIO_gets(bio, buf, 4), 3); -} - -static void test_conn_gets_eof_mid(void **state) -{ - /* One char read, then EOF: returns the char count */ - BIO *bio = *state; - char buf[8] = { 'z' }; - - expect_read(FAKE_SOCKET, buf, 1, 1); - expect_read(FAKE_SOCKET, buf + 1, 1, 0); - expect_BIO_sock_should_retry(0, 0); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), 1); -} - -static void test_conn_gets_immediate_eof(void **state) -{ - /* First read returns 0: EOF flag set, returns 0 */ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 1, 0); - expect_BIO_sock_should_retry(0, 0); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), 0); - assert_int_equal(buf[0], '\0'); -} - -static void test_conn_gets_retry(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 1, -1); - expect_BIO_sock_should_retry(-1, 1); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), -1); - assert_true(BIO_should_retry(bio)); -} - -/* conn_puts */ - -static void test_conn_puts_success(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_write(FAKE_SOCKET, str, 5, 5); - assert_int_equal(BIO_puts(bio, str), 5); -} - -static void test_conn_puts_write_fails(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_write(FAKE_SOCKET, str, 5, -1); - expect_BIO_sock_should_retry(-1, 0); - assert_true(BIO_puts(bio, str) <= 0); -} - -/* conn_ctrl */ - -static void test_conn_ctrl_reset_no_socket(void **state) -{ - /* INVALID_SOCKET -> conn_close_socket is a no-op */ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_RESET, 0, NULL), 0); - assert_int_equal(get_data(*state)->state, BIO_CONN_S_BEFORE); -} - -static void test_conn_ctrl_reset_clears_addrs(void **state) -{ - /* RESET also nulls the iterators and clears flags */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->addr_first = NULL; /* keep BIO_ADDRINFO_free a no-op */ - data->addr_iter = &g_addrinfo1; - bio->flags = BIO_FLAGS_IN_EOF; - bio->num = (int)INVALID_SOCKET; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL), 0); - assert_null(data->addr_first); - assert_null(data->addr_iter); - assert_int_equal(bio->flags, 0); - assert_int_equal(data->state, BIO_CONN_S_BEFORE); -} - -static void test_conn_ctrl_get_connect(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - const char *out = NULL; - - /* NULL ptr always returns 0 regardless of num */ - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 0, NULL), 0); - - data->param_hostname = OPENSSL_strdup("host.example"); - data->param_service = OPENSSL_strdup("443"); - data->connect_mode = BIO_SOCK_KEEPALIVE; - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 0, &out), 1); - assert_string_equal(out, "host.example"); - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 1, &out), 1); - assert_string_equal(out, "443"); - - /* num==4: connect_mode; ptr just needs to be non-NULL */ - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 4, &out), - BIO_SOCK_KEEPALIVE); - - /* unknown num with non-NULL ptr -> 0 */ - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 99, &out), 0); -} - -static void test_conn_ctrl_get_connect_address(void **state) -{ - /* num==2: address pointer from addr_iter */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - const char *out = NULL; - - data->addr_iter = &g_addrinfo1; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 2, &out), 1); - assert_non_null(out); - data->addr_iter = NULL; -} - -static void test_conn_ctrl_get_connect_family(void **state) -{ - /* num==3: AF_INET addr_iter maps to BIO_FAMILY_IPV4 */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - const char *out = NULL; - - data->addr_iter = &g_addrinfo1; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 3, &out), - BIO_FAMILY_IPV4); - data->addr_iter = NULL; -} - -static void test_conn_ctrl_set_connect_null_ptr(void **state) -{ - /* ptr == NULL: no-op, init left untouched */ - BIO *bio = *state; - - assert_int_equal(bio->init, 0); - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, NULL), 1); - assert_int_equal(bio->init, 0); -} - -static void test_conn_ctrl_set_connect_hostname(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, "host.example:443"), - 1); - assert_int_equal(bio->init, 1); - assert_string_equal(data->param_hostname, "host.example"); - assert_string_equal(data->param_service, "443"); -} - -static void test_conn_ctrl_set_connect_port(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, "8443"), 1); - assert_string_equal(data->param_service, "8443"); -} - -static void test_conn_ctrl_set_connect_address(void **state) -{ - /* num==2: derive host/service from a BIO_ADDR */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_ADDR *addr = BIO_ADDR_new(); - - assert_non_null(addr); - assert_true(BIO_ADDR_rawmake(addr, AF_INET, &g_sin.sin_addr, - sizeof(g_sin.sin_addr), g_sin.sin_port)); - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 2, addr), 1); - assert_non_null(data->param_hostname); - assert_non_null(data->param_service); - assert_null(data->addr_first); - - BIO_ADDR_free(addr); -} - -static void test_conn_ctrl_set_connect_family(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - int family = BIO_FAMILY_IPV4; - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 3, &family), 1); - assert_int_equal(data->connect_family, BIO_FAMILY_IPV4); -} - -static void test_conn_ctrl_set_sock_type(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_SOCK_TYPE, SOCK_DGRAM, NULL), 1); - assert_int_equal(data->connect_sock_type, SOCK_DGRAM); - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_SOCK_TYPE, SOCK_STREAM, NULL), 1); - assert_int_equal(data->connect_sock_type, SOCK_STREAM); - - /* Invalid socktype */ - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_SOCK_TYPE, 9999, NULL), 0); - - /* Too late once past BEFORE */ - data->state = BIO_CONN_S_GET_ADDR; - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_SOCK_TYPE, SOCK_DGRAM, NULL), 0); - data->state = BIO_CONN_S_BEFORE; -} - -static void test_conn_ctrl_get_sock_type(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - data->connect_sock_type = SOCK_DGRAM; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_SOCK_TYPE, 0, NULL), SOCK_DGRAM); - data->connect_sock_type = SOCK_STREAM; -} - -static void test_conn_ctrl_get_dgram_bio(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO *out = NULL; - BIO fake_dgram; - - /* dgram_bio NULL -> 0 */ - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_DGRAM_BIO, 0, &out), 0); - - data->dgram_bio = &fake_dgram; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_DGRAM_BIO, 0, &out), 1); - assert_ptr_equal(out, &fake_dgram); - data->dgram_bio = NULL; -} - -static void test_conn_ctrl_nbio(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - BIO_ctrl(bio, BIO_C_SET_NBIO, 1, NULL); - assert_true(data->connect_mode & BIO_SOCK_NONBLOCK); - - BIO_ctrl(bio, BIO_C_SET_NBIO, 0, NULL); - assert_false(data->connect_mode & BIO_SOCK_NONBLOCK); -} - -static void test_conn_ctrl_nbio_dgram(void **state) -{ - /* with a dgram_bio attached the mode flips and the call delegates */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO *dg = make_fake_dgram(); - - data->dgram_bio = dg; - BIO_ctrl(bio, BIO_C_SET_NBIO, 1, NULL); - assert_true(data->connect_mode & BIO_SOCK_NONBLOCK); - - data->dgram_bio = NULL; - BIO_free(dg); -} - -static void test_conn_ctrl_connect_mode(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - - BIO_ctrl(bio, BIO_C_SET_CONNECT_MODE, BIO_SOCK_KEEPALIVE, NULL); - assert_int_equal(data->connect_mode, BIO_SOCK_KEEPALIVE); - assert_int_equal(data->tfo_first, 0); -} - -static void test_conn_ctrl_get_fd(void **state) -{ - BIO *bio = *state; - int fd = -1; - - /* init==0 -> -1 */ - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_FD, 0, &fd), -1); - - bio->init = 1; - bio->num = FAKE_SOCKET; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_FD, 0, &fd), FAKE_SOCKET); - assert_int_equal(fd, FAKE_SOCKET); - - bio->init = 0; - bio->num = (int)INVALID_SOCKET; -} - -static void test_conn_ctrl_get_set_close(void **state) -{ - BIO *bio = *state; - - bio->shutdown = BIO_NOCLOSE; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_GET_CLOSE, 0, NULL), BIO_NOCLOSE); - - BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, BIO_CLOSE, NULL); - assert_int_equal(bio->shutdown, BIO_CLOSE); -} - -static void test_conn_ctrl_pending_flush(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL), 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL), 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL), 1); -} - -static void test_conn_ctrl_eof(void **state) -{ - BIO *bio = *state; - - bio->flags &= ~BIO_FLAGS_IN_EOF; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL), 0); - - bio->flags |= BIO_FLAGS_IN_EOF; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL), 1); - bio->flags &= ~BIO_FLAGS_IN_EOF; -} - -static void test_conn_ctrl_set_callback_defers(void **state) -{ - /* BIO_CTRL_SET_CALLBACK via conn_ctrl returns 0 (use callback ctrl) */ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_SET_CALLBACK, 0, NULL), 0); -} - -static void test_conn_ctrl_default(void **state) -{ - assert_int_equal(BIO_ctrl(*state, 9999, 0, NULL), 0); -} - -/* conn_callback_ctrl */ - -static int dummy_cb(BIO *b, int s, int res) -{ - (void)b; - (void)s; - return res; -} - -static void test_conn_ctrl_get_callback(void **state) -{ - /* BIO_CTRL_GET_CALLBACK returns the stored info_callback */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_info_cb *fp = NULL; - - data->info_callback = dummy_cb; - BIO_ctrl(bio, BIO_CTRL_GET_CALLBACK, 0, &fp); - assert_ptr_equal(fp, dummy_cb); - data->info_callback = NULL; -} - -static void test_conn_callback_ctrl_set(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_info_cb *retrieved; - - assert_int_equal(BIO_set_info_callback(bio, dummy_cb), 1); - assert_ptr_equal(data->info_callback, dummy_cb); - - assert_int_equal(BIO_get_info_callback(bio, &retrieved), 1); - assert_ptr_equal(retrieved, dummy_cb); - - assert_int_equal(BIO_set_info_callback(bio, NULL), 1); -} - -static void test_conn_callback_ctrl_default(void **state) -{ - assert_int_equal(BIO_callback_ctrl(*state, BIO_CTRL_SET_CALLBACK, dummy_cb), 1); -} - -static void test_conn_callback_ctrl_invalid(void **state) -{ - /* If cmd different than BIO_CTRL_SET_CALLBACK, return -2. */ - assert_int_equal(BIO_callback_ctrl(*state, 9999, dummy_cb), -2); -} - -/* conn_sendmmsg / conn_recvmmsg */ - -static void test_conn_sendmmsg_no_dgram(void **state) -{ - /* State OK, dgram_bio NULL -> error */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_MSG msg = { 0 }; - size_t processed = 1; - - data->state = BIO_CONN_S_OK; - bio->num = FAKE_SOCKET; - - assert_int_equal( - BIO_sendmmsg(bio, &msg, sizeof(msg), 1, 0, &processed), 0); - assert_int_equal(processed, 0); - - reset_for_teardown(bio); -} - -static void test_conn_sendmmsg_state_fails(void **state) -{ - /* state != OK and conn_state fails -> 0, processed zeroed */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_MSG msg = { 0 }; - size_t processed = 5; - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - bio->init = 1; /* BIO_sendmmsg rejects !init before dispatch */ - - expect_BIO_lookup(NULL, 0); - - assert_int_equal( - BIO_sendmmsg(bio, &msg, sizeof(msg), 1, 0, &processed), 0); - assert_int_equal(processed, 0); - - reset_for_teardown(bio); -} - -static void test_conn_sendmmsg_dgram_delegates(void **state) -{ - /* state OK with dgram_bio -> delegates to BIO_sendmmsg on it */ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO *dg = make_fake_dgram(); - BIO_MSG msg = { 0 }; - size_t processed = 0; - - data->dgram_bio = dg; - - expect_fake_dgram_sendmmsg(&msg, sizeof(msg), 1, 0, 1, 1); - - assert_int_equal( - BIO_sendmmsg(bio, &msg, sizeof(msg), 1, 0, &processed), 1); - assert_int_equal(processed, 1); - - data->dgram_bio = NULL; - BIO_free(dg); - reset_for_teardown(bio); -} - -static void test_conn_recvmmsg_no_dgram(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_MSG msg = { 0 }; - size_t processed = 1; - - data->state = BIO_CONN_S_OK; - bio->num = FAKE_SOCKET; - - assert_int_equal( - BIO_recvmmsg(bio, &msg, sizeof(msg), 1, 0, &processed), 0); - assert_int_equal(processed, 0); - - reset_for_teardown(bio); -} - -static void test_conn_recvmmsg_state_fails(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO_MSG msg = { 0 }; - size_t processed = 5; - - data->param_hostname = OPENSSL_strdup("host"); - data->param_service = OPENSSL_strdup("443"); - bio->init = 1; - - expect_BIO_lookup(NULL, 0); - - assert_int_equal( - BIO_recvmmsg(bio, &msg, sizeof(msg), 1, 0, &processed), 0); - assert_int_equal(processed, 0); - - reset_for_teardown(bio); -} - -static void test_conn_recvmmsg_dgram_delegates(void **state) -{ - BIO *bio = *state; - BIO_CONNECT *data = get_data(bio); - BIO *dg = make_fake_dgram(); - BIO_MSG msg = { 0 }; - size_t processed = 0; - - data->dgram_bio = dg; - - expect_fake_dgram_recvmmsg(&msg, sizeof(msg), 1, 0, 1, 1); - - assert_int_equal( - BIO_recvmmsg(bio, &msg, sizeof(msg), 1, 0, &processed), 1); - assert_int_equal(processed, 1); - - data->dgram_bio = NULL; - BIO_free(dg); - reset_for_teardown(bio); -} - -/* main */ - -#define CONN_TEST(name) \ - cmocka_unit_test_setup_teardown(name, setup, teardown) - -#define CONN_TEST_IO(name) \ - cmocka_unit_test_setup_teardown(name, setup_io, teardown_io) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* conn_new */ - CONN_TEST(test_conn_new), - /* conn_free */ - CONN_TEST(test_conn_free_no_shutdown), - /* conn_close_socket */ - CONN_TEST(test_close_socket_none), - CONN_TEST(test_close_socket_non_ok_state), - CONN_TEST(test_close_socket_ok_state), - /* conn_state */ - CONN_TEST(test_conn_state_no_hostname), - CONN_TEST(test_conn_state_unsupported_family), - CONN_TEST(test_conn_state_lookup_fails), - CONN_TEST(test_conn_state_socket_fails), - CONN_TEST(test_conn_state_connect_succeeds), - CONN_TEST(test_conn_state_already_ok), - CONN_TEST(test_conn_state_connect_retry), - CONN_TEST(test_conn_state_connect_error), - CONN_TEST(test_conn_state_connect_next_addr), - CONN_TEST(test_conn_state_blocked_ok), - CONN_TEST(test_conn_state_blocked_error), -#ifndef OPENSSL_NO_DGRAM - CONN_TEST(test_conn_state_connect_dgram_ok), -#endif - /* conn_read */ - CONN_TEST_IO(test_conn_read_success), - CONN_TEST_IO(test_conn_read_eof), - CONN_TEST_IO(test_conn_read_retry), - CONN_TEST_IO(test_conn_read_error), - CONN_TEST(test_conn_read_enters_state_machine), - CONN_TEST(test_conn_read_state_machine_fails), - CONN_TEST_IO(test_conn_read_dgram_delegates), - /* conn_write */ - CONN_TEST_IO(test_conn_write_success), - CONN_TEST_IO(test_conn_write_retry), - CONN_TEST_IO(test_conn_write_error), - CONN_TEST_IO(test_conn_write_dgram_delegates), - /* conn_gets */ - CONN_TEST(test_conn_gets_null_buf), - CONN_TEST(test_conn_gets_zero_size), - CONN_TEST(test_conn_gets_null_ptr), - CONN_TEST_IO(test_conn_gets_dgram_bio_set), - CONN_TEST_IO(test_conn_gets_newline), - CONN_TEST_IO(test_conn_gets_fills_buffer), - CONN_TEST_IO(test_conn_gets_eof_mid), - CONN_TEST_IO(test_conn_gets_immediate_eof), - CONN_TEST_IO(test_conn_gets_retry), - /* conn_puts */ - CONN_TEST_IO(test_conn_puts_success), - CONN_TEST_IO(test_conn_puts_write_fails), - /* conn_ctrl */ - CONN_TEST(test_conn_ctrl_reset_no_socket), - CONN_TEST(test_conn_ctrl_reset_clears_addrs), - CONN_TEST(test_conn_ctrl_get_connect), - CONN_TEST(test_conn_ctrl_get_connect_address), - CONN_TEST(test_conn_ctrl_get_connect_family), - CONN_TEST(test_conn_ctrl_set_connect_null_ptr), - CONN_TEST(test_conn_ctrl_set_connect_hostname), - CONN_TEST(test_conn_ctrl_set_connect_port), - CONN_TEST(test_conn_ctrl_set_connect_address), - CONN_TEST(test_conn_ctrl_set_connect_family), - CONN_TEST(test_conn_ctrl_set_sock_type), - CONN_TEST(test_conn_ctrl_get_sock_type), - CONN_TEST(test_conn_ctrl_get_dgram_bio), - CONN_TEST(test_conn_ctrl_nbio), - CONN_TEST_IO(test_conn_ctrl_nbio_dgram), - CONN_TEST(test_conn_ctrl_connect_mode), - CONN_TEST(test_conn_ctrl_get_fd), - CONN_TEST(test_conn_ctrl_get_set_close), - CONN_TEST(test_conn_ctrl_pending_flush), - CONN_TEST(test_conn_ctrl_eof), - CONN_TEST(test_conn_ctrl_set_callback_defers), - CONN_TEST(test_conn_ctrl_default), - /* conn_callback_ctrl */ - CONN_TEST(test_conn_ctrl_get_callback), - CONN_TEST(test_conn_callback_ctrl_set), - CONN_TEST(test_conn_callback_ctrl_default), - CONN_TEST(test_conn_callback_ctrl_invalid), - /* conn_sendmmsg / conn_recvmmsg */ - CONN_TEST(test_conn_sendmmsg_no_dgram), - CONN_TEST(test_conn_sendmmsg_state_fails), - CONN_TEST_IO(test_conn_sendmmsg_dgram_delegates), - CONN_TEST(test_conn_recvmmsg_no_dgram), - CONN_TEST(test_conn_recvmmsg_state_fails), - CONN_TEST_IO(test_conn_recvmmsg_dgram_delegates), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, group_setup, group_teardown); -} - -#else - -int main(void) -{ - return 0; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/test/unit/crypto/bio/test_bss_dgram.c b/test/unit/crypto/bio/test_bss_dgram.c deleted file mode 100644 index 4a39ebba5d..0000000000 --- a/test/unit/crypto/bio/test_bss_dgram.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#if defined(OPENSSL_NO_SOCK) || defined(OPENSSL_NO_DGRAM) - -int main(void) -{ - return 0; -} - -#else - -#include -#include -#include -#include -#include -#include -#include -#include "bio_local.h" -#include - -#define FAKE_SOCKET 42 - -/* prototypes for __wrap_* (required by -Wmissing-prototypes) */ -ssize_t __wrap_recvfrom(int fd, void *buf, size_t len, int flags, - struct sockaddr *src, socklen_t *slen); -ssize_t __wrap_sendto(int fd, const void *buf, size_t len, int flags, - const struct sockaddr *dst, socklen_t slen); -ssize_t __wrap_write(int fd, const void *buf, size_t count); -int __wrap_getsockname(int fd, struct sockaddr *addr, socklen_t *slen); -int __wrap_getpeername(int fd, struct sockaddr *addr, socklen_t *slen); -int __wrap_BIO_closesocket(int fd); -int __wrap_BIO_socket_nbio(int fd, int mode); - -/* - * Shared sockaddrs handed back by the address-returning mocks. group_setup - * fills g_sin (AF_INET loopback); g_sin6 is an AF_INET6 loopback and - * g_sin6_v4m an IPv4-mapped IPv6 address (::ffff:127.0.0.1). - */ -static struct sockaddr_in g_sin; -static struct sockaddr_in6 g_sin6; -static struct sockaddr_in6 g_sin6_v4m; - -/* wraps */ - -ssize_t __wrap_recvfrom(int fd, void *buf, size_t len, int flags, - struct sockaddr *src, socklen_t *slen) -{ - ssize_t rc; - - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(len); - check_expected(flags); - rc = mock_type(ssize_t); - if (rc >= 0 && src != NULL && slen != NULL) { - const struct sockaddr *sa = mock_ptr_type(const struct sockaddr *); - - if (sa != NULL && *slen >= sizeof(g_sin)) { - memcpy(src, sa, sizeof(g_sin)); - *slen = sizeof(g_sin); - } - } - if (rc < 0) - errno = mock_type(int); - return rc; -} - -ssize_t __wrap_sendto(int fd, const void *buf, size_t len, int flags, - const struct sockaddr *dst, socklen_t slen) -{ - ssize_t rc; - - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(len); - check_expected(flags); - check_expected(slen); - (void)dst; - rc = mock_type(ssize_t); - if (rc < 0) - errno = mock_type(int); - return rc; -} - -ssize_t __wrap_write(int fd, const void *buf, size_t count) -{ - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - return mock_type(ssize_t); -} - -int __wrap_getsockname(int fd, struct sockaddr *addr, socklen_t *slen) -{ - int rc; - - function_called(); - check_expected(fd); - rc = mock_type(int); - if (rc == 0 && addr != NULL && slen != NULL) { - const struct sockaddr *sa = mock_ptr_type(const struct sockaddr *); - socklen_t sl = (socklen_t)mock_type(int); - - if (sa != NULL && *slen >= sl) { - memcpy(addr, sa, sl); - *slen = sl; - } - } - return rc; -} - -int __wrap_getpeername(int fd, struct sockaddr *addr, socklen_t *slen) -{ - int rc; - - function_called(); - check_expected(fd); - rc = mock_type(int); - if (rc == 0 && addr != NULL && slen != NULL && *slen >= sizeof(g_sin)) { - memcpy(addr, &g_sin, sizeof(g_sin)); - *slen = sizeof(g_sin); - } - return rc; -} - -int __wrap_BIO_closesocket(int fd) -{ - function_called(); - check_expected(fd); - return mock_type(int); -} - -int __wrap_BIO_socket_nbio(int fd, int mode) -{ - function_called(); - check_expected(fd); - check_expected(mode); - return mock_type(int); -} - -/* expectations */ - -static void expect_recvfrom(int fd, const void *buf, size_t len, int flags, - ssize_t rc, const struct sockaddr *src, int errnoval) -{ - expect_function_call(__wrap_recvfrom); - expect_value(__wrap_recvfrom, fd, fd); - expect_value(__wrap_recvfrom, buf, buf); - expect_value(__wrap_recvfrom, len, len); - expect_value(__wrap_recvfrom, flags, flags); - will_return(__wrap_recvfrom, rc); - if (rc >= 0) - will_return(__wrap_recvfrom, src); - else - will_return(__wrap_recvfrom, errnoval); -} - -static void expect_sendto(int fd, const void *buf, size_t len, int flags, - socklen_t slen, ssize_t rc, int errnoval) -{ - expect_function_call(__wrap_sendto); - expect_value(__wrap_sendto, fd, fd); - expect_value(__wrap_sendto, buf, buf); - expect_value(__wrap_sendto, len, len); - expect_value(__wrap_sendto, flags, flags); - expect_value(__wrap_sendto, slen, slen); - will_return(__wrap_sendto, rc); - if (rc < 0) - will_return(__wrap_sendto, errnoval); -} - -static void expect_write(int fd, const void *buf, size_t count, ssize_t rc) -{ - expect_function_call(__wrap_write); - expect_value(__wrap_write, fd, fd); - expect_value(__wrap_write, buf, buf); - expect_value(__wrap_write, count, count); - will_return(__wrap_write, rc); -} - -static void expect_getsockname(int fd, int rc) -{ - expect_function_call(__wrap_getsockname); - expect_value(__wrap_getsockname, fd, fd); - will_return(__wrap_getsockname, rc); - if (rc == 0) { - will_return(__wrap_getsockname, (const struct sockaddr *)&g_sin); - will_return(__wrap_getsockname, (int)sizeof(g_sin)); - } -} - -static void expect_getpeername(int fd, int rc) -{ - expect_function_call(__wrap_getpeername); - expect_value(__wrap_getpeername, fd, fd); - will_return(__wrap_getpeername, rc); -} - -static void expect_BIO_closesocket(int fd, int rc) -{ - expect_function_call(__wrap_BIO_closesocket); - expect_value(__wrap_BIO_closesocket, fd, fd); - will_return(__wrap_BIO_closesocket, rc); -} - -static void expect_BIO_socket_nbio(int fd, int mode, int rc) -{ - expect_function_call(__wrap_BIO_socket_nbio); - expect_value(__wrap_BIO_socket_nbio, fd, fd); - expect_value(__wrap_BIO_socket_nbio, mode, mode); - will_return(__wrap_BIO_socket_nbio, rc); -} - -/* helpers */ - -static bio_dgram_data *get_data(BIO *bio) -{ - return (bio_dgram_data *)bio->ptr; -} - -static void make_peer(BIO *bio, unsigned short port) -{ - struct sockaddr_in sa; - - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, &sa); -} - -/* - * Detach the fake socket before teardown so BIO_free does not call a real - * close: BIO_NOCLOSE already guards it, but resetting num keeps any stray - * dgram_clear path inert. - */ -static void reset_for_teardown(BIO *bio) -{ - bio->num = (int)INVALID_SOCKET; - bio->shutdown = BIO_NOCLOSE; -} - -/* setup / teardown */ - -static int setup(void **state) -{ - BIO *bio = BIO_new(BIO_s_datagram()); - - assert_non_null(bio); - *state = bio; - return 0; -} - -static int teardown(void **state) -{ - if (*state != NULL) - BIO_free(*state); - return 0; -} - -/* I/O tests attach the fake socket up front so the BIO is init'ed. */ -static int setup_io(void **state) -{ - BIO *bio; - - if (setup(state) != 0) - return -1; - bio = *state; - expect_getsockname(FAKE_SOCKET, 0); - expect_getpeername(FAKE_SOCKET, -1); - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - return 0; -} - -static int teardown_io(void **state) -{ - if (*state != NULL) - reset_for_teardown(*state); - return teardown(state); -} - -static int group_setup(void **state) -{ - struct in6_addr loop6 = IN6ADDR_LOOPBACK_INIT; - - (void)state; - memset(&g_sin, 0, sizeof(g_sin)); - g_sin.sin_family = AF_INET; - g_sin.sin_port = htons(443); - g_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - memset(&g_sin6, 0, sizeof(g_sin6)); - g_sin6.sin6_family = AF_INET6; - g_sin6.sin6_port = htons(443); - g_sin6.sin6_addr = loop6; - - /* ::ffff:127.0.0.1 -> IPv4-mapped, exercises the v4mapped MTU branch */ - memset(&g_sin6_v4m, 0, sizeof(g_sin6_v4m)); - g_sin6_v4m.sin6_family = AF_INET6; - g_sin6_v4m.sin6_port = htons(443); - g_sin6_v4m.sin6_addr.s6_addr[10] = 0xff; - g_sin6_v4m.sin6_addr.s6_addr[11] = 0xff; - g_sin6_v4m.sin6_addr.s6_addr[12] = 127; - g_sin6_v4m.sin6_addr.s6_addr[15] = 1; - return 0; -} - -/* BIO_new_dgram */ -static void test_new_dgram(void **state) -{ - int out = -1; - BIO *bio; - - (void)state; - expect_getsockname(FAKE_SOCKET, 0); - expect_getpeername(FAKE_SOCKET, -1); - bio = BIO_new_dgram(FAKE_SOCKET, BIO_NOCLOSE); - assert_non_null(bio); - assert_int_equal(BIO_get_fd(bio, &out), FAKE_SOCKET); - assert_int_equal(out, FAKE_SOCKET); - reset_for_teardown(bio); - BIO_free(bio); -} - -static void test_dgram_new_defaults(void **state) -{ - BIO *bio = *state; - - assert_non_null(get_data(bio)); - assert_int_equal(bio->num, 0); - assert_int_equal(bio->init, 0); -} - -/* BIO_C_SET_FD / BIO_C_GET_FD */ - -static void test_set_fd_unconnected(void **state) -{ - BIO *bio = *state; - bio_dgram_data *data; - int out = -1; - - expect_getsockname(FAKE_SOCKET, 0); - expect_getpeername(FAKE_SOCKET, -1); - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - - data = get_data(bio); - assert_int_equal(data->connected, 0); - assert_int_equal(bio->init, 1); - assert_int_equal(BIO_get_fd(bio, &out), FAKE_SOCKET); - assert_int_equal(out, FAKE_SOCKET); - reset_for_teardown(bio); -} - -static void test_set_fd_connected(void **state) -{ - /* getpeername succeeds: peer is recorded and connected is set */ - BIO *bio = *state; - bio_dgram_data *data; - - expect_getsockname(FAKE_SOCKET, 0); - expect_getpeername(FAKE_SOCKET, 0); - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - - data = get_data(bio); - assert_int_equal(data->connected, 1); - assert_int_equal(BIO_ADDR_family(&data->peer), AF_INET); - reset_for_teardown(bio); -} - -static void test_get_fd_uninit(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_C_GET_FD, 0, NULL), -1); -} - -/* dgram_read */ - -static void test_dgram_read_noop(void **state) -{ - /* outl == 0: recvfrom is never reached */ - BIO *bio = *state; - char buf[1]; - - assert_int_equal(BIO_read(bio, buf, 0), 0); -} - -static void test_dgram_read_success(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_recvfrom(FAKE_SOCKET, buf, sizeof(buf), 0, 4, NULL, 0); - assert_int_equal(BIO_read(bio, buf, sizeof(buf)), 4); - assert_false(BIO_should_retry(bio)); -} - -static void test_dgram_read_sets_peer(void **state) -{ - /* unconnected receive records the source address as the peer */ - BIO *bio = *state; - bio_dgram_data *data = get_data(bio); - char buf[16] = { 0 }; - - expect_recvfrom(FAKE_SOCKET, buf, sizeof(buf), 0, 4, - (const struct sockaddr *)&g_sin, 0); - assert_int_equal(BIO_read(bio, buf, sizeof(buf)), 4); - assert_int_equal(BIO_ADDR_family(&data->peer), AF_INET); -} - -static void test_dgram_read_peek(void **state) -{ - /* peekmode passes MSG_PEEK to recvfrom */ - BIO *bio = *state; - char buf[16] = { 0 }; - - get_data(bio)->peekmode = 1; - expect_recvfrom(FAKE_SOCKET, buf, sizeof(buf), MSG_PEEK, 4, NULL, 0); - assert_int_equal(BIO_read(bio, buf, sizeof(buf)), 4); -} - -static void test_dgram_read_retry(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_recvfrom(FAKE_SOCKET, buf, sizeof(buf), 0, -1, NULL, EAGAIN); - assert_true(BIO_read(bio, buf, sizeof(buf)) <= 0); - assert_true(BIO_should_read(bio)); -} - -static void test_dgram_read_error(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_recvfrom(FAKE_SOCKET, buf, sizeof(buf), 0, -1, NULL, ECONNREFUSED); - assert_true(BIO_read(bio, buf, sizeof(buf)) <= 0); - assert_false(BIO_should_retry(bio)); -} - -/* dgram_write */ - -static void test_dgram_write_unconnected(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - make_peer(bio, 4433); - expect_sendto(FAKE_SOCKET, buf, 5, 0, - (socklen_t)sizeof(struct sockaddr_in), 5, 0); - assert_int_equal(BIO_write(bio, buf, 5), 5); - assert_false(BIO_should_retry(bio)); -} - -static void test_dgram_write_connected(void **state) -{ - BIO *bio = *state; - bio_dgram_data *data = get_data(bio); - const char buf[] = "hello"; - - data->connected = 1; - expect_write(FAKE_SOCKET, buf, 5, 5); - assert_int_equal(BIO_write(bio, buf, 5), 5); - data->connected = 0; -} - -static void test_dgram_write_retry(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - make_peer(bio, 4433); - expect_sendto(FAKE_SOCKET, buf, 5, 0, - (socklen_t)sizeof(struct sockaddr_in), -1, EAGAIN); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_true(BIO_should_write(bio)); -} - -static void test_dgram_write_error(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - make_peer(bio, 4433); - expect_sendto(FAKE_SOCKET, buf, 5, 0, - (socklen_t)sizeof(struct sockaddr_in), -1, ECONNREFUSED); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_false(BIO_should_retry(bio)); -} - -/* dgram_ctrl */ - -static void test_ctrl_reset(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_RESET, 0, NULL), 0); -} - -static void test_ctrl_info(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_INFO, 0, NULL), 0); -} - -static void test_ctrl_pending_wpending(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_PENDING, 0, NULL), 0); - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_WPENDING, 0, NULL), 0); -} - -static void test_ctrl_dup_flush(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_DUP, 0, NULL), 1); - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_FLUSH, 0, NULL), 1); -} - -static void test_ctrl_get_set_close(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_GET_CLOSE, 0, NULL), BIO_NOCLOSE); - BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, BIO_CLOSE, NULL); - assert_int_equal(bio->shutdown, BIO_CLOSE); - bio->shutdown = BIO_NOCLOSE; -} - -static void test_ctrl_connect(void **state) -{ - BIO *bio = *state; - bio_dgram_data *data = get_data(bio); - struct sockaddr_in sa; - - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(4433); - sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - BIO_ctrl(bio, BIO_CTRL_DGRAM_CONNECT, 0, &sa); - assert_int_equal(BIO_ADDR_family(&data->peer), AF_INET); - assert_int_equal(data->peer.s_in.sin_port, htons(4433)); -} - -static void test_ctrl_set_get_peer(void **state) -{ - BIO *bio = *state; - BIO_ADDR got; - - make_peer(bio, 4433); - memset(&got, 0, sizeof(got)); - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_PEER, sizeof(got), &got); - assert_int_equal(got.s_in.sin_family, AF_INET); - assert_int_equal(got.s_in.sin_port, htons(4433)); -} - -static void test_ctrl_set_connected(void **state) -{ - BIO *bio = *state; - bio_dgram_data *data = get_data(bio); - struct sockaddr_in sa; - - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(4433); - sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &sa); - assert_int_equal(data->connected, 1); - assert_int_equal(BIO_ADDR_family(&data->peer), AF_INET); - - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, NULL); - assert_int_equal(data->connected, 0); - assert_int_equal(BIO_ADDR_family(&data->peer), AF_UNSPEC); -} - -static void test_ctrl_detect_peer_addr_from_data(void **state) -{ - /* peer already known: returned without touching getpeername */ - BIO *bio = *state; - BIO_ADDR got; - - make_peer(bio, 4433); - memset(&got, 0, sizeof(got)); - assert_true( - BIO_ctrl(bio, BIO_CTRL_DGRAM_DETECT_PEER_ADDR, sizeof(got), &got) > 0); - assert_int_equal(got.s_in.sin_family, AF_INET); -} - -static void test_ctrl_detect_peer_addr_via_getpeername(void **state) -{ - /* peer unset: dgram_ctrl falls back to getpeername */ - BIO *bio = *state; - BIO_ADDR got; - - memset(&got, 0, sizeof(got)); - expect_getpeername(FAKE_SOCKET, 0); - assert_true( - BIO_ctrl(bio, BIO_CTRL_DGRAM_DETECT_PEER_ADDR, sizeof(got), &got) > 0); - assert_int_equal(got.s_in.sin_family, AF_INET); -} - -static void test_ctrl_set_get_mtu(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_MTU, 1400, NULL), 1400); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_MTU, 0, NULL), 1400); -} - -static void test_ctrl_fallback_mtu_ipv4(void **state) -{ - /* AF_INET peer: 576 payload minus 28 bytes IP+UDP overhead */ - BIO *bio = *state; - - make_peer(bio, 4433); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL), 576 - 28); -} - -#if OPENSSL_USE_IPV6 -static void test_ctrl_fallback_mtu_ipv6(void **state) -{ - /* AF_INET6 non-mapped peer: 1280 minus 48 bytes overhead */ - BIO *bio = *state; - - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, &g_sin6); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL), 1280 - 48); -} - -#ifdef IN6_IS_ADDR_V4MAPPED -static void test_ctrl_fallback_mtu_ipv6_v4mapped(void **state) -{ - /* v4-mapped AF_INET6 peer: treated as IPv4, 576 minus 28 overhead */ - BIO *bio = *state; - - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, &g_sin6_v4m); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL), 576 - 28); -} -#endif -#endif - -#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) -static void test_ctrl_mtu_discover_getsockname_fails(void **state) -{ - /* getsockname fails before any setsockopt: ret 0 */ - BIO *bio = *state; - - expect_getsockname(FAKE_SOCKET, -1); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL), 0); -} -#endif - -static void test_ctrl_nbio(void **state) -{ - BIO *bio = *state; - - expect_BIO_socket_nbio(FAKE_SOCKET, 1, 1); - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_NBIO, 1, NULL), 1); -} - -static void test_ctrl_set_next_timeout(void **state) -{ - BIO *bio = *state; - struct timeval tv = { 1, 0 }; - - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &tv), 1); -} - -/* dgram_clear / dgram_free */ - -static void test_free_closes_when_shutdown(void **state) -{ - BIO *bio = BIO_new(BIO_s_datagram()); - - (void)state; - assert_non_null(bio); - expect_getsockname(FAKE_SOCKET, 0); - expect_getpeername(FAKE_SOCKET, -1); - BIO_set_fd(bio, FAKE_SOCKET, BIO_CLOSE); - - expect_BIO_closesocket(FAKE_SOCKET, 0); - BIO_free(bio); -} - -static void test_free_no_close_when_noclose(void **state) -{ - BIO *bio = BIO_new(BIO_s_datagram()); - - (void)state; - assert_non_null(bio); - expect_getsockname(FAKE_SOCKET, 0); - expect_getpeername(FAKE_SOCKET, -1); - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - BIO_free(bio); -} - -/* main */ - -#define DG_TEST(name) \ - cmocka_unit_test_setup_teardown(name, setup, teardown) - -#define DG_TEST_IO(name) \ - cmocka_unit_test_setup_teardown(name, setup_io, teardown_io) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* BIO_new_dgram */ - DG_TEST(test_new_dgram), - DG_TEST(test_dgram_new_defaults), - /* SET_FD / GET_FD */ - DG_TEST(test_set_fd_unconnected), - DG_TEST(test_set_fd_connected), - DG_TEST(test_get_fd_uninit), - /* dgram_read */ - DG_TEST_IO(test_dgram_read_noop), - DG_TEST_IO(test_dgram_read_success), - DG_TEST_IO(test_dgram_read_sets_peer), - DG_TEST_IO(test_dgram_read_peek), - DG_TEST_IO(test_dgram_read_retry), - DG_TEST_IO(test_dgram_read_error), - /* dgram_write */ - DG_TEST_IO(test_dgram_write_unconnected), - DG_TEST_IO(test_dgram_write_connected), - DG_TEST_IO(test_dgram_write_retry), - DG_TEST_IO(test_dgram_write_error), - /* dgram_ctrl */ - DG_TEST_IO(test_ctrl_reset), - DG_TEST_IO(test_ctrl_info), - DG_TEST_IO(test_ctrl_pending_wpending), - DG_TEST_IO(test_ctrl_dup_flush), - DG_TEST_IO(test_ctrl_get_set_close), - DG_TEST_IO(test_ctrl_connect), - DG_TEST_IO(test_ctrl_set_get_peer), - DG_TEST_IO(test_ctrl_set_connected), - DG_TEST_IO(test_ctrl_detect_peer_addr_from_data), - DG_TEST_IO(test_ctrl_detect_peer_addr_via_getpeername), - DG_TEST_IO(test_ctrl_set_get_mtu), - DG_TEST_IO(test_ctrl_fallback_mtu_ipv4), -#if OPENSSL_USE_IPV6 - DG_TEST_IO(test_ctrl_fallback_mtu_ipv6), -#ifdef IN6_IS_ADDR_V4MAPPED - DG_TEST_IO(test_ctrl_fallback_mtu_ipv6_v4mapped), -#endif -#endif -#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) - DG_TEST_IO(test_ctrl_mtu_discover_getsockname_fails), -#endif - DG_TEST_IO(test_ctrl_nbio), - DG_TEST_IO(test_ctrl_set_next_timeout), - /* dgram_clear / dgram_free */ - DG_TEST(test_free_closes_when_shutdown), - DG_TEST(test_free_no_close_when_noclose), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, group_setup, NULL); -} - -#endif /* OPENSSL_NO_SOCK || OPENSSL_NO_DGRAM */ diff --git a/test/unit/crypto/bio/test_bss_dgram_win.c b/test/unit/crypto/bio/test_bss_dgram_win.c deleted file mode 100644 index 080d91c4e2..0000000000 --- a/test/unit/crypto/bio/test_bss_dgram_win.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * test/bss_dgram_win_test.c - * - * Windows-only side test for bss_dgram.c Windows-specific paths. - * Uses Microsoft Detours to intercept Winsock calls at runtime. - * Does NOT replace the normal --wrap-based bss_dgram test; it only - * covers branches that differ under OPENSSL_SYS_WINDOWS. - * - * NOTE: not compiled/verified by the author's toolchain. The first - * test (detour_probe) is a hard gate: if Detours does not intercept - * cross-module Winsock calls, every other result is meaningless. - */ - -#include "openssl/e_os2.h" - -#if defined(OPENSSL_NO_SOCK) || defined(OPENSSL_NO_DGRAM) \ - || !defined(OPENSSL_SYS_WINDOWS) -int main(void) { return 0; } -#else - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "internal/sockets.h" -#include "bio_local.h" -#include - -#define FAKE_SOCKET ((SOCKET)42) - -/* - * Real function pointers. After DetourAttach commits, Detours rewrites - * these to trampolines pointing at the original code. - */ -static int(WSAAPI *real_getsockname)(SOCKET, struct sockaddr *, int *) - = getsockname; -static int(WSAAPI *real_getpeername)(SOCKET, struct sockaddr *, int *) - = getpeername; -static int(WSAAPI *real_setsockopt)(SOCKET, int, int, const char *, int) - = setsockopt; -static int(WSAAPI *real_getsockopt)(SOCKET, int, int, char *, int *) - = getsockopt; -static int(WSAAPI *real_recvfrom)(SOCKET, char *, int, int, - struct sockaddr *, int *) - = recvfrom; - -static struct sockaddr_in g_sin; - -/* - * detour_probe uses this to confirm the mock actually fired. It is the - * only place a mock is allowed to run outside a cmocka expectation, so - * the mocks below special-case it. - */ -static int g_probe_active; -static int g_probe_getsockopt_hits; - -/* mocks */ - -static int WSAAPI mock_getsockname(SOCKET s, struct sockaddr *name, - int *namelen) -{ - int rc; - - function_called(); - check_expected_uint(s); - - rc = mock_type(int); - if (rc == 0) { - const struct sockaddr *sa = mock_ptr_type(const struct sockaddr *); - int sl = mock_type(int); - - assert_non_null(name); - assert_non_null(namelen); - assert_true(*namelen >= sl); - memcpy(name, sa, (size_t)sl); - *namelen = sl; - } else { - WSASetLastError(mock_type(int)); - } - return rc; -} - -static int WSAAPI mock_getpeername(SOCKET s, struct sockaddr *name, - int *namelen) -{ - int rc; - - function_called(); - check_expected_uint(s); - - rc = mock_type(int); - if (rc == 0) { - assert_non_null(name); - assert_non_null(namelen); - assert_true(*namelen >= (int)sizeof(g_sin)); - memcpy(name, &g_sin, sizeof(g_sin)); - *namelen = (int)sizeof(g_sin); - } else { - WSASetLastError(mock_type(int)); - } - return rc; -} - -static int WSAAPI mock_setsockopt(SOCKET s, int level, int optname, - const char *optval, int optlen) -{ - int expected_int; - int rc; - - function_called(); - check_expected_uint(s); - check_expected_int(level); - check_expected_int(optname); - check_expected_int(optlen); - - /* Every Windows path routed here passes a single int. */ - assert_int_equal(optlen, (int)sizeof(int)); - expected_int = mock_type(int); - assert_int_equal(*(const int *)optval, expected_int); - - rc = mock_type(int); - if (rc == SOCKET_ERROR) - WSASetLastError(mock_type(int)); - return rc; -} - -static int WSAAPI mock_getsockopt(SOCKET s, int level, int optname, - char *optval, int *optlen) -{ - int out_value; - int rc; - - /* Probe path: no expectations queued, just record and answer. */ - if (g_probe_active) { - g_probe_getsockopt_hits++; - if (optval != NULL && optlen != NULL && *optlen >= (int)sizeof(int)) { - *(int *)optval = 0; - *optlen = (int)sizeof(int); - } - return 0; - } - - function_called(); - check_expected_uint(s); - check_expected_int(level); - check_expected_int(optname); - - assert_non_null(optval); - assert_non_null(optlen); - assert_int_equal(*optlen, (int)sizeof(int)); - - out_value = mock_type(int); - rc = mock_type(int); - if (rc == 0) { - *(int *)optval = out_value; - *optlen = (int)sizeof(int); - } else { - WSASetLastError(mock_type(int)); - } - return rc; -} - -static int WSAAPI mock_recvfrom(SOCKET s, char *buf, int len, int flags, - struct sockaddr *from, int *fromlen) -{ - int rc; - - (void)from; - (void)fromlen; - - function_called(); - check_expected_uint(s); - check_expected_ptr(buf); - check_expected_int(len); - check_expected_int(flags); - - rc = mock_type(int); - if (rc == SOCKET_ERROR) - WSASetLastError(mock_type(int)); - return rc; -} - -/* expectations */ - -static void expect_getsockname_ok(void) -{ - expect_function_call(mock_getsockname); - expect_uint_value(mock_getsockname, s, FAKE_SOCKET); - will_return_int(mock_getsockname, 0); - will_return_ptr(mock_getsockname, (const struct sockaddr *)&g_sin); - will_return_int(mock_getsockname, (int)sizeof(g_sin)); -} - -static void expect_getpeername_fail(void) -{ - expect_function_call(mock_getpeername); - expect_uint_value(mock_getpeername, s, FAKE_SOCKET); - will_return_int(mock_getpeername, SOCKET_ERROR); - will_return_int(mock_getpeername, WSAENOTCONN); -} - -static void expect_setsockopt_int(int level, int optname, int value, int rc) -{ - expect_function_call(mock_setsockopt); - expect_uint_value(mock_setsockopt, s, FAKE_SOCKET); - expect_int_value(mock_setsockopt, level, level); - expect_int_value(mock_setsockopt, optname, optname); - expect_int_value(mock_setsockopt, optlen, (int)sizeof(int)); - will_return_int(mock_setsockopt, value); - will_return_int(mock_setsockopt, rc); - if (rc == SOCKET_ERROR) - will_return(mock_setsockopt, WSAEINVAL); -} - -static void expect_getsockopt_int(int level, int optname, int value, int rc) -{ - expect_function_call(mock_getsockopt); - expect_uint_value(mock_getsockopt, s, FAKE_SOCKET); - expect_int_value(mock_getsockopt, level, level); - expect_int_value(mock_getsockopt, optname, optname); - will_return_int(mock_getsockopt, value); - will_return_int(mock_getsockopt, rc); - if (rc == SOCKET_ERROR) - will_return_int(mock_getsockopt, WSAEINVAL); -} - -static void expect_recvfrom_error(char *buf, int len, int flags, int wsaerr) -{ - expect_function_call(mock_recvfrom); - expect_uint_value(mock_recvfrom, s, FAKE_SOCKET); - expect_value(mock_recvfrom, buf, buf); - expect_int_value(mock_recvfrom, len, len); - expect_int_value(mock_recvfrom, flags, flags); - will_return_int(mock_recvfrom, SOCKET_ERROR); - will_return_int(mock_recvfrom, wsaerr); -} - -/* detours */ - -static int attach_detours(void) -{ - if (DetourTransactionBegin() != NO_ERROR) - return 0; - if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) - return 0; - if (DetourAttach((PVOID *)&real_getsockname, mock_getsockname) != NO_ERROR) - return 0; - if (DetourAttach((PVOID *)&real_getpeername, mock_getpeername) != NO_ERROR) - return 0; - if (DetourAttach((PVOID *)&real_setsockopt, mock_setsockopt) != NO_ERROR) - return 0; - if (DetourAttach((PVOID *)&real_getsockopt, mock_getsockopt) != NO_ERROR) - return 0; - if (DetourAttach((PVOID *)&real_recvfrom, mock_recvfrom) != NO_ERROR) - return 0; - return DetourTransactionCommit() == NO_ERROR; -} - -static int detach_detours(void) -{ - if (DetourTransactionBegin() != NO_ERROR) - return 0; - if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) - return 0; - DetourDetach((PVOID *)&real_getsockname, mock_getsockname); - DetourDetach((PVOID *)&real_getpeername, mock_getpeername); - DetourDetach((PVOID *)&real_setsockopt, mock_setsockopt); - DetourDetach((PVOID *)&real_getsockopt, mock_getsockopt); - DetourDetach((PVOID *)&real_recvfrom, mock_recvfrom); - return DetourTransactionCommit() == NO_ERROR; -} - -/* setup / teardown */ - -static int setup_io(void **state) -{ - BIO *bio = BIO_new(BIO_s_datagram()); - - assert_non_null(bio); - expect_getsockname_ok(); - expect_getpeername_fail(); - BIO_set_fd(bio, (int)FAKE_SOCKET, BIO_NOCLOSE); - *state = bio; - return 0; -} - -static int teardown_io(void **state) -{ - if (*state != NULL) { - BIO *bio = *state; - - bio->num = (int)INVALID_SOCKET; - bio->shutdown = BIO_NOCLOSE; - BIO_free(bio); - } - return 0; -} - -static int group_setup(void **state) -{ - WSADATA wsa; - - (void)state; - memset(&g_sin, 0, sizeof(g_sin)); - g_sin.sin_family = AF_INET; - g_sin.sin_port = htons(443); - g_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - assert_int_equal(WSAStartup(MAKEWORD(2, 2), &wsa), 0); - assert_true(attach_detours()); - return 0; -} - -static int group_teardown(void **state) -{ - (void)state; - assert_true(detach_detours()); - WSACleanup(); - return 0; -} - -/* - * GATE: prove Detours intercepts a Winsock call made through the same - * import machinery the production library uses. If this fails, fix the - * linkage (e.g. DetourFindFunction on ws2_32.dll) before trusting any - * other test below. - */ -static void detour_probe(void **state) -{ - int val = -1; - int len = (int)sizeof(val); - int rc; - - (void)state; - g_probe_getsockopt_hits = 0; - g_probe_active = 1; - rc = getsockopt(FAKE_SOCKET, SOL_SOCKET, SO_TYPE, (char *)&val, &len); - g_probe_active = 0; - - assert_int_equal(rc, 0); - assert_int_equal(g_probe_getsockopt_hits, 1); -} - -/* SO_RCVTIMEO / SO_SNDTIMEO use int milliseconds on Windows. */ - -static void test_win_set_recv_timeout_uses_milliseconds(void **state) -{ - BIO *bio = *state; - struct timeval tv = { 1, 500000 }; - - expect_setsockopt_int(SOL_SOCKET, SO_RCVTIMEO, 1500, 0); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &tv), 0); -} - -static void test_win_get_recv_timeout_converts_milliseconds(void **state) -{ - BIO *bio = *state; - struct timeval tv; - - memset(&tv, 0, sizeof(tv)); - expect_getsockopt_int(SOL_SOCKET, SO_RCVTIMEO, 2500, 0); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_RECV_TIMEOUT, 0, &tv), - (int)sizeof(tv)); - assert_int_equal(tv.tv_sec, 2); - assert_int_equal(tv.tv_usec, 500000); -} - -static void test_win_set_send_timeout_uses_milliseconds(void **state) -{ - BIO *bio = *state; - struct timeval tv = { 3, 250000 }; - - expect_setsockopt_int(SOL_SOCKET, SO_SNDTIMEO, 3250, 0); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &tv), 0); -} - -static void test_win_get_send_timeout_converts_milliseconds(void **state) -{ - BIO *bio = *state; - struct timeval tv; - - memset(&tv, 0, sizeof(tv)); - expect_getsockopt_int(SOL_SOCKET, SO_SNDTIMEO, 4250, 0); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_SEND_TIMEOUT, 0, &tv), - (int)sizeof(tv)); - assert_int_equal(tv.tv_sec, 4); - assert_int_equal(tv.tv_usec, 250000); -} - -/* - * GET_RECV_TIMER_EXP checks data->_errno == WSAETIMEDOUT on Windows - * (EAGAIN elsewhere), then consumes/clears it. WSAETIMEDOUT is treated - * as fatal by BIO_dgram_non_fatal_error, so we set _errno directly - * rather than driving it through a recvfrom retry that never sets it. - */ -static void test_win_recv_timer_exp_consumes_errno(void **state) -{ - BIO *bio = *state; - bio_dgram_data *data = (bio_dgram_data *)bio->ptr; - - data->_errno = WSAETIMEDOUT; - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL), 1); - /* second read reports 0: the ctrl cleared _errno */ - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL), 0); -} - -/* - * A fatal recvfrom error (WSAECONNRESET) must NOT set a retry flag. - * This exercises the real Windows recvfrom signature through Detours. - */ -static void test_win_recvfrom_fatal_no_retry(void **state) -{ - BIO *bio = *state; - char buf[16]; - - memset(buf, 0, sizeof(buf)); - expect_recvfrom_error(buf, (int)sizeof(buf), 0, WSAECONNRESET); - assert_true(BIO_read(bio, buf, (int)sizeof(buf)) <= 0); - assert_false(BIO_should_retry(bio)); -} - -#if defined(IP_DONTFRAGMENT) -/* - * IPv4 don't-fragment falls to IP_DONTFRAGMENT on Windows. This branch - * is reached only when IP_DONTFRAG is NOT defined (it is the #elif). - */ -static void test_win_set_dont_frag_ipv4(void **state) -{ - BIO *bio = *state; - struct sockaddr_in peer; - - memset(&peer, 0, sizeof(peer)); - peer.sin_family = AF_INET; - peer.sin_port = htons(4433); - peer.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, &peer); - - expect_setsockopt_int(IPPROTO_IP, IP_DONTFRAGMENT, 1, 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_DONT_FRAG, 1, NULL), 0); -} -#endif - -#define DG_WIN(name) \ - cmocka_unit_test_setup_teardown(name, setup_io, teardown_io) - -int main(void) -{ - const struct CMUnitTest tests[] = { - DG_WIN(detour_probe), - DG_WIN(test_win_set_recv_timeout_uses_milliseconds), - DG_WIN(test_win_get_recv_timeout_converts_milliseconds), - DG_WIN(test_win_set_send_timeout_uses_milliseconds), - DG_WIN(test_win_get_send_timeout_converts_milliseconds), - DG_WIN(test_win_recv_timer_exp_consumes_errno), - DG_WIN(test_win_recvfrom_fatal_no_retry), -#if defined(IP_DONTFRAGMENT) - DG_WIN(test_win_set_dont_frag_ipv4), -#endif - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - return cmocka_run_group_tests(tests, group_setup, group_teardown); -} - -#endif diff --git a/test/unit/crypto/bio/test_bss_fd.c b/test/unit/crypto/bio/test_bss_fd.c deleted file mode 100644 index 3bb6b7d714..0000000000 --- a/test/unit/crypto/bio/test_bss_fd.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#ifdef OPENSSL_NO_POSIX_IO - -int main(void) -{ - return 0; -} - -#else - -#include -#include -#include -#include -#include - -#include "bio_local.h" - -#include - -#define FAKE_FD 42 - -/* wraps */ - -ssize_t __wrap_read(int fd, void *buf, size_t count); -ssize_t __wrap_write(int fd, const void *buf, size_t count); -off_t __wrap_lseek(int fd, off_t offset, int whence); -int __wrap_close(int fd); - -ssize_t __wrap_read(int fd, void *buf, size_t count) -{ - ssize_t rc; - - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - rc = mock_type(ssize_t); - if (rc <= 0) - errno = mock_type(int); - return rc; -} - -ssize_t __wrap_write(int fd, const void *buf, size_t count) -{ - ssize_t rc; - - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - rc = mock_type(ssize_t); - if (rc <= 0) - errno = mock_type(int); - return rc; -} - -off_t __wrap_lseek(int fd, off_t offset, int whence) -{ - function_called(); - check_expected(fd); - check_expected(offset); - check_expected(whence); - - return mock_type(off_t); -} - -int __wrap_close(int fd) -{ - function_called(); - check_expected(fd); - - return mock_type(int); -} - -/* expectations */ - -/* - * errnoval is consumed by __wrap_read only when rc <= 0; pass 0 for success - * calls where the value is irrelevant. - */ -static void expect_read(int fd, const void *buf, size_t count, ssize_t rc, - int errnoval) -{ - expect_function_call(__wrap_read); - expect_value(__wrap_read, fd, fd); - expect_value(__wrap_read, buf, buf); - expect_value(__wrap_read, count, count); - will_return(__wrap_read, rc); - if (rc <= 0) - will_return(__wrap_read, errnoval); -} - -static void expect_write(int fd, const void *buf, size_t count, ssize_t rc, - int errnoval) -{ - expect_function_call(__wrap_write); - expect_value(__wrap_write, fd, fd); - expect_value(__wrap_write, buf, buf); - expect_value(__wrap_write, count, count); - will_return(__wrap_write, rc); - if (rc <= 0) - will_return(__wrap_write, errnoval); -} - -static void expect_lseek(int fd, off_t offset, int whence, off_t rc) -{ - expect_function_call(__wrap_lseek); - expect_value(__wrap_lseek, fd, fd); - expect_value(__wrap_lseek, offset, offset); - expect_value(__wrap_lseek, whence, whence); - will_return(__wrap_lseek, rc); -} - -static void expect_close(int fd, int rc) -{ - expect_function_call(__wrap_close); - expect_value(__wrap_close, fd, fd); - will_return(__wrap_close, rc); -} - -/* setup / teardown */ - -static int setup(void **state) -{ - BIO *bio = BIO_new(BIO_s_fd()); - - assert_non_null(bio); - BIO_set_fd(bio, FAKE_FD, BIO_NOCLOSE); - *state = bio; - return 0; -} - -static int teardown(void **state) -{ - if (*state != NULL) - BIO_free(*state); - return 0; -} - -/* BIO_fd_non_fatal_error */ - -static void test_non_fatal_error_retryable(void **state) -{ - static const int errs[] = { -#ifdef EAGAIN - EAGAIN, -#endif -#ifdef EINTR - EINTR, -#endif -#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || EWOULDBLOCK != EAGAIN) - EWOULDBLOCK, -#endif -#ifdef EINPROGRESS - EINPROGRESS, -#endif -#ifdef EALREADY - EALREADY, -#endif -#ifdef ENOTCONN - ENOTCONN, -#endif -#ifdef EPROTO - EPROTO, -#endif - }; - size_t i; - - (void)state; - for (i = 0; i < sizeof(errs) / sizeof(errs[0]); i++) - assert_int_equal(BIO_fd_non_fatal_error(errs[i]), 1); -} - -static void test_non_fatal_error_fatal(void **state) -{ - (void)state; - assert_int_equal(BIO_fd_non_fatal_error(ENOENT), 0); - assert_int_equal(BIO_fd_non_fatal_error(EBADF), 0); - assert_int_equal(BIO_fd_non_fatal_error(0), 0); -} - -/* BIO_fd_should_retry */ - -static void test_should_retry_positive_i(void **state) -{ - /* i > 0: always returns 0 regardless of errno */ - (void)state; - errno = EAGAIN; - assert_int_equal(BIO_fd_should_retry(1), 0); - assert_int_equal(BIO_fd_should_retry(100), 0); -} - -static void test_should_retry_fatal_errno(void **state) -{ - (void)state; - errno = ENOENT; - assert_int_equal(BIO_fd_should_retry(-1), 0); - errno = ENOENT; - assert_int_equal(BIO_fd_should_retry(0), 0); -} - -static void test_should_retry_non_fatal_errno(void **state) -{ - (void)state; - errno = EAGAIN; - assert_int_equal(BIO_fd_should_retry(-1), 1); - errno = EINTR; - assert_int_equal(BIO_fd_should_retry(0), 1); -} - -/* fd_read (via BIO_read) */ - -static void test_fd_read_success(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_FD, buf, 8, 8, 0); - assert_int_equal(BIO_read(bio, buf, 8), 8); - assert_false(BIO_should_retry(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_fd_read_eof(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_FD, buf, 8, 0, 0); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_true(BIO_eof(bio)); - assert_false(BIO_should_retry(bio)); -} - -static void test_fd_read_retry(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_FD, buf, 8, -1, EAGAIN); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_true(BIO_should_retry(bio)); - assert_true(BIO_should_read(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_fd_read_error(void **state) -{ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_FD, buf, 8, -1, ENOENT); - assert_true(BIO_read(bio, buf, 8) <= 0); - assert_false(BIO_should_retry(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_fd_read_clears_eof(void **state) -{ - /* BIO_FLAGS_IN_EOF is cleared at the start of each new read attempt. */ - BIO *bio = *state; - char buf[1] = { 0 }; - - expect_read(FAKE_FD, buf, 1, 0, 0); - BIO_read(bio, buf, 1); - assert_true(BIO_eof(bio)); - - expect_read(FAKE_FD, buf, 1, 1, 0); - assert_int_equal(BIO_read(bio, buf, 1), 1); - assert_false(BIO_eof(bio)); -} - -/* fd_write (via BIO_write) */ - -static void test_fd_write_success(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_FD, buf, 5, 5, 0); - assert_int_equal(BIO_write(bio, buf, 5), 5); - assert_false(BIO_should_retry(bio)); -} - -static void test_fd_write_retry(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_FD, buf, 5, -1, EAGAIN); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_true(BIO_should_retry(bio)); - assert_true(BIO_should_write(bio)); -} - -static void test_fd_write_error(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_FD, buf, 5, -1, ENOSPC); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_false(BIO_should_retry(bio)); -} - -/* fd_ctrl (via BIO_ctrl) */ - -static void test_fd_ctrl_reset(void **state) -{ - BIO *bio = *state; - - /* RESET sets num=0 then falls through to FILE_SEEK: lseek(fd, 0, 0) */ - expect_lseek(FAKE_FD, 0, 0, 0); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL), 0); -} - -static void test_fd_ctrl_seek(void **state) -{ - BIO *bio = *state; - - expect_lseek(FAKE_FD, 512, 0, 512); - assert_int_equal(BIO_ctrl(bio, BIO_C_FILE_SEEK, 512, NULL), 512); -} - -static void test_fd_ctrl_tell(void **state) -{ - BIO *bio = *state; - - expect_lseek(FAKE_FD, 0, 1, 256); - assert_int_equal(BIO_ctrl(bio, BIO_C_FILE_TELL, 0, NULL), 256); -} - -static void test_fd_ctrl_info(void **state) -{ - BIO *bio = *state; - - /* BIO_CTRL_INFO shares the lseek(fd, 0, 1) branch with FILE_TELL */ - expect_lseek(FAKE_FD, 0, 1, 128); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_INFO, 0, NULL), 128); -} - -static void test_fd_ctrl_set_fd(void **state) -{ - BIO *bio = *state; - int newfd = 99; - - /* fd_free is called first; existing shutdown=BIO_NOCLOSE so no close */ - BIO_ctrl(bio, BIO_C_SET_FD, BIO_NOCLOSE, &newfd); - assert_int_equal(bio->num, 99); - assert_int_equal(bio->shutdown, BIO_NOCLOSE); - assert_int_equal(bio->init, 1); -} - -static void test_fd_ctrl_get_fd_init(void **state) -{ - BIO *bio = *state; - int out = -1; - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_FD, 0, &out), FAKE_FD); - assert_int_equal(out, FAKE_FD); -} - -static void test_fd_ctrl_get_fd_uninit(void **state) -{ - BIO *bio = *state; - - /* teardown is safe: shutdown=BIO_NOCLOSE guards the close call */ - bio->init = 0; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_FD, 0, NULL), -1); -} - -static void test_fd_ctrl_get_close(void **state) -{ - BIO *bio = *state; - - bio->shutdown = BIO_NOCLOSE; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_GET_CLOSE, 0, NULL), BIO_NOCLOSE); - bio->shutdown = BIO_CLOSE; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_GET_CLOSE, 0, NULL), BIO_CLOSE); - bio->shutdown = BIO_NOCLOSE; -} - -static void test_fd_ctrl_set_close(void **state) -{ - BIO *bio = *state; - - BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, BIO_CLOSE, NULL); - assert_int_equal(bio->shutdown, BIO_CLOSE); - /* Restore before teardown to avoid an unexpected close call. */ - BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, BIO_NOCLOSE, NULL); -} - -static void test_fd_ctrl_pending(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_PENDING, 0, NULL), 0); -} - -static void test_fd_ctrl_wpending(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_WPENDING, 0, NULL), 0); -} - -static void test_fd_ctrl_dup(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_DUP, 0, NULL), 1); -} - -static void test_fd_ctrl_flush(void **state) -{ - assert_int_equal(BIO_ctrl(*state, BIO_CTRL_FLUSH, 0, NULL), 1); -} - -static void test_fd_ctrl_eof_clear(void **state) -{ - BIO *bio = *state; - - bio->flags &= ~BIO_FLAGS_IN_EOF; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL), 0); -} - -static void test_fd_ctrl_eof_set(void **state) -{ - BIO *bio = *state; - - bio->flags |= BIO_FLAGS_IN_EOF; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL), 1); - bio->flags &= ~BIO_FLAGS_IN_EOF; -} - -static void test_fd_ctrl_default(void **state) -{ - assert_int_equal(BIO_ctrl(*state, 9999, 0, NULL), 0); -} - -/* fd_free (via BIO_free) */ - -static void test_fd_free_shutdown_with_init(void **state) -{ - /* shutdown=1 and init=1: close must be called */ - BIO *bio = BIO_new(BIO_s_fd()); - - assert_non_null(bio); - bio->num = FAKE_FD; - bio->shutdown = BIO_CLOSE; - bio->init = 1; - - expect_close(FAKE_FD, 0); - BIO_free(bio); - *state = NULL; -} - -static void test_fd_free_shutdown_no_init(void **state) -{ - /* shutdown=1 but init=0: close must NOT be called */ - BIO *bio = BIO_new(BIO_s_fd()); - - assert_non_null(bio); - bio->num = FAKE_FD; - bio->shutdown = BIO_CLOSE; - bio->init = 0; - - BIO_free(bio); - *state = NULL; -} - -static void test_fd_free_no_shutdown(void **state) -{ - /* shutdown=0: close must NOT be called regardless of init */ - BIO *bio = BIO_new(BIO_s_fd()); - - assert_non_null(bio); - bio->num = FAKE_FD; - bio->shutdown = BIO_NOCLOSE; - bio->init = 1; - - BIO_free(bio); - *state = NULL; -} - -/* fd_puts (via BIO_puts) */ - -static void test_fd_puts_success(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_write(FAKE_FD, str, 5, 5, 0); - assert_int_equal(BIO_puts(bio, str), 5); -} - -static void test_fd_puts_write_fails(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_write(FAKE_FD, str, 5, -1, ENOSPC); - assert_true(BIO_puts(bio, str) <= 0); -} - -/* - * fd_gets (via BIO_gets) - * - * fd_gets calls fd_read one byte at a time, which in turn calls read. - * The buffer is pre-filled with the data that each mocked read delivers, - * since __wrap_read returns the count without writing into the buffer. - */ - -static void test_fd_gets_size_one(void **state) -{ - /* end == buf when size=1, so the loop body never executes */ - BIO *bio = *state; - char buf[4] = { 0 }; - - assert_int_equal(BIO_gets(bio, buf, 1), 0); - assert_int_equal(buf[0], '\0'); -} - -static void test_fd_gets_newline_terminates(void **state) -{ - BIO *bio = *state; - char buf[8] = { 'h', 'i', '\n' }; - - expect_read(FAKE_FD, buf, 1, 1, 0); - expect_read(FAKE_FD, buf + 1, 1, 1, 0); - expect_read(FAKE_FD, buf + 2, 1, 1, 0); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), 3); - assert_memory_equal(buf, "hi\n", 4); -} - -static void test_fd_gets_fills_to_limit(void **state) -{ - /* size=4: reads at most 3 chars (buf+3 is the null slot) */ - BIO *bio = *state; - char buf[4] = { 'a', 'b', 'c' }; - - expect_read(FAKE_FD, buf, 1, 1, 0); - expect_read(FAKE_FD, buf + 1, 1, 1, 0); - expect_read(FAKE_FD, buf + 2, 1, 1, 0); - - assert_int_equal(BIO_gets(bio, buf, 4), 3); - assert_memory_equal(buf, "abc", 4); -} - -static void test_fd_gets_eof_mid_line(void **state) -{ - /* read returns 0 after the first byte: return what was read */ - BIO *bio = *state; - char buf[8] = { 'z' }; - - expect_read(FAKE_FD, buf, 1, 1, 0); - expect_read(FAKE_FD, buf + 1, 1, 0, 0); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), 1); - assert_memory_equal(buf, "z", 2); -} - -static void test_fd_gets_immediate_eof(void **state) -{ - /* First read returns 0: returns 0 and buf[0] is '\0' */ - BIO *bio = *state; - char buf[8] = { 0 }; - - expect_read(FAKE_FD, buf, 1, 0, 0); - - assert_int_equal(BIO_gets(bio, buf, sizeof(buf)), 0); - assert_int_equal(buf[0], '\0'); -} - -/* main */ - -#define FD_TEST(name) \ - cmocka_unit_test_setup_teardown(name, setup, teardown) - -#define FD_TEST_PLAIN(name) \ - cmocka_unit_test(name) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* BIO_fd_non_fatal_error */ - FD_TEST_PLAIN(test_non_fatal_error_retryable), - FD_TEST_PLAIN(test_non_fatal_error_fatal), - /* BIO_fd_should_retry */ - FD_TEST_PLAIN(test_should_retry_positive_i), - FD_TEST_PLAIN(test_should_retry_fatal_errno), - FD_TEST_PLAIN(test_should_retry_non_fatal_errno), - /* fd_read */ - FD_TEST(test_fd_read_success), - FD_TEST(test_fd_read_eof), - FD_TEST(test_fd_read_retry), - FD_TEST(test_fd_read_error), - FD_TEST(test_fd_read_clears_eof), - /* fd_write */ - FD_TEST(test_fd_write_success), - FD_TEST(test_fd_write_retry), - FD_TEST(test_fd_write_error), - /* fd_ctrl */ - FD_TEST(test_fd_ctrl_reset), - FD_TEST(test_fd_ctrl_seek), - FD_TEST(test_fd_ctrl_tell), - FD_TEST(test_fd_ctrl_info), - FD_TEST(test_fd_ctrl_set_fd), - FD_TEST(test_fd_ctrl_get_fd_init), - FD_TEST(test_fd_ctrl_get_fd_uninit), - FD_TEST(test_fd_ctrl_get_close), - FD_TEST(test_fd_ctrl_set_close), - FD_TEST(test_fd_ctrl_pending), - FD_TEST(test_fd_ctrl_wpending), - FD_TEST(test_fd_ctrl_dup), - FD_TEST(test_fd_ctrl_flush), - FD_TEST(test_fd_ctrl_eof_clear), - FD_TEST(test_fd_ctrl_eof_set), - FD_TEST(test_fd_ctrl_default), - /* fd_free */ - FD_TEST(test_fd_free_shutdown_with_init), - FD_TEST(test_fd_free_shutdown_no_init), - FD_TEST(test_fd_free_no_shutdown), - /* fd_puts */ - FD_TEST(test_fd_puts_success), - FD_TEST(test_fd_puts_write_fails), - /* fd_gets */ - FD_TEST(test_fd_gets_size_one), - FD_TEST(test_fd_gets_newline_terminates), - FD_TEST(test_fd_gets_fills_to_limit), - FD_TEST(test_fd_gets_eof_mid_line), - FD_TEST(test_fd_gets_immediate_eof), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#endif /* OPENSSL_NO_POSIX_IO */ diff --git a/test/unit/crypto/bio/test_bss_sock.c b/test/unit/crypto/bio/test_bss_sock.c deleted file mode 100644 index 8d5aa547f0..0000000000 --- a/test/unit/crypto/bio/test_bss_sock.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/sockets.h" - -#ifndef OPENSSL_NO_SOCK - -#include -#include -#include -#include -#include -#include -#include -#include "bio_local.h" -#include "internal/bio_tfo.h" -#include - -#define FAKE_SOCKET 42 - -/* prototypes for __wrap_* (required by -Wmissing-prototypes) */ -ssize_t __wrap_read(int fd, void *buf, size_t count); -ssize_t __wrap_write(int fd, const void *buf, size_t count); -int __wrap_BIO_closesocket(int fd); - -/* wraps */ - -ssize_t __wrap_read(int fd, void *buf, size_t count) -{ - ssize_t rc; - - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - rc = mock_type(ssize_t); - if (rc < 0) - errno = mock_type(int); - return rc; -} - -ssize_t __wrap_write(int fd, const void *buf, size_t count) -{ - ssize_t rc; - - function_called(); - check_expected(fd); - check_expected_ptr(buf); - check_expected(count); - rc = mock_type(ssize_t); - if (rc < 0) - errno = mock_type(int); - return rc; -} - -int __wrap_BIO_closesocket(int fd) -{ - function_called(); - check_expected(fd); - return mock_type(int); -} - -/* expectations */ - -static void expect_read(int fd, const void *buf, size_t count, ssize_t rc, - int errnoval) -{ - expect_function_call(__wrap_read); - expect_value(__wrap_read, fd, fd); - expect_value(__wrap_read, buf, buf); - expect_value(__wrap_read, count, count); - will_return(__wrap_read, rc); - if (rc < 0) - will_return(__wrap_read, errnoval); -} - -static void expect_write(int fd, const void *buf, size_t count, ssize_t rc, - int errnoval) -{ - expect_function_call(__wrap_write); - expect_value(__wrap_write, fd, fd); - expect_value(__wrap_write, buf, buf); - expect_value(__wrap_write, count, count); - will_return(__wrap_write, rc); - if (rc < 0) - will_return(__wrap_write, errnoval); -} - -static void expect_BIO_closesocket(int fd, int rc) -{ - expect_function_call(__wrap_BIO_closesocket); - expect_value(__wrap_BIO_closesocket, fd, fd); - will_return(__wrap_BIO_closesocket, rc); -} - -/* setup / teardown */ - -static int setup(void **state) -{ - BIO *bio = BIO_new(BIO_s_socket()); - - assert_non_null(bio); - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - *state = bio; - return 0; -} - -static int teardown(void **state) -{ - if (*state != NULL) - BIO_free(*state); - return 0; -} - -/* sock_new defaults */ - -static void test_sock_new_defaults(void **state) -{ - /* fresh BIO before BIO_set_fd: init 0, num 0, ptr allocated */ - BIO *bio = BIO_new(BIO_s_socket()); - - (void)state; - assert_non_null(bio); - assert_int_equal(bio->init, 0); - assert_int_equal(bio->num, 0); - assert_non_null(bio->ptr); - BIO_free(bio); -} - -/* BIO_new_socket */ - -static void test_new_socket(void **state) -{ - int out = -1; - BIO *bio = BIO_new_socket(FAKE_SOCKET, BIO_NOCLOSE); - - (void)state; - assert_non_null(bio); - assert_int_equal(bio->init, 1); - assert_int_equal(BIO_get_fd(bio, &out), FAKE_SOCKET); - assert_int_equal(out, FAKE_SOCKET); - BIO_free(bio); -} - -/* sock_read */ - -static void test_sock_read_noop(void **state) -{ - /* outl == 0: readsocket is never reached */ - BIO *bio = *state; - char buf[1]; - - assert_int_equal(BIO_read(bio, buf, 0), 0); -} - -static void test_sock_read_success(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 16, 4, 0); - assert_int_equal(BIO_read(bio, buf, sizeof(buf)), 4); - assert_false(BIO_should_retry(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_sock_read_eof(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 16, 0, 0); - assert_true(BIO_read(bio, buf, sizeof(buf)) <= 0); - assert_true(BIO_eof(bio)); - assert_false(BIO_should_retry(bio)); -} - -static void test_sock_read_retry(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 16, -1, EAGAIN); - assert_true(BIO_read(bio, buf, sizeof(buf)) <= 0); - assert_true(BIO_should_read(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_sock_read_error(void **state) -{ - BIO *bio = *state; - char buf[16] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 16, -1, ECONNREFUSED); - assert_true(BIO_read(bio, buf, sizeof(buf)) <= 0); - assert_false(BIO_should_retry(bio)); - assert_false(BIO_eof(bio)); -} - -static void test_sock_read_clears_eof(void **state) -{ - /* BIO_FLAGS_IN_EOF is cleared at the start of each new read attempt */ - BIO *bio = *state; - char buf[1] = { 0 }; - - expect_read(FAKE_SOCKET, buf, 1, 0, 0); - BIO_read(bio, buf, 1); - assert_true(BIO_eof(bio)); - - expect_read(FAKE_SOCKET, buf, 1, 1, 0); - assert_int_equal(BIO_read(bio, buf, 1), 1); - assert_false(BIO_eof(bio)); -} - -/* sock_write */ - -static void test_sock_write_success(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_SOCKET, buf, 5, 5, 0); - assert_int_equal(BIO_write(bio, buf, 5), 5); - assert_false(BIO_should_retry(bio)); -} - -static void test_sock_write_retry(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_SOCKET, buf, 5, -1, EAGAIN); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_true(BIO_should_write(bio)); -} - -static void test_sock_write_error(void **state) -{ - BIO *bio = *state; - const char buf[] = "hello"; - - expect_write(FAKE_SOCKET, buf, 5, -1, ECONNREFUSED); - assert_true(BIO_write(bio, buf, 5) <= 0); - assert_false(BIO_should_retry(bio)); -} - -/* sock_ctrl */ - -static void test_ctrl_get_fd(void **state) -{ - BIO *bio = *state; - int out = -1; - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_FD, 0, &out), FAKE_SOCKET); - assert_int_equal(out, FAKE_SOCKET); -} - -static void test_ctrl_get_fd_uninit(void **state) -{ - BIO *bio = *state; - - bio->init = 0; - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_FD, 0, NULL), -1); - bio->init = 1; -} - -static void test_ctrl_set_fd(void **state) -{ - BIO *bio = *state; - int newfd = 99; - - /* existing shutdown=BIO_NOCLOSE so the old fd is not closed */ - BIO_ctrl(bio, BIO_C_SET_FD, BIO_NOCLOSE, &newfd); - assert_int_equal(bio->num, 99); - assert_int_equal(bio->shutdown, BIO_NOCLOSE); - assert_int_equal(bio->init, 1); -} - -static void test_ctrl_get_set_close(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_GET_CLOSE, 0, NULL), BIO_NOCLOSE); - BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, BIO_CLOSE, NULL); - assert_int_equal(bio->shutdown, BIO_CLOSE); - bio->shutdown = BIO_NOCLOSE; -} - -static void test_ctrl_dup_flush(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_DUP, 0, NULL), 1); - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL), 1); -} - -static void test_ctrl_rpoll_descriptor(void **state) -{ - BIO *bio = *state; - BIO_POLL_DESCRIPTOR pd; - - memset(&pd, 0, sizeof(pd)); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_GET_RPOLL_DESCRIPTOR, 0, &pd), 1); - assert_int_equal(pd.type, BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD); - assert_int_equal(pd.value.fd, FAKE_SOCKET); -} - -static void test_ctrl_wpoll_descriptor(void **state) -{ - BIO *bio = *state; - BIO_POLL_DESCRIPTOR pd; - - memset(&pd, 0, sizeof(pd)); - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_GET_WPOLL_DESCRIPTOR, 0, &pd), 1); - assert_int_equal(pd.type, BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD); - assert_int_equal(pd.value.fd, FAKE_SOCKET); -} - -static void test_ctrl_poll_descriptor_uninit(void **state) -{ - BIO *bio = *state; - BIO_POLL_DESCRIPTOR pd; - - memset(&pd, 0, sizeof(pd)); - bio->init = 0; - assert_int_equal( - BIO_ctrl(bio, BIO_CTRL_GET_RPOLL_DESCRIPTOR, 0, &pd), 0); - bio->init = 1; -} - -static void test_ctrl_eof_clear(void **state) -{ - BIO *bio = *state; - - bio->flags &= ~BIO_FLAGS_IN_EOF; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL), 0); -} - -static void test_ctrl_eof_set(void **state) -{ - BIO *bio = *state; - - bio->flags |= BIO_FLAGS_IN_EOF; - assert_int_equal(BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL), 1); - bio->flags &= ~BIO_FLAGS_IN_EOF; -} - -static void test_ctrl_get_connect(void **state) -{ - /* num==2: returns a pointer to the stored tfo_peer */ - BIO *bio = *state; - const char *ptr = NULL; - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 2, &ptr), 1); - assert_non_null(ptr); -} - -static void test_ctrl_get_connect_bad_num(void **state) -{ - BIO *bio = *state; - const char *ptr = NULL; - - assert_int_equal(BIO_ctrl(bio, BIO_C_GET_CONNECT, 0, &ptr), 0); -} - -static void test_ctrl_set_connect(void **state) -{ - BIO *bio = *state; - struct sockaddr_in sa; - BIO_ADDR addr; - - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(4433); - sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - assert_true(BIO_ADDR_make(&addr, (const struct sockaddr *)&sa)); - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 2, &addr), 1); -} - -static void test_ctrl_set_connect_bad_num(void **state) -{ - BIO *bio = *state; - BIO_ADDR addr; - - memset(&addr, 0, sizeof(addr)); - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, &addr), 0); -} - -static void test_ctrl_set_send_flags(void **state) -{ - BIO *bio = *state; - - assert_int_equal(BIO_ctrl(bio, BIO_C_SET_SEND_FLAGS, 0, NULL), 1); -} - -static void test_ctrl_default(void **state) -{ - assert_int_equal(BIO_ctrl(*state, 9999, 0, NULL), 0); -} - -/* sock_puts */ - -static void test_sock_puts_success(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_write(FAKE_SOCKET, str, 5, 5, 0); - assert_int_equal(BIO_puts(bio, str), 5); -} - -static void test_sock_puts_write_fails(void **state) -{ - BIO *bio = *state; - const char *str = "hello"; - - expect_write(FAKE_SOCKET, str, 5, -1, ECONNREFUSED); - assert_true(BIO_puts(bio, str) <= 0); -} - -/* sock_free (via BIO_free) - mostly just coverage for ASAN */ - -static void test_free_closes_when_shutdown(void **state) -{ - BIO *bio = BIO_new(BIO_s_socket()); - - (void)state; - assert_non_null(bio); - BIO_set_fd(bio, FAKE_SOCKET, BIO_CLOSE); - - expect_BIO_closesocket(FAKE_SOCKET, 0); - BIO_free(bio); -} - -static void test_free_no_close_when_noclose(void **state) -{ - BIO *bio = BIO_new(BIO_s_socket()); - - (void)state; - assert_non_null(bio); - BIO_set_fd(bio, FAKE_SOCKET, BIO_NOCLOSE); - BIO_free(bio); -} - -static void test_free_no_close_when_uninit(void **state) -{ - /* shutdown set but init==0: closesocket must NOT be called */ - BIO *bio = BIO_new(BIO_s_socket()); - - (void)state; - assert_non_null(bio); - bio->num = FAKE_SOCKET; - bio->shutdown = BIO_CLOSE; - bio->init = 0; - BIO_free(bio); -} - -/* main */ - -#define SOCK_TEST(name) \ - cmocka_unit_test_setup_teardown(name, setup, teardown) - -#define SOCK_TEST_PLAIN(name) \ - cmocka_unit_test(name) - -int main(void) -{ - const struct CMUnitTest tests[] = { - /* sock_new / BIO_new_socket */ - SOCK_TEST_PLAIN(test_sock_new_defaults), - SOCK_TEST_PLAIN(test_new_socket), - /* sock_read */ - SOCK_TEST(test_sock_read_noop), - SOCK_TEST(test_sock_read_success), - SOCK_TEST(test_sock_read_eof), - SOCK_TEST(test_sock_read_retry), - SOCK_TEST(test_sock_read_error), - SOCK_TEST(test_sock_read_clears_eof), - /* sock_write */ - SOCK_TEST(test_sock_write_success), - SOCK_TEST(test_sock_write_retry), - SOCK_TEST(test_sock_write_error), - /* sock_ctrl */ - SOCK_TEST(test_ctrl_get_fd), - SOCK_TEST(test_ctrl_get_fd_uninit), - SOCK_TEST(test_ctrl_set_fd), - SOCK_TEST(test_ctrl_get_set_close), - SOCK_TEST(test_ctrl_dup_flush), - SOCK_TEST(test_ctrl_rpoll_descriptor), - SOCK_TEST(test_ctrl_wpoll_descriptor), - SOCK_TEST(test_ctrl_poll_descriptor_uninit), - SOCK_TEST(test_ctrl_eof_clear), - SOCK_TEST(test_ctrl_eof_set), - SOCK_TEST(test_ctrl_get_connect), - SOCK_TEST(test_ctrl_get_connect_bad_num), - SOCK_TEST(test_ctrl_set_connect), - SOCK_TEST(test_ctrl_set_connect_bad_num), - SOCK_TEST(test_ctrl_set_send_flags), - SOCK_TEST(test_ctrl_default), - /* sock_puts */ - SOCK_TEST(test_sock_puts_success), - SOCK_TEST(test_sock_puts_write_fails), - /* sock_free */ - SOCK_TEST(test_free_closes_when_shutdown), - SOCK_TEST(test_free_no_close_when_noclose), - SOCK_TEST(test_free_no_close_when_uninit), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#else - -int main(void) -{ - return 0; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/test/v3ext.c b/test/v3ext.c index e2b6441197..2e852804ee 100644 --- a/test/v3ext.c +++ b/test/v3ext.c @@ -417,595 +417,6 @@ static int test_ext_syntax(void) return testresult; } -/* - * Number of entries the large-canonize regression tests construct. - * Chosen well above the legacy 4096 cap and large enough that the - * previous O(N^2) merge would be visibly slow under any sanitiser - * configuration, while still small enough to keep CI cost negligible - * with the linear merge. - */ -#define V3EXT_TEST_LARGE_N 8192 - -/* - * Build an ASIdentifiers extension containing V3EXT_TEST_LARGE_N - * adjacent single integers (1, 2, 3, ...), exercise canonize, and - * verify that the entire list collapses to one ASIdOrRange_range and - * that the post-canonize result reports canonical. Stresses the - * linear merge path that replaced the quadratic in-place delete. - */ -static int test_asid_large_canonize_merge(void) -{ - ASIdentifiers *asid = NULL; - ASN1_INTEGER *val = NULL; - int i; - int testresult = 0; - - if (!TEST_ptr(asid = ASIdentifiers_new())) - goto err; - - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - if (!TEST_ptr(val = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(val, (int64_t)(i + 1)))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - val, NULL))) - goto err; - /* Ownership of val transferred on success. */ - val = NULL; - } - - if (!TEST_int_eq(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges), - V3EXT_TEST_LARGE_N)) - goto err; - - if (!TEST_true(X509v3_asid_canonize(asid))) - goto err; - - /* The whole list must collapse to a single merged range [1, N]. */ - if (!TEST_int_eq(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges), 1)) - goto err; - { - ASIdOrRange *aor = sk_ASIdOrRange_value(asid->asnum->u.asIdsOrRanges, - 0); - int64_t got_min = 0, got_max = 0; - - if (!TEST_ptr(aor) || !TEST_int_eq(aor->type, ASIdOrRange_range)) - goto err; - if (!TEST_true(ASN1_INTEGER_get_int64(&got_min, aor->u.range->min)) - || !TEST_int64_t_eq(got_min, 1) - || !TEST_true(ASN1_INTEGER_get_int64(&got_max, aor->u.range->max)) - || !TEST_int64_t_eq(got_max, (int64_t)V3EXT_TEST_LARGE_N)) - goto err; - } - - if (!TEST_int_eq(X509v3_asid_is_canonical(asid), 1)) - goto err; - - testresult = 1; -err: - ASN1_INTEGER_free(val); - ASIdentifiers_free(asid); - return testresult; -} - -/* - * Build an ASIdentifiers extension containing V3EXT_TEST_LARGE_N - * non-mergeable single integers (1, 3, 5, ...). After canonize the - * list must be unchanged in length, every entry must remain an id - * with its original value (none silently merged or transformed), and - * is_canonical must report canonical -- i.e. the large list is - * accepted on its merits with no arbitrary cap kicking in. - */ -static int test_asid_large_canonize_no_merge(void) -{ - ASIdentifiers *asid = NULL; - ASN1_INTEGER *val = NULL; - int i; - int testresult = 0; - - if (!TEST_ptr(asid = ASIdentifiers_new())) - goto err; - - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - if (!TEST_ptr(val = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(val, (int64_t)(2 * i + 1)))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - val, NULL))) - goto err; - val = NULL; - } - - if (!TEST_true(X509v3_asid_canonize(asid))) - goto err; - - if (!TEST_int_eq(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges), - V3EXT_TEST_LARGE_N)) - goto err; - - /* - * Every entry must still be a single id with its original value; - * adjacent ids should NOT have been merged. - */ - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - ASIdOrRange *aor = sk_ASIdOrRange_value(asid->asnum->u.asIdsOrRanges, - i); - int64_t got = 0; - - if (!TEST_ptr(aor) - || !TEST_int_eq(aor->type, ASIdOrRange_id) - || !TEST_true(ASN1_INTEGER_get_int64(&got, aor->u.id)) - || !TEST_int64_t_eq(got, (int64_t)(2 * i + 1))) - goto err; - } - - if (!TEST_int_eq(X509v3_asid_is_canonical(asid), 1)) - goto err; - - testresult = 1; -err: - ASN1_INTEGER_free(val); - ASIdentifiers_free(asid); - return testresult; -} - -/* - * Build an IPAddrBlocks with a single IPv4 family carrying - * V3EXT_TEST_LARGE_N adjacent /32 host prefixes starting at 1.0.0.1 - * (deliberately offset by one from the prefix-aligned 1.0.0.0 so the - * merged span [1.0.0.1, 1.0.32.0] cannot be expressed as a single - * prefix and stays an IPAddressOrRange_addressRange). After canonize - * the family must contain exactly one IPAddressOrRange of type - * addressRange covering the whole block, and is_canonical must - * accept it. Stresses the linear merge path in v3_addr.c. - */ -static int test_addr_large_canonize_merge(void) -{ - IPAddrBlocks *addr = NULL; - int i; - int testresult = 0; - - if (!TEST_ptr(addr = sk_IPAddressFamily_new_null())) - goto end; - - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - unsigned char ip[4]; - unsigned int v = 0x01000001u + (unsigned int)i; /* 1.0.0.1 + i */ - - ip[0] = (unsigned char)((v >> 24) & 0xFF); - ip[1] = (unsigned char)((v >> 16) & 0xFF); - ip[2] = (unsigned char)((v >> 8) & 0xFF); - ip[3] = (unsigned char)(v & 0xFF); - if (!TEST_true(X509v3_addr_add_prefix(addr, IANA_AFI_IPV4, NULL, - ip, 32))) - goto end; - } - - if (!TEST_true(X509v3_addr_canonize(addr))) - goto end; - - if (!TEST_int_eq(sk_IPAddressFamily_num(addr), 1)) - goto end; - { - IPAddressFamily *f = sk_IPAddressFamily_value(addr, 0); - IPAddressOrRange *aor; - unsigned char got_min[4], got_max[4]; - unsigned int expected_max = 0x01000001u + V3EXT_TEST_LARGE_N - 1; - unsigned char want_min[4] = { 0x01, 0x00, 0x00, 0x01 }; - unsigned char want_max[4]; - - want_max[0] = (unsigned char)((expected_max >> 24) & 0xFF); - want_max[1] = (unsigned char)((expected_max >> 16) & 0xFF); - want_max[2] = (unsigned char)((expected_max >> 8) & 0xFF); - want_max[3] = (unsigned char)(expected_max & 0xFF); - - if (!TEST_ptr(f) - || !TEST_int_eq(f->ipAddressChoice->type, - IPAddressChoice_addressesOrRanges) - || !TEST_int_eq(sk_IPAddressOrRange_num( - f->ipAddressChoice->u.addressesOrRanges), - 1)) - goto end; - - aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges, - 0); - if (!TEST_ptr(aor) - || !TEST_int_eq(aor->type, IPAddressOrRange_addressRange)) - goto end; - if (!TEST_int_eq(X509v3_addr_get_range(aor, IANA_AFI_IPV4, - got_min, got_max, sizeof(got_min)), - 4) - || !TEST_mem_eq(got_min, 4, want_min, 4) - || !TEST_mem_eq(got_max, 4, want_max, 4)) - goto end; - } - - if (!TEST_int_eq(X509v3_addr_is_canonical(addr), 1)) - goto end; - - testresult = 1; -end: - sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); - return testresult; -} - -/* - * Interleaved merge / no-merge pattern, exercising the slide-forward - * arm of the linear-sweep compaction in ASIdentifierChoice_canonize. - * - * We build pairs of adjacent integers separated by gaps: (1, 2), (5, 6), - * (9, 10), ... Each pair merges to a single range, so the canonical - * output has exactly V3EXT_TEST_LARGE_N / 2 entries. Critically, after - * the second element of every pair merges into the first the merge - * loop's `write` index falls behind `read`; the *next* (non-mergeable) - * pair-start must then be slid forward into slot `write` and the source - * slot at `read` must be NULL'd. This is the path with no coverage in - * the all-merge or all-no-merge tests. - */ -static int test_asid_interleaved_canonize(void) -{ - ASIdentifiers *asid = NULL; - ASN1_INTEGER *val = NULL; - int i; - int expected = V3EXT_TEST_LARGE_N / 2; - int testresult = 0; - - if (!TEST_ptr(asid = ASIdentifiers_new())) - goto err; - - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - /* Pair starts at 4*p, then 4*p+1; the next pair starts at 4*(p+1). */ - int pair = i / 2; - int within = i % 2; - int64_t v = 4 * (int64_t)pair + within + 1; - - if (!TEST_ptr(val = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(val, v))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - val, NULL))) - goto err; - val = NULL; - } - - if (!TEST_true(X509v3_asid_canonize(asid))) - goto err; - - if (!TEST_int_eq(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges), - expected)) - goto err; - - /* Every entry must now be a 2-wide range (the merge result of a pair). */ - for (i = 0; i < expected; i++) { - ASIdOrRange *aor = sk_ASIdOrRange_value(asid->asnum->u.asIdsOrRanges, i); - - if (!TEST_ptr(aor) || !TEST_int_eq(aor->type, ASIdOrRange_range)) - goto err; - } - - if (!TEST_int_eq(X509v3_asid_is_canonical(asid), 1)) - goto err; - - testresult = 1; -err: - ASN1_INTEGER_free(val); - ASIdentifiers_free(asid); - return testresult; -} - -/* - * IP-address counterpart to test_asid_interleaved_canonize: pairs of - * adjacent /32 prefixes separated by a gap of 2, so each pair merges - * but the next pair-start must be slid forward. - */ -static int test_addr_interleaved_canonize(void) -{ - IPAddrBlocks *addr = NULL; - int i; - int expected = V3EXT_TEST_LARGE_N / 2; - int testresult = 0; - - if (!TEST_ptr(addr = sk_IPAddressFamily_new_null())) - goto end; - - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - unsigned char ip[4]; - unsigned int pair = (unsigned int)(i / 2); - unsigned int within = (unsigned int)(i % 2); - unsigned int v = 0x01000000u + 4u * pair + within; - - ip[0] = (unsigned char)((v >> 24) & 0xFF); - ip[1] = (unsigned char)((v >> 16) & 0xFF); - ip[2] = (unsigned char)((v >> 8) & 0xFF); - ip[3] = (unsigned char)(v & 0xFF); - if (!TEST_true(X509v3_addr_add_prefix(addr, IANA_AFI_IPV4, NULL, - ip, 32))) - goto end; - } - - if (!TEST_true(X509v3_addr_canonize(addr))) - goto end; - - if (!TEST_int_eq(sk_IPAddressFamily_num(addr), 1)) - goto end; - { - IPAddressFamily *f = sk_IPAddressFamily_value(addr, 0); - - if (!TEST_ptr(f) - || !TEST_int_eq(f->ipAddressChoice->type, - IPAddressChoice_addressesOrRanges) - || !TEST_int_eq(sk_IPAddressOrRange_num( - f->ipAddressChoice->u.addressesOrRanges), - expected)) - goto end; - } - - if (!TEST_int_eq(X509v3_addr_is_canonical(addr), 1)) - goto end; - - testresult = 1; -end: - sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); - return testresult; -} - -/* - * Trigger an overlap-detection error partway through the linear - * merge. The first V3EXT_TEST_LARGE_N / 2 entries are adjacent and - * mergeable; entry K is a duplicate of entry K-1 (overlap). The - * canonize call must return 0, and the caller's normal teardown of - * the choice must safely free the stack -- some slots hold merged - * results, some hold NULL (from earlier merges), and some hold - * originals that the loop never reached. ASan / UBSan-instrumented - * builds will catch any double-free or use-after-free in the - * teardown that the mixed-state-on-error invariant claims to avoid. - */ -static int test_asid_canonize_error_midsweep(void) -{ - ASIdentifiers *asid = NULL; - ASN1_INTEGER *val = NULL; - int i; - int n = V3EXT_TEST_LARGE_N; - int k = n / 2; - int testresult = 0; - - if (!TEST_ptr(asid = ASIdentifiers_new())) - goto err; - - for (i = 0; i < n; i++) { - /* - * Entries 1..k are 1,2,...,k (all adjacent). - * Entry k+1 duplicates entry k (overlap, triggers the error). - * Remaining entries are far away so they sort after the overlap. - */ - int64_t v; - - if (i < k) - v = (int64_t)i + 1; - else if (i == k) - v = (int64_t)k; /* duplicate, overlap */ - else - v = (int64_t)i + 1000000; /* far suffix, untouched */ - - if (!TEST_ptr(val = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(val, v))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - val, NULL))) - goto err; - val = NULL; - } - - /* canonize must reject overlap. */ - if (!TEST_int_eq(X509v3_asid_canonize(asid), 0)) - goto err; - - /* - * Successful return below relies on ASIdentifiers_free walking - * the partially-compacted stack without UAF or double-free. - * Under ASan / UBSan that walk is the actual test. - */ - testresult = 1; -err: - ASN1_INTEGER_free(val); - ASIdentifiers_free(asid); - return testresult; -} - -/* - * Trigger an overlap-detection error partway through the linear merge - * in IPAddressOrRanges_canonize. Construct a list whose first half is - * adjacent and mergeable, with a duplicate at position k that hits the - * overlap check after a series of merges has driven write < read. - * The canonize call must return 0, and the family's normal teardown - * (sk_IPAddressFamily_pop_free) must safely walk the partially - * compacted stack -- ASan / UBSan catches any double-free or UAF the - * mixed-state-on-error invariant would otherwise miss. Because the - * v3_addr.c canonize uses direct `return 0` rather than a `done:` - * cleanup label, the teardown invariant for this file is different - * from the asid path and warrants its own coverage. - */ -static int test_addr_canonize_error_midsweep(void) -{ - IPAddrBlocks *addr = NULL; - int i; - int n = V3EXT_TEST_LARGE_N; - int k = n / 2; - int testresult = 0; - - if (!TEST_ptr(addr = sk_IPAddressFamily_new_null())) - goto end; - - for (i = 0; i < n; i++) { - unsigned char ip[4]; - unsigned int v; - - if (i < k) - v = 0x01000000u + (unsigned int)i; /* adjacent /32 prefixes */ - else if (i == k) - v = 0x01000000u + (unsigned int)(k - 1); /* duplicate, overlap */ - else - v = 0x02000000u + (unsigned int)i; /* far suffix, untouched */ - - ip[0] = (unsigned char)((v >> 24) & 0xFF); - ip[1] = (unsigned char)((v >> 16) & 0xFF); - ip[2] = (unsigned char)((v >> 8) & 0xFF); - ip[3] = (unsigned char)(v & 0xFF); - if (!TEST_true(X509v3_addr_add_prefix(addr, IANA_AFI_IPV4, NULL, - ip, 32))) - goto end; - } - - /* canonize must reject overlap. */ - if (!TEST_int_eq(X509v3_addr_canonize(addr), 0)) - goto end; - - /* - * Successful return below relies on sk_IPAddressFamily_pop_free - * walking the partially-compacted aors stack without UAF or - * double-free. Under ASan / UBSan that walk is the actual test. - */ - testresult = 1; -end: - sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); - return testresult; -} - -/* - * Exercise the merge arm where `cur` is itself a range (rather than a - * single integer), hitting the `case ASIdOrRange_range` detach branch - * in ASIdentifierChoice_canonize. Build adjacent 2-wide ranges - * [1,2], [3,4], [5,6], ... which all fold into a single big range - * [1, 2 * V3EXT_TEST_LARGE_N]. - */ -static int test_asid_range_merge_canonize(void) -{ - ASIdentifiers *asid = NULL; - ASN1_INTEGER *minv = NULL, *maxv = NULL; - int i; - int testresult = 0; - - if (!TEST_ptr(asid = ASIdentifiers_new())) - goto err; - - for (i = 0; i < V3EXT_TEST_LARGE_N; i++) { - if (!TEST_ptr(minv = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(minv, - (int64_t)(2 * i + 1))) - || !TEST_ptr(maxv = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(maxv, - (int64_t)(2 * i + 2)))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - minv, maxv))) - goto err; - minv = maxv = NULL; - } - - if (!TEST_true(X509v3_asid_canonize(asid))) - goto err; - - if (!TEST_int_eq(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges), 1)) - goto err; - { - ASIdOrRange *aor = sk_ASIdOrRange_value(asid->asnum->u.asIdsOrRanges, - 0); - int64_t got_min = 0, got_max = 0; - - if (!TEST_ptr(aor) || !TEST_int_eq(aor->type, ASIdOrRange_range)) - goto err; - /* - * The merged range must cover [1, 2 * V3EXT_TEST_LARGE_N]; - * incorrect max-propagation would still leave a single range - * but with a truncated upper bound. - */ - if (!TEST_true(ASN1_INTEGER_get_int64(&got_min, aor->u.range->min)) - || !TEST_int64_t_eq(got_min, 1) - || !TEST_true(ASN1_INTEGER_get_int64(&got_max, aor->u.range->max)) - || !TEST_int64_t_eq(got_max, (int64_t)(2 * V3EXT_TEST_LARGE_N))) - goto err; - } - - if (!TEST_int_eq(X509v3_asid_is_canonical(asid), 1)) - goto err; - - testresult = 1; -err: - ASN1_INTEGER_free(minv); - ASN1_INTEGER_free(maxv); - ASIdentifiers_free(asid); - return testresult; -} - -/* - * Trigger the inverted-range guard partway through the linear merge - * in ASIdentifierChoice_canonize. The first half of the list is - * well-formed adjacent integers; entry k is an explicitly inverted - * range (min = 1000, max = 100). X509v3_asid_add_id_or_range does - * not validate min <= max for ranges, so the bad entry is admitted - * into the list, and canonize must detect it on the sweep. The - * teardown under ASan / UBSan verifies that the early-exit path - * leaves the asIdsOrRanges stack in a freeable state. - * - * The addr-side counterpart of this branch (v3_addr.c:849) is not - * reachable through the public API: make_addressRange refuses to - * construct an inverted IPAddressOrRange in the first place. The - * guard remains as defence against a DER-decoded extension that - * carries inverted min/max bit strings; exercising it from C would - * require hand-building an IPAddressOrRange, which would bind the - * test to internal ASN.1 layout. - */ -static int test_asid_canonize_inverted_midsweep(void) -{ - ASIdentifiers *asid = NULL; - ASN1_INTEGER *val = NULL, *minv = NULL, *maxv = NULL; - int i; - int n = V3EXT_TEST_LARGE_N; - int k = n / 2; - int testresult = 0; - - if (!TEST_ptr(asid = ASIdentifiers_new())) - goto err; - - for (i = 0; i < n; i++) { - if (i == k) { - /* Inverted range: min=1000, max=100. */ - if (!TEST_ptr(minv = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(minv, 1000)) - || !TEST_ptr(maxv = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(maxv, 100))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - minv, maxv))) - goto err; - minv = maxv = NULL; - } else { - int64_t v = (i < k) ? (int64_t)i + 1 - : (int64_t)i + 1000000; /* far suffix */ - - if (!TEST_ptr(val = ASN1_INTEGER_new()) - || !TEST_true(ASN1_INTEGER_set_int64(val, v))) - goto err; - if (!TEST_true(X509v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, - val, NULL))) - goto err; - val = NULL; - } - } - - /* canonize must reject the inverted entry. */ - if (!TEST_int_eq(X509v3_asid_canonize(asid), 0)) - goto err; - - testresult = 1; -err: - ASN1_INTEGER_free(val); - ASN1_INTEGER_free(minv); - ASN1_INTEGER_free(maxv); - ASIdentifiers_free(asid); - return testresult; -} - static int test_addr_subset(void) { int i; @@ -1069,15 +480,6 @@ int setup_tests(void) ADD_TEST(test_ext_syntax); ADD_TEST(test_addr_fam_len); ADD_TEST(test_addr_subset); - ADD_TEST(test_asid_large_canonize_merge); - ADD_TEST(test_asid_large_canonize_no_merge); - ADD_TEST(test_addr_large_canonize_merge); - ADD_TEST(test_asid_interleaved_canonize); - ADD_TEST(test_addr_interleaved_canonize); - ADD_TEST(test_asid_canonize_error_midsweep); - ADD_TEST(test_addr_canonize_error_midsweep); - ADD_TEST(test_asid_range_merge_canonize); - ADD_TEST(test_asid_canonize_inverted_midsweep); #endif /* OPENSSL_NO_RFC3779 */ return 1; } diff --git a/test/v3nametest.c b/test/v3nametest.c index 757db8a18e..8ae7a9e54f 100644 --- a/test/v3nametest.c +++ b/test/v3nametest.c @@ -149,7 +149,7 @@ static int set_altname(X509 *crt, ...) ia5 = ASN1_IA5STRING_new(); if (ia5 == NULL) goto out; - if (!ASN1_STRING_set_string(ia5, name)) + if (!ASN1_STRING_set(ia5, name, -1)) goto out; switch (type) { case GEN_EMAIL: diff --git a/test/x509_internal_test.c b/test/x509_internal_test.c index 1176ef49ef..19a7c2469d 100644 --- a/test/x509_internal_test.c +++ b/test/x509_internal_test.c @@ -152,7 +152,7 @@ static int test_a2i_ipaddress(int idx) { int good = 1; ASN1_OCTET_STRING *ip; - size_t len = a2i_ipaddress_tests[idx].length; + int len = a2i_ipaddress_tests[idx].length; ip = a2i_IPADDRESS(a2i_ipaddress_tests[idx].ipasc); if (len == 0) { @@ -162,7 +162,7 @@ static int test_a2i_ipaddress(int idx) } } else { if (!TEST_ptr(ip) - || !TEST_size_t_eq(ASN1_STRING_length_ex(ip), len) + || !TEST_int_eq(ASN1_STRING_length(ip), len) || !TEST_mem_eq(ASN1_STRING_get0_data(ip), len, a2i_ipaddress_tests[idx].data, len)) { good = 0; diff --git a/test/x509_load_cert_file_test.c b/test/x509_load_cert_file_test.c index f9656aaa31..0df654559a 100644 --- a/test/x509_load_cert_file_test.c +++ b/test/x509_load_cert_file_test.c @@ -198,38 +198,6 @@ err: return ret; } -static int test_x509_get1_objects_mfail(void) -{ - X509 *cert1 = NULL, *cert2 = NULL; - X509_STORE *store = NULL; - STACK_OF(X509_OBJECT) *objs = NULL; - int ret = 0; - - if (!TEST_ptr(cert1 = X509_from_strings(cn_cert1)) - || !TEST_ptr(cert2 = X509_from_strings(cn_cert2))) - goto err; - - store = X509_STORE_new(); - if (!TEST_ptr(store)) - goto err; - if (!TEST_true(X509_STORE_add_cert(store, cert1)) - || !TEST_true(X509_STORE_add_cert(store, cert2))) - goto err; - - MFAIL_start(); - objs = X509_STORE_get1_objects(store); - MFAIL_end(); - - ret = (objs != NULL); - -err: - sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free); - X509_STORE_free(store); - X509_free(cert1); - X509_free(cert2); - return ret; -} - OPT_TEST_DECLARE_USAGE("cert.pem [crl.pem]\n") int setup_tests(void) @@ -248,7 +216,6 @@ int setup_tests(void) ADD_TEST(test_load_cert_file); ADD_TEST(test_load_same_cn_certs); ADD_MFAIL_TEST(test_x509_store_add_mfail); - ADD_MFAIL_TEST(test_x509_get1_objects_mfail); return 1; } diff --git a/test/x509_test.c b/test/x509_test.c index a5beb7ca2f..e9529148d4 100644 --- a/test/x509_test.c +++ b/test/x509_test.c @@ -550,101 +550,6 @@ err: return ret; } -/* - * nameConstraints extnValue contents with one empty directoryName subtree. - * Empty X509_NAME has canon_enc == NULL / canon_enclen == 0. - * - * SEQUENCE { [0|1] { SEQUENCE { [4] { SEQUENCE {} } } } } - */ -static const unsigned char nc_excluded_empty_dirname[] = { - 0x30, 0x08, 0xa1, 0x06, 0x30, 0x04, 0xa4, 0x02, 0x30, 0x00 -}; -static const unsigned char nc_permitted_empty_dirname[] = { - 0x30, 0x08, 0xa0, 0x06, 0x30, 0x04, 0xa4, 0x02, 0x30, 0x00 -}; - -/* Decode a raw nameConstraints extnValue into a NAME_CONSTRAINTS object. */ -static NAME_CONSTRAINTS *nc_empty_dirname_from_der(const unsigned char *der, - unsigned int der_len) -{ - NAME_CONSTRAINTS *nc = NULL; - ASN1_OCTET_STRING *os = NULL; - X509_EXTENSION *ext = NULL; - - os = ASN1_OCTET_STRING_new(); - if (!TEST_ptr(os) - || !TEST_true(ASN1_OCTET_STRING_set(os, der, der_len))) - goto end; - ext = X509_EXTENSION_create_by_NID(NULL, NID_name_constraints, - 1 /* critical */, os); - if (!TEST_ptr(ext)) - goto end; - nc = X509V3_EXT_d2i(ext); - -end: - X509_EXTENSION_free(ext); - ASN1_OCTET_STRING_free(os); - return nc; -} - -/* Build a minimal certificate with a non-empty subject DN. */ -static X509 *nc_empty_dirname_subject(const char *cn) -{ - X509 *x = NULL; - X509_NAME *nm = NULL; - - if (!TEST_ptr(x = X509_new())) - goto err; - nm = X509_NAME_new(); - if (!TEST_ptr(nm) - || !TEST_true(X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, - (const unsigned char *)cn, -1, -1, 0)) - || !TEST_true(X509_set_subject_name(x, nm))) - goto err; - X509_NAME_free(nm); - return x; - -err: - X509_NAME_free(nm); - X509_free(x); - return NULL; -} - -/* Check an empty directoryName constraint against a non-empty subject DN. */ -static int nc_check_empty_dirname(const unsigned char *der, unsigned int der_len, - int expected) -{ - int ok = 0; - NAME_CONSTRAINTS *nc = NULL; - X509 *x = NULL; - - if (!TEST_ptr(nc = nc_empty_dirname_from_der(der, der_len)) - || !TEST_ptr(x = nc_empty_dirname_subject("leaf.example")) - || !TEST_int_eq(NAME_CONSTRAINTS_check(x, nc), expected)) - goto end; - - ok = 1; - -end: - X509_free(x); - NAME_CONSTRAINTS_free(nc); - return ok; -} - -/* Empty excluded directoryName matches the subject DN: excluded violation. */ -static int test_nc_empty_dirname_excluded(void) -{ - return nc_check_empty_dirname(nc_excluded_empty_dirname, - sizeof(nc_excluded_empty_dirname), X509_V_ERR_EXCLUDED_VIOLATION); -} - -/* Empty permitted directoryName matches the subject DN: permitted. */ -static int test_nc_empty_dirname_permitted(void) -{ - return nc_check_empty_dirname(nc_permitted_empty_dirname, - sizeof(nc_permitted_empty_dirname), X509_V_OK); -} - OPT_TEST_DECLARE_USAGE("\n") int setup_tests(void) @@ -686,8 +591,6 @@ int setup_tests(void) ADD_TEST(test_drop_empty_csr_keyids); ADD_TEST(test_rsaesoaep_spki); ADD_TEST(test_x509_verify_with_new); - ADD_TEST(test_nc_empty_dirname_excluded); - ADD_TEST(test_nc_empty_dirname_permitted); return 1; } diff --git a/util/libcrypto.num b/util/libcrypto.num index c7b7777cc4..777dfbf70e 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -1616,7 +1616,7 @@ EVP_KDF_get0_description 1614 4_0_0 EXIST::FUNCTION: EVP_KDF_is_a 1615 4_0_0 EXIST::FUNCTION: EVP_KDF_get0_name 1616 4_0_0 EXIST::FUNCTION: EVP_KDF_get0_provider 1617 4_0_0 EXIST::FUNCTION: -EVP_KDF_CTX_kdf 1618 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_4_1 +EVP_KDF_CTX_kdf 1618 4_0_0 EXIST::FUNCTION: EVP_KDF_CTX_reset 1619 4_0_0 EXIST::FUNCTION: EVP_KDF_CTX_get_kdf_size 1620 4_0_0 EXIST::FUNCTION: EVP_KDF_derive 1621 4_0_0 EXIST::FUNCTION: @@ -2571,9 +2571,9 @@ ASN1_STRING_copy 2569 4_0_0 EXIST::FUNCTION: ASN1_STRING_dup 2570 4_0_0 EXIST::FUNCTION: ASN1_STRING_type_new 2571 4_0_0 EXIST::FUNCTION: ASN1_STRING_cmp 2572 4_0_0 EXIST::FUNCTION: -ASN1_STRING_set 2573 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_4_1 +ASN1_STRING_set 2573 4_0_0 EXIST::FUNCTION: ASN1_STRING_set0 2574 4_0_0 EXIST::FUNCTION: -ASN1_STRING_length 2575 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_4_1 +ASN1_STRING_length 2575 4_0_0 EXIST::FUNCTION: ASN1_STRING_length_set 2576 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_3_0 ASN1_STRING_type 2577 4_0_0 EXIST::FUNCTION: ASN1_STRING_get0_data 2578 4_0_0 EXIST::FUNCTION: @@ -5722,8 +5722,3 @@ CRYPTO_atomic_cmp_exch_ptr ? 4_1_0 EXIST::FUNCTION: EVP_EC_affine2oct ? 4_1_0 EXIST::FUNCTION: OPENSSL_sk_set_copy_thunks ? 4_1_0 EXIST::FUNCTION: ASN1_STRING_new_not_owned ? 4_1_0 EXIST::FUNCTION: -EVP_KDF_CTX_get0_kdf ? 4_1_0 EXIST::FUNCTION: -EVP_KDF_CTX_get1_kdf ? 4_1_0 EXIST::FUNCTION: -ASN1_STRING_set_data ? 4_1_0 EXIST::FUNCTION: -ASN1_STRING_set_string ? 4_1_0 EXIST::FUNCTION: -ASN1_STRING_length_ex ? 4_1_0 EXIST::FUNCTION: diff --git a/util/libssl.num b/util/libssl.num index 9b24054a7c..9fe992bc39 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -558,7 +558,7 @@ SSL_CTX_get_security_callback 557 4_0_0 EXIST::FUNCTION: SSL_CTX_set0_security_ex_data 558 4_0_0 EXIST::FUNCTION: SSL_CTX_get0_security_ex_data 559 4_0_0 EXIST::FUNCTION: OPENSSL_init_ssl 560 4_0_0 EXIST::FUNCTION: -SSL_test_functions 561 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_4_1,UNIT_TEST +SSL_test_functions 561 4_0_0 EXIST::FUNCTION:UNIT_TEST SSL_free_buffers 562 4_0_0 EXIST::FUNCTION: SSL_alloc_buffers 563 4_0_0 EXIST::FUNCTION: SSL_CTX_set_session_ticket_cb 564 4_0_0 EXIST::FUNCTION: diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 5e8126d12c..57a255a4a5 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -570,6 +570,8 @@ LONG_it(3) MD2_options(3) MD4_Transform(3) MD5_Transform(3) +NAME_CONSTRAINTS_check(3) +NAME_CONSTRAINTS_check_CN(3) NAME_CONSTRAINTS_it(3) NAMING_AUTHORITY_it(3) NCONF_WIN32(3) diff --git a/util/missingmacro.txt b/util/missingmacro.txt index 20e6077c6b..50b4b17b15 100644 --- a/util/missingmacro.txt +++ b/util/missingmacro.txt @@ -137,6 +137,7 @@ SSL_get0_certificate_types(3) SSL_CTX_set1_client_certificate_types(3) SSL_set1_client_certificate_types(3) SSL_get0_raw_cipherlist(3) +SSL_get0_ec_point_formats(3) SSL_CTX_need_tmp_RSA(3) SSL_CTX_set_tmp_rsa(3) SSL_need_tmp_RSA(3) diff --git a/util/mkinstallvars.pl b/util/mkinstallvars.pl index 09924901ce..578d344f4e 100644 --- a/util/mkinstallvars.pl +++ b/util/mkinstallvars.pl @@ -54,9 +54,9 @@ foreach (@ARGV) { # the former doesn't have a value, we give it the latter's value, and rely # on mechanisms further down to do the rest of the processing. # If they're both empty, it's still fine. -print STDERR "DEBUG: LIBDIR = $values{LIBDIR}->[0], libdir = $values{libdir}->[0] => " if $debug; +print STDERR "DEBUG: LIBDIR = $values{LIBDIR}->[0], libdir = $values{libdir}->[0] => "; $values{LIBDIR}->[0] = $values{libdir}->[0] unless $values{LIBDIR}->[0]; -print STDERR "LIBDIR = $values{LIBDIR}->[0]\n" if $debug; +print STDERR "LIBDIR = $values{LIBDIR}->[0]\n"; # warn if there are missing values, and also if there are unexpected values foreach my $k (sort keys %all) { diff --git a/util/mkwraps.pl b/util/mkwraps.pl deleted file mode 100755 index 91a44cbb3f..0000000000 --- a/util/mkwraps.pl +++ /dev/null @@ -1,592 +0,0 @@ -#! /usr/bin/env perl -# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html - -use strict; -use warnings; - -use Getopt::Long; -use File::Spec::Functions qw(catdir catfile file_name_is_absolute rel2abs); -use File::Basename qw(dirname); - -my $build_info_file; -my $target; -my @extra_includes; -my $output_file; -my $mode = 'both'; -my $cc; -my $use_system = 1; -my $verbose = 0; -my $help = 0; - -GetOptions('build-info=s' => \$build_info_file, - 'target=s' => \$target, - 'include=s' => \@extra_includes, - 'output=s' => \$output_file, - 'mode=s' => \$mode, - 'cc=s' => \$cc, - 'system!' => \$use_system, - 'verbose' => \$verbose, - 'help' => \$help) - or die "Error in command line arguments\n"; - -$cc = $ENV{CC} || 'cc' unless defined $cc; - -sub help -{ - print STDERR <<"EOF"; -mkwraps.pl [options] - -Options: - - --build-info FILE build.info file containing a WRAP[] entry. - - --target NAME Test program name used as the WRAP[]/INCLUDE[] key. - - --include DIR Extra include directory to search. Cumulative. - - --output FILE Output file. Defaults to stdout. - - --mode MODE What to emit: 'wraps', 'expects' or 'both'. - Defaults to 'both'. - - --cc NAME C compiler used to discover the default system - include search paths. Defaults to \$CC or 'cc'. - - --no-system Do not fall back to the compiler's default system - include directories. By default, functions not - found in the project headers (typically libc/POSIX - functions) are looked up there. - - --verbose Print progress to stderr. - - --help Show this help text. - -For each function name listed in WRAP[], the script searches -the headers (*.h) under each directory in INCLUDE[], resolved -relative to the directory containing the build.info file, plus any -extra --include directories. The search recurses into subdirectories, -mirroring how the compiler resolves via -I flags. -The first header containing a matching declaration provides the -prototype. - -Functions not found in those directories (typically system functions -such as read() or socket()) are then looked up under the compiler's -default include search paths, as reported by the C compiler. System -prototypes are emitted with angle-bracket #include directives. Use ---no-system to disable this fallback. - -The output is meant as a stub for further editing. Custom logic -(out-parameters, variadic forwarding, side effects on globals) still -needs to be written manually, and the emitted #include directives may -need to be adjusted (e.g. to add internal headers for opaque types). -Long lines in the output are not wrapped. -EOF -} - -if ($help) { - &help(); - exit 0; -} - -unless (defined $build_info_file && defined $target) { - &help(); - exit 1; -} - -die "--mode must be 'wraps', 'expects' or 'both'\n" - unless $mode =~ /^(?:wraps|expects|both)$/; - -my @t = localtime(); -my $YEAR = $t[5] + 1900; - -# Parse the build.info file. We are only interested in two directives, -# WRAP[] and INCLUDE[], either of which may be split -# across several physical lines using the usual backslash continuation. - -my @wraps; -my @includes; - -open(IN, "<$build_info_file") || die "Can't open $build_info_file, $!,"; -my $content = do { local $/; }; -close IN; - -$content =~ s/\\\n\s*/ /g; - -foreach (split /\n/, $content) { - next if /^\s*#/ || /^\s*$/; - if (/^\s*WRAP\[\Q$target\E\]\s*=\s*(.+?)\s*$/) { - push @wraps, split(/\s+/, $1); - } elsif (/^\s*INCLUDE\[\Q$target\E\]\s*=\s*(.+?)\s*$/) { - push @includes, split(/\s+/, $1); - } -} - -die "No WRAP[$target] entry found in $build_info_file\n" unless @wraps; - -my $bi_dir = dirname($build_info_file); -my @search_dirs; -foreach my $inc (@includes, @extra_includes) { - push @search_dirs, - file_name_is_absolute($inc) ? $inc : rel2abs(catdir($bi_dir, $inc)); -} - -print STDERR "Wraps:\n ", join("\n ", @wraps), "\n" if $verbose; -print STDERR "Search dirs:\n ", join("\n ", @search_dirs), "\n" if $verbose; - -# Walk all search directories and get them in the order that level ones are -# first followed by subdirs so if there are nested includes, we get the -# shortest ones first searched. Each base is a [dir, is_system] pair and the -# is_system flag is carried onto every header found beneath it, so that system -# prototypes can later be emitted with angle-bracket includes. -sub find_headers -{ - my (@bases) = @_; - my @found; - my @queue = map { [$_->[0], '', $_->[1]] } @bases; - - while (@queue) { - my @next; - my @level_files; - foreach my $entry (@queue) { - my ($dir, $rel, $sys) = @$entry; - next unless -d $dir; - opendir(my $dh, $dir) or next; - foreach my $name (readdir $dh) { - next if $name =~ /^\./; - my $full = catfile($dir, $name); - my $newrel = $rel eq '' ? $name : "$rel/$name"; - if (-d $full) { - push @next, [$full, $newrel, $sys]; - } elsif (-f $full && $name =~ /\.h$/) { - push @level_files, [$full, $newrel, $sys]; - } - } - closedir $dh; - } - # Stable sort within a level for deterministic ordering. - push @found, sort { $a->[1] cmp $b->[1] } @level_files; - @queue = sort { $a->[1] cmp $b->[1] } @next; - } - return @found; -} - -# Ask the C compiler for its default "#include <...>" search paths. Returns -# the list of existing directories, in search order. Empty on failure. -sub system_include_dirs -{ - my ($compiler) = @_; - my $out = `$compiler -xc -E -v /dev/null 2>&1`; - return () unless defined $out - && $out =~ /search starts here:(.*?)End of search list\./s; - my @dirs; - foreach my $line (split /\n/, $1) { - $line =~ s/^\s+//; - $line =~ s/\s+$//; - # clang annotates framework directories; skip those. - next if $line eq '' || $line =~ /\(framework directory\)$/; - push @dirs, $line if -d $line; - } - return @dirs; -} - -# Project headers are searched first (with is_system = 0) so that a project -# declaration always wins over a colliding system one. The system headers are -# appended lazily, only if some function is not found in the project headers. -my @search_files = find_headers(map { [$_, 0] } @search_dirs); -my $system_loaded = 0; - -sub load_system_headers -{ - return if $system_loaded; - $system_loaded = 1; - return unless $use_system; - my @sys_dirs = system_include_dirs($cc); - unless (@sys_dirs) { - warn "WARNING: could not determine system include dirs from '$cc'\n"; - return; - } - print STDERR "System include dirs:\n ", join("\n ", @sys_dirs), "\n" - if $verbose; - push @search_files, find_headers(map { [$_, 1] } @sys_dirs); -} - -my %file_cache; - -sub strip_c_comments -{ - my $s = shift; - $s =~ s{/\*.*?\*/}{}sg; - $s =~ s{//[^\n]*}{}g; - return $s; -} - -# Drop attribute and qualifier macros that should not appear in the -# emitted return type. -sub strip_attribute_macros -{ - my $s = shift; - foreach my $kw (qw(__owur __pure __malloc__ ossl_inline static inline - extern OSSL_DEPRECATEDIN_0_9_8 - OSSL_DEPRECATEDIN_1_0_0 OSSL_DEPRECATEDIN_1_1_0 - OSSL_DEPRECATEDIN_3_0 OSSL_DEPRECATEDIN_3_1 - OSSL_DEPRECATEDIN_3_2 OSSL_DEPRECATEDIN_3_3 - OSSL_DEPRECATEDIN_3_4 OSSL_DEPRECATEDIN_3_5)) { - $s =~ s/\b\Q$kw\E\b//g; - } - $s =~ s/\b__attribute__\s*\(\([^)]*\)\)//g; - $s =~ s/\s+/ /g; - $s =~ s/^\s+|\s+$//g; - return $s; -} - -# Consume reserved-namespace decorations between a declaration's closing -# parenthesis and its semicolon, e.g. glibc's __THROW, __wur or -# __attr_access ((...)). Only __-prefixed tokens (with an optional balanced -# argument list) are eaten, so a genuine following declaration is left alone. -sub skip_trailing_attributes -{ - my $s = shift; - while (1) { - $s =~ s/^\s+//; - last unless $s =~ /^(__\w+)/; - $s = substr($s, length($1)); - $s =~ s/^\s+//; - if ($s =~ /^\(/) { - my $depth = 0; - my $i = 0; - while ($i < length($s)) { - my $c = substr($s, $i, 1); - $depth++ if $c eq '('; - $depth-- if $c eq ')'; - $i++; - last if $depth == 0; - } - return $s if $depth != 0; - $s = substr($s, $i); - } - } - return $s; -} - -sub find_function_decl -{ - my ($funcname) = @_; - - foreach my $entry (@search_files) { - my ($file, $relpath, $is_system) = @$entry; - unless (exists $file_cache{$file}) { - my $text = ''; - if (open(my $fh, '<', $file)) { - local $/; - $text = <$fh>; - close $fh; - } - $file_cache{$file} = strip_c_comments($text); - } - my $text = $file_cache{$file}; - - while ($text =~ /\b\Q$funcname\E\s*\(/g) { - my $name_start = $-[0]; - my $paren_start = pos($text); - - # Find matching closing paren, respecting nesting. - my $depth = 1; - my $cursor = $paren_start; - while ($cursor < length($text) && $depth > 0) { - my $c = substr($text, $cursor, 1); - $depth++ if $c eq '('; - $depth-- if $c eq ')'; - $cursor++; - } - next if $depth != 0; - my $params_str = - substr($text, $paren_start, $cursor - $paren_start - 1); - - # What follows must be ; for this to be a declaration, possibly - # after trailing attribute macros (__THROW, __wur, ...). - my $after = substr($text, $cursor); - $after = skip_trailing_attributes($after); - next unless $after =~ /^;/; - - # Anything since the previous statement terminator is the return - # type expression. - my $pre = substr($text, 0, $name_start); - $pre =~ s/\s+$//; - my $ret_start = 0; - $ret_start = $-[2] if $pre =~ /([;}\n])([^;}\n]*)$/s; - my $rettype = strip_attribute_macros(substr($pre, $ret_start)); - - # Normalise to forward slashes for use as an #include path. - my $include_path = $relpath; - $include_path =~ s|\\|/|g; - - return { name => $funcname, - rettype => $rettype, - params => $params_str, - file => $file, - include_path => $include_path, - system => $is_system }; - } - } - return undef; -} - -# Split a parameter list on top-level commas, respecting parentheses -sub split_params -{ - my $str = shift; - $str =~ s/^\s+|\s+$//g; - return () if $str eq '' || $str eq 'void'; - - my @parts; - my $current = ''; - my $depth = 0; - foreach my $c (split //, $str) { - if ($c eq '(') { - $depth++; - $current .= $c; - } elsif ($c eq ')') { - $depth--; - $current .= $c; - } elsif ($c eq ',' && $depth == 0) { - push @parts, $current; - $current = ''; - } else { - $current .= $c; - } - } - push @parts, $current if $current ne ''; - foreach my $p (@parts) { - $p =~ s/^\s+|\s+$//g; - } - return @parts; -} - -sub parse_param -{ - my $param = shift; - return { type => '', name => '', is_variadic => 1, is_ptr => 0 } - if $param eq '...'; - - # Drop the restrict qualifier; it plays no role in a mock signature. - $param =~ s/\b(?:__restrict(?:__)?|restrict)\b//g; - - # Reduce TYPE NAME[size] to TYPE * NAME for our purposes. - my $is_array = 0; - $is_array = 1 if $param =~ s/\[\s*[^\]]*\s*\]\s*$//; - - my ($type, $name); - if ($param =~ /^(.*?)([A-Za-z_]\w*)\s*$/) { - $type = $1; - $name = $2; - $type =~ s/\s+$//; - } else { - $type = $param; - $name = ''; - } - - # System headers name parameters in the reserved __ namespace; strip the - # leading underscores so the generated wrap uses ordinary local names. - $name =~ s/^_+//; - - return { type => $type, - name => $name, - is_ptr => (($type =~ /\*/) || $is_array) ? 1 : 0, - is_variadic => 0, - is_array => $is_array }; -} - -sub is_void_type -{ - my $t = shift; - $t =~ s/^\s+|\s+$//g; - $t =~ s/\s+/ /g; - return $t eq 'void'; -} - -sub is_ptr_type { return $_[0] =~ /\*/; } - -# Look up each WRAP entry's signature. Functions we cannot find are -# skipped with a warning rather than aborting. -my @signatures; -my @found_includes; -my %seen_include; -foreach my $func (@wraps) { - my $info = find_function_decl($func); - if (!defined $info && !$system_loaded) { - # Not in the project headers: pull in the system ones and retry. - load_system_headers(); - $info = find_function_decl($func); - } - unless (defined $info) { - warn "WARNING: $func: declaration not found in any include dir\n"; - next; - } - - my @params = map { parse_param($_) } split_params($info->{params}); - - my $idx = 0; - foreach my $p (@params) { - next if $p->{is_variadic}; - $p->{name} = "arg$idx" if $p->{name} eq ''; - $idx++; - } - - push @signatures, { name => $func, - rettype => $info->{rettype}, - params => \@params }; - - unless ($seen_include{$info->{include_path}}) { - $seen_include{$info->{include_path}} = 1; - push @found_includes, { path => $info->{include_path}, - system => $info->{system} }; - } - print STDERR " found $func in $info->{file}\n" if $verbose; -} - -die "No declarations found, nothing to emit\n" unless @signatures; - -my $out_fh; -if (defined $output_file) { - open($out_fh, '>', $output_file) or die "$output_file: $!\n"; -} else { - $out_fh = \*STDOUT; -} - -print $out_fh <<"EOF"; -/* - * Copyright $YEAR The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -EOF - -print $out_fh "#include \n"; -print $out_fh "\n"; -if (@found_includes) { - my @angle; - my @local; - foreach my $inc (sort { $a->{path} cmp $b->{path} } @found_includes) { - if ($inc->{system} || $inc->{path} =~ m|^openssl/|) { - push @angle, $inc->{path}; - } else { - push @local, $inc->{path}; - } - } - foreach my $inc (@angle) { - print $out_fh "#include <$inc>\n"; - } - print $out_fh "\n" if @angle && @local; - foreach my $inc (@local) { - print $out_fh "#include \"$inc\"\n"; - } - print $out_fh "\n"; -} - -if ($mode eq 'wraps' || $mode eq 'both') { - print $out_fh "/* wraps */\n\n"; - foreach my $f (@signatures) { - print $out_fh format_signature($f->{rettype}, - "__wrap_$f->{name}", - $f->{params}), ";\n"; - } - print $out_fh "\n"; - - foreach my $f (@signatures) { - emit_wrap($out_fh, $f); - print $out_fh "\n"; - } -} - -if ($mode eq 'expects' || $mode eq 'both') { - print $out_fh "/* expectations */\n\n"; - foreach my $f (@signatures) { - emit_expect($out_fh, $f); - print $out_fh "\n"; - } -} - -close $out_fh if defined $output_file; - -exit 0; - -sub format_decl -{ - my ($type, $name) = @_; - return $type =~ /\*$/ ? "$type$name" : "$type $name"; -} - -sub format_param -{ - my $p = shift; - return '...' if $p->{is_variadic}; - return format_decl($p->{type}, $p->{name}); -} - -sub format_signature -{ - my ($rettype, $name, $params) = @_; - my $param_str = @$params - ? join(', ', map { format_param($_) } @$params) - : 'void'; - return format_decl($rettype, $name) . "($param_str)"; -} - -sub emit_wrap -{ - my ($fh, $f) = @_; - print $fh format_signature($f->{rettype}, "__wrap_$f->{name}", - $f->{params}), "\n{\n"; - print $fh " function_called();\n"; - foreach my $p (@{$f->{params}}) { - next if $p->{is_variadic}; - if ($p->{is_ptr}) { - print $fh " check_expected_ptr($p->{name});\n"; - } else { - print $fh " check_expected($p->{name});\n"; - } - } - if ( ! is_void_type($f->{rettype})) { - if (is_ptr_type($f->{rettype})) { - print $fh "\n return mock_ptr_type($f->{rettype});\n"; - } else { - print $fh "\n return mock_type($f->{rettype});\n"; - } - } - print $fh "}\n"; -} - -sub emit_expect -{ - my ($fh, $f) = @_; - my $name = $f->{name}; - my @params = @{$f->{params}}; - - my @sig_parts; - foreach my $p (@params) { - next if $p->{is_variadic}; - push @sig_parts, format_param($p); - } - - my $needs_rc = !is_void_type($f->{rettype}); - push @sig_parts, format_decl($f->{rettype}, 'rc') if $needs_rc; - - my $param_str = @sig_parts ? join(', ', @sig_parts) : 'void'; - print $fh "static void expect_$name($param_str)\n{\n"; - print $fh " expect_function_call(__wrap_$name);\n"; - foreach my $p (@params) { - next if $p->{is_variadic}; - print $fh " expect_value(__wrap_$name, $p->{name}, $p->{name});\n"; - } - print $fh " will_return(__wrap_$name, rc);\n" if $needs_rc; - print $fh "}\n"; -} diff --git a/util/other.syms b/util/other.syms index 114e25a348..fa54186811 100644 --- a/util/other.syms +++ b/util/other.syms @@ -314,7 +314,6 @@ ERR_raise define ERR_raise_data define EVP_DigestSignUpdate define EVP_DigestVerifyUpdate define -EVP_KDF_CTX_kdf define EVP_MD_CTX_get_block_size define EVP_MD_CTX_get0_name define EVP_MD_CTX_get_size define @@ -647,7 +646,6 @@ SSL_clear_mode define SSL_disable_ct define SSL_get0_chain_certs define SSL_get0_iana_groups define -SSL_get0_ec_point_formats define SSL_get0_session define SSL_get0_chain_cert_store define SSL_get0_verify_cert_store define diff --git a/util/perl/OpenSSL/ParseC.pm b/util/perl/OpenSSL/ParseC.pm index 6249704a23..c2546280c8 100644 --- a/util/perl/OpenSSL/ParseC.pm +++ b/util/perl/OpenSSL/ParseC.pm @@ -62,7 +62,7 @@ my @opensslcpphandlers = ( ################################################################## # OpenSSL CPP specials # - # These are used to convert certain pre-processor expressions into + # These are used to convert certain pre-precessor expressions into # others that @cpphandlers have a better chance to understand. # This changes any OPENSSL_NO_DEPRECATED_x_y[_z] check to a check of diff --git a/util/perl/OpenSSL/Test.pm b/util/perl/OpenSSL/Test.pm index 570d3a8631..369d4f2b9a 100644 --- a/util/perl/OpenSSL/Test.pm +++ b/util/perl/OpenSSL/Test.pm @@ -333,7 +333,7 @@ sub app { $idx=$idx+1; my $resultdir = result_dir(); my $srcdir = srctop_dir(); - return cmd([ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "--gen-suppressions=all", "--suppressions=$srcdir/util/valgrind.suppression", "--log-file=$resultdir/valgrind.log.$idx.%p", "--suppressions=$srcdir/util/valgrind.suppression", @prog, @cmdargs ], + return cmd([ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "--gen-suppressions=all", "--suppressions=$srcdir/util/valgrind.suppression", "--log-file=$resultdir/valgrind.log.$idx", "--suppressions=$srcdir/util/valgrind.suppression", @prog, @cmdargs ], exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift); } else { return cmd([ @prog, @cmdargs ], @@ -363,7 +363,7 @@ sub test { $idx=$idx+1; my $resultdir = result_dir(); my $srcdir = srctop_dir(); - return cmd([ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "--gen-suppressions=all", "--suppressions=$srcdir/util/valgrind.suppression", "--log-file=$resultdir/valgrind.log.$idx.%p", "--suppressions=$srcdir/util/valgrind.suppression", @prog, @cmdargs ], + return cmd([ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "--gen-suppressions=all", "--suppressions=$srcdir/util/valgrind.suppression", "--log-file=$resultdir/valgrind.log.$idx", "--suppressions=$srcdir/util/valgrind.suppression", @prog, @cmdargs ], exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift); } elsif (defined $ENV{OSSL_VALGRIND_CT}) { # Constant-time validation mode: mark secret data as undefined and @@ -448,14 +448,6 @@ If used, B must be a reference to a scalar variable. It will be assigned a boolean indicating if the command succeeded or not. This is particularly useful together with B. -=item B 0|1> - -If true, suppress the diagnostic line that C normally prints to STDERR -after the command completes (the C exitcode> line) when running -under a non-verbose test harness. Has no effect outside a harness or under -C. Useful for loops that invoke many commands where that -line would be noise. - =back Usually 1 indicates that the command was successful and 0 indicates failure. @@ -530,20 +522,19 @@ sub run { ${$opts{statusvar}} = $r; } - my $harness_quiet = $ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}; + # Restore STDOUT / STDERR on VMS if ($^O eq 'VMS') { - # Restore STDOUT / STDERR on VMS - if ($harness_quiet) { + if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) { close STDOUT; close STDERR; open STDOUT, '>&', $save_STDOUT or die "Can't restore STDOUT: $!"; open STDERR, '>&', $save_STDERR or die "Can't restore STDERR: $!"; } - print STDERR "$prefix$display_cmd => $e\n" unless $harness_quiet; - } else { print STDERR "$prefix$display_cmd => $e\n" - unless $opts{quiet} && $harness_quiet; + if !$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}; + } else { + print STDERR "$prefix$display_cmd => $e\n"; } # At this point, $? stops being interesting, and unfortunately, diff --git a/util/perl/OpenSSL/config.pm b/util/perl/OpenSSL/config.pm index e9dc9d3243..f781068bf5 100755 --- a/util/perl/OpenSSL/config.pm +++ b/util/perl/OpenSSL/config.pm @@ -411,7 +411,7 @@ sub determine_compiler_settings { $CCVER = 0; my $v = `cl 2>&1`; - if ( $v =~ /Microsoft .* Version ([0-9\.]+) for (x86|x64|ARM)/ ) { + if ( $v =~ /Microsoft .* Version ([0-9\.]+) for (x86|x64|ARM|ia64)/ ) { $CCVER = $1; $CL_ARCH = $2; } @@ -898,7 +898,7 @@ EOF ], # Windows values found by looking at Perl 5's win32/win32.c - [ '(amd64|x86|ARM)-.*?-Windows NT', + [ '(amd64|ia64|x86|ARM)-.*?-Windows NT', sub { # If we determined the arch by asking cl, take that value, # otherwise the SYSTEM we got from from POSIX::uname(). @@ -907,6 +907,7 @@ EOF if ($arch) { $config = { 'amd64' => { target => 'VC-WIN64A' }, + 'ia64' => { target => 'VC-WIN64I' }, 'x86' => { target => 'VC-WIN32' }, 'x64' => { target => 'VC-WIN64A' }, 'ARM' => { target => 'VC-WIN64-ARM' }, diff --git a/util/perl/OpenSSL/stackhash.pm b/util/perl/OpenSSL/stackhash.pm index b3446f7747..39f71e1ce7 100644 --- a/util/perl/OpenSSL/stackhash.pm +++ b/util/perl/OpenSSL/stackhash.pm @@ -28,30 +28,9 @@ sub generate_stack_macros_int { SKM_DEFINE_STACK_OF_INTERNAL(${nametype}, ${realtype}, ${plaintype}) #define sk_${nametype}_num(sk) OPENSSL_sk_num(ossl_check_const_${nametype}_sk_type(sk)) #define sk_${nametype}_value(sk, idx) ((${realtype} *)OPENSSL_sk_value(ossl_check_const_${nametype}_sk_type(sk), (idx))) -#define sk_${nametype}_new(cmp) \\ - ((STACK_OF(${nametype}) *)OPENSSL_sk_set_thunks( \\ - OPENSSL_sk_set_copy_thunks( \\ - OPENSSL_sk_set_cmp_thunks( \\ - OPENSSL_sk_new(ossl_check_${nametype}_compfunc_type(cmp)), \\ - sk_${nametype}_cmpfunc_thunk), \\ - sk_${nametype}_copyfunc_thunk), \\ - sk_${nametype}_freefunc_thunk)) -#define sk_${nametype}_new_null() \\ - ((STACK_OF(${nametype}) *)OPENSSL_sk_set_thunks( \\ - OPENSSL_sk_set_copy_thunks( \\ - OPENSSL_sk_set_cmp_thunks( \\ - OPENSSL_sk_new_null(), \\ - sk_${nametype}_cmpfunc_thunk), \\ - sk_${nametype}_copyfunc_thunk), \\ - sk_${nametype}_freefunc_thunk)) -#define sk_${nametype}_new_reserve(cmp, n) \\ - ((STACK_OF(${nametype}) *)OPENSSL_sk_set_thunks( \\ - OPENSSL_sk_set_copy_thunks( \\ - OPENSSL_sk_set_cmp_thunks( \\ - OPENSSL_sk_new_reserve(ossl_check_${nametype}_compfunc_type(cmp), (n)), \\ - sk_${nametype}_cmpfunc_thunk), \\ - sk_${nametype}_copyfunc_thunk), \\ - sk_${nametype}_freefunc_thunk)) +#define sk_${nametype}_new(cmp) ((STACK_OF(${nametype}) *)OPENSSL_sk_set_copy_thunks(OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_${nametype}_compfunc_type(cmp)), sk_${nametype}_cmpfunc_thunk), sk_${nametype}_copyfunc_thunk)) +#define sk_${nametype}_new_null() ((STACK_OF(${nametype}) *)OPENSSL_sk_set_thunks(OPENSSL_sk_set_copy_thunks(OPENSSL_sk_new_null(), sk_${nametype}_copyfunc_thunk), sk_${nametype}_freefunc_thunk)) +#define sk_${nametype}_new_reserve(cmp, n) ((STACK_OF(${nametype}) *)OPENSSL_sk_set_copy_thunks(OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_${nametype}_compfunc_type(cmp), (n)), sk_${nametype}_cmpfunc_thunk), sk_${nametype}_copyfunc_thunk)) #define sk_${nametype}_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_${nametype}_sk_type(sk), (n)) #define sk_${nametype}_free(sk) OPENSSL_sk_free(ossl_check_${nametype}_sk_type(sk)) #define sk_${nametype}_zero(sk) OPENSSL_sk_zero(ossl_check_${nametype}_sk_type(sk)) @@ -69,25 +48,8 @@ SKM_DEFINE_STACK_OF_INTERNAL(${nametype}, ${realtype}, ${plaintype}) #define sk_${nametype}_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_${nametype}_sk_type(sk), ossl_check_${nametype}_type(ptr), pnum) #define sk_${nametype}_sort(sk) OPENSSL_sk_sort(ossl_check_${nametype}_sk_type(sk)) #define sk_${nametype}_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_${nametype}_sk_type(sk)) -#define sk_${nametype}_dup(sk) \\ - ((STACK_OF(${nametype}) *)OPENSSL_sk_set_thunks( \\ - OPENSSL_sk_set_copy_thunks( \\ - OPENSSL_sk_set_cmp_thunks( \\ - OPENSSL_sk_dup(ossl_check_const_${nametype}_sk_type(sk)), \\ - sk_${nametype}_cmpfunc_thunk), \\ - sk_${nametype}_copyfunc_thunk), \\ - sk_${nametype}_freefunc_thunk)) -#define sk_${nametype}_deep_copy(sk, copyfunc, freefunc) \\ - ((STACK_OF(${nametype}) *)OPENSSL_sk_set_thunks( \\ - OPENSSL_sk_set_copy_thunks( \\ - OPENSSL_sk_set_cmp_thunks( \\ - OPENSSL_sk_deep_copy( \\ - ossl_check_const_${nametype}_sk_type(sk), \\ - ossl_check_${nametype}_copyfunc_type(copyfunc), \\ - ossl_check_${nametype}_freefunc_type(freefunc)), \\ - sk_${nametype}_cmpfunc_thunk), \\ - sk_${nametype}_copyfunc_thunk), \\ - sk_${nametype}_freefunc_thunk)) +#define sk_${nametype}_dup(sk) ((STACK_OF(${nametype}) *)OPENSSL_sk_dup(ossl_check_const_${nametype}_sk_type(sk))) +#define sk_${nametype}_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(${nametype}) *)OPENSSL_sk_deep_copy(ossl_check_const_${nametype}_sk_type(sk), ossl_check_${nametype}_copyfunc_type(copyfunc), ossl_check_${nametype}_freefunc_type(freefunc))) #define sk_${nametype}_set_cmp_func(sk, cmp) ((sk_${nametype}_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_${nametype}_sk_type(sk), ossl_check_${nametype}_compfunc_type(cmp))) END_MACROS diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index 8c4f9564fa..4c1ba50de4 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -51,8 +51,7 @@ use constant { AL_DESC_DECRYPT_ERROR => 51, AL_DESC_PROTOCOL_VERSION => 70, AL_DESC_NO_RENEGOTIATION => 100, - AL_DESC_MISSING_EXTENSION => 109, - AL_DESC_UNSUPPORTED_EXTENSION => 110 + AL_DESC_MISSING_EXTENSION => 109 }; my %message_type = ( diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm index a7fe48e9ce..5ba6579ed3 100644 --- a/util/perl/TLSProxy/Proxy.pm +++ b/util/perl/TLSProxy/Proxy.pm @@ -181,7 +181,6 @@ sub init server_port => 0, serverpid => 0, clientpid => 0, - clientexit => 0, execute => $execute, cert => $cert, debug => $debug, @@ -220,7 +219,6 @@ sub clearClient $self->{clientflags} = ""; $self->{sessionfile} = undef; $self->{clientpid} = 0; - $self->{clientexit} = 0; $is_tls13 = 0; $ciphersuite = undef; @@ -606,7 +604,6 @@ sub clientstart $pid = $self->{clientpid}; print "Waiting for s_client process to close: $pid...\n"; waitpid($pid, 0); - $self->{clientexit} = $?; return $success; } @@ -744,11 +741,6 @@ sub clientpid my $self = shift; return $self->{clientpid}; } -sub clientexit -{ - my $self = shift; - return $self->{clientexit}; -} #Read/write accessors sub filter diff --git a/util/platform_symbols/windows-symbols.txt b/util/platform_symbols/windows-symbols.txt index 7ae58a3f18..0f6cc11450 100644 --- a/util/platform_symbols/windows-symbols.txt +++ b/util/platform_symbols/windows-symbols.txt @@ -1,6 +1,5 @@ AcquireSRWLockExclusive AcquireSRWLockShared -BCryptGenRandom CertCloseStore CertFindCertificateInStore CertFreeCertificateContext diff --git a/util/valgrind.suppression b/util/valgrind.suppression index e4f14372d4..4514e702b0 100644 --- a/util/valgrind.suppression +++ b/util/valgrind.suppression @@ -121,7 +121,6 @@ fun:malloc ... fun:OSSL_provider_init - fun:provider_init fun:provider_activate ... }